2 * FreeRDP: A Remote Desktop Protocol client.
3 * Serial Port Device Service Virtual Channel
5 * Copyright 2011 O.S. Systems Software Ltda.
6 * Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 #ifdef HAVE_SYS_MODEM_H
29 #include <sys/modem.h>
31 #ifdef HAVE_SYS_FILIO_H
32 #include <sys/filio.h>
34 #ifdef HAVE_SYS_STRTIO_H
35 #include <sys/strtio.h>
41 #include "rdpdr_types.h"
42 #include "rdpdr_constants.h"
44 #include "serial_tty.h"
45 #include "serial_constants.h"
47 #include <freerdp/utils/stream.h>
48 #include <freerdp/utils/thread.h>
49 #include <freerdp/utils/unicode.h>
50 #include <freerdp/utils/wait_obj.h>
52 typedef struct _SERIAL_DEVICE SERIAL_DEVICE;
62 freerdp_thread* thread;
63 struct wait_obj* in_event;
69 uint32 select_timeout;
73 static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 abort_io, uint32 io_status);
74 static void serial_check_for_events(SERIAL_DEVICE* serial);
75 static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp);
76 static boolean serial_check_fds(SERIAL_DEVICE* serial);
78 static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp)
86 stream_seek(irp->input, 28); /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
87 /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */
88 stream_read_uint32(irp->input, PathLength);
90 uniconv = freerdp_uniconv_new();
91 path = freerdp_uniconv_in(uniconv, stream_get_tail(irp->input), PathLength);
92 freerdp_uniconv_free(uniconv);
94 FileId = irp->devman->id_sequence++;
96 tty = serial_tty_new(serial->path, FileId);
99 irp->IoStatus = STATUS_UNSUCCESSFUL;
102 DEBUG_WARN("failed to create %s", path);
107 DEBUG_SVC("%s(%d) created.", serial->path, FileId);
110 stream_write_uint32(irp->output, FileId);
111 stream_write_uint8(irp->output, 0);
118 static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp)
125 irp->IoStatus = STATUS_UNSUCCESSFUL;
126 DEBUG_WARN("tty not valid.");
130 DEBUG_SVC("%s(%d) closed.", serial->path, tty->id);
132 serial_tty_free(tty);
136 stream_write_zero(irp->output, 5); /* Padding(5) */
141 static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp)
146 uint8* buffer = NULL;
148 stream_read_uint32(irp->input, Length);
149 stream_read_uint64(irp->input, Offset);
151 DEBUG_SVC("length %u offset %llu", Length, Offset);
156 irp->IoStatus = STATUS_UNSUCCESSFUL;
159 DEBUG_WARN("tty not valid.");
163 buffer = (uint8*)xmalloc(Length);
164 if (!serial_tty_read(tty, buffer, &Length))
166 irp->IoStatus = STATUS_UNSUCCESSFUL;
171 DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id);
175 DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id);
179 stream_write_uint32(irp->output, Length);
182 stream_check_size(irp->output, Length);
183 stream_write(irp->output, buffer, Length);
190 static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp)
196 stream_read_uint32(irp->input, Length);
197 stream_read_uint64(irp->input, Offset);
198 stream_seek(irp->input, 20); /* Padding */
200 DEBUG_SVC("length %u offset %llu", Length, Offset);
205 irp->IoStatus = STATUS_UNSUCCESSFUL;
208 DEBUG_WARN("tty not valid.");
210 else if (!serial_tty_write(tty, stream_get_tail(irp->input), Length))
212 irp->IoStatus = STATUS_UNSUCCESSFUL;
215 DEBUG_WARN("write %s(%d) failed.", serial->path, tty->id);
219 DEBUG_SVC("write %llu-%llu to %s(%d).", Offset, Offset + Length, serial->path, tty->id);
222 stream_write_uint32(irp->output, Length);
223 stream_write_uint8(irp->output, 0); /* Padding */
228 static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp)
231 uint32 IoControlCode;
232 uint32 InputBufferLength;
233 uint32 OutputBufferLength;
234 uint32 abort_io = SERIAL_ABORT_IO_NONE;
236 DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
238 stream_read_uint32(irp->input, InputBufferLength);
239 stream_read_uint32(irp->input, OutputBufferLength);
240 stream_read_uint32(irp->input, IoControlCode);
241 stream_seek(irp->input, 20); /* Padding */
246 irp->IoStatus = STATUS_UNSUCCESSFUL;
247 OutputBufferLength = 0;
249 DEBUG_WARN("tty not valid.");
253 irp->IoStatus = serial_tty_control(tty, IoControlCode, irp->input, irp->output, &abort_io);
256 if (abort_io & SERIAL_ABORT_IO_WRITE)
257 serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_WRITE, STATUS_CANCELLED);
258 if (abort_io & SERIAL_ABORT_IO_READ)
259 serial_abort_single_io(serial, tty->id, SERIAL_ABORT_IO_READ, STATUS_CANCELLED);
261 if (irp->IoStatus == STATUS_PENDING)
262 list_enqueue(serial->pending_irps, irp);
267 static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp)
269 DEBUG_SVC("MajorFunction %u", irp->MajorFunction);
271 switch (irp->MajorFunction)
274 serial_process_irp_create(serial, irp);
278 serial_process_irp_close(serial, irp);
282 serial_handle_async_irp(serial, irp);
283 //serial_process_irp_read(serial, irp);
287 serial_handle_async_irp(serial, irp);
288 //serial_process_irp_write(serial, irp);
291 case IRP_MJ_DEVICE_CONTROL:
292 serial_process_irp_device_control(serial, irp);
296 DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
297 irp->IoStatus = STATUS_NOT_SUPPORTED;
302 serial_check_for_events(serial);
305 static void serial_process_irp_list(SERIAL_DEVICE* serial)
311 if (freerdp_thread_is_stopped(serial->thread))
314 freerdp_thread_lock(serial->thread);
315 irp = (IRP*)list_dequeue(serial->irp_list);
316 freerdp_thread_unlock(serial->thread);
321 serial_process_irp(serial, irp);
325 static void* serial_thread_func(void* arg)
327 SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
331 freerdp_thread_wait(serial->thread);
334 FD_ZERO(&serial->read_fds);
335 FD_ZERO(&serial->write_fds);
337 serial->tv.tv_sec = 20;
338 serial->tv.tv_usec = 0;
339 serial->select_timeout = 0;
341 if (freerdp_thread_is_stopped(serial->thread))
344 freerdp_thread_reset(serial->thread);
345 serial_process_irp_list(serial);
347 if (wait_obj_is_set(serial->in_event))
349 if (serial_check_fds(serial))
350 wait_obj_clear(serial->in_event);
354 freerdp_thread_quit(serial->thread);
359 static void serial_irp_request(DEVICE* device, IRP* irp)
361 SERIAL_DEVICE* serial = (SERIAL_DEVICE*)device;
363 freerdp_thread_lock(serial->thread);
364 list_enqueue(serial->irp_list, irp);
365 freerdp_thread_unlock(serial->thread);
367 freerdp_thread_signal(serial->thread);
370 static void serial_free(DEVICE* device)
372 SERIAL_DEVICE* serial = (SERIAL_DEVICE*)device;
375 DEBUG_SVC("freeing device");
377 freerdp_thread_stop(serial->thread);
378 freerdp_thread_free(serial->thread);
380 while ((irp = (IRP*)list_dequeue(serial->irp_list)) != NULL)
382 list_free(serial->irp_list);
384 while ((irp = (IRP*)list_dequeue(serial->pending_irps)) != NULL)
386 list_free(serial->pending_irps);
391 int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
393 SERIAL_DEVICE* serial;
398 name = (char*)pEntryPoints->plugin_data->data[1];
399 path = (char*)pEntryPoints->plugin_data->data[2];
401 if (name[0] && path[0])
403 serial = xnew(SERIAL_DEVICE);
405 serial->device.type = RDPDR_DTYP_SERIAL;
406 serial->device.name = name;
407 serial->device.IRPRequest = serial_irp_request;
408 serial->device.Free = serial_free;
411 serial->device.data = stream_new(len + 1);
412 for (i = 0; i <= len; i++)
413 stream_write_uint8(serial->device.data, name[i] < 0 ? '_' : name[i]);
416 serial->irp_list = list_new();
417 serial->pending_irps = list_new();
418 serial->thread = freerdp_thread_new();
419 serial->in_event = wait_obj_new();
421 pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)serial);
423 freerdp_thread_start(serial->thread, serial_thread_func, serial);
429 static void serial_abort_single_io(SERIAL_DEVICE* serial, uint32 file_id, uint32 abort_io, uint32 io_status)
435 DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
441 case SERIAL_ABORT_IO_NONE:
445 case SERIAL_ABORT_IO_READ:
449 case SERIAL_ABORT_IO_WRITE:
450 major = IRP_MJ_WRITE;
454 DEBUG_SVC("unexpected abort_io code %d", abort_io);
458 irp = (IRP*)list_peek(serial->pending_irps);
461 if (irp->FileId != file_id || irp->MajorFunction != major)
463 irp = (IRP*)list_next(serial->pending_irps, irp);
467 /* Process a SINGLE FileId and MajorFunction */
468 list_remove(serial->pending_irps, irp);
469 irp->IoStatus = io_status;
470 stream_write_uint32(irp->output, 0);
473 wait_obj_set(serial->in_event);
477 DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps));
480 static void serial_check_for_events(SERIAL_DEVICE* serial)
489 DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
491 irp = (IRP*)list_peek(serial->pending_irps);
496 if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
498 if (serial_tty_get_event(tty, &result))
500 DEBUG_SVC("got event result %u", result);
502 irp->IoStatus = STATUS_SUCCESS;
503 stream_write_uint32(irp->output, result);
507 irp = (IRP*)list_next(serial->pending_irps, irp);
508 list_remove(serial->pending_irps, prev);
510 wait_obj_set(serial->in_event);
515 irp = (IRP*)list_next(serial->pending_irps, irp);
518 DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps));
521 void serial_get_timeouts(SERIAL_DEVICE* serial, IRP* irp, uint32* timeout, uint32* interval_timeout)
527 pos = stream_get_pos(irp->input);
528 stream_read_uint32(irp->input, Length);
529 stream_set_pos(irp->input, pos);
531 DEBUG_SVC("length read %u", Length);
534 *timeout = (tty->read_total_timeout_multiplier * Length) +
535 tty->read_total_timeout_constant;
536 *interval_timeout = tty->read_interval_timeout;
538 DEBUG_SVC("timeouts %u %u", *timeout, *interval_timeout);
541 static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp)
544 uint32 itv_timeout = 0;
549 switch (irp->MajorFunction)
552 DEBUG_SVC("handling IRP_MJ_WRITE");
556 DEBUG_SVC("handling IRP_MJ_READ");
558 serial_get_timeouts(serial, irp, &timeout, &itv_timeout);
560 /* Check if io request timeout is smaller than current (but not 0). */
561 if (timeout && (serial->select_timeout == 0 || timeout < serial->select_timeout))
563 serial->select_timeout = timeout;
564 serial->tv.tv_sec = serial->select_timeout / 1000;
565 serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000;
566 serial->timeout_id = tty->id;
568 if (itv_timeout && (serial->select_timeout == 0 || itv_timeout < serial->select_timeout))
570 serial->select_timeout = itv_timeout;
571 serial->tv.tv_sec = serial->select_timeout / 1000;
572 serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000;
573 serial->timeout_id = tty->id;
575 DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u",
576 serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id);
580 DEBUG_SVC("no need to handle %d", irp->MajorFunction);
584 irp->IoStatus = STATUS_PENDING;
585 list_enqueue(serial->pending_irps, irp);
586 wait_obj_set(serial->in_event);
589 static void __serial_check_fds(SERIAL_DEVICE* serial)
596 memset(&serial->tv, 0, sizeof(struct timeval));
599 /* scan every pending */
600 irp = list_peek(serial->pending_irps);
603 DEBUG_SVC("MajorFunction %u", irp->MajorFunction);
605 switch (irp->MajorFunction)
608 if (FD_ISSET(tty->fd, &serial->read_fds))
610 irp->IoStatus = STATUS_SUCCESS;
611 serial_process_irp_read(serial, irp);
616 if (FD_ISSET(tty->fd, &serial->write_fds))
618 irp->IoStatus = STATUS_SUCCESS;
619 serial_process_irp_write(serial, irp);
623 case IRP_MJ_DEVICE_CONTROL:
624 if (serial_tty_get_event(tty, &result))
626 DEBUG_SVC("got event result %u", result);
628 irp->IoStatus = STATUS_SUCCESS;
629 stream_write_uint32(irp->output, result);
635 DEBUG_SVC("no request found");
640 irp = (IRP*)list_next(serial->pending_irps, irp);
641 if (prev->IoStatus == STATUS_SUCCESS)
643 list_remove(serial->pending_irps, prev);
644 wait_obj_set(serial->in_event);
649 static void serial_set_fds(SERIAL_DEVICE* serial)
655 DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps));
658 irp = (IRP*)list_peek(serial->pending_irps);
663 switch (irp->MajorFunction)
666 fds = &serial->write_fds;
670 fds = &serial->read_fds;
674 if (fds && (tty->fd >= 0))
676 FD_SET(tty->fd, fds);
677 serial->nfds = MAX(serial->nfds, tty->fd);
679 irp = (IRP*)list_next(serial->pending_irps, irp);
683 static boolean serial_check_fds(SERIAL_DEVICE* serial)
685 if (list_size(serial->pending_irps) == 0)
688 serial_set_fds(serial);
689 DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec);
691 switch (select(serial->nfds + 1, &serial->read_fds, &serial->write_fds, NULL, &serial->tv))
694 DEBUG_SVC("select has returned -1 with error: %s", strerror(errno));
698 if (serial->select_timeout)
700 serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, STATUS_TIMEOUT);
701 serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, STATUS_TIMEOUT);
702 serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_TIMEOUT);
704 DEBUG_SVC("select has timed out");
711 __serial_check_fds(serial);