diff --git a/channels/rdpdr/CMakeLists.txt b/channels/rdpdr/CMakeLists.txt index 7eda1144c..b953a4923 100644 --- a/channels/rdpdr/CMakeLists.txt +++ b/channels/rdpdr/CMakeLists.txt @@ -39,4 +39,5 @@ install(TARGETS rdpdr DESTINATION ${FREERDP_PLUGIN_PATH}) add_subdirectory(disk) add_subdirectory(printer) - +add_subdirectory(serial) +add_subdirectory(parallel) diff --git a/channels/rdpdr/parallel/CMakeLists.txt b/channels/rdpdr/parallel/CMakeLists.txt new file mode 100644 index 000000000..44387f57b --- /dev/null +++ b/channels/rdpdr/parallel/CMakeLists.txt @@ -0,0 +1,31 @@ +# FreeRDP: A Remote Desktop Protocol Client +# FreeRDP cmake build script +# +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 Marc-Andre Moreau +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(PARALLEL_SRCS + parallel_main.c +) + +include_directories(..) + +add_library(parallel ${PARALLEL_SRCS}) +set_target_properties(parallel PROPERTIES PREFIX "") + +target_link_libraries(parallel freerdp-utils) + +install(TARGETS parallel DESTINATION ${FREERDP_PLUGIN_PATH}) diff --git a/channels/rdpdr/parallel/parallel_main.c b/channels/rdpdr/parallel/parallel_main.c new file mode 100644 index 000000000..1d31f4f51 --- /dev/null +++ b/channels/rdpdr/parallel/parallel_main.c @@ -0,0 +1,212 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * Redirected Parallel Port Device Service + * + * Copyright 2010 O.S. Systems Software Ltda. + * Copyright 2010 Eduardo Fiss Beloni + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rdpdr_constants.h" +#include "rdpdr_types.h" + +struct _PARALLEL_DEVICE +{ + DEVICE device; + + char* path; + + LIST* irp_list; + freerdp_thread* thread; +}; +typedef struct _PARALLEL_DEVICE PARALLEL_DEVICE; + +static void parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) +{ + irp->Complete(irp); +} + +static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp) +{ + irp->Complete(irp); +} + +static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) +{ + irp->Complete(irp); +} + +static void parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) +{ + irp->Complete(irp); +} + +static void parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) +{ + irp->Complete(irp); +} + +static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) +{ + switch (irp->MajorFunction) + { + case IRP_MJ_CREATE: + parallel_process_irp_create(parallel, irp); + break; + + case IRP_MJ_CLOSE: + parallel_process_irp_close(parallel, irp); + break; + + case IRP_MJ_READ: + parallel_process_irp_read(parallel, irp); + break; + + case IRP_MJ_WRITE: + parallel_process_irp_write(parallel, irp); + break; + + case IRP_MJ_DEVICE_CONTROL: + parallel_process_irp_device_control(parallel, irp); + break; + + default: + DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); + irp->IoStatus = STATUS_NOT_SUPPORTED; + irp->Complete(irp); + break; + } +} + +static void parallel_process_irp_list(PARALLEL_DEVICE* parallel) +{ + IRP* irp; + + while (1) + { + if (freerdp_thread_is_stopped(parallel->thread)) + break; + + freerdp_thread_lock(parallel->thread); + irp = (IRP*) list_dequeue(parallel->irp_list); + freerdp_thread_unlock(parallel->thread); + + if (irp == NULL) + break; + + parallel_process_irp(parallel, irp); + } +} + +static void* parallel_thread_func(void* arg) +{ + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg; + + while (1) + { + freerdp_thread_wait(parallel->thread); + + if (freerdp_thread_is_stopped(parallel->thread)) + break; + + freerdp_thread_reset(parallel->thread); + parallel_process_irp_list(parallel); + } + + freerdp_thread_quit(parallel->thread); + + return NULL; +} + +static void parallel_irp_request(DEVICE* device, IRP* irp) +{ + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; + + freerdp_thread_lock(parallel->thread); + list_enqueue(parallel->irp_list, irp); + freerdp_thread_unlock(parallel->thread); + + freerdp_thread_signal(parallel->thread); +} + +static void parallel_free(DEVICE* device) +{ + IRP* irp; + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; + + freerdp_thread_stop(parallel->thread); + freerdp_thread_free(parallel->thread); + + while ((irp = (IRP*) list_dequeue(parallel->irp_list)) != NULL) + irp->Discard(irp); + + list_free(parallel->irp_list); + + xfree(parallel); +} + +int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) +{ + char* name; + char* path; + int i, length; + PARALLEL_DEVICE* parallel; + + name = (char*) pEntryPoints->plugin_data->data[1]; + path = (char*) pEntryPoints->plugin_data->data[2]; + + if (name[0] && path[0]) + { + parallel = xnew(PARALLEL_DEVICE); + + parallel->device.type = RDPDR_DTYP_PARALLEL; + parallel->device.name = name; + parallel->device.IRPRequest = parallel_irp_request; + parallel->device.Free = parallel_free; + + length = strlen(name); + parallel->device.data = stream_new(length + 1); + + for (i = 0; i <= length; i++) + stream_write_uint8(parallel->device.data, name[i] < 0 ? '_' : name[i]); + + parallel->path = path; + + parallel->irp_list = list_new(); + parallel->thread = freerdp_thread_new(); + + pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) parallel); + + freerdp_thread_start(parallel->thread, parallel_thread_func, parallel); + } + + return 0; +} diff --git a/channels/rdpdr/serial/CMakeLists.txt b/channels/rdpdr/serial/CMakeLists.txt new file mode 100644 index 000000000..a487edb15 --- /dev/null +++ b/channels/rdpdr/serial/CMakeLists.txt @@ -0,0 +1,31 @@ +# FreeRDP: A Remote Desktop Protocol Client +# FreeRDP cmake build script +# +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 Marc-Andre Moreau +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(SERIAL_SRCS + serial_main.c +) + +include_directories(..) + +add_library(serial ${SERIAL_SRCS}) +set_target_properties(serial PROPERTIES PREFIX "") + +target_link_libraries(serial freerdp-utils) + +install(TARGETS serial DESTINATION ${FREERDP_PLUGIN_PATH}) diff --git a/channels/rdpdr/serial/serial_main.c b/channels/rdpdr/serial/serial_main.c new file mode 100644 index 000000000..4fcd6f834 --- /dev/null +++ b/channels/rdpdr/serial/serial_main.c @@ -0,0 +1,212 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * Redirected Serial Port Device Service + * + * Copyright 2010 O.S. Systems Software Ltda. + * Copyright 2010 Eduardo Fiss Beloni + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rdpdr_constants.h" +#include "rdpdr_types.h" + +struct _SERIAL_DEVICE +{ + DEVICE device; + + char* path; + + LIST* irp_list; + freerdp_thread* thread; +}; +typedef struct _SERIAL_DEVICE SERIAL_DEVICE; + +static void serial_process_irp_create(SERIAL_DEVICE* serial, IRP* irp) +{ + irp->Complete(irp); +} + +static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) +{ + irp->Complete(irp); +} + +static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) +{ + irp->Complete(irp); +} + +static void serial_process_irp_write(SERIAL_DEVICE* serial, IRP* irp) +{ + irp->Complete(irp); +} + +static void serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) +{ + irp->Complete(irp); +} + +static void serial_process_irp(SERIAL_DEVICE* serial, IRP* irp) +{ + switch (irp->MajorFunction) + { + case IRP_MJ_CREATE: + serial_process_irp_create(serial, irp); + break; + + case IRP_MJ_CLOSE: + serial_process_irp_close(serial, irp); + break; + + case IRP_MJ_READ: + serial_process_irp_read(serial, irp); + break; + + case IRP_MJ_WRITE: + serial_process_irp_write(serial, irp); + break; + + case IRP_MJ_DEVICE_CONTROL: + serial_process_irp_device_control(serial, irp); + break; + + default: + DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); + irp->IoStatus = STATUS_NOT_SUPPORTED; + irp->Complete(irp); + break; + } +} + +static void serial_process_irp_list(SERIAL_DEVICE* serial) +{ + IRP* irp; + + while (1) + { + if (freerdp_thread_is_stopped(serial->thread)) + break; + + freerdp_thread_lock(serial->thread); + irp = (IRP*) list_dequeue(serial->irp_list); + freerdp_thread_unlock(serial->thread); + + if (irp == NULL) + break; + + serial_process_irp(serial, irp); + } +} + +static void* serial_thread_func(void* arg) +{ + SERIAL_DEVICE* serial = (SERIAL_DEVICE*) arg; + + while (1) + { + freerdp_thread_wait(serial->thread); + + if (freerdp_thread_is_stopped(serial->thread)) + break; + + freerdp_thread_reset(serial->thread); + serial_process_irp_list(serial); + } + + freerdp_thread_quit(serial->thread); + + return NULL; +} + +static void serial_irp_request(DEVICE* device, IRP* irp) +{ + SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; + + freerdp_thread_lock(serial->thread); + list_enqueue(serial->irp_list, irp); + freerdp_thread_unlock(serial->thread); + + freerdp_thread_signal(serial->thread); +} + +static void serial_free(DEVICE* device) +{ + IRP* irp; + SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; + + freerdp_thread_stop(serial->thread); + freerdp_thread_free(serial->thread); + + while ((irp = (IRP*) list_dequeue(serial->irp_list)) != NULL) + irp->Discard(irp); + + list_free(serial->irp_list); + + xfree(serial); +} + +int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) +{ + char* name; + char* path; + int i, length; + SERIAL_DEVICE* serial; + + name = (char*) pEntryPoints->plugin_data->data[1]; + path = (char*) pEntryPoints->plugin_data->data[2]; + + if (name[0] && path[0]) + { + serial = xnew(SERIAL_DEVICE); + + serial->device.type = RDPDR_DTYP_SERIAL; + serial->device.name = name; + serial->device.IRPRequest = serial_irp_request; + serial->device.Free = serial_free; + + length = strlen(name); + serial->device.data = stream_new(length + 1); + + for (i = 0; i <= length; i++) + stream_write_uint8(serial->device.data, name[i] < 0 ? '_' : name[i]); + + serial->path = path; + + serial->irp_list = list_new(); + serial->thread = freerdp_thread_new(); + + pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) serial); + + freerdp_thread_start(serial->thread, serial_thread_func, serial); + } + + return 0; +}