21 #include <winpr/assert.h>
27 #include <winpr/pool.h>
28 #include <winpr/print.h>
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/string.h>
33 #include <winpr/cmdline.h>
35 #include <freerdp/dvc.h>
36 #include <freerdp/addin.h>
37 #include <freerdp/channels/log.h>
38 #include <freerdp/channels/urbdrc.h>
40 #include "urbdrc_types.h"
41 #include "urbdrc_main.h"
42 #include "data_transfer.h"
44 #include <urbdrc_helpers.h>
46 static IWTSVirtualChannel* get_channel(IUDEVMAN* idevman)
48 IWTSVirtualChannelManager* channel_mgr = NULL;
56 if (!urbdrc || !urbdrc->listener_callback)
59 channel_mgr = urbdrc->listener_callback->channel_mgr;
64 return channel_mgr->FindChannelById(channel_mgr, idevman->controlChannelId);
67 static int func_container_id_generate(IUDEVICE* pdev,
char* strContainerId)
71 UINT8 containerId[17] = { 0 };
74 idVendor = (UINT16)pdev->query_device_descriptor(pdev, ID_VENDOR);
75 idProduct = (UINT16)pdev->query_device_descriptor(pdev, ID_PRODUCT);
76 path = pdev->getPath(pdev);
79 p = (path + strlen(path)) - 8;
83 (void)sprintf_s((
char*)containerId,
sizeof(containerId),
"%04" PRIX16
"%04" PRIX16
"%s",
84 idVendor, idProduct, p);
86 (void)sprintf_s(strContainerId, DEVICE_CONTAINER_STR_SIZE,
87 "{%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
88 "-%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
89 "%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"}",
90 containerId[0], containerId[1], containerId[2], containerId[3], containerId[4],
91 containerId[5], containerId[6], containerId[7], containerId[8], containerId[9],
92 containerId[10], containerId[11], containerId[12], containerId[13],
93 containerId[14], containerId[15]);
97 static int func_instance_id_generate(IUDEVICE* pdev,
char* strInstanceId,
size_t len)
99 char instanceId[17] = { 0 };
100 (void)sprintf_s(instanceId,
sizeof(instanceId),
"\\%s", pdev->getPath(pdev));
102 (void)sprintf_s(strInstanceId, len,
103 "%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
104 "-%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
"-%02" PRIx8
"%02" PRIx8
105 "%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"%02" PRIx8
"",
106 instanceId[0], instanceId[1], instanceId[2], instanceId[3], instanceId[4],
107 instanceId[5], instanceId[6], instanceId[7], instanceId[8], instanceId[9],
108 instanceId[10], instanceId[11], instanceId[12], instanceId[13], instanceId[14],
121 UINT32 InterfaceId = 0;
127 return ERROR_INVALID_PARAMETER;
129 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
130 return ERROR_INVALID_DATA;
132 Stream_Read_UINT32(s, Version);
134 if (Version > RIM_CAPABILITY_VERSION_01)
135 Version = RIM_CAPABILITY_VERSION_01;
137 InterfaceId = ((STREAM_ID_NONE << 30) | CAPABILITIES_NEGOTIATOR);
139 out = Stream_New(NULL, out_size);
142 return ERROR_OUTOFMEMORY;
144 Stream_Write_UINT32(out, InterfaceId);
145 Stream_Write_UINT32(out, MessageId);
146 Stream_Write_UINT32(out, Version);
147 Stream_Write_UINT32(out, 0x00000000);
148 return stream_write_and_free(callback->plugin, callback->channel, out);
159 UINT32 InterfaceId = 0;
161 UINT32 MajorVersion = 0;
162 UINT32 MinorVersion = 0;
163 UINT32 Capabilities = 0;
167 if (!callback || !s || !callback->plugin)
168 return ERROR_INVALID_PARAMETER;
172 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
173 return ERROR_INVALID_DATA;
175 Stream_Read_UINT32(s, MajorVersion);
176 Stream_Read_UINT32(s, MinorVersion);
177 Stream_Read_UINT32(s, Capabilities);
180 if ((MajorVersion != 1) || (MinorVersion != 0))
182 WLog_Print(urbdrc->log, WLOG_WARN,
183 "server supports USB channel version %" PRIu32
".%" PRIu32);
184 WLog_Print(urbdrc->log, WLOG_WARN,
"we only support channel version 1.0");
189 InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_CHANNEL_NOTIFICATION);
191 out = Stream_New(NULL, out_size);
194 return ERROR_OUTOFMEMORY;
196 Stream_Write_UINT32(out, InterfaceId);
197 Stream_Write_UINT32(out, MessageId);
198 Stream_Write_UINT32(out, CHANNEL_CREATED);
199 Stream_Write_UINT32(out, MajorVersion);
200 Stream_Write_UINT32(out, MinorVersion);
201 Stream_Write_UINT32(out, Capabilities);
202 return stream_write_and_free(callback->plugin, callback->channel, out);
205 static UINT urdbrc_send_virtual_channel_add(IWTSPlugin* plugin, IWTSVirtualChannel* channel,
208 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK);
209 wStream* out = Stream_New(NULL, 12);
212 return ERROR_OUTOFMEMORY;
214 Stream_Write_UINT32(out, InterfaceId);
215 Stream_Write_UINT32(out, MessageId);
216 Stream_Write_UINT32(out, ADD_VIRTUAL_CHANNEL);
217 return stream_write_and_free(plugin, channel, out);
228 UINT32 InterfaceId = 0;
229 char HardwareIds[2][DEVICE_HARDWARE_ID_SIZE] = { { 0 } };
230 char CompatibilityIds[3][DEVICE_COMPATIBILITY_ID_SIZE] = { { 0 } };
231 char strContainerId[DEVICE_CONTAINER_STR_SIZE] = { 0 };
232 char strInstanceId[DEVICE_INSTANCE_STR_SIZE] = { 0 };
233 const char* composite_str =
"USB\\COMPOSITE";
234 const size_t composite_len = 13;
236 size_t CompatibilityIdLen[3];
237 size_t HardwareIdsLen[2];
238 size_t ContainerIdLen = 0;
239 size_t InstanceIdLen = 0;
240 size_t cchCompatIds = 0;
242 InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK);
244 pdev->detach_kernel_driver(pdev);
246 const UINT16 idVendor = (UINT16)pdev->query_device_descriptor(pdev, ID_VENDOR);
247 const UINT16 idProduct = (UINT16)pdev->query_device_descriptor(pdev, ID_PRODUCT);
248 const UINT16 bcdDevice = (UINT16)pdev->query_device_descriptor(pdev, BCD_DEVICE);
249 (void)sprintf_s(HardwareIds[1], DEVICE_HARDWARE_ID_SIZE,
250 "USB\\VID_%04" PRIX16
"&PID_%04" PRIX16
"", idVendor, idProduct);
251 (void)sprintf_s(HardwareIds[0], DEVICE_HARDWARE_ID_SIZE,
252 "USB\\VID_%04" PRIX16
"&PID_%04" PRIX16
"&REV_%04" PRIX16
"", idVendor,
253 idProduct, bcdDevice);
256 const UINT8 bDeviceClass = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_CLASS);
257 const UINT8 bDeviceSubClass = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_SUBCLASS);
258 const UINT8 bDeviceProtocol = (UINT8)pdev->query_device_descriptor(pdev, B_DEVICE_PROTOCOL);
260 if (!(pdev->isCompositeDevice(pdev)))
262 (void)sprintf_s(CompatibilityIds[2], DEVICE_COMPATIBILITY_ID_SIZE,
263 "USB\\Class_%02" PRIX8
"", bDeviceClass);
264 (void)sprintf_s(CompatibilityIds[1], DEVICE_COMPATIBILITY_ID_SIZE,
265 "USB\\Class_%02" PRIX8
"&SubClass_%02" PRIX8
"", bDeviceClass,
267 (void)sprintf_s(CompatibilityIds[0], DEVICE_COMPATIBILITY_ID_SIZE,
268 "USB\\Class_%02" PRIX8
"&SubClass_%02" PRIX8
"&Prot_%02" PRIX8
"",
269 bDeviceClass, bDeviceSubClass, bDeviceProtocol);
273 (void)sprintf_s(CompatibilityIds[2], DEVICE_COMPATIBILITY_ID_SIZE,
"USB\\DevClass_00");
274 (void)sprintf_s(CompatibilityIds[1], DEVICE_COMPATIBILITY_ID_SIZE,
275 "USB\\DevClass_00&SubClass_00");
276 (void)sprintf_s(CompatibilityIds[0], DEVICE_COMPATIBILITY_ID_SIZE,
277 "USB\\DevClass_00&SubClass_00&Prot_00");
280 func_instance_id_generate(pdev, strInstanceId, DEVICE_INSTANCE_STR_SIZE);
281 func_container_id_generate(pdev, strContainerId);
282 CompatibilityIdLen[0] = strnlen(CompatibilityIds[0],
sizeof(CompatibilityIds[0]));
283 CompatibilityIdLen[1] = strnlen(CompatibilityIds[1],
sizeof(CompatibilityIds[1]));
284 CompatibilityIdLen[2] = strnlen(CompatibilityIds[2],
sizeof(CompatibilityIds[2]));
285 HardwareIdsLen[0] = strnlen(HardwareIds[0],
sizeof(HardwareIds[0]));
286 HardwareIdsLen[1] = strnlen(HardwareIds[1],
sizeof(HardwareIds[1]));
288 CompatibilityIdLen[0] + 1 + CompatibilityIdLen[1] + 1 + CompatibilityIdLen[2] + 2;
289 InstanceIdLen = strnlen(strInstanceId,
sizeof(strInstanceId));
290 ContainerIdLen = strnlen(strContainerId,
sizeof(strContainerId));
292 if (pdev->isCompositeDevice(pdev))
293 cchCompatIds += composite_len + 1;
296 size += (InstanceIdLen + 1) * 2 + (HardwareIdsLen[0] + 1) * 2 + 4 +
297 (HardwareIdsLen[1] + 1) * 2 + 2 + 4 + (cchCompatIds)*2 + (ContainerIdLen + 1) * 2 + 4 +
299 out = Stream_New(NULL, size);
302 return ERROR_OUTOFMEMORY;
304 Stream_Write_UINT32(out, InterfaceId);
305 Stream_Write_UINT32(out, 0);
306 Stream_Write_UINT32(out, ADD_DEVICE);
307 Stream_Write_UINT32(out, 0x00000001);
308 Stream_Write_UINT32(out, pdev->get_UsbDevice(pdev));
309 Stream_Write_UINT32(out, (UINT32)InstanceIdLen + 1);
310 if (Stream_Write_UTF16_String_From_UTF8(out, InstanceIdLen, strInstanceId, InstanceIdLen,
313 Stream_Write_UINT16(out, 0);
314 const size_t len = HardwareIdsLen[0] + HardwareIdsLen[1] + 3;
315 if (len > UINT32_MAX)
317 Stream_Write_UINT32(out, (UINT32)len);
319 if (Stream_Write_UTF16_String_From_UTF8(out, HardwareIdsLen[0], HardwareIds[0],
320 HardwareIdsLen[0], TRUE) < 0)
322 Stream_Write_UINT16(out, 0);
323 if (Stream_Write_UTF16_String_From_UTF8(out, HardwareIdsLen[1], HardwareIds[1],
324 HardwareIdsLen[1], TRUE) < 0)
326 Stream_Write_UINT16(out, 0);
327 Stream_Write_UINT16(out, 0);
328 Stream_Write_UINT32(out, (UINT32)cchCompatIds);
330 if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[0], CompatibilityIds[0],
331 CompatibilityIdLen[0], TRUE) < 0)
333 Stream_Write_UINT16(out, 0);
334 if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[1], CompatibilityIds[1],
335 CompatibilityIdLen[1], TRUE) < 0)
337 Stream_Write_UINT16(out, 0);
338 if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[2], CompatibilityIds[2],
339 CompatibilityIdLen[2], TRUE) < 0)
341 Stream_Write_UINT16(out, 0);
343 if (pdev->isCompositeDevice(pdev))
345 if (Stream_Write_UTF16_String_From_UTF8(out, composite_len, composite_str, composite_len,
348 Stream_Write_UINT16(out, 0);
351 Stream_Write_UINT16(out, 0x0000);
352 Stream_Write_UINT32(out, (UINT32)ContainerIdLen + 1);
354 if (Stream_Write_UTF16_String_From_UTF8(out, ContainerIdLen, strContainerId, ContainerIdLen,
357 Stream_Write_UINT16(out, 0);
359 Stream_Write_UINT32(out, 0x0000001c);
360 Stream_Write_UINT32(out, 2);
361 Stream_Write_UINT32(out, 0x600);
363 bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
364 Stream_Write_UINT32(out, bcdUSB);
365 Stream_Write_UINT32(out, 0x00000000);
368 Stream_Write_UINT32(out, 0x00000000);
370 Stream_Write_UINT32(out, 0x00000001);
372 Stream_Write_UINT32(out, 0x50);
373 return stream_write_and_free(callback->plugin, callback->channel, out);
376 Stream_Free(out, TRUE);
377 return ERROR_INTERNAL_ERROR;
387 UINT32 MessageId = 0;
388 UINT32 FunctionId = 0;
389 UINT32 InterfaceId = 0;
390 UINT error = CHANNEL_RC_OK;
393 return ERROR_INVALID_PARAMETER;
395 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
396 return ERROR_INVALID_DATA;
398 Stream_Rewind_UINT32(data);
399 Stream_Read_UINT32(data, InterfaceId);
400 Stream_Read_UINT32(data, MessageId);
401 Stream_Read_UINT32(data, FunctionId);
405 case RIM_EXCHANGE_CAPABILITY_REQUEST:
406 error = urbdrc_process_capability_request(callback, data, MessageId);
409 case RIMCALL_RELEASE:
413 error = ERROR_NOT_FOUND;
420 static BOOL urbdrc_announce_devices(IUDEVMAN* udevman)
422 UINT error = ERROR_SUCCESS;
424 udevman->loading_lock(udevman);
425 udevman->rewind(udevman);
427 while (udevman->has_next(udevman))
429 IUDEVICE* pdev = udevman->get_next(udevman);
431 if (!pdev->isAlreadySend(pdev))
433 const UINT32 deviceId = pdev->get_UsbDevice(pdev);
435 urdbrc_send_virtual_channel_add(udevman->plugin, get_channel(udevman), deviceId);
437 if (cerror != ERROR_SUCCESS)
442 udevman->loading_unlock(udevman);
444 return error == ERROR_SUCCESS;
450 IUDEVMAN* udevman = urbdrc->udevman;
451 IWTSVirtualChannel* channel = callback->channel;
452 IUDEVICE* pdev = NULL;
454 UINT error = ERROR_INTERNAL_ERROR;
455 UINT32 channelId = callback->channel_mgr->GetChannelId(channel);
457 switch (urbdrc->vchannel_status)
459 case INIT_CHANNEL_IN:
461 error = ERROR_SUCCESS;
462 udevman->initialize(udevman, channelId);
464 if (!urbdrc_announce_devices(udevman))
467 urbdrc->vchannel_status = INIT_CHANNEL_OUT;
470 case INIT_CHANNEL_OUT:
473 udevman->loading_lock(udevman);
474 udevman->rewind(udevman);
476 while (udevman->has_next(udevman))
478 pdev = udevman->get_next(udevman);
480 if (!pdev->isAlreadySend(pdev))
482 const UINT32 channelID = callback->channel_mgr->GetChannelId(channel);
484 pdev->setAlreadySend(pdev);
485 pdev->set_channelManager(pdev, callback->channel_mgr);
486 pdev->set_channelID(pdev, channelID);
491 udevman->loading_unlock(udevman);
492 error = ERROR_SUCCESS;
494 if (found && pdev->isAlreadySend(pdev))
495 error = urdbrc_send_usb_device_add(callback, pdev);
500 WLog_Print(urbdrc->log, WLOG_ERROR,
"vchannel_status unknown value %" PRIu32
"",
501 urbdrc->vchannel_status);
516 UINT32 MessageId = 0;
517 UINT32 FunctionId = 0;
518 UINT32 InterfaceId = 0;
519 UINT error = CHANNEL_RC_OK;
522 if (!callback || !data)
523 return ERROR_INVALID_PARAMETER;
528 return ERROR_INVALID_PARAMETER;
530 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
531 return ERROR_INVALID_DATA;
533 Stream_Rewind(data, 4);
534 Stream_Read_UINT32(data, InterfaceId);
535 Stream_Read_UINT32(data, MessageId);
536 Stream_Read_UINT32(data, FunctionId);
537 WLog_Print(urbdrc->log, WLOG_TRACE,
"%s [%" PRIu32
"]",
538 call_to_string(FALSE, InterfaceId, FunctionId), FunctionId);
542 case CHANNEL_CREATED:
543 error = urbdrc_process_channel_create(callback, data, MessageId);
546 case RIMCALL_RELEASE:
547 error = urbdrc_device_control_channel(callback, data);
551 WLog_Print(urbdrc->log, WLOG_TRACE,
"unknown FunctionId 0x%" PRIX32
"", FunctionId);
564 static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
568 IUDEVMAN* udevman = NULL;
569 UINT32 InterfaceId = 0;
570 UINT error = ERROR_INTERNAL_ERROR;
572 if (callback == NULL)
573 return ERROR_INVALID_PARAMETER;
575 if (callback->plugin == NULL)
580 if (urbdrc->udevman == NULL)
583 udevman = urbdrc->udevman;
585 if (!Stream_CheckAndLogRequiredLength(TAG, data, 12))
586 return ERROR_INVALID_DATA;
588 urbdrc_dump_message(urbdrc->log, FALSE, FALSE, data);
589 Stream_Read_UINT32(data, InterfaceId);
594 case CAPABILITIES_NEGOTIATOR | (STREAM_ID_NONE << 30):
595 error = urbdrc_exchange_capabilities(callback, data);
598 case SERVER_CHANNEL_NOTIFICATION | (STREAM_ID_PROXY << 30):
599 error = urbdrc_process_channel_notification(callback, data);
603 error = urbdrc_process_udev_data_transfer(callback, urbdrc, udevman, data);
604 WLog_DBG(TAG,
"urbdrc_process_udev_data_transfer returned 0x%08" PRIx32, error);
605 error = ERROR_SUCCESS;
617 static UINT urbdrc_on_close(IWTSVirtualChannelCallback* pChannelCallback)
625 IUDEVMAN* udevman = urbdrc->udevman;
626 if (udevman && callback->channel_mgr)
628 UINT32 control = callback->channel_mgr->GetChannelId(callback->channel);
629 if (udevman->controlChannelId == control)
630 udevman->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
633 IUDEVICE* pdev = udevman->get_udevice_by_ChannelID(udevman, control);
635 pdev->markChannelClosed(pdev);
641 return CHANNEL_RC_OK;
649 static UINT urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
650 IWTSVirtualChannel* pChannel, BYTE* pData,
652 IWTSVirtualChannelCallback** ppCallback)
658 return ERROR_INVALID_PARAMETER;
663 return ERROR_OUTOFMEMORY;
665 callback->iface.OnDataReceived = urbdrc_on_data_received;
666 callback->iface.OnClose = urbdrc_on_close;
667 callback->plugin = listener_callback->plugin;
668 callback->channel_mgr = listener_callback->channel_mgr;
669 callback->channel = pChannel;
670 *ppCallback = (IWTSVirtualChannelCallback*)callback;
671 return CHANNEL_RC_OK;
679 static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
683 IUDEVMAN* udevman = NULL;
684 char channelName[
sizeof(URBDRC_CHANNEL_NAME)] = { URBDRC_CHANNEL_NAME };
686 if (!urbdrc || !urbdrc->udevman)
687 return ERROR_INVALID_PARAMETER;
689 if (urbdrc->initialized)
691 WLog_ERR(TAG,
"[%s] channel initialized twice, aborting", URBDRC_CHANNEL_NAME);
692 return ERROR_INVALID_DATA;
694 udevman = urbdrc->udevman;
695 urbdrc->listener_callback =
698 if (!urbdrc->listener_callback)
699 return CHANNEL_RC_NO_MEMORY;
701 urbdrc->listener_callback->iface.OnNewChannelConnection = urbdrc_on_new_channel_connection;
702 urbdrc->listener_callback->plugin = pPlugin;
703 urbdrc->listener_callback->channel_mgr = pChannelMgr;
706 CharUpperA(channelName);
707 status = pChannelMgr->CreateListener(pChannelMgr, channelName, 0,
708 &urbdrc->listener_callback->iface, &urbdrc->listener);
709 if (status != CHANNEL_RC_OK)
712 status = CHANNEL_RC_OK;
713 if (udevman->listener_created_callback)
714 status = udevman->listener_created_callback(udevman);
716 urbdrc->initialized = status == CHANNEL_RC_OK;
725 static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
728 IUDEVMAN* udevman = NULL;
731 return ERROR_INVALID_DATA;
732 if (urbdrc->listener_callback)
734 IWTSVirtualChannelManager* mgr = urbdrc->listener_callback->channel_mgr;
736 IFCALL(mgr->DestroyListener, mgr, urbdrc->listener);
738 udevman = urbdrc->udevman;
742 udevman->free(udevman);
746 free(urbdrc->subsystem);
747 free(urbdrc->listener_callback);
749 return CHANNEL_RC_OK;
752 static BOOL urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
758 WLog_Print(urbdrc->log, WLOG_ERROR,
"existing device, abort.");
762 DEBUG_DVC(
"device registered.");
763 urbdrc->udevman = udevman;
772 static UINT urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, LPCSTR name,
const ADDIN_ARGV* args)
777 PVIRTUALCHANNELENTRY pvce =
778 freerdp_load_channel_addin_entry(URBDRC_CHANNEL_NAME, name, NULL, 0);
779 PFREERDP_URBDRC_DEVICE_ENTRY entry = WINPR_FUNC_PTR_CAST(pvce, PFREERDP_URBDRC_DEVICE_ENTRY);
782 return ERROR_INVALID_OPERATION;
784 entryPoints.plugin = pPlugin;
785 entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_addin;
786 entryPoints.args = args;
788 const UINT error = entry(&entryPoints);
791 WLog_Print(urbdrc->log, WLOG_ERROR,
"%s entry returns error.", name);
795 return CHANNEL_RC_OK;
798 static BOOL urbdrc_set_subsystem(
URBDRC_PLUGIN* urbdrc,
const char* subsystem)
800 free(urbdrc->subsystem);
801 urbdrc->subsystem = _strdup(subsystem);
802 return (urbdrc->subsystem != NULL);
814 {
"dbg", COMMAND_LINE_VALUE_FLAG,
"", NULL, BoolValueFalse, -1, NULL,
"debug" },
815 {
"sys", COMMAND_LINE_VALUE_REQUIRED,
"<subsystem>", NULL, NULL, -1, NULL,
"subsystem" },
816 {
"dev", COMMAND_LINE_VALUE_REQUIRED,
"<device list>", NULL, NULL, -1, NULL,
"devices" },
817 {
"encode", COMMAND_LINE_VALUE_FLAG,
"", NULL, NULL, -1, NULL,
"encode" },
818 {
"quality", COMMAND_LINE_VALUE_REQUIRED,
"<[0-2] -> [high-medium-low]>", NULL, NULL, -1,
820 { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
824 COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
827 CommandLineParseArgumentsA(args->argc, args->argv, urbdrc_args, flags, urbdrc, NULL, NULL);
830 return ERROR_INVALID_DATA;
836 if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
839 CommandLineSwitchStart(arg) CommandLineSwitchCase(arg,
"dbg")
841 WLog_SetLogLevel(urbdrc->log, WLOG_TRACE);
843 CommandLineSwitchCase(arg,
"sys")
845 if (!urbdrc_set_subsystem(urbdrc, arg->Value))
846 return ERROR_OUTOFMEMORY;
848 CommandLineSwitchDefault(arg)
851 CommandLineSwitchEnd(arg)
852 }
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
854 return CHANNEL_RC_OK;
857 BOOL add_device(IUDEVMAN* idevman, UINT32 flags, BYTE busnum, BYTE devnum, UINT16 idVendor,
870 if (!urbdrc || !urbdrc->listener_callback)
873 mask = (DEVICE_ADD_FLAG_VENDOR | DEVICE_ADD_FLAG_PRODUCT);
874 if ((flags & mask) == mask)
875 regflags |= UDEVMAN_FLAG_ADD_BY_VID_PID;
876 mask = (DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV);
877 if ((flags & mask) == mask)
878 regflags |= UDEVMAN_FLAG_ADD_BY_ADDR;
880 success = idevman->register_udevice(idevman, busnum, devnum, idVendor, idProduct, regflags);
882 if ((success > 0) && (flags & DEVICE_ADD_FLAG_REGISTER))
884 if (!urbdrc_announce_devices(idevman))
891 BOOL del_device(IUDEVMAN* idevman, UINT32 flags, BYTE busnum, BYTE devnum, UINT16 idVendor,
894 IUDEVICE* pdev = NULL;
902 if (!urbdrc || !urbdrc->listener_callback)
905 idevman->loading_lock(idevman);
906 idevman->rewind(idevman);
908 while (idevman->has_next(idevman))
911 IUDEVICE* dev = idevman->get_next(idevman);
913 if ((flags & (DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV | DEVICE_ADD_FLAG_VENDOR |
914 DEVICE_ADD_FLAG_PRODUCT)) == 0)
916 if (flags & DEVICE_ADD_FLAG_BUS)
918 if (dev->get_bus_number(dev) != busnum)
921 if (flags & DEVICE_ADD_FLAG_DEV)
923 if (dev->get_dev_number(dev) != devnum)
926 if (flags & DEVICE_ADD_FLAG_VENDOR)
928 int vid = dev->query_device_descriptor(dev, ID_VENDOR);
932 if (flags & DEVICE_ADD_FLAG_PRODUCT)
934 int pid = dev->query_device_descriptor(dev, ID_PRODUCT);
935 if (pid != idProduct)
947 pdev->setChannelClosed(pdev);
949 idevman->loading_unlock(idevman);
958 FREERDP_ENTRY_POINT(UINT VCAPITYPE urbdrc_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
963 urbdrc = (
URBDRC_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, URBDRC_CHANNEL_NAME);
964 args = pEntryPoints->GetPluginData(pEntryPoints);
971 return CHANNEL_RC_NO_MEMORY;
973 urbdrc->iface.Initialize = urbdrc_plugin_initialize;
974 urbdrc->iface.Terminated = urbdrc_plugin_terminated;
975 urbdrc->vchannel_status = INIT_CHANNEL_IN;
976 status = pEntryPoints->RegisterPlugin(pEntryPoints, URBDRC_CHANNEL_NAME, &urbdrc->iface);
979 if (status != CHANNEL_RC_OK)
985 urbdrc->log = WLog_Get(TAG);
991 status = urbdrc_process_addin_args(urbdrc, args);
993 if (status != CHANNEL_RC_OK)
996 if (!urbdrc->subsystem && !urbdrc_set_subsystem(urbdrc,
"libusb"))
999 return urbdrc_load_udevman_addin(&urbdrc->iface, urbdrc->subsystem, args);
1004 UINT stream_write_and_free(IWTSPlugin* plugin, IWTSVirtualChannel* channel,
wStream* out)
1009 return ERROR_INVALID_PARAMETER;
1011 if (!channel || !out || !urbdrc)
1013 Stream_Free(out, TRUE);
1014 return ERROR_INVALID_PARAMETER;
1017 if (!channel->Write)
1019 Stream_Free(out, TRUE);
1020 return ERROR_INTERNAL_ERROR;
1023 urbdrc_dump_message(urbdrc->log, TRUE, TRUE, out);
1024 const size_t len = Stream_GetPosition(out);
1025 UINT rc = ERROR_INTERNAL_ERROR;
1026 if (len <= UINT32_MAX)
1027 rc = channel->Write(channel, (UINT32)len, Stream_Buffer(out), NULL);
1028 Stream_Free(out, TRUE);