FreeRDP
urbdrc_main.c
1 
21 #include <winpr/assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 
27 #include <winpr/pool.h>
28 #include <winpr/print.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/string.h>
33 #include <winpr/cmdline.h>
34 
35 #include <freerdp/dvc.h>
36 #include <freerdp/addin.h>
37 #include <freerdp/channels/log.h>
38 #include <freerdp/channels/urbdrc.h>
39 
40 #include "urbdrc_types.h"
41 #include "urbdrc_main.h"
42 #include "data_transfer.h"
43 
44 #include <urbdrc_helpers.h>
45 
46 static IWTSVirtualChannel* get_channel(IUDEVMAN* idevman)
47 {
48  IWTSVirtualChannelManager* channel_mgr = NULL;
49  URBDRC_PLUGIN* urbdrc = NULL;
50 
51  if (!idevman)
52  return NULL;
53 
54  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
55 
56  if (!urbdrc || !urbdrc->listener_callback)
57  return NULL;
58 
59  channel_mgr = urbdrc->listener_callback->channel_mgr;
60 
61  if (!channel_mgr)
62  return NULL;
63 
64  return channel_mgr->FindChannelById(channel_mgr, idevman->controlChannelId);
65 }
66 
67 static int func_container_id_generate(IUDEVICE* pdev, char* strContainerId)
68 {
69  char* p = NULL;
70  char* path = NULL;
71  UINT8 containerId[17] = { 0 };
72  UINT16 idVendor = 0;
73  UINT16 idProduct = 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);
77 
78  if (strlen(path) > 8)
79  p = (path + strlen(path)) - 8;
80  else
81  p = path;
82 
83  (void)sprintf_s((char*)containerId, sizeof(containerId), "%04" PRIX16 "%04" PRIX16 "%s",
84  idVendor, idProduct, p);
85  /* format */
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]);
94  return 0;
95 }
96 
97 static int func_instance_id_generate(IUDEVICE* pdev, char* strInstanceId, size_t len)
98 {
99  char instanceId[17] = { 0 };
100  (void)sprintf_s(instanceId, sizeof(instanceId), "\\%s", pdev->getPath(pdev));
101  /* format */
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],
109  instanceId[15]);
110  return 0;
111 }
112 
118 static UINT urbdrc_process_capability_request(GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
119  UINT32 MessageId)
120 {
121  UINT32 InterfaceId = 0;
122  UINT32 Version = 0;
123  UINT32 out_size = 0;
124  wStream* out = NULL;
125 
126  if (!callback || !s)
127  return ERROR_INVALID_PARAMETER;
128 
129  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
130  return ERROR_INVALID_DATA;
131 
132  Stream_Read_UINT32(s, Version);
133 
134  if (Version > RIM_CAPABILITY_VERSION_01)
135  Version = RIM_CAPABILITY_VERSION_01;
136 
137  InterfaceId = ((STREAM_ID_NONE << 30) | CAPABILITIES_NEGOTIATOR);
138  out_size = 16;
139  out = Stream_New(NULL, out_size);
140 
141  if (!out)
142  return ERROR_OUTOFMEMORY;
143 
144  Stream_Write_UINT32(out, InterfaceId); /* interface id */
145  Stream_Write_UINT32(out, MessageId); /* message id */
146  Stream_Write_UINT32(out, Version); /* usb protocol version */
147  Stream_Write_UINT32(out, 0x00000000); /* HRESULT */
148  return stream_write_and_free(callback->plugin, callback->channel, out);
149 }
150 
156 static UINT urbdrc_process_channel_create(GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
157  UINT32 MessageId)
158 {
159  UINT32 InterfaceId = 0;
160  UINT32 out_size = 0;
161  UINT32 MajorVersion = 0;
162  UINT32 MinorVersion = 0;
163  UINT32 Capabilities = 0;
164  wStream* out = NULL;
165  URBDRC_PLUGIN* urbdrc = NULL;
166 
167  if (!callback || !s || !callback->plugin)
168  return ERROR_INVALID_PARAMETER;
169 
170  urbdrc = (URBDRC_PLUGIN*)callback->plugin;
171 
172  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
173  return ERROR_INVALID_DATA;
174 
175  Stream_Read_UINT32(s, MajorVersion);
176  Stream_Read_UINT32(s, MinorVersion);
177  Stream_Read_UINT32(s, Capabilities);
178 
179  /* Version check, we only support version 1.0 */
180  if ((MajorVersion != 1) || (MinorVersion != 0))
181  {
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");
185  MajorVersion = 1;
186  MinorVersion = 0;
187  }
188 
189  InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_CHANNEL_NOTIFICATION);
190  out_size = 24;
191  out = Stream_New(NULL, out_size);
192 
193  if (!out)
194  return ERROR_OUTOFMEMORY;
195 
196  Stream_Write_UINT32(out, InterfaceId); /* interface id */
197  Stream_Write_UINT32(out, MessageId); /* message id */
198  Stream_Write_UINT32(out, CHANNEL_CREATED); /* function id */
199  Stream_Write_UINT32(out, MajorVersion);
200  Stream_Write_UINT32(out, MinorVersion);
201  Stream_Write_UINT32(out, Capabilities); /* capabilities version */
202  return stream_write_and_free(callback->plugin, callback->channel, out);
203 }
204 
205 static UINT urdbrc_send_virtual_channel_add(IWTSPlugin* plugin, IWTSVirtualChannel* channel,
206  UINT32 MessageId)
207 {
208  const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK);
209  wStream* out = Stream_New(NULL, 12);
210 
211  if (!out)
212  return ERROR_OUTOFMEMORY;
213 
214  Stream_Write_UINT32(out, InterfaceId); /* interface */
215  Stream_Write_UINT32(out, MessageId); /* message id */
216  Stream_Write_UINT32(out, ADD_VIRTUAL_CHANNEL); /* function id */
217  return stream_write_and_free(plugin, channel, out);
218 }
219 
225 static UINT urdbrc_send_usb_device_add(GENERIC_CHANNEL_CALLBACK* callback, IUDEVICE* pdev)
226 {
227  wStream* out = NULL;
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;
235  size_t size = 0;
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;
241  UINT32 bcdUSB = 0;
242  InterfaceId = ((STREAM_ID_PROXY << 30) | CLIENT_DEVICE_SINK);
243  /* USB kernel driver detach!! */
244  pdev->detach_kernel_driver(pdev);
245  {
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);
254  }
255  {
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);
259 
260  if (!(pdev->isCompositeDevice(pdev)))
261  {
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,
266  bDeviceSubClass);
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);
270  }
271  else
272  {
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");
278  }
279  }
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]));
287  cchCompatIds =
288  CompatibilityIdLen[0] + 1 + CompatibilityIdLen[1] + 1 + CompatibilityIdLen[2] + 2;
289  InstanceIdLen = strnlen(strInstanceId, sizeof(strInstanceId));
290  ContainerIdLen = strnlen(strContainerId, sizeof(strContainerId));
291 
292  if (pdev->isCompositeDevice(pdev))
293  cchCompatIds += composite_len + 1;
294 
295  size = 24;
296  size += (InstanceIdLen + 1) * 2 + (HardwareIdsLen[0] + 1) * 2 + 4 +
297  (HardwareIdsLen[1] + 1) * 2 + 2 + 4 + (cchCompatIds)*2 + (ContainerIdLen + 1) * 2 + 4 +
298  28;
299  out = Stream_New(NULL, size);
300 
301  if (!out)
302  return ERROR_OUTOFMEMORY;
303 
304  Stream_Write_UINT32(out, InterfaceId); /* interface */
305  Stream_Write_UINT32(out, 0);
306  Stream_Write_UINT32(out, ADD_DEVICE); /* function id */
307  Stream_Write_UINT32(out, 0x00000001); /* NumUsbDevice */
308  Stream_Write_UINT32(out, pdev->get_UsbDevice(pdev)); /* UsbDevice */
309  Stream_Write_UINT32(out, (UINT32)InstanceIdLen + 1); /* cchDeviceInstanceId */
310  if (Stream_Write_UTF16_String_From_UTF8(out, InstanceIdLen, strInstanceId, InstanceIdLen,
311  TRUE) < 0)
312  goto fail;
313  Stream_Write_UINT16(out, 0);
314  const size_t len = HardwareIdsLen[0] + HardwareIdsLen[1] + 3;
315  if (len > UINT32_MAX)
316  goto fail;
317  Stream_Write_UINT32(out, (UINT32)len); /* cchHwIds */
318  /* HardwareIds 1 */
319  if (Stream_Write_UTF16_String_From_UTF8(out, HardwareIdsLen[0], HardwareIds[0],
320  HardwareIdsLen[0], TRUE) < 0)
321  goto fail;
322  Stream_Write_UINT16(out, 0);
323  if (Stream_Write_UTF16_String_From_UTF8(out, HardwareIdsLen[1], HardwareIds[1],
324  HardwareIdsLen[1], TRUE) < 0)
325  goto fail;
326  Stream_Write_UINT16(out, 0);
327  Stream_Write_UINT16(out, 0); /* add "\0" */
328  Stream_Write_UINT32(out, (UINT32)cchCompatIds); /* cchCompatIds */
329  /* CompatibilityIds */
330  if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[0], CompatibilityIds[0],
331  CompatibilityIdLen[0], TRUE) < 0)
332  goto fail;
333  Stream_Write_UINT16(out, 0);
334  if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[1], CompatibilityIds[1],
335  CompatibilityIdLen[1], TRUE) < 0)
336  goto fail;
337  Stream_Write_UINT16(out, 0);
338  if (Stream_Write_UTF16_String_From_UTF8(out, CompatibilityIdLen[2], CompatibilityIds[2],
339  CompatibilityIdLen[2], TRUE) < 0)
340  goto fail;
341  Stream_Write_UINT16(out, 0);
342 
343  if (pdev->isCompositeDevice(pdev))
344  {
345  if (Stream_Write_UTF16_String_From_UTF8(out, composite_len, composite_str, composite_len,
346  TRUE) < 0)
347  goto fail;
348  Stream_Write_UINT16(out, 0);
349  }
350 
351  Stream_Write_UINT16(out, 0x0000); /* add "\0" */
352  Stream_Write_UINT32(out, (UINT32)ContainerIdLen + 1); /* cchContainerId */
353  /* ContainerId */
354  if (Stream_Write_UTF16_String_From_UTF8(out, ContainerIdLen, strContainerId, ContainerIdLen,
355  TRUE) < 0)
356  goto fail;
357  Stream_Write_UINT16(out, 0);
358  /* USB_DEVICE_CAPABILITIES 28 bytes */
359  Stream_Write_UINT32(out, 0x0000001c); /* CbSize */
360  Stream_Write_UINT32(out, 2); /* UsbBusInterfaceVersion, 0 ,1 or 2 */ // TODO: Get from libusb
361  Stream_Write_UINT32(out, 0x600); /* USBDI_Version, 0x500 or 0x600 */ // TODO: Get from libusb
362  /* Supported_USB_Version, 0x110,0x110 or 0x200(usb2.0) */
363  bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
364  Stream_Write_UINT32(out, bcdUSB);
365  Stream_Write_UINT32(out, 0x00000000); /* HcdCapabilities, MUST always be zero */
366 
367  if (bcdUSB < 0x200)
368  Stream_Write_UINT32(out, 0x00000000); /* DeviceIsHighSpeed */
369  else
370  Stream_Write_UINT32(out, 0x00000001); /* DeviceIsHighSpeed */
371 
372  Stream_Write_UINT32(out, 0x50); /* NoAckIsochWriteJitterBufferSizeInMs, >=10 or <=512 */
373  return stream_write_and_free(callback->plugin, callback->channel, out);
374 
375 fail:
376  Stream_Free(out, TRUE);
377  return ERROR_INTERNAL_ERROR;
378 }
379 
385 static UINT urbdrc_exchange_capabilities(GENERIC_CHANNEL_CALLBACK* callback, wStream* data)
386 {
387  UINT32 MessageId = 0;
388  UINT32 FunctionId = 0;
389  UINT32 InterfaceId = 0;
390  UINT error = CHANNEL_RC_OK;
391 
392  if (!data)
393  return ERROR_INVALID_PARAMETER;
394 
395  if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
396  return ERROR_INVALID_DATA;
397 
398  Stream_Rewind_UINT32(data);
399  Stream_Read_UINT32(data, InterfaceId);
400  Stream_Read_UINT32(data, MessageId);
401  Stream_Read_UINT32(data, FunctionId);
402 
403  switch (FunctionId)
404  {
405  case RIM_EXCHANGE_CAPABILITY_REQUEST:
406  error = urbdrc_process_capability_request(callback, data, MessageId);
407  break;
408 
409  case RIMCALL_RELEASE:
410  break;
411 
412  default:
413  error = ERROR_NOT_FOUND;
414  break;
415  }
416 
417  return error;
418 }
419 
420 static BOOL urbdrc_announce_devices(IUDEVMAN* udevman)
421 {
422  UINT error = ERROR_SUCCESS;
423 
424  udevman->loading_lock(udevman);
425  udevman->rewind(udevman);
426 
427  while (udevman->has_next(udevman))
428  {
429  IUDEVICE* pdev = udevman->get_next(udevman);
430 
431  if (!pdev->isAlreadySend(pdev))
432  {
433  const UINT32 deviceId = pdev->get_UsbDevice(pdev);
434  UINT cerror =
435  urdbrc_send_virtual_channel_add(udevman->plugin, get_channel(udevman), deviceId);
436 
437  if (cerror != ERROR_SUCCESS)
438  break;
439  }
440  }
441 
442  udevman->loading_unlock(udevman);
443 
444  return error == ERROR_SUCCESS;
445 }
446 
447 static UINT urbdrc_device_control_channel(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
448 {
449  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
450  IUDEVMAN* udevman = urbdrc->udevman;
451  IWTSVirtualChannel* channel = callback->channel;
452  IUDEVICE* pdev = NULL;
453  BOOL found = FALSE;
454  UINT error = ERROR_INTERNAL_ERROR;
455  UINT32 channelId = callback->channel_mgr->GetChannelId(channel);
456 
457  switch (urbdrc->vchannel_status)
458  {
459  case INIT_CHANNEL_IN:
460  /* Control channel was established */
461  error = ERROR_SUCCESS;
462  udevman->initialize(udevman, channelId);
463 
464  if (!urbdrc_announce_devices(udevman))
465  goto fail;
466 
467  urbdrc->vchannel_status = INIT_CHANNEL_OUT;
468  break;
469 
470  case INIT_CHANNEL_OUT:
471  /* A new device channel was created, add the channel
472  * to the device */
473  udevman->loading_lock(udevman);
474  udevman->rewind(udevman);
475 
476  while (udevman->has_next(udevman))
477  {
478  pdev = udevman->get_next(udevman);
479 
480  if (!pdev->isAlreadySend(pdev))
481  {
482  const UINT32 channelID = callback->channel_mgr->GetChannelId(channel);
483  found = TRUE;
484  pdev->setAlreadySend(pdev);
485  pdev->set_channelManager(pdev, callback->channel_mgr);
486  pdev->set_channelID(pdev, channelID);
487  break;
488  }
489  }
490 
491  udevman->loading_unlock(udevman);
492  error = ERROR_SUCCESS;
493 
494  if (found && pdev->isAlreadySend(pdev))
495  error = urdbrc_send_usb_device_add(callback, pdev);
496 
497  break;
498 
499  default:
500  WLog_Print(urbdrc->log, WLOG_ERROR, "vchannel_status unknown value %" PRIu32 "",
501  urbdrc->vchannel_status);
502  break;
503  }
504 
505 fail:
506  return error;
507 }
508 
514 static UINT urbdrc_process_channel_notification(GENERIC_CHANNEL_CALLBACK* callback, wStream* data)
515 {
516  UINT32 MessageId = 0;
517  UINT32 FunctionId = 0;
518  UINT32 InterfaceId = 0;
519  UINT error = CHANNEL_RC_OK;
520  URBDRC_PLUGIN* urbdrc = NULL;
521 
522  if (!callback || !data)
523  return ERROR_INVALID_PARAMETER;
524 
525  urbdrc = (URBDRC_PLUGIN*)callback->plugin;
526 
527  if (!urbdrc)
528  return ERROR_INVALID_PARAMETER;
529 
530  if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
531  return ERROR_INVALID_DATA;
532 
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);
539 
540  switch (FunctionId)
541  {
542  case CHANNEL_CREATED:
543  error = urbdrc_process_channel_create(callback, data, MessageId);
544  break;
545 
546  case RIMCALL_RELEASE:
547  error = urbdrc_device_control_channel(callback, data);
548  break;
549 
550  default:
551  WLog_Print(urbdrc->log, WLOG_TRACE, "unknown FunctionId 0x%" PRIX32 "", FunctionId);
552  error = 1;
553  break;
554  }
555 
556  return error;
557 }
558 
564 static UINT urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
565 {
566  GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
567  URBDRC_PLUGIN* urbdrc = NULL;
568  IUDEVMAN* udevman = NULL;
569  UINT32 InterfaceId = 0;
570  UINT error = ERROR_INTERNAL_ERROR;
571 
572  if (callback == NULL)
573  return ERROR_INVALID_PARAMETER;
574 
575  if (callback->plugin == NULL)
576  return error;
577 
578  urbdrc = (URBDRC_PLUGIN*)callback->plugin;
579 
580  if (urbdrc->udevman == NULL)
581  return error;
582 
583  udevman = urbdrc->udevman;
584 
585  if (!Stream_CheckAndLogRequiredLength(TAG, data, 12))
586  return ERROR_INVALID_DATA;
587 
588  urbdrc_dump_message(urbdrc->log, FALSE, FALSE, data);
589  Stream_Read_UINT32(data, InterfaceId);
590 
591  /* Need to check InterfaceId and mask values */
592  switch (InterfaceId)
593  {
594  case CAPABILITIES_NEGOTIATOR | (STREAM_ID_NONE << 30):
595  error = urbdrc_exchange_capabilities(callback, data);
596  break;
597 
598  case SERVER_CHANNEL_NOTIFICATION | (STREAM_ID_PROXY << 30):
599  error = urbdrc_process_channel_notification(callback, data);
600  break;
601 
602  default:
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; /* Ignore errors, the device may have been unplugged. */
606  break;
607  }
608 
609  return error;
610 }
611 
617 static UINT urbdrc_on_close(IWTSVirtualChannelCallback* pChannelCallback)
618 {
619  GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
620  if (callback)
621  {
622  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
623  if (urbdrc)
624  {
625  IUDEVMAN* udevman = urbdrc->udevman;
626  if (udevman && callback->channel_mgr)
627  {
628  UINT32 control = callback->channel_mgr->GetChannelId(callback->channel);
629  if (udevman->controlChannelId == control)
630  udevman->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
631  else
632  { /* Need to notify the local backend the device is gone */
633  IUDEVICE* pdev = udevman->get_udevice_by_ChannelID(udevman, control);
634  if (pdev)
635  pdev->markChannelClosed(pdev);
636  }
637  }
638  }
639  }
640  free(callback);
641  return CHANNEL_RC_OK;
642 }
643 
649 static UINT urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
650  IWTSVirtualChannel* pChannel, BYTE* pData,
651  BOOL* pbAccept,
652  IWTSVirtualChannelCallback** ppCallback)
653 {
654  GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback;
655  GENERIC_CHANNEL_CALLBACK* callback = NULL;
656 
657  if (!ppCallback)
658  return ERROR_INVALID_PARAMETER;
659 
660  callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK));
661 
662  if (!callback)
663  return ERROR_OUTOFMEMORY;
664 
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;
672 }
673 
679 static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
680 {
681  UINT status = 0;
682  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin;
683  IUDEVMAN* udevman = NULL;
684  char channelName[sizeof(URBDRC_CHANNEL_NAME)] = { URBDRC_CHANNEL_NAME };
685 
686  if (!urbdrc || !urbdrc->udevman)
687  return ERROR_INVALID_PARAMETER;
688 
689  if (urbdrc->initialized)
690  {
691  WLog_ERR(TAG, "[%s] channel initialized twice, aborting", URBDRC_CHANNEL_NAME);
692  return ERROR_INVALID_DATA;
693  }
694  udevman = urbdrc->udevman;
695  urbdrc->listener_callback =
697 
698  if (!urbdrc->listener_callback)
699  return CHANNEL_RC_NO_MEMORY;
700 
701  urbdrc->listener_callback->iface.OnNewChannelConnection = urbdrc_on_new_channel_connection;
702  urbdrc->listener_callback->plugin = pPlugin;
703  urbdrc->listener_callback->channel_mgr = pChannelMgr;
704 
705  /* [MS-RDPEUSB] 2.1 Transport defines the channel name in uppercase letters */
706  CharUpperA(channelName);
707  status = pChannelMgr->CreateListener(pChannelMgr, channelName, 0,
708  &urbdrc->listener_callback->iface, &urbdrc->listener);
709  if (status != CHANNEL_RC_OK)
710  return status;
711 
712  status = CHANNEL_RC_OK;
713  if (udevman->listener_created_callback)
714  status = udevman->listener_created_callback(udevman);
715 
716  urbdrc->initialized = status == CHANNEL_RC_OK;
717  return status;
718 }
719 
725 static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
726 {
727  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin;
728  IUDEVMAN* udevman = NULL;
729 
730  if (!urbdrc)
731  return ERROR_INVALID_DATA;
732  if (urbdrc->listener_callback)
733  {
734  IWTSVirtualChannelManager* mgr = urbdrc->listener_callback->channel_mgr;
735  if (mgr)
736  IFCALL(mgr->DestroyListener, mgr, urbdrc->listener);
737  }
738  udevman = urbdrc->udevman;
739 
740  if (udevman)
741  {
742  udevman->free(udevman);
743  udevman = NULL;
744  }
745 
746  free(urbdrc->subsystem);
747  free(urbdrc->listener_callback);
748  free(urbdrc);
749  return CHANNEL_RC_OK;
750 }
751 
752 static BOOL urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
753 {
754  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin;
755 
756  if (urbdrc->udevman)
757  {
758  WLog_Print(urbdrc->log, WLOG_ERROR, "existing device, abort.");
759  return FALSE;
760  }
761 
762  DEBUG_DVC("device registered.");
763  urbdrc->udevman = udevman;
764  return TRUE;
765 }
766 
772 static UINT urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, LPCSTR name, const ADDIN_ARGV* args)
773 {
774  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin;
775  FREERDP_URBDRC_SERVICE_ENTRY_POINTS entryPoints = { 0 };
776 
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);
780 
781  if (!entry)
782  return ERROR_INVALID_OPERATION;
783 
784  entryPoints.plugin = pPlugin;
785  entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_addin;
786  entryPoints.args = args;
787 
788  const UINT error = entry(&entryPoints);
789  if (error)
790  {
791  WLog_Print(urbdrc->log, WLOG_ERROR, "%s entry returns error.", name);
792  return error;
793  }
794 
795  return CHANNEL_RC_OK;
796 }
797 
798 static BOOL urbdrc_set_subsystem(URBDRC_PLUGIN* urbdrc, const char* subsystem)
799 {
800  free(urbdrc->subsystem);
801  urbdrc->subsystem = _strdup(subsystem);
802  return (urbdrc->subsystem != NULL);
803 }
804 
810 static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, const ADDIN_ARGV* args)
811 {
812  int status = 0;
813  COMMAND_LINE_ARGUMENT_A urbdrc_args[] = {
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,
819  NULL, "quality" },
820  { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
821  };
822 
823  const DWORD flags =
824  COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
825  const COMMAND_LINE_ARGUMENT_A* arg = NULL;
826  status =
827  CommandLineParseArgumentsA(args->argc, args->argv, urbdrc_args, flags, urbdrc, NULL, NULL);
828 
829  if (status < 0)
830  return ERROR_INVALID_DATA;
831 
832  arg = urbdrc_args;
833 
834  do
835  {
836  if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
837  continue;
838 
839  CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dbg")
840  {
841  WLog_SetLogLevel(urbdrc->log, WLOG_TRACE);
842  }
843  CommandLineSwitchCase(arg, "sys")
844  {
845  if (!urbdrc_set_subsystem(urbdrc, arg->Value))
846  return ERROR_OUTOFMEMORY;
847  }
848  CommandLineSwitchDefault(arg)
849  {
850  }
851  CommandLineSwitchEnd(arg)
852  } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
853 
854  return CHANNEL_RC_OK;
855 }
856 
857 BOOL add_device(IUDEVMAN* idevman, UINT32 flags, BYTE busnum, BYTE devnum, UINT16 idVendor,
858  UINT16 idProduct)
859 {
860  size_t success = 0;
861  URBDRC_PLUGIN* urbdrc = NULL;
862  UINT32 mask = 0;
863  UINT32 regflags = 0;
864 
865  if (!idevman)
866  return FALSE;
867 
868  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
869 
870  if (!urbdrc || !urbdrc->listener_callback)
871  return FALSE;
872 
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;
879 
880  success = idevman->register_udevice(idevman, busnum, devnum, idVendor, idProduct, regflags);
881 
882  if ((success > 0) && (flags & DEVICE_ADD_FLAG_REGISTER))
883  {
884  if (!urbdrc_announce_devices(idevman))
885  return FALSE;
886  }
887 
888  return TRUE;
889 }
890 
891 BOOL del_device(IUDEVMAN* idevman, UINT32 flags, BYTE busnum, BYTE devnum, UINT16 idVendor,
892  UINT16 idProduct)
893 {
894  IUDEVICE* pdev = NULL;
895  URBDRC_PLUGIN* urbdrc = NULL;
896 
897  if (!idevman)
898  return FALSE;
899 
900  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
901 
902  if (!urbdrc || !urbdrc->listener_callback)
903  return FALSE;
904 
905  idevman->loading_lock(idevman);
906  idevman->rewind(idevman);
907 
908  while (idevman->has_next(idevman))
909  {
910  BOOL match = TRUE;
911  IUDEVICE* dev = idevman->get_next(idevman);
912 
913  if ((flags & (DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV | DEVICE_ADD_FLAG_VENDOR |
914  DEVICE_ADD_FLAG_PRODUCT)) == 0)
915  match = FALSE;
916  if (flags & DEVICE_ADD_FLAG_BUS)
917  {
918  if (dev->get_bus_number(dev) != busnum)
919  match = FALSE;
920  }
921  if (flags & DEVICE_ADD_FLAG_DEV)
922  {
923  if (dev->get_dev_number(dev) != devnum)
924  match = FALSE;
925  }
926  if (flags & DEVICE_ADD_FLAG_VENDOR)
927  {
928  int vid = dev->query_device_descriptor(dev, ID_VENDOR);
929  if (vid != idVendor)
930  match = FALSE;
931  }
932  if (flags & DEVICE_ADD_FLAG_PRODUCT)
933  {
934  int pid = dev->query_device_descriptor(dev, ID_PRODUCT);
935  if (pid != idProduct)
936  match = FALSE;
937  }
938 
939  if (match)
940  {
941  pdev = dev;
942  break;
943  }
944  }
945 
946  if (pdev)
947  pdev->setChannelClosed(pdev);
948 
949  idevman->loading_unlock(idevman);
950  return TRUE;
951 }
952 
958 FREERDP_ENTRY_POINT(UINT VCAPITYPE urbdrc_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
959 {
960  UINT status = 0;
961  const ADDIN_ARGV* args = NULL;
962  URBDRC_PLUGIN* urbdrc = NULL;
963  urbdrc = (URBDRC_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, URBDRC_CHANNEL_NAME);
964  args = pEntryPoints->GetPluginData(pEntryPoints);
965 
966  if (urbdrc == NULL)
967  {
968  urbdrc = (URBDRC_PLUGIN*)calloc(1, sizeof(URBDRC_PLUGIN));
969 
970  if (!urbdrc)
971  return CHANNEL_RC_NO_MEMORY;
972 
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);
977 
978  /* After we register the plugin free will be taken care of by dynamic channel */
979  if (status != CHANNEL_RC_OK)
980  {
981  free(urbdrc);
982  goto fail;
983  }
984 
985  urbdrc->log = WLog_Get(TAG);
986 
987  if (!urbdrc->log)
988  goto fail;
989  }
990 
991  status = urbdrc_process_addin_args(urbdrc, args);
992 
993  if (status != CHANNEL_RC_OK)
994  goto fail;
995 
996  if (!urbdrc->subsystem && !urbdrc_set_subsystem(urbdrc, "libusb"))
997  goto fail;
998 
999  return urbdrc_load_udevman_addin(&urbdrc->iface, urbdrc->subsystem, args);
1000 fail:
1001  return status;
1002 }
1003 
1004 UINT stream_write_and_free(IWTSPlugin* plugin, IWTSVirtualChannel* channel, wStream* out)
1005 {
1006  URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)plugin;
1007 
1008  if (!out)
1009  return ERROR_INVALID_PARAMETER;
1010 
1011  if (!channel || !out || !urbdrc)
1012  {
1013  Stream_Free(out, TRUE);
1014  return ERROR_INVALID_PARAMETER;
1015  }
1016 
1017  if (!channel->Write)
1018  {
1019  Stream_Free(out, TRUE);
1020  return ERROR_INTERNAL_ERROR;
1021  }
1022 
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);
1029  return rc;
1030 }
Definition: urbdrc_main.h:71