~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to channels/rdpdr/parallel/parallel_main.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * FreeRDP: A Remote Desktop Protocol client.
3
 
 * Redirected Parallel Port Device Service
4
 
 *
5
 
 * Copyright 2010 O.S. Systems Software Ltda.
6
 
 * Copyright 2010 Eduardo Fiss Beloni <beloni@ossystems.com.br>
7
 
 *
8
 
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 
 * you may not use this file except in compliance with the License.
10
 
 * You may obtain a copy of the License at
11
 
 *
12
 
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 
 *
14
 
 * Unless required by applicable law or agreed to in writing, software
15
 
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 
 * See the License for the specific language governing permissions and
18
 
 * limitations under the License.
19
 
 */
20
 
 
21
 
#include <stdio.h>
22
 
#include <stdlib.h>
23
 
#include <string.h>
24
 
 
25
 
#include <unistd.h>
26
 
#include <fcntl.h>
27
 
#include <termios.h>
28
 
#include <errno.h>
29
 
#include <strings.h>
30
 
#include <sys/ioctl.h>
31
 
#ifdef __LINUX__
32
 
#include <linux/ppdev.h>
33
 
#include <linux/parport.h>
34
 
#endif
35
 
 
36
 
#include <freerdp/types.h>
37
 
#include <freerdp/constants.h>
38
 
#include <freerdp/utils/list.h>
39
 
#include <freerdp/utils/thread.h>
40
 
#include <freerdp/utils/memory.h>
41
 
#include <freerdp/utils/stream.h>
42
 
#include <freerdp/utils/svc_plugin.h>
43
 
 
44
 
#include "rdpdr_constants.h"
45
 
#include "rdpdr_types.h"
46
 
 
47
 
struct _PARALLEL_DEVICE
48
 
{
49
 
        DEVICE device;
50
 
 
51
 
        int file;
52
 
        char* path;
53
 
        uint32 id;
54
 
 
55
 
        LIST* irp_list;
56
 
        freerdp_thread* thread;
57
 
};
58
 
typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE;
59
 
 
60
 
static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
61
 
{
62
 
        uint32 PathLength;
63
 
        char* path;
64
 
        UNICONV* uniconv;
65
 
 
66
 
        stream_seek(irp->input, 28);
67
 
        /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
68
 
        /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
69
 
        stream_read_uint32(irp->input, PathLength);
70
 
 
71
 
        uniconv = freerdp_uniconv_new();
72
 
        path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength);
73
 
        freerdp_uniconv_free(uniconv);
74
 
 
75
 
        parallel->id = irp->devman->id_sequence++;
76
 
        parallel->file = open(parallel->path, O_RDWR);
77
 
        if (parallel->file < 0)
78
 
        {
79
 
                irp->IoStatus = STATUS_ACCESS_DENIED;
80
 
                parallel->id = 0;
81
 
 
82
 
                DEBUG_WARN("failed to create %s: %s", parallel->path, strerror(errno));
83
 
        }
84
 
        else
85
 
        {
86
 
                /* all read and write operations should be non-blocking */
87
 
                if (fcntl(parallel->file, F_SETFL, O_NONBLOCK) == -1)
88
 
                        DEBUG_WARN("%s fcntl %s", path, strerror(errno));
89
 
 
90
 
                DEBUG_SVC("%s(%d) created", parallel->path, parallel->file);
91
 
        }
92
 
 
93
 
        stream_write_uint32(irp->output, parallel->id);
94
 
        stream_write_uint8(irp->output, 0);
95
 
 
96
 
        xfree(path);
97
 
 
98
 
        irp->Complete(irp);
99
 
}
100
 
 
101
 
static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
102
 
{
103
 
        if (close(parallel->file) < 0)
104
 
                DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id);
105
 
        else
106
 
                DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id);
107
 
 
108
 
        stream_write_zero(irp->output, 5); /* Padding(5) */
109
 
 
110
 
        irp->Complete(irp);
111
 
}
112
 
 
113
 
static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
114
 
{
115
 
        uint32 Length;
116
 
        uint64 Offset;
117
 
        ssize_t status;
118
 
        uint8* buffer = NULL;
119
 
 
120
 
        stream_read_uint32(irp->input, Length);
121
 
        stream_read_uint64(irp->input, Offset);
122
 
 
123
 
        buffer = (uint8*) xmalloc(Length);
124
 
 
125
 
        status = read(parallel->file, irp->output->p, Length);
126
 
 
127
 
        if (status < 0)
128
 
        {
129
 
                irp->IoStatus = STATUS_UNSUCCESSFUL;
130
 
                xfree(buffer);
131
 
                buffer = NULL;
132
 
                Length = 0;
133
 
 
134
 
                DEBUG_WARN("read %s(%d) failed", parallel->path, parallel->id);
135
 
        }
136
 
        else
137
 
        {
138
 
                DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, parallel->id);
139
 
        }
140
 
 
141
 
        stream_write_uint32(irp->output, Length);
142
 
        if (Length > 0)
143
 
        {
144
 
                stream_check_size(irp->output, Length);
145
 
                stream_write(irp->output, buffer, Length);
146
 
        }
147
 
        xfree(buffer);
148
 
 
149
 
        irp->Complete(irp);
150
 
}
151
 
 
152
 
static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
153
 
{
154
 
        uint32 Length;
155
 
        uint64 Offset;
156
 
        ssize_t status;
157
 
        uint32 len;
158
 
 
159
 
        stream_read_uint32(irp->input, Length);
160
 
        stream_read_uint64(irp->input, Offset);
161
 
        stream_seek(irp->input, 20); /* Padding */
162
 
 
163
 
        DEBUG_SVC("Length %u Offset %llu", Length, Offset);
164
 
 
165
 
        len = Length;
166
 
        while (len > 0)
167
 
        {
168
 
                status = write(parallel->file, stream_get_tail(irp->input), len);
169
 
 
170
 
                if (status < 0)
171
 
                {
172
 
                        irp->IoStatus = STATUS_UNSUCCESSFUL;
173
 
                        Length = 0;
174
 
 
175
 
                        DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id);
176
 
                        break;
177
 
                }
178
 
 
179
 
                stream_seek(irp->input, status);
180
 
                len -= status;
181
 
        }
182
 
 
183
 
        stream_write_uint32(irp->output, Length);
184
 
        stream_write_uint8(irp->output, 0); /* Padding */
185
 
 
186
 
        irp->Complete(irp);
187
 
}
188
 
 
189
 
static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp)
190
 
{
191
 
        DEBUG_SVC("in");
192
 
        stream_write_uint32(irp->output, 0); /* OutputBufferLength */
193
 
        irp->Complete(irp);
194
 
}
195
 
 
196
 
static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
197
 
{
198
 
        DEBUG_SVC("MajorFunction %u", irp->MajorFunction);
199
 
 
200
 
        switch (irp->MajorFunction)
201
 
        {
202
 
                case IRP_MJ_CREATE:
203
 
                        parallel_process_irp_create(parallel, irp);
204
 
                        break;
205
 
 
206
 
                case IRP_MJ_CLOSE:
207
 
                        parallel_process_irp_close(parallel, irp);
208
 
                        break;
209
 
 
210
 
                case IRP_MJ_READ:
211
 
                        parallel_process_irp_read(parallel, irp);
212
 
                        break;
213
 
 
214
 
                case IRP_MJ_WRITE:
215
 
                        parallel_process_irp_write(parallel, irp);
216
 
                        break;
217
 
 
218
 
                case IRP_MJ_DEVICE_CONTROL:
219
 
                        parallel_process_irp_device_control(parallel, irp);
220
 
                        break;
221
 
 
222
 
                default:
223
 
                        DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
224
 
                        irp->IoStatus = STATUS_NOT_SUPPORTED;
225
 
                        irp->Complete(irp);
226
 
                        break;
227
 
        }
228
 
}
229
 
 
230
 
static void parallel_process_irp_list(PARALLEL_DEVICE* parallel)
231
 
{
232
 
        IRP* irp;
233
 
 
234
 
        while (1)
235
 
        {
236
 
                if (freerdp_thread_is_stopped(parallel->thread))
237
 
                        break;
238
 
 
239
 
                freerdp_thread_lock(parallel->thread);
240
 
                irp = (IRP*) list_dequeue(parallel->irp_list);
241
 
                freerdp_thread_unlock(parallel->thread);
242
 
 
243
 
                if (irp == NULL)
244
 
                        break;
245
 
 
246
 
                parallel_process_irp(parallel, irp);
247
 
        }
248
 
}
249
 
 
250
 
static void* parallel_thread_func(void* arg)
251
 
{
252
 
        PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg;
253
 
 
254
 
        while (1)
255
 
        {
256
 
                freerdp_thread_wait(parallel->thread);
257
 
 
258
 
                if (freerdp_thread_is_stopped(parallel->thread))
259
 
                        break;
260
 
 
261
 
                freerdp_thread_reset(parallel->thread);
262
 
                parallel_process_irp_list(parallel);
263
 
        }
264
 
 
265
 
        freerdp_thread_quit(parallel->thread);
266
 
 
267
 
        return NULL;
268
 
}
269
 
 
270
 
static void parallel_irp_request(DEVICE* device, IRP* irp)
271
 
{
272
 
        PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
273
 
 
274
 
        freerdp_thread_lock(parallel->thread);
275
 
        list_enqueue(parallel->irp_list, irp);
276
 
        freerdp_thread_unlock(parallel->thread);
277
 
 
278
 
        freerdp_thread_signal(parallel->thread);
279
 
}
280
 
 
281
 
static void parallel_free(DEVICE* device)
282
 
{
283
 
        IRP* irp;
284
 
        PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;
285
 
 
286
 
        DEBUG_SVC("freeing device");
287
 
 
288
 
        freerdp_thread_stop(parallel->thread);
289
 
        freerdp_thread_free(parallel->thread);
290
 
 
291
 
        while ((irp = (IRP*) list_dequeue(parallel->irp_list)) != NULL)
292
 
                irp->Discard(irp);
293
 
 
294
 
        list_free(parallel->irp_list);
295
 
 
296
 
        xfree(parallel);
297
 
}
298
 
 
299
 
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
300
 
{
301
 
        char* name;
302
 
        char* path;
303
 
        int i, length;
304
 
        PARALLEL_DEVICE* parallel;
305
 
 
306
 
        name = (char*) pEntryPoints->plugin_data->data[1];
307
 
        path = (char*) pEntryPoints->plugin_data->data[2];
308
 
 
309
 
        if (name[0] && path[0])
310
 
        {
311
 
                parallel = xnew(PARALLEL_DEVICE);
312
 
 
313
 
                parallel->device.type = RDPDR_DTYP_PARALLEL;
314
 
                parallel->device.name = name;
315
 
                parallel->device.IRPRequest = parallel_irp_request;
316
 
                parallel->device.Free = parallel_free;
317
 
 
318
 
                length = strlen(name);
319
 
                parallel->device.data = stream_new(length + 1);
320
 
 
321
 
                for (i = 0; i <= length; i++)
322
 
                        stream_write_uint8(parallel->device.data, name[i] < 0 ? '_' : name[i]);
323
 
 
324
 
                parallel->path = path;
325
 
 
326
 
                parallel->irp_list = list_new();
327
 
                parallel->thread = freerdp_thread_new();
328
 
 
329
 
                pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel);
330
 
 
331
 
                freerdp_thread_start(parallel->thread, parallel_thread_func, parallel);
332
 
        }
333
 
 
334
 
        return 0;
335
 
}