~paulliu/ubuntu/quantal/freerdp/fixext

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20120131100214-zvig71djj2sqgq22
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- c-basic-offset: 8 -*-
2
 
   FreeRDP: A Remote Desktop Protocol client.
3
 
   Redirected Parallel Port Device Service
4
 
 
5
 
   Copyright (C) Eduardo Fiss Beloni <beloni@ossystems.com.br> 2010
6
 
 
7
 
   This program is free software; you can redistribute it and/or modify
8
 
   it under the terms of the GNU General Public License as published by
9
 
   the Free Software Foundation; either version 2 of the License, or
10
 
   (at your option) any later version.
11
 
 
12
 
   This program is distributed in the hope that it will be useful,
13
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
   GNU General Public License for more details.
16
 
 
17
 
   You should have received a copy of the GNU General Public License
18
 
   along with this program; if not, write to the Free Software
19
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
*/
 
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
 */
21
20
 
22
21
#include <stdio.h>
23
22
#include <stdlib.h>
24
23
#include <string.h>
 
24
 
25
25
#include <unistd.h>
26
26
#include <fcntl.h>
27
27
#include <termios.h>
28
28
#include <errno.h>
29
29
#include <strings.h>
30
30
#include <sys/ioctl.h>
31
 
 
 
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"
32
45
#include "rdpdr_types.h"
33
 
#include "rdpdr_constants.h"
34
 
#include "devman.h"
35
 
 
36
 
#define MAX_PARALLEL_DEVICES               1
37
 
#define FILE_DEVICE_PARALLEL               0x22
38
 
 
39
 
#define IOCTL_PAR_QUERY_INFORMATION        0x00160004
40
 
#define IOCTL_PAR_SET_INFORMATION          0x00160008
41
 
#define IOCTL_PAR_QUERY_DEVICE_ID          0x0016000C
42
 
#define IOCTL_PAR_QUERY_DEVICE_ID_SIZE     0x00160010
43
 
#define IOCTL_PAR_SET_WRITE_ADDRESS        0x0016001C
44
 
#define IOCTL_PAR_SET_READ_ADDRESS         0x00160020
45
 
#define IOCTL_PAR_GET_DEVICE_CAPS          0x00160024
46
 
#define IOCTL_PAR_GET_DEFAULT_MODES        0x00160028
47
 
#define IOCTL_PAR_QUERY_RAW_DEVICE_ID      0x00160030
48
 
#define IOCTL_PAR_IS_PORT_FREE             0x00160054
49
 
 
50
 
 
51
 
struct _PARALLEL_DEVICE_INFO
 
46
 
 
47
struct _PARALLEL_DEVICE
52
48
{
53
 
        PDEVMAN devman;
54
 
 
55
 
        PDEVMAN_REGISTER_SERVICE DevmanRegisterService;
56
 
        PDEVMAN_UNREGISTER_SERVICE DevmanUnregisterService;
57
 
        PDEVMAN_REGISTER_DEVICE DevmanRegisterDevice;
58
 
        PDEVMAN_UNREGISTER_DEVICE DevmanUnregisterDevice;
 
49
        DEVICE device;
59
50
 
60
51
        int file;
61
 
        char * path;
 
52
        char* path;
 
53
        uint32 id;
62
54
 
63
 
/*      char *driver, *printer;*/
64
 
/*      uint32 queue_in_size,*/
65
 
/*              queue_out_size,*/
66
 
/*              wait_mask,*/
67
 
/*              read_interval_timeout,*/
68
 
/*              read_total_timeout_multiplier,*/
69
 
/*              read_total_timeout_constant,*/
70
 
/*              write_total_timeout_multiplier,*/
71
 
/*              write_total_timeout_constant, posix_wait_mask, bloblen;*/
72
 
/*      uint8 *blob;*/
 
55
        LIST* irp_list;
 
56
        freerdp_thread* thread;
73
57
};
74
 
typedef struct _PARALLEL_DEVICE_INFO PARALLEL_DEVICE_INFO;
75
 
 
76
 
static int
77
 
get_error_status(void)
78
 
{
79
 
        switch (errno)
80
 
        {
81
 
                case EAGAIN:
82
 
                        return RD_STATUS_DEVICE_OFF_LINE;
83
 
                case ENOSPC:
84
 
                        return RD_STATUS_DEVICE_PAPER_EMPTY;
85
 
                case EIO:
86
 
                        return RD_STATUS_DEVICE_OFF_LINE;
87
 
                default:
88
 
                        return RD_STATUS_DEVICE_POWERED_OFF;
89
 
        }
90
 
}
91
 
 
92
 
static int
93
 
parallel_get_fd(IRP * irp)
94
 
{
95
 
        return  ((PARALLEL_DEVICE_INFO *) irp->dev->info)->file;
96
 
}
97
 
 
98
 
static uint32
99
 
parallel_control(IRP * irp)
100
 
{
101
 
        int size = 0, ret = RD_STATUS_SUCCESS;
102
 
        char *outbuf = NULL;
103
 
 
104
 
        LLOGLN(10, ("parallel_control: id=%d io=%X", irp->fileID, irp->ioControlCode));
105
 
 
106
 
        switch (irp->ioControlCode)
107
 
        {
108
 
                case IOCTL_PAR_QUERY_INFORMATION:
109
 
 
110
 
                case IOCTL_PAR_SET_INFORMATION:
111
 
 
112
 
                case IOCTL_PAR_QUERY_DEVICE_ID:
113
 
 
114
 
                case IOCTL_PAR_QUERY_DEVICE_ID_SIZE:
115
 
 
116
 
                case IOCTL_PAR_SET_WRITE_ADDRESS:
117
 
 
118
 
                case IOCTL_PAR_SET_READ_ADDRESS:
119
 
 
120
 
                case IOCTL_PAR_GET_DEVICE_CAPS:
121
 
 
122
 
                case IOCTL_PAR_GET_DEFAULT_MODES:
123
 
 
124
 
                case IOCTL_PAR_QUERY_RAW_DEVICE_ID:
125
 
 
126
 
                case IOCTL_PAR_IS_PORT_FREE:
127
 
 
128
 
                default:
129
 
                        LLOGLN(10, ("NOT FOUND IoControlCode PARALLEL IOCTL %d", irp->ioControlCode));
130
 
                        return RD_STATUS_INVALID_PARAMETER;
131
 
        }
132
 
 
133
 
        irp->outputBuffer = outbuf;
134
 
        irp->outputBufferLength = size;
135
 
 
136
 
        return ret;
137
 
}
138
 
 
139
 
static uint32
140
 
parallel_read(IRP * irp)
141
 
{
142
 
        PARALLEL_DEVICE_INFO *info;
143
 
        char *buf;
144
 
        ssize_t r;
145
 
 
146
 
        info = (PARALLEL_DEVICE_INFO *) irp->dev->info;
147
 
        buf = malloc(irp->length);
148
 
        memset(buf, 0, irp->length);
149
 
 
150
 
        r = read(info->file, buf, irp->length);
151
 
        if (r == -1)
152
 
        {
153
 
                free(buf);
154
 
                return get_error_status();
155
 
        }
156
 
        else
157
 
        {
158
 
                irp->outputBuffer = buf;
159
 
                irp->outputBufferLength = r;
160
 
                return RD_STATUS_SUCCESS;
161
 
        }
162
 
}
163
 
 
164
 
static uint32
165
 
parallel_write(IRP * irp)
166
 
{
167
 
        PARALLEL_DEVICE_INFO * info;
168
 
        ssize_t r;
 
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;
169
157
        uint32 len;
170
158
 
171
 
        info = (PARALLEL_DEVICE_INFO *) irp->dev->info;
172
 
 
173
 
        len = 0;
174
 
        while (len < irp->inputBufferLength)
175
 
        {
176
 
                r = write(info->file, irp->inputBuffer, irp->inputBufferLength);
177
 
                if (r == -1)
178
 
                        return get_error_status();
179
 
 
180
 
                len += r;
181
 
        }
182
 
        LLOGLN(10, ("parallel_write: id=%d len=%d off=%lld", irp->fileID, irp->inputBufferLength, irp->offset));
183
 
        return RD_STATUS_SUCCESS;
184
 
}
185
 
 
186
 
static uint32
187
 
parallel_free(DEVICE * dev)
188
 
{
189
 
        LLOGLN(10, ("parallel_free"));
190
 
 
191
 
        free(dev->info);
192
 
        if (dev->data)
193
 
        {
194
 
                free(dev->data);
195
 
                dev->data = NULL;
196
 
        }
197
 
        return 0;
198
 
}
199
 
 
200
 
static uint32
201
 
parallel_create(IRP * irp, const char * path)
202
 
{
203
 
        PARALLEL_DEVICE_INFO *info;
204
 
 
205
 
        info = (PARALLEL_DEVICE_INFO *) irp->dev->info;
206
 
 
207
 
        info->file = open(info->path, O_RDWR);
208
 
        if (info->file == -1)
209
 
        {
210
 
                perror("parallel open");
211
 
                return RD_STATUS_ACCESS_DENIED;
212
 
        }
213
 
 
214
 
        /* all read and writes should be non blocking */
215
 
        if (fcntl(info->file, F_SETFL, O_NONBLOCK) == -1)
216
 
                perror("fcntl");
217
 
        LLOGLN(10, ("parallel create"));
218
 
 
219
 
/*      info->read_total_timeout_constant = 5;*/
220
 
        return RD_STATUS_SUCCESS;
221
 
}
222
 
 
223
 
static uint32
224
 
parallel_close(IRP * irp)
225
 
{
226
 
        PARALLEL_DEVICE_INFO *info = (PARALLEL_DEVICE_INFO *) irp->dev->info;
227
 
 
228
 
        close(info->file);
229
 
 
230
 
        LLOGLN(10, ("parallel_close: id=%d", irp->fileID));
231
 
        return RD_STATUS_SUCCESS;
232
 
}
233
 
 
234
 
static SERVICE *
235
 
parallel_register_service(PDEVMAN pDevman, PDEVMAN_ENTRY_POINTS pEntryPoints)
236
 
{
237
 
        SERVICE * srv;
238
 
 
239
 
        srv = pEntryPoints->pDevmanRegisterService(pDevman);
240
 
 
241
 
        srv->create = parallel_create;
242
 
        srv->close = parallel_close;
243
 
        srv->read = parallel_read;
244
 
        srv->write = parallel_write;
245
 
        srv->control = parallel_control;
246
 
        srv->query_volume_info = NULL;
247
 
        srv->query_info = NULL;
248
 
        srv->set_info = NULL;
249
 
        srv->query_directory = NULL;
250
 
        srv->notify_change_directory = NULL;
251
 
        srv->lock_control = NULL;
252
 
        srv->free = parallel_free;
253
 
        srv->type = RDPDR_DTYP_PARALLEL;
254
 
        srv->get_event = NULL;
255
 
        srv->file_descriptor = parallel_get_fd;
256
 
        srv->get_timeouts = NULL;
257
 
 
258
 
        return srv;
259
 
}
260
 
 
261
 
int
262
 
DeviceServiceEntry(PDEVMAN pDevman, PDEVMAN_ENTRY_POINTS pEntryPoints)
263
 
{
264
 
        SERVICE * srv = NULL;
265
 
        DEVICE * dev;
266
 
        PARALLEL_DEVICE_INFO * info;
267
 
        RD_PLUGIN_DATA * data;
268
 
        int i;
269
 
 
270
 
        data = (RD_PLUGIN_DATA *) pEntryPoints->pExtendedData;
271
 
        while (data && data->size > 0)
272
 
        {
273
 
                if (strcmp((char*)data->data[0], "parallel") == 0)
 
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)
274
171
                {
275
 
                        if (srv == NULL)
276
 
                                srv = parallel_register_service(pDevman, pEntryPoints);
277
 
 
278
 
                        info = (PARALLEL_DEVICE_INFO *) malloc(sizeof(PARALLEL_DEVICE_INFO));
279
 
                        memset(info, 0, sizeof(PARALLEL_DEVICE_INFO));
280
 
                        info->devman = pDevman;
281
 
                        info->DevmanRegisterService = pEntryPoints->pDevmanRegisterService;
282
 
                        info->DevmanUnregisterService = pEntryPoints->pDevmanUnregisterService;
283
 
                        info->DevmanRegisterDevice = pEntryPoints->pDevmanRegisterDevice;
284
 
                        info->DevmanUnregisterDevice = pEntryPoints->pDevmanUnregisterDevice;
285
 
                        info->path = (char *) data->data[2];
286
 
 
287
 
                        dev = info->DevmanRegisterDevice(pDevman, srv, (char*)data->data[1]);
288
 
                        dev->info = info;
289
 
 
290
 
                        /* [MS-RDPEFS] 2.2.3.1 said this is a unicode string, however, only ASCII works.
291
 
                           Any non-ASCII characters simply screw up the whole channel. Long name is supported though.
292
 
                           This is yet to be investigated. */
293
 
                        dev->data_len = strlen(dev->name) + 1;
294
 
                        dev->data = strdup(dev->name);
295
 
                        for (i = 0; i < dev->data_len; i++)
296
 
                        {
297
 
                                if (dev->data[i] < 0)
298
 
                                {
299
 
                                        dev->data[i] = '_';
300
 
                                }
301
 
                        }
 
172
                        irp->IoStatus = STATUS_UNSUCCESSFUL;
 
173
                        Length = 0;
 
174
 
 
175
                        DEBUG_WARN("write %s(%d) failed.", parallel->path, parallel->id);
 
176
                        break;
302
177
                }
303
 
                data = (RD_PLUGIN_DATA *) (((void *) data) + data->size);
304
 
        }
305
 
 
306
 
        return 1;
 
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;
307
335
}