FreeRDP
Loading...
Searching...
No Matches
libusb_udevice.c
1
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <winpr/assert.h>
26#include <winpr/cast.h>
27#include <winpr/wtypes.h>
28#include <winpr/sysinfo.h>
29#include <winpr/collections.h>
30
31#include <errno.h>
32
33#include "libusb_udevice.h"
34#include "msusb.h"
35#include "../common/urbdrc_types.h"
36
37#define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
38 static _type udev_get_##_arg(IUDEVICE* idev) \
39 { \
40 UDEVICE* pdev = (UDEVICE*)idev; \
41 return pdev->_arg; \
42 } \
43 static void udev_set_##_arg(IUDEVICE* idev, _type _t) \
44 { \
45 UDEVICE* pdev = (UDEVICE*)idev; \
46 pdev->_arg = _t; \
47 }
48
49#define BASIC_POINT_FUNC_DEFINED(_arg, _type) \
50 static _type udev_get_p_##_arg(IUDEVICE* idev) \
51 { \
52 UDEVICE* pdev = (UDEVICE*)idev; \
53 return pdev->_arg; \
54 } \
55 static void udev_set_p_##_arg(IUDEVICE* idev, _type _t) \
56 { \
57 UDEVICE* pdev = (UDEVICE*)idev; \
58 pdev->_arg = _t; \
59 }
60
61#define BASIC_STATE_FUNC_REGISTER(_arg, _dev) \
62 _dev->iface.get_##_arg = udev_get_##_arg; \
63 (_dev)->iface.set_##_arg = udev_set_##_arg
64
65#if LIBUSB_API_VERSION >= 0x01000103
66#define HAVE_STREAM_ID_API 1
67#endif
68
69typedef struct
70{
71 wStream* data;
72 BOOL noack;
73 UINT32 MessageId;
74 UINT32 StartFrame;
75 UINT32 ErrorCount;
76 IUDEVICE* idev;
77 UINT32 OutputBufferSize;
78 /* Completion framing depends on the outer RDPEUSB request direction. */
79 int transferDir;
81 t_isoch_transfer_cb cb;
82 wArrayList* queue;
83#if !defined(HAVE_STREAM_ID_API)
84 UINT32 streamID;
85#endif
86} ASYNC_TRANSFER_USER_DATA;
87
88static void request_free(void* value);
89
90static struct libusb_transfer* list_contains(wArrayList* list, UINT32 streamID)
91{
92 size_t count = 0;
93 if (!list)
94 return nullptr;
95 count = ArrayList_Count(list);
96 for (size_t x = 0; x < count; x++)
97 {
98 struct libusb_transfer* transfer = ArrayList_GetItem(list, x);
99
100#if defined(HAVE_STREAM_ID_API)
101 const UINT32 currentID = libusb_transfer_get_stream_id(transfer);
102#else
103 const ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
104 const UINT32 currentID = user_data->streamID;
105#endif
106 if (currentID == streamID)
107 return transfer;
108 }
109 return nullptr;
110}
111
112static UINT32 stream_id_from_buffer(struct libusb_transfer* transfer)
113{
114 if (!transfer)
115 return 0;
116#if defined(HAVE_STREAM_ID_API)
117 return libusb_transfer_get_stream_id(transfer);
118#else
119 ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
120 if (!user_data)
121 return 0;
122 return user_data->streamID;
123#endif
124}
125
126static void set_stream_id_for_buffer(struct libusb_transfer* transfer, UINT32 streamID)
127{
128#if defined(HAVE_STREAM_ID_API)
129 libusb_transfer_set_stream_id(transfer, streamID);
130#else
131 ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
132 if (!user_data)
133 return;
134 user_data->streamID = streamID;
135#endif
136}
137
138WINPR_ATTR_FORMAT_ARG(3, 8)
139static BOOL log_libusb_result_(wLog* log, DWORD lvl, WINPR_FORMAT_ARG const char* fmt,
140 const char* fkt, const char* file, size_t line, int error, ...)
141{
142 WINPR_UNUSED(file);
143
144 if (error < 0)
145 {
146 char buffer[8192] = WINPR_C_ARRAY_INIT;
147 va_list ap = WINPR_C_ARRAY_INIT;
148 va_start(ap, error);
149 (void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
150 va_end(ap);
151
152 WLog_Print(log, lvl, "[%s:%" PRIuz "]: %s: error %s[%d]", fkt, line, buffer,
153 libusb_error_name(error), error);
154 return TRUE;
155 }
156 return FALSE;
157}
158
159#define log_libusb_result(log, lvl, fmt, error, ...) \
160 log_libusb_result_((log), (lvl), (fmt), __func__, __FILE__, __LINE__, error, ##__VA_ARGS__)
161
162const char* usb_interface_class_to_string(uint8_t c_class)
163{
164 switch (c_class)
165 {
166 case LIBUSB_CLASS_PER_INTERFACE:
167 return "LIBUSB_CLASS_PER_INTERFACE";
168 case LIBUSB_CLASS_AUDIO:
169 return "LIBUSB_CLASS_AUDIO";
170 case LIBUSB_CLASS_COMM:
171 return "LIBUSB_CLASS_COMM";
172 case LIBUSB_CLASS_HID:
173 return "LIBUSB_CLASS_HID";
174 case LIBUSB_CLASS_PHYSICAL:
175 return "LIBUSB_CLASS_PHYSICAL";
176 case LIBUSB_CLASS_PRINTER:
177 return "LIBUSB_CLASS_PRINTER";
178 case LIBUSB_CLASS_IMAGE:
179 return "LIBUSB_CLASS_IMAGE";
180 case LIBUSB_CLASS_MASS_STORAGE:
181 return "LIBUSB_CLASS_MASS_STORAGE";
182 case LIBUSB_CLASS_HUB:
183 return "LIBUSB_CLASS_HUB";
184 case LIBUSB_CLASS_DATA:
185 return "LIBUSB_CLASS_DATA";
186 case LIBUSB_CLASS_SMART_CARD:
187 return "LIBUSB_CLASS_SMART_CARD";
188 case LIBUSB_CLASS_CONTENT_SECURITY:
189 return "LIBUSB_CLASS_CONTENT_SECURITY";
190 case LIBUSB_CLASS_VIDEO:
191 return "LIBUSB_CLASS_VIDEO";
192 case LIBUSB_CLASS_PERSONAL_HEALTHCARE:
193 return "LIBUSB_CLASS_PERSONAL_HEALTHCARE";
194 case LIBUSB_CLASS_DIAGNOSTIC_DEVICE:
195 return "LIBUSB_CLASS_DIAGNOSTIC_DEVICE";
196 case LIBUSB_CLASS_WIRELESS:
197 return "LIBUSB_CLASS_WIRELESS";
198 case LIBUSB_CLASS_APPLICATION:
199 return "LIBUSB_CLASS_APPLICATION";
200 case LIBUSB_CLASS_VENDOR_SPEC:
201 return "LIBUSB_CLASS_VENDOR_SPEC";
202 default:
203 return "UNKNOWN_DEVICE_CLASS";
204 }
205}
206
207static ASYNC_TRANSFER_USER_DATA*
208async_transfer_user_data_new(IUDEVICE* idev, UINT32 MessageId, size_t offset, size_t BufferSize,
209 const BYTE* data, size_t packetSize, BOOL NoAck, int transferDir,
210 t_isoch_transfer_cb cb, GENERIC_CHANNEL_CALLBACK* callback)
211{
212 ASYNC_TRANSFER_USER_DATA* user_data = nullptr;
213 UDEVICE* pdev = (UDEVICE*)idev;
214
215 if (BufferSize > UINT32_MAX)
216 return nullptr;
217
218 user_data = calloc(1, sizeof(ASYNC_TRANSFER_USER_DATA));
219 if (!user_data)
220 return nullptr;
221
222 user_data->data = Stream_New(nullptr, offset + BufferSize + packetSize);
223
224 if (!user_data->data)
225 {
226 free(user_data);
227 return nullptr;
228 }
229
230 Stream_Seek(user_data->data, offset); /* Skip header offset */
231 if (data)
232 memcpy(Stream_Pointer(user_data->data), data, BufferSize);
233
234 user_data->noack = NoAck;
235 user_data->transferDir = transferDir;
236 user_data->cb = cb;
237 user_data->callback = callback;
238 user_data->idev = idev;
239 user_data->MessageId = MessageId;
240
241 user_data->queue = pdev->request_queue;
242
243 return user_data;
244}
245
246static void async_transfer_user_data_free(ASYNC_TRANSFER_USER_DATA* user_data)
247{
248 if (user_data)
249 {
250 Stream_Free(user_data->data, TRUE);
251 free(user_data);
252 }
253}
254
255static void LIBUSB_CALL func_iso_callback(struct libusb_transfer* transfer)
256{
257 ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
258 const UINT32 streamID = stream_id_from_buffer(transfer);
259 wArrayList* list = user_data->queue;
260
261 ArrayList_Lock(list);
262 switch (transfer->status)
263 {
264 case LIBUSB_TRANSFER_COMPLETED:
265 {
266 UINT32 index = 0;
267 BYTE* dataStart = Stream_Pointer(user_data->data);
268 if (!Stream_SetPosition(user_data->data,
269 40)) /* TS_URB_ISOCH_TRANSFER_RESULT IsoPacket offset */
270 break;
271
272 for (uint32_t i = 0; i < WINPR_ASSERTING_INT_CAST(uint32_t, transfer->num_iso_packets);
273 i++)
274 {
275 const UINT32 act_len = transfer->iso_packet_desc[i].actual_length;
276 Stream_Write_UINT32(user_data->data, index);
277 Stream_Write_UINT32(user_data->data, act_len);
278 Stream_Write_UINT32(user_data->data, transfer->iso_packet_desc[i].status);
279
280 if (transfer->iso_packet_desc[i].status != USBD_STATUS_SUCCESS)
281 user_data->ErrorCount++;
282 else
283 {
284 const unsigned char* packetBuffer =
285 libusb_get_iso_packet_buffer_simple(transfer, i);
286 BYTE* data = dataStart + index;
287
288 if (data != packetBuffer)
289 memmove(data, packetBuffer, act_len);
290
291 index += act_len;
292 }
293 }
294 user_data->OutputBufferSize = index;
295 }
296 /* fallthrough */
297 WINPR_FALLTHROUGH
298 case LIBUSB_TRANSFER_CANCELLED:
299 /* fallthrough */
300 WINPR_FALLTHROUGH
301 case LIBUSB_TRANSFER_TIMED_OUT:
302 /* fallthrough */
303 WINPR_FALLTHROUGH
304 case LIBUSB_TRANSFER_ERROR:
305 {
306 const UINT32 InterfaceId =
307 ((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
308
309 if (list_contains(list, streamID))
310 {
311 if (!user_data->noack)
312 {
313 const UINT32 RequestID = streamID & INTERFACE_ID_MASK;
314 user_data->cb(user_data->idev, user_data->callback, user_data->data,
315 InterfaceId, user_data->noack, user_data->MessageId, RequestID,
316 WINPR_ASSERTING_INT_CAST(uint32_t, transfer->num_iso_packets),
317 transfer->status, user_data->StartFrame, user_data->ErrorCount,
318 user_data->OutputBufferSize, user_data->transferDir);
319 user_data->data = nullptr;
320 }
321 ArrayList_Remove(list, transfer);
322 }
323 }
324 break;
325 default:
326 break;
327 }
328 ArrayList_Unlock(list);
329}
330
331static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig,
332 MSUSB_CONFIG_DESCRIPTOR* MsConfig,
333 UINT32 EndpointAddress)
334{
335 MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces;
336 const LIBUSB_INTERFACE* interface = LibusbConfig->interface;
337
338 for (UINT32 inum = 0; inum < MsConfig->NumInterfaces; inum++)
339 {
340 BYTE alt = MsInterfaces[inum]->AlternateSetting;
341 const LIBUSB_ENDPOINT_DESCEIPTOR* endpoint = interface[inum].altsetting[alt].endpoint;
342
343 for (UINT32 pnum = 0; pnum < MsInterfaces[inum]->NumberOfPipes; pnum++)
344 {
345 if (endpoint[pnum].bEndpointAddress == EndpointAddress)
346 {
347 return &endpoint[pnum];
348 }
349 }
350 }
351
352 return nullptr;
353}
354
355static void LIBUSB_CALL func_bulk_transfer_cb(struct libusb_transfer* transfer)
356{
357 ASYNC_TRANSFER_USER_DATA* user_data = nullptr;
358 uint32_t streamID = 0;
359 wArrayList* list = nullptr;
360
361 user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
362 if (!user_data)
363 {
364 WLog_ERR(TAG, "Invalid transfer->user_data!");
365 return;
366 }
367 list = user_data->queue;
368 ArrayList_Lock(list);
369 streamID = stream_id_from_buffer(transfer);
370
371 if (list_contains(list, streamID))
372 {
373 const UINT32 InterfaceId =
374 ((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
375 const UINT32 RequestID = streamID & INTERFACE_ID_MASK;
376
377 user_data->cb(user_data->idev, user_data->callback, user_data->data, InterfaceId,
378 user_data->noack, user_data->MessageId, RequestID,
379 WINPR_ASSERTING_INT_CAST(uint32_t, transfer->num_iso_packets),
380 transfer->status, user_data->StartFrame, user_data->ErrorCount,
381 WINPR_ASSERTING_INT_CAST(uint32_t, transfer->actual_length),
382 user_data->transferDir);
383 user_data->data = nullptr;
384 ArrayList_Remove(list, transfer);
385 }
386 ArrayList_Unlock(list);
387}
388
389static BOOL func_set_usbd_status(URBDRC_PLUGIN* urbdrc, UDEVICE* pdev, UINT32* status,
390 int err_result)
391{
392 if (!urbdrc || !status)
393 return FALSE;
394
395 switch (err_result)
396 {
397 case LIBUSB_SUCCESS:
398 *status = USBD_STATUS_SUCCESS;
399 break;
400
401 case LIBUSB_ERROR_IO:
402 *status = USBD_STATUS_STALL_PID;
403 break;
404
405 case LIBUSB_ERROR_INVALID_PARAM:
406 *status = USBD_STATUS_INVALID_PARAMETER;
407 break;
408
409 case LIBUSB_ERROR_ACCESS:
410 *status = USBD_STATUS_NOT_ACCESSED;
411 break;
412
413 case LIBUSB_ERROR_NO_DEVICE:
414 *status = USBD_STATUS_DEVICE_GONE;
415
416 if (pdev)
417 {
418 if (!(pdev->status & URBDRC_DEVICE_NOT_FOUND))
419 pdev->status |= URBDRC_DEVICE_NOT_FOUND;
420 }
421
422 break;
423
424 case LIBUSB_ERROR_NOT_FOUND:
425 *status = USBD_STATUS_STALL_PID;
426 break;
427
428 case LIBUSB_ERROR_BUSY:
429 *status = USBD_STATUS_STALL_PID;
430 break;
431
432 case LIBUSB_ERROR_TIMEOUT:
433 *status = USBD_STATUS_TIMEOUT;
434 break;
435
436 case LIBUSB_ERROR_OVERFLOW:
437 *status = USBD_STATUS_STALL_PID;
438 break;
439
440 case LIBUSB_ERROR_PIPE:
441 *status = USBD_STATUS_STALL_PID;
442 break;
443
444 case LIBUSB_ERROR_INTERRUPTED:
445 *status = USBD_STATUS_STALL_PID;
446 break;
447
448 case LIBUSB_ERROR_NO_MEM:
449 *status = USBD_STATUS_NO_MEMORY;
450 break;
451
452 case LIBUSB_ERROR_NOT_SUPPORTED:
453 *status = USBD_STATUS_NOT_SUPPORTED;
454 break;
455
456 case LIBUSB_ERROR_OTHER:
457 *status = USBD_STATUS_STALL_PID;
458 break;
459
460 default:
461 *status = USBD_STATUS_SUCCESS;
462 break;
463 }
464
465 return TRUE;
466}
467
468static int func_config_release_all_interface(URBDRC_PLUGIN* urbdrc,
469 LIBUSB_DEVICE_HANDLE* libusb_handle,
470 UINT32 NumInterfaces)
471{
472 if (NumInterfaces > INT32_MAX)
473 return -1;
474 for (INT32 i = 0; i < (INT32)NumInterfaces; i++)
475 {
476 int ret = libusb_release_interface(libusb_handle, i);
477
478 if (log_libusb_result(urbdrc->log, WLOG_WARN, "libusb_release_interface", ret))
479 return -1;
480 }
481
482 return 0;
483}
484
485static int func_claim_all_interface(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE_HANDLE* libusb_handle,
486 int NumInterfaces)
487{
488 int ret = 0;
489
490 for (int i = 0; i < NumInterfaces; i++)
491 {
492 ret = libusb_claim_interface(libusb_handle, i);
493
494 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_claim_interface", ret))
495 return -1;
496 }
497
498 return 0;
499}
500
501static LIBUSB_DEVICE* udev_get_libusb_dev(libusb_context* context, uint8_t bus_number,
502 uint8_t dev_number)
503{
504 LIBUSB_DEVICE** libusb_list = nullptr;
505 LIBUSB_DEVICE* device = nullptr;
506 const ssize_t total_device = libusb_get_device_list(context, &libusb_list);
507
508 for (ssize_t i = 0; i < total_device; i++)
509 {
510 LIBUSB_DEVICE* dev = libusb_list[i];
511 if ((bus_number == libusb_get_bus_number(dev)) &&
512 (dev_number == libusb_get_device_address(dev)))
513 device = dev;
514 else
515 libusb_unref_device(dev);
516 }
517
518 libusb_free_device_list(libusb_list, 0);
519 return device;
520}
521
522static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* libusb_dev)
523{
524 int ret = 0;
525 LIBUSB_DEVICE_DESCRIPTOR* descriptor =
526 (LIBUSB_DEVICE_DESCRIPTOR*)calloc(1, sizeof(LIBUSB_DEVICE_DESCRIPTOR));
527 if (!descriptor)
528 return nullptr;
529 ret = libusb_get_device_descriptor(libusb_dev, descriptor);
530
531 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_get_device_descriptor", ret))
532 {
533 free(descriptor);
534 return nullptr;
535 }
536
537 return descriptor;
538}
539
540static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BYTE AlternateSetting)
541{
542 UDEVICE* pdev = (UDEVICE*)idev;
543
544 if (!pdev || !pdev->urbdrc)
545 return -1;
546
547 URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
548
549 const int error =
550 libusb_set_interface_alt_setting(pdev->libusb_handle, InterfaceNumber, AlternateSetting);
551
552 log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_interface_alt_setting", error);
553
554 return error;
555}
556
558libusb_udev_complete_msconfig_setup(IUDEVICE* idev, MSUSB_CONFIG_DESCRIPTOR* MsConfig)
559{
560 UDEVICE* pdev = (UDEVICE*)idev;
561 UINT32 MsOutSize = 0;
562
563 if (!pdev || !pdev->LibusbConfig || !pdev->urbdrc || !MsConfig)
564 return nullptr;
565
566 URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
567 LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig = pdev->LibusbConfig;
568
569 if (LibusbConfig->bNumInterfaces != MsConfig->NumInterfaces)
570 {
571 WLog_Print(urbdrc->log, WLOG_ERROR,
572 "Select Configuration: Libusb NumberInterfaces(%" PRIu8 ") is different "
573 "with MsConfig NumberInterfaces(%" PRIu32 ")",
574 LibusbConfig->bNumInterfaces, MsConfig->NumInterfaces);
575 return nullptr;
576 }
577
578 /* replace MsPipes for libusb */
579 MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces;
580
581 for (UINT32 inum = 0; inum < MsConfig->NumInterfaces; inum++)
582 {
583 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = MsInterfaces[inum];
584 if (MsInterface->InterfaceNumber >= MsConfig->NumInterfaces)
585 {
586 WLog_Print(urbdrc->log, WLOG_ERROR,
587 "MSUSB_CONFIG_DESCRIPTOR::NumInterfaces (%" PRIu32
588 " <= MSUSB_INTERFACE_DESCRIPTOR::InterfaceNumber( %" PRIu8 ")",
589 MsConfig->NumInterfaces, MsInterface->InterfaceNumber);
590 return nullptr;
591 }
592
593 const LIBUSB_INTERFACE* LibusbInterface =
594 &LibusbConfig->interface[MsInterface->InterfaceNumber];
595 if (MsInterface->AlternateSetting >= LibusbInterface->num_altsetting)
596 {
597 WLog_Print(urbdrc->log, WLOG_ERROR,
598 "LIBUSB_INTERFACE::num_altsetting (%" PRId32
599 " <= MSUSB_INTERFACE_DESCRIPTOR::AlternateSetting( %" PRIu8 ")",
600 LibusbInterface->num_altsetting, MsInterface->AlternateSetting);
601 return nullptr;
602 }
603 }
604
605 for (UINT32 inum = 0; inum < MsConfig->NumInterfaces; inum++)
606 {
607 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = MsInterfaces[inum];
608
609 /* get libusb's number of endpoints */
610 const LIBUSB_INTERFACE* LibusbInterface =
611 &LibusbConfig->interface[MsInterface->InterfaceNumber];
612 const LIBUSB_INTERFACE_DESCRIPTOR* LibusbAltsetting =
613 &LibusbInterface->altsetting[MsInterface->AlternateSetting];
614 const BYTE LibusbNumEndpoint = LibusbAltsetting->bNumEndpoints;
615 MSUSB_PIPE_DESCRIPTOR** t_MsPipes =
616 (MSUSB_PIPE_DESCRIPTOR**)calloc(LibusbNumEndpoint, sizeof(MSUSB_PIPE_DESCRIPTOR*));
617
618 for (UINT32 pnum = 0; pnum < LibusbNumEndpoint; pnum++)
619 {
620 MSUSB_PIPE_DESCRIPTOR* t_MsPipe =
621 (MSUSB_PIPE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_PIPE_DESCRIPTOR));
622
623 if (pnum < MsInterface->NumberOfPipes && MsInterface->MsPipes)
624 {
625 MSUSB_PIPE_DESCRIPTOR* MsPipe = MsInterface->MsPipes[pnum];
626 t_MsPipe->MaximumPacketSize = MsPipe->MaximumPacketSize;
627 t_MsPipe->MaximumTransferSize = MsPipe->MaximumTransferSize;
628 t_MsPipe->PipeFlags = MsPipe->PipeFlags;
629 }
630 else
631 {
632 t_MsPipe->MaximumPacketSize = 0;
633 t_MsPipe->MaximumTransferSize = 0xffffffff;
634 t_MsPipe->PipeFlags = 0;
635 }
636
637 t_MsPipe->PipeHandle = 0;
638 t_MsPipe->bEndpointAddress = 0;
639 t_MsPipe->bInterval = 0;
640 t_MsPipe->PipeType = 0;
641 t_MsPipe->InitCompleted = 0;
642 t_MsPipes[pnum] = t_MsPipe;
643 }
644
645 msusb_mspipes_replace(MsInterface, t_MsPipes, LibusbNumEndpoint);
646 }
647
648 /* setup configuration */
649 MsOutSize = 8;
650 /* ConfigurationHandle: 4 bytes
651 * ---------------------------------------------------------------
652 * ||<<< 1 byte >>>|<<< 1 byte >>>|<<<<<<<<<< 2 byte >>>>>>>>>>>||
653 * || bus_number | dev_number | bConfigurationValue ||
654 * ---------------------------------------------------------------
655 * ***********************/
656 MsConfig->ConfigurationHandle = (uint32_t)MsConfig->bConfigurationValue |
657 ((uint32_t)pdev->bus_number << 24) |
658 (((uint32_t)pdev->dev_number << 16) & 0xFF0000);
659 MsInterfaces = MsConfig->MsInterfaces;
660
661 for (UINT32 inum = 0; inum < MsConfig->NumInterfaces; inum++)
662 {
663 MsOutSize += 16;
664 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = MsInterfaces[inum];
665 /* get libusb's interface */
666 const LIBUSB_INTERFACE* LibusbInterface =
667 &LibusbConfig->interface[MsInterface->InterfaceNumber];
668 const LIBUSB_INTERFACE_DESCRIPTOR* LibusbAltsetting =
669 &LibusbInterface->altsetting[MsInterface->AlternateSetting];
670 /* InterfaceHandle: 4 bytes
671 * ---------------------------------------------------------------
672 * ||<<< 1 byte >>>|<<< 1 byte >>>|<<< 1 byte >>>|<<< 1 byte >>>||
673 * || bus_number | dev_number | altsetting | interfaceNum ||
674 * ---------------------------------------------------------------
675 * ***********************/
676 MsInterface->InterfaceHandle =
677 WINPR_ASSERTING_INT_CAST(UINT32, (LibusbAltsetting->bInterfaceNumber |
678 (LibusbAltsetting->bAlternateSetting << 8) |
679 (pdev->dev_number << 16) | (pdev->bus_number << 24)));
680 const size_t len = 16 + (MsInterface->NumberOfPipes * 20);
681 MsInterface->Length = WINPR_ASSERTING_INT_CAST(UINT16, len);
682 MsInterface->bInterfaceClass = LibusbAltsetting->bInterfaceClass;
683 MsInterface->bInterfaceSubClass = LibusbAltsetting->bInterfaceSubClass;
684 MsInterface->bInterfaceProtocol = LibusbAltsetting->bInterfaceProtocol;
685 MsInterface->InitCompleted = 1;
686 MSUSB_PIPE_DESCRIPTOR** MsPipes = MsInterface->MsPipes;
687 const BYTE LibusbNumEndpoint = LibusbAltsetting->bNumEndpoints;
688
689 for (UINT32 pnum = 0; pnum < LibusbNumEndpoint; pnum++)
690 {
691 MsOutSize += 20;
692
693 MSUSB_PIPE_DESCRIPTOR* MsPipe = MsPipes[pnum];
694 /* get libusb's endpoint */
695 const LIBUSB_ENDPOINT_DESCEIPTOR* LibusbEndpoint = &LibusbAltsetting->endpoint[pnum];
696 /* PipeHandle: 4 bytes
697 * ---------------------------------------------------------------
698 * ||<<< 1 byte >>>|<<< 1 byte >>>|<<<<<<<<<< 2 byte >>>>>>>>>>>||
699 * || bus_number | dev_number | bEndpointAddress ||
700 * ---------------------------------------------------------------
701 * ***********************/
702 MsPipe->PipeHandle = LibusbEndpoint->bEndpointAddress |
703 (((uint32_t)pdev->dev_number << 16) & 0xFF0000) |
704 (((uint32_t)pdev->bus_number << 24) & 0xFF000000);
705 /* count endpoint max packet size */
706 unsigned max = LibusbEndpoint->wMaxPacketSize & 0x07ff;
707 BYTE attr = LibusbEndpoint->bmAttributes;
708
709 if ((attr & 0x3) == 1 || (attr & 0x3) == 3)
710 {
711 max *= (1 + ((LibusbEndpoint->wMaxPacketSize >> 11) & 3));
712 }
713
714 MsPipe->MaximumPacketSize = WINPR_ASSERTING_INT_CAST(uint16_t, max);
715 MsPipe->bEndpointAddress = LibusbEndpoint->bEndpointAddress;
716 MsPipe->bInterval = LibusbEndpoint->bInterval;
717 MsPipe->PipeType = attr & 0x3;
718 MsPipe->InitCompleted = 1;
719 }
720 }
721
722 MsConfig->MsOutSize = WINPR_ASSERTING_INT_CAST(int, MsOutSize);
723 MsConfig->InitCompleted = 1;
724
725 /* replace device's MsConfig */
726 if (MsConfig != pdev->MsConfig)
727 {
728 msusb_msconfig_free(pdev->MsConfig);
729 pdev->MsConfig = MsConfig;
730 }
731
732 return MsConfig;
733}
734
735static int libusb_udev_select_configuration(IUDEVICE* idev, UINT32 bConfigurationValue)
736{
737 UDEVICE* pdev = (UDEVICE*)idev;
738 MSUSB_CONFIG_DESCRIPTOR* MsConfig = nullptr;
739 LIBUSB_DEVICE_HANDLE* libusb_handle = nullptr;
740 LIBUSB_DEVICE* libusb_dev = nullptr;
741 URBDRC_PLUGIN* urbdrc = nullptr;
742 LIBUSB_CONFIG_DESCRIPTOR** LibusbConfig = nullptr;
743 int ret = 0;
744
745 if (!pdev || !pdev->MsConfig || !pdev->LibusbConfig || !pdev->urbdrc)
746 return -1;
747
748 urbdrc = pdev->urbdrc;
749 MsConfig = pdev->MsConfig;
750 libusb_handle = pdev->libusb_handle;
751 libusb_dev = pdev->libusb_dev;
752 LibusbConfig = &pdev->LibusbConfig;
753
754 if (MsConfig->InitCompleted)
755 {
756 func_config_release_all_interface(pdev->urbdrc, libusb_handle,
757 (*LibusbConfig)->bNumInterfaces);
758 }
759
760 /* The configuration value -1 is mean to put the device in unconfigured state. */
761 if (bConfigurationValue == 0)
762 ret = libusb_set_configuration(libusb_handle, -1);
763 else
764 ret = libusb_set_configuration(libusb_handle,
765 WINPR_ASSERTING_INT_CAST(int, bConfigurationValue));
766
767 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_configuration", ret))
768 {
769 func_claim_all_interface(urbdrc, libusb_handle, (*LibusbConfig)->bNumInterfaces);
770 return -1;
771 }
772 else
773 {
774 ret = libusb_get_active_config_descriptor(libusb_dev, LibusbConfig);
775
776 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_set_configuration", ret))
777 {
778 func_claim_all_interface(urbdrc, libusb_handle, (*LibusbConfig)->bNumInterfaces);
779 return -1;
780 }
781 }
782
783 func_claim_all_interface(urbdrc, libusb_handle, (*LibusbConfig)->bNumInterfaces);
784 return 0;
785}
786
787static int libusb_udev_control_pipe_request(IUDEVICE* idev, WINPR_ATTR_UNUSED UINT32 RequestId,
788 UINT32 EndpointAddress, UINT32* UsbdStatus, int command)
789{
790 int error = 0;
791 UDEVICE* pdev = (UDEVICE*)idev;
792
793 WINPR_ASSERT(EndpointAddress <= UINT8_MAX);
794 /*
795 pdev->request_queue->register_request(pdev->request_queue, RequestId, nullptr, 0);
796 */
797 switch (command)
798 {
799 case PIPE_CANCEL:
801 idev->cancel_all_transfer_request(idev);
802 // dummy_wait_s_obj(1);
804 /*
805 uint8_t request_type, uint8_t bRequest,
806 */
807 error = libusb_control_transfer(pdev->libusb_handle,
808 (uint8_t)LIBUSB_ENDPOINT_OUT |
809 (uint8_t)LIBUSB_RECIPIENT_ENDPOINT,
810 LIBUSB_REQUEST_SET_FEATURE, ENDPOINT_HALT,
811 (uint16_t)EndpointAddress, nullptr, 0, 1000);
812 break;
813
814 case PIPE_RESET:
815 idev->cancel_all_transfer_request(idev);
816 error = libusb_clear_halt(pdev->libusb_handle, (uint8_t)EndpointAddress);
817 // func_set_usbd_status(pdev, UsbdStatus, error);
818 break;
819
820 default:
821 error = -0xff;
822 break;
823 }
824
825 *UsbdStatus = 0;
826 return error;
827}
828
829static UINT32 libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextType,
830 UINT16 LocaleId, UINT8* BufferSize,
831 BYTE* Buffer)
832{
833 UDEVICE* pdev = (UDEVICE*)idev;
834 LIBUSB_DEVICE_DESCRIPTOR* devDescriptor = nullptr;
835 const char strDesc[] = "Generic Usb String";
836 char deviceLocation[25] = WINPR_C_ARRAY_INIT;
837 BYTE bus_number = 0;
838 BYTE device_address = 0;
839 int ret = 0;
840 URBDRC_PLUGIN* urbdrc = nullptr;
841 WCHAR* text = (WCHAR*)Buffer;
842 BYTE slen = 0;
843 BYTE locale = 0;
844 const UINT8 inSize = *BufferSize;
845
846 *BufferSize = 0;
847 if (!pdev || !pdev->devDescriptor || !pdev->urbdrc)
848 return ERROR_INVALID_DATA;
849
850 urbdrc = pdev->urbdrc;
851 devDescriptor = pdev->devDescriptor;
852
853 switch (TextType)
854 {
855 case DeviceTextDescription:
856 {
857 BYTE data[0x100] = WINPR_C_ARRAY_INIT;
858 ret = libusb_get_string_descriptor(pdev->libusb_handle, devDescriptor->iProduct,
859 LocaleId, data, 0xFF);
860 /* The returned data in the buffer is:
861 * 1 byte length of following data
862 * 1 byte descriptor type, must be 0x03 for strings
863 * n WCHAR unicode string (of length / 2 characters) including '\0'
864 */
865 slen = data[0];
866 locale = data[1];
867
868 if ((ret <= 0) || (ret <= 4) || (slen <= 4) || (locale != LIBUSB_DT_STRING) ||
869 (ret > UINT8_MAX))
870 {
871 const char* msg = "SHORT_DESCRIPTOR";
872 if (ret < 0)
873 msg = libusb_error_name(ret);
874 WLog_Print(urbdrc->log, WLOG_DEBUG,
875 "libusb_get_string_descriptor: "
876 "%s [%d], iProduct: %" PRIu8 "!",
877 msg, ret, devDescriptor->iProduct);
878
879 size_t len = MIN(sizeof(strDesc), inSize);
880 for (size_t i = 0; i < len; i++)
881 text[i] = (WCHAR)strDesc[i];
882
883 *BufferSize = (BYTE)(len * sizeof(WCHAR));
884 }
885 else
886 {
887 size_t maxlen = inSize;
888 size_t len = 0;
889 if (inSize > sizeof(WCHAR))
890 {
891 maxlen -= sizeof(WCHAR);
892
893 /* ret and slen should be equals, but you never know creativity
894 * of device manufacturers...
895 * So also check the string length returned as server side does
896 * not honor strings with multi '\0' characters well.
897 */
898 const size_t rchar =
899 _wcsnlen((WCHAR*)&data[2], (sizeof(data) / sizeof(WCHAR)) - 1);
900 len = MIN((BYTE)ret - 2, slen);
901 len = MIN(len, rchar * sizeof(WCHAR));
902 len = MIN(len, maxlen);
903
904 memcpy(Buffer, &data[2], len);
905
906 /* Just as above, the returned WCHAR string should be '\0'
907 * terminated, but never trust hardware to conform to specs... */
908 if (Buffer[len] != '\0')
909 {
910 Buffer[len++] = '\0';
911 Buffer[len++] = '\0';
912 }
913 }
914 *BufferSize = (BYTE)len;
915 }
916 }
917 break;
918
919 case DeviceTextLocationInformation:
920 {
921 bus_number = libusb_get_bus_number(pdev->libusb_dev);
922 device_address = libusb_get_device_address(pdev->libusb_dev);
923 (void)sprintf_s(deviceLocation, sizeof(deviceLocation),
924 "Port_#%04" PRIu8 ".Hub_#%04" PRIu8 "", device_address, bus_number);
925
926 size_t len = strnlen(deviceLocation,
927 MIN(sizeof(deviceLocation), (inSize > 0) ? inSize - 1U : 0));
928 for (size_t i = 0; i < len; i++)
929 text[i] = (WCHAR)deviceLocation[i];
930 text[len++] = '\0';
931 *BufferSize = (UINT8)(len * sizeof(WCHAR));
932 }
933 break;
934
935 default:
936 WLog_Print(urbdrc->log, WLOG_DEBUG, "Query Text: unknown TextType %" PRIu32 "",
937 TextType);
938 return ERROR_INVALID_DATA;
939 }
940
941 return S_OK;
942}
943
944static int libusb_udev_os_feature_descriptor_request(IUDEVICE* idev,
945 WINPR_ATTR_UNUSED UINT32 RequestId,
946 BYTE Recipient, BYTE InterfaceNumber,
947 BYTE Ms_PageIndex, UINT16 Ms_featureDescIndex,
948 UINT32* UsbdStatus, UINT32* BufferSize,
949 BYTE* Buffer, UINT32 Timeout)
950{
951 UDEVICE* pdev = (UDEVICE*)idev;
952 BYTE ms_string_desc[0x13] = WINPR_C_ARRAY_INIT;
953 int error = 0;
954
955 WINPR_ASSERT(idev);
956 WINPR_ASSERT(UsbdStatus);
957 WINPR_ASSERT(BufferSize);
958 WINPR_ASSERT(*BufferSize <= UINT16_MAX);
959 const UINT16 requestedSize = (UINT16)*BufferSize;
960 *BufferSize = 0;
961
962 /*
963 pdev->request_queue->register_request(pdev->request_queue, RequestId, nullptr, 0);
964 */
965 error = libusb_control_transfer(pdev->libusb_handle, LIBUSB_ENDPOINT_IN | Recipient,
966 LIBUSB_REQUEST_GET_DESCRIPTOR, 0x03ee, 0, ms_string_desc, 0x12,
967 Timeout);
968
969 log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", error);
970
971 if (error > 0)
972 {
973 const BYTE bMS_Vendorcode = ms_string_desc[16];
975 error = libusb_control_transfer(
976 pdev->libusb_handle,
977 (uint8_t)LIBUSB_ENDPOINT_IN | (uint8_t)LIBUSB_REQUEST_TYPE_VENDOR | Recipient,
978 bMS_Vendorcode, (UINT16)((InterfaceNumber << 8) | Ms_PageIndex), Ms_featureDescIndex,
979 Buffer, requestedSize, Timeout);
980 log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", error);
981
982 if (error >= 0)
983 *BufferSize = (UINT32)error;
984 }
985
986 if (error < 0)
987 *UsbdStatus = USBD_STATUS_STALL_PID;
988 else
989 *UsbdStatus = USBD_STATUS_SUCCESS;
990
991 return ERROR_SUCCESS;
992}
993
994static int libusb_udev_query_device_descriptor(IUDEVICE* idev, int offset)
995{
996 UDEVICE* pdev = (UDEVICE*)idev;
997
998 switch (offset)
999 {
1000 case B_LENGTH:
1001 return pdev->devDescriptor->bLength;
1002
1003 case B_DESCRIPTOR_TYPE:
1004 return pdev->devDescriptor->bDescriptorType;
1005
1006 case BCD_USB:
1007 return pdev->devDescriptor->bcdUSB;
1008
1009 case B_DEVICE_CLASS:
1010 return pdev->devDescriptor->bDeviceClass;
1011
1012 case B_DEVICE_SUBCLASS:
1013 return pdev->devDescriptor->bDeviceSubClass;
1014
1015 case B_DEVICE_PROTOCOL:
1016 return pdev->devDescriptor->bDeviceProtocol;
1017
1018 case B_MAX_PACKET_SIZE0:
1019 return pdev->devDescriptor->bMaxPacketSize0;
1020
1021 case ID_VENDOR:
1022 return pdev->devDescriptor->idVendor;
1023
1024 case ID_PRODUCT:
1025 return pdev->devDescriptor->idProduct;
1026
1027 case BCD_DEVICE:
1028 return pdev->devDescriptor->bcdDevice;
1029
1030 case I_MANUFACTURER:
1031 return pdev->devDescriptor->iManufacturer;
1032
1033 case I_PRODUCT:
1034 return pdev->devDescriptor->iProduct;
1035
1036 case I_SERIAL_NUMBER:
1037 return pdev->devDescriptor->iSerialNumber;
1038
1039 case B_NUM_CONFIGURATIONS:
1040 return pdev->devDescriptor->bNumConfigurations;
1041
1042 default:
1043 return 0;
1044 }
1045}
1046
1047static BOOL libusb_udev_detach_kernel_driver(IUDEVICE* idev)
1048{
1049 int err = 0;
1050 UDEVICE* pdev = (UDEVICE*)idev;
1051 URBDRC_PLUGIN* urbdrc = nullptr;
1052
1053 if (!pdev || !pdev->LibusbConfig || !pdev->libusb_handle || !pdev->urbdrc)
1054 return FALSE;
1055
1056#ifdef _WIN32
1057 return TRUE;
1058#else
1059 urbdrc = pdev->urbdrc;
1060
1061 if ((pdev->status & URBDRC_DEVICE_DETACH_KERNEL) == 0)
1062 {
1063 for (int i = 0; i < pdev->LibusbConfig->bNumInterfaces; i++)
1064 {
1065 err = libusb_kernel_driver_active(pdev->libusb_handle, i);
1066 log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_kernel_driver_active", err);
1067
1068 if (err)
1069 {
1070 err = libusb_detach_kernel_driver(pdev->libusb_handle, i);
1071 log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_detach_kernel_driver", err);
1072 }
1073 }
1074
1075 pdev->status |= URBDRC_DEVICE_DETACH_KERNEL;
1076 }
1077
1078 return TRUE;
1079#endif
1080}
1081
1082static BOOL libusb_udev_attach_kernel_driver(IUDEVICE* idev)
1083{
1084 int err = 0;
1085 UDEVICE* pdev = (UDEVICE*)idev;
1086
1087 if (!pdev || !pdev->LibusbConfig || !pdev->libusb_handle || !pdev->urbdrc)
1088 return FALSE;
1089
1090 for (int i = 0; i < pdev->LibusbConfig->bNumInterfaces && err != LIBUSB_ERROR_NO_DEVICE; i++)
1091 {
1092 err = libusb_release_interface(pdev->libusb_handle, i);
1093
1094 log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_release_interface", err);
1095
1096#ifndef _WIN32
1097 if (err != LIBUSB_ERROR_NO_DEVICE)
1098 {
1099 err = libusb_attach_kernel_driver(pdev->libusb_handle, i);
1100 log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_attach_kernel_driver if=%d",
1101 err, i);
1102 }
1103#endif
1104 }
1105
1106 return TRUE;
1107}
1108
1109static int libusb_udev_is_composite_device(IUDEVICE* idev)
1110{
1111 UDEVICE* pdev = (UDEVICE*)idev;
1112 return pdev->isCompositeDevice;
1113}
1114
1115static int libusb_udev_is_exist(IUDEVICE* idev)
1116{
1117 UDEVICE* pdev = (UDEVICE*)idev;
1118 return (pdev->status & URBDRC_DEVICE_NOT_FOUND) ? 0 : 1;
1119}
1120
1121static int libusb_udev_is_channel_closed(IUDEVICE* idev)
1122{
1123 UDEVICE* pdev = (UDEVICE*)idev;
1124 IUDEVMAN* udevman = nullptr;
1125 if (!pdev || !pdev->urbdrc)
1126 return 1;
1127
1128 udevman = pdev->urbdrc->udevman;
1129 if (udevman)
1130 {
1131 if (udevman->status & URBDRC_DEVICE_CHANNEL_CLOSED)
1132 return 1;
1133 }
1134
1135 if (pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED)
1136 return 1;
1137
1138 return 0;
1139}
1140
1141static int libusb_udev_is_already_send(IUDEVICE* idev)
1142{
1143 UDEVICE* pdev = (UDEVICE*)idev;
1144 return (pdev->status & URBDRC_DEVICE_ALREADY_SEND) ? 1 : 0;
1145}
1146
1147/* This is called from channel cleanup code.
1148 * Avoid double free, just remove the device and mark the channel closed. */
1149static void libusb_udev_mark_channel_closed(IUDEVICE* idev)
1150{
1151 UDEVICE* pdev = (UDEVICE*)idev;
1152 if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
1153 {
1154 URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
1155 const uint8_t busNr = idev->get_bus_number(idev);
1156 const uint8_t devNr = idev->get_dev_number(idev);
1157
1158 pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
1159 pdev->iface.cancel_all_transfer_request(&pdev->iface);
1160 if (!urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr))
1161 {
1162 WLog_Print(pdev->urbdrc->log, WLOG_WARN, "unregister_udevice failed for %d, %d", busNr,
1163 devNr);
1164 }
1165 }
1166}
1167
1168/* This is called by local events where the device is removed or in an error
1169 * state. Remove the device from redirection and close the channel. */
1170static void libusb_udev_channel_closed(IUDEVICE* idev)
1171{
1172 UDEVICE* pdev = (UDEVICE*)idev;
1173 if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
1174 {
1175 URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
1176 const uint8_t busNr = idev->get_bus_number(idev);
1177 const uint8_t devNr = idev->get_dev_number(idev);
1178 IWTSVirtualChannel* channel = nullptr;
1179
1180 if (pdev->channelManager)
1181 channel = IFCALLRESULT(nullptr, pdev->channelManager->FindChannelById,
1182 pdev->channelManager, pdev->channelID);
1183
1184 pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
1185
1186 if (channel)
1187 {
1188 const UINT rc = channel->Write(channel, 0, nullptr, nullptr);
1189 if (rc != CHANNEL_RC_OK)
1190 WLog_Print(urbdrc->log, WLOG_WARN, "channel->Write failed with %" PRIu32, rc);
1191 }
1192
1193 if (!urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr))
1194 WLog_Print(urbdrc->log, WLOG_WARN, "unregister_udevice failed for %d, %d", busNr,
1195 devNr);
1196 }
1197}
1198
1199static void libusb_udev_set_already_send(IUDEVICE* idev)
1200{
1201 UDEVICE* pdev = (UDEVICE*)idev;
1202 pdev->status |= URBDRC_DEVICE_ALREADY_SEND;
1203}
1204
1205static char* libusb_udev_get_path(IUDEVICE* idev)
1206{
1207 UDEVICE* pdev = (UDEVICE*)idev;
1208 return pdev->path;
1209}
1210
1211static int libusb_udev_query_device_port_status(IUDEVICE* idev, UINT32* UsbdStatus,
1212 UINT32* BufferSize, BYTE* Buffer)
1213{
1214 UDEVICE* pdev = (UDEVICE*)idev;
1215 int success = 0;
1216 int ret = 0;
1217 URBDRC_PLUGIN* urbdrc = nullptr;
1218
1219 if (!pdev || !pdev->urbdrc)
1220 return -1;
1221
1222 urbdrc = pdev->urbdrc;
1223
1224 if (pdev->hub_handle != nullptr)
1225 {
1226 ret = idev->control_transfer(
1227 idev, 0xffff, 0, 0,
1228 (uint8_t)LIBUSB_ENDPOINT_IN | (uint8_t)LIBUSB_REQUEST_TYPE_CLASS |
1229 (uint8_t)LIBUSB_RECIPIENT_OTHER,
1230 LIBUSB_REQUEST_GET_STATUS, 0, pdev->port_number, UsbdStatus, BufferSize, Buffer, 1000);
1231
1232 if (log_libusb_result(urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", ret))
1233 *BufferSize = 0;
1234 else
1235 {
1236 WLog_Print(urbdrc->log, WLOG_DEBUG,
1237 "PORT STATUS:0x%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "%02" PRIx8 "", Buffer[3],
1238 Buffer[2], Buffer[1], Buffer[0]);
1239 success = 1;
1240 }
1241 }
1242
1243 return success;
1244}
1245
1246static int libusb_udev_isoch_transfer(IUDEVICE* idev, GENERIC_CHANNEL_CALLBACK* callback,
1247 UINT32 MessageId, UINT32 RequestId, UINT32 EndpointAddress,
1248 WINPR_ATTR_UNUSED UINT32 TransferFlags, UINT32 StartFrame,
1249 UINT32 ErrorCount, BOOL NoAck,
1250 WINPR_ATTR_UNUSED const BYTE* packetDescriptorData,
1251 UINT32 NumberOfPackets, UINT32 BufferSize, const BYTE* Buffer,
1252 int transferDir, t_isoch_transfer_cb cb, UINT32 Timeout)
1253{
1254 int rc = 0;
1255 UINT32 iso_packet_size = 0;
1256 UDEVICE* pdev = (UDEVICE*)idev;
1257 ASYNC_TRANSFER_USER_DATA* user_data = nullptr;
1258 struct libusb_transfer* iso_transfer = nullptr;
1259 URBDRC_PLUGIN* urbdrc = nullptr;
1260 size_t outSize = (12ULL * NumberOfPackets);
1261 uint32_t streamID = 0x40000000 | RequestId;
1262
1263 if (!pdev || !pdev->urbdrc)
1264 return -1;
1265
1266 urbdrc = pdev->urbdrc;
1267 user_data = async_transfer_user_data_new(idev, MessageId, 48, BufferSize, Buffer,
1268 outSize + 1024, NoAck, transferDir, cb, callback);
1269
1270 if (!user_data)
1271 return -1;
1272
1273 user_data->ErrorCount = ErrorCount;
1274 user_data->StartFrame = StartFrame;
1275
1276 if (!Buffer)
1277 Stream_Seek(user_data->data, (12ULL * NumberOfPackets));
1278
1279 if (NumberOfPackets > 0)
1280 {
1281 iso_packet_size = BufferSize / NumberOfPackets;
1282 iso_transfer = libusb_alloc_transfer((int)NumberOfPackets);
1283 }
1284
1285 if (iso_transfer == nullptr)
1286 {
1287 WLog_Print(urbdrc->log, WLOG_ERROR,
1288 "Error: libusb_alloc_transfer [NumberOfPackets=%" PRIu32 ", BufferSize=%" PRIu32
1289 " ]",
1290 NumberOfPackets, BufferSize);
1291 async_transfer_user_data_free(user_data);
1292 return -1;
1293 }
1294
1296 libusb_fill_iso_transfer(
1297 iso_transfer, pdev->libusb_handle, WINPR_ASSERTING_INT_CAST(uint8_t, EndpointAddress),
1298 Stream_Pointer(user_data->data), WINPR_ASSERTING_INT_CAST(int, BufferSize),
1299 WINPR_ASSERTING_INT_CAST(int, NumberOfPackets), func_iso_callback, user_data, Timeout);
1300 set_stream_id_for_buffer(iso_transfer, streamID);
1301 libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size);
1302
1303 if (!ArrayList_Append(pdev->request_queue, iso_transfer))
1304 {
1305 WLog_Print(urbdrc->log, WLOG_WARN,
1306 "Failed to queue iso transfer, streamID %08" PRIx32 " already in use!",
1307 streamID);
1308 request_free(iso_transfer);
1309 return -1;
1310 }
1311 rc = libusb_submit_transfer(iso_transfer);
1312 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_submit_transfer", rc))
1313 return -1;
1314 return rc;
1315}
1316
1317static BOOL libusb_udev_control_transfer(IUDEVICE* idev, WINPR_ATTR_UNUSED UINT32 RequestId,
1318 WINPR_ATTR_UNUSED UINT32 EndpointAddress,
1319 WINPR_ATTR_UNUSED UINT32 TransferFlags, BYTE bmRequestType,
1320 BYTE Request, UINT16 Value, UINT16 Index,
1321 UINT32* UrbdStatus, UINT32* BufferSize, BYTE* Buffer,
1322 UINT32 Timeout)
1323{
1324 int status = 0;
1325 UDEVICE* pdev = (UDEVICE*)idev;
1326
1327 WINPR_ASSERT(BufferSize);
1328 WINPR_ASSERT(*BufferSize <= UINT16_MAX);
1329
1330 if (!pdev || !pdev->urbdrc)
1331 return FALSE;
1332
1333 status = libusb_control_transfer(pdev->libusb_handle, bmRequestType, Request, Value, Index,
1334 Buffer, (UINT16)*BufferSize, Timeout);
1335
1336 if (status >= 0)
1337 *BufferSize = (UINT32)status;
1338 else
1339 {
1340 *BufferSize = 0;
1341 log_libusb_result(pdev->urbdrc->log, WLOG_ERROR, "libusb_control_transfer", status);
1342 }
1343
1344 if (!func_set_usbd_status(pdev->urbdrc, pdev, UrbdStatus, status))
1345 return FALSE;
1346
1347 return TRUE;
1348}
1349
1350static int libusb_udev_bulk_or_interrupt_transfer(
1351 IUDEVICE* idev, GENERIC_CHANNEL_CALLBACK* callback, UINT32 MessageId, UINT32 RequestId,
1352 UINT32 EndpointAddress, UINT32 TransferFlags, BOOL NoAck, UINT32 BufferSize, const BYTE* data,
1353 int transferDir, t_isoch_transfer_cb cb, UINT32 Timeout)
1354{
1355 int rc = 0;
1356 UINT32 transfer_type = 0;
1357 UDEVICE* pdev = (UDEVICE*)idev;
1358 const LIBUSB_ENDPOINT_DESCEIPTOR* ep_desc = nullptr;
1359 struct libusb_transfer* transfer = nullptr;
1360 URBDRC_PLUGIN* urbdrc = nullptr;
1361 ASYNC_TRANSFER_USER_DATA* user_data = nullptr;
1362 uint32_t streamID = 0x80000000 | RequestId;
1363
1364 if (!pdev || !pdev->LibusbConfig || !pdev->urbdrc)
1365 return -1;
1366
1367 urbdrc = pdev->urbdrc;
1368 user_data = async_transfer_user_data_new(idev, MessageId, 36, BufferSize, data, 0, NoAck,
1369 transferDir, cb, callback);
1370
1371 if (!user_data)
1372 return -1;
1373
1374 /* alloc memory for urb transfer */
1375 transfer = libusb_alloc_transfer(0);
1376 if (!transfer)
1377 {
1378 async_transfer_user_data_free(user_data);
1379 return -1;
1380 }
1381 transfer->user_data = user_data;
1382
1383 ep_desc = func_get_ep_desc(pdev->LibusbConfig, pdev->MsConfig, EndpointAddress);
1384
1385 if (!ep_desc)
1386 {
1387 WLog_Print(urbdrc->log, WLOG_ERROR, "func_get_ep_desc: endpoint 0x%" PRIx32 " not found",
1388 EndpointAddress);
1389 request_free(transfer);
1390 return -1;
1391 }
1392
1393 transfer_type = (ep_desc->bmAttributes) & 0x3;
1394 WLog_Print(urbdrc->log, WLOG_DEBUG,
1395 "urb_bulk_or_interrupt_transfer: ep:0x%" PRIx32 " "
1396 "transfer_type %" PRIu32 " flag:%" PRIu32 " OutputBufferSize:0x%" PRIx32 "",
1397 EndpointAddress, transfer_type, TransferFlags, BufferSize);
1398
1399 switch (transfer_type)
1400 {
1401 case BULK_TRANSFER:
1403 libusb_fill_bulk_transfer(
1404 transfer, pdev->libusb_handle, WINPR_ASSERTING_INT_CAST(uint8_t, EndpointAddress),
1405 Stream_Pointer(user_data->data), WINPR_ASSERTING_INT_CAST(int, BufferSize),
1406 func_bulk_transfer_cb, user_data, Timeout);
1407 break;
1408
1409 case INTERRUPT_TRANSFER:
1411 libusb_fill_interrupt_transfer(
1412 transfer, pdev->libusb_handle, WINPR_ASSERTING_INT_CAST(uint8_t, EndpointAddress),
1413 Stream_Pointer(user_data->data), WINPR_ASSERTING_INT_CAST(int, BufferSize),
1414 func_bulk_transfer_cb, user_data, Timeout);
1415 break;
1416
1417 default:
1418 WLog_Print(urbdrc->log, WLOG_DEBUG,
1419 "urb_bulk_or_interrupt_transfer:"
1420 " other transfer type 0x%" PRIX32 "",
1421 transfer_type);
1422 request_free(transfer);
1423 return -1;
1424 }
1425
1426 set_stream_id_for_buffer(transfer, streamID);
1427
1428 if (!ArrayList_Append(pdev->request_queue, transfer))
1429 {
1430 WLog_Print(urbdrc->log, WLOG_WARN,
1431 "Failed to queue transfer, streamID %08" PRIx32 " already in use!", streamID);
1432 request_free(transfer);
1433 return -1;
1434 }
1435 rc = libusb_submit_transfer(transfer);
1436 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_submit_transfer", rc))
1437 return -1;
1438 return rc;
1439}
1440
1441static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, struct libusb_transfer* transfer)
1442{
1443 int status = 0;
1444
1445 if (!urbdrc || !transfer)
1446 return -1;
1447
1448 status = libusb_cancel_transfer(transfer);
1449
1450 if (log_libusb_result(urbdrc->log, WLOG_WARN, "libusb_cancel_transfer", status))
1451 {
1452 if (status == LIBUSB_ERROR_NOT_FOUND)
1453 return -1;
1454 }
1455 else
1456 return 1;
1457
1458 return 0;
1459}
1460
1461static void libusb_udev_cancel_all_transfer_request(IUDEVICE* idev)
1462{
1463 UDEVICE* pdev = (UDEVICE*)idev;
1464 size_t count = 0;
1465
1466 if (!pdev || !pdev->request_queue || !pdev->urbdrc)
1467 return;
1468
1469 ArrayList_Lock(pdev->request_queue);
1470 count = ArrayList_Count(pdev->request_queue);
1471
1472 for (size_t x = 0; x < count; x++)
1473 {
1474 struct libusb_transfer* transfer = ArrayList_GetItem(pdev->request_queue, x);
1475 func_cancel_xact_request(pdev->urbdrc, transfer);
1476 }
1477
1478 ArrayList_Unlock(pdev->request_queue);
1479}
1480
1481static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId)
1482{
1483 int rc = -1;
1484 UDEVICE* pdev = (UDEVICE*)idev;
1485 struct libusb_transfer* transfer = nullptr;
1486 uint32_t cancelID1 = 0x40000000 | RequestId;
1487 uint32_t cancelID2 = 0x80000000 | RequestId;
1488
1489 if (!idev || !pdev->urbdrc || !pdev->request_queue)
1490 return -1;
1491
1492 ArrayList_Lock(pdev->request_queue);
1493 transfer = list_contains(pdev->request_queue, cancelID1);
1494 if (!transfer)
1495 transfer = list_contains(pdev->request_queue, cancelID2);
1496
1497 if (transfer)
1498 {
1499 URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
1500
1501 rc = func_cancel_xact_request(urbdrc, transfer);
1502 }
1503 ArrayList_Unlock(pdev->request_queue);
1504 return rc;
1505}
1506
1507BASIC_STATE_FUNC_DEFINED(channelManager, IWTSVirtualChannelManager*)
1508BASIC_STATE_FUNC_DEFINED(channelID, UINT32)
1509BASIC_STATE_FUNC_DEFINED(ReqCompletion, UINT32)
1510BASIC_STATE_FUNC_DEFINED(bus_number, BYTE)
1511BASIC_STATE_FUNC_DEFINED(dev_number, BYTE)
1512BASIC_STATE_FUNC_DEFINED(port_number, UINT8)
1513BASIC_STATE_FUNC_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR*)
1514
1515BASIC_POINT_FUNC_DEFINED(udev, void*)
1516BASIC_POINT_FUNC_DEFINED(prev, void*)
1517BASIC_POINT_FUNC_DEFINED(next, void*)
1518
1519static UINT32 udev_get_UsbDevice(IUDEVICE* idev)
1520{
1521 UDEVICE* pdev = (UDEVICE*)idev;
1522
1523 if (!pdev)
1524 return 0;
1525
1526 return pdev->UsbDevice;
1527}
1528
1529static void udev_set_UsbDevice(IUDEVICE* idev, UINT32 val)
1530{
1531 UDEVICE* pdev = (UDEVICE*)idev;
1532
1533 if (!pdev)
1534 return;
1535
1536 pdev->UsbDevice = val;
1537}
1538
1539static void udev_free(IUDEVICE* idev)
1540{
1541 int rc = 0;
1542 UDEVICE* udev = (UDEVICE*)idev;
1543 URBDRC_PLUGIN* urbdrc = nullptr;
1544
1545 if (!idev || !udev->urbdrc)
1546 return;
1547
1548 urbdrc = udev->urbdrc;
1549
1550 libusb_udev_cancel_all_transfer_request(&udev->iface);
1551 if (udev->libusb_handle)
1552 {
1553 rc = libusb_reset_device(udev->libusb_handle);
1554
1555 log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_reset_device", rc);
1556 }
1557
1558 /* HACK: We need to wait until the cancel transfer has been processed by
1559 * poll_libusb_events
1560 */
1561 Sleep(100);
1562
1563 /* release all interface and attach kernel driver */
1564 if (!udev->iface.attach_kernel_driver(idev))
1565 WLog_Print(udev->urbdrc->log, WLOG_WARN, "attach_kernel_driver failed for device");
1566 ArrayList_Free(udev->request_queue);
1567 /* free the config descriptor that send from windows */
1568 msusb_msconfig_free(udev->MsConfig);
1569 libusb_unref_device(udev->libusb_dev);
1570 libusb_close(udev->libusb_handle);
1571 libusb_close(udev->hub_handle);
1572 free(udev->devDescriptor);
1573 free(idev);
1574}
1575
1576static void udev_load_interface(UDEVICE* pdev)
1577{
1578 WINPR_ASSERT(pdev);
1579
1580 /* load interface */
1581 /* Basic */
1582 BASIC_STATE_FUNC_REGISTER(channelManager, pdev);
1583 BASIC_STATE_FUNC_REGISTER(channelID, pdev);
1584 BASIC_STATE_FUNC_REGISTER(UsbDevice, pdev);
1585 BASIC_STATE_FUNC_REGISTER(ReqCompletion, pdev);
1586 BASIC_STATE_FUNC_REGISTER(bus_number, pdev);
1587 BASIC_STATE_FUNC_REGISTER(dev_number, pdev);
1588 BASIC_STATE_FUNC_REGISTER(port_number, pdev);
1589 BASIC_STATE_FUNC_REGISTER(MsConfig, pdev);
1590 BASIC_STATE_FUNC_REGISTER(p_udev, pdev);
1591 BASIC_STATE_FUNC_REGISTER(p_prev, pdev);
1592 BASIC_STATE_FUNC_REGISTER(p_next, pdev);
1593 pdev->iface.isCompositeDevice = libusb_udev_is_composite_device;
1594 pdev->iface.isExist = libusb_udev_is_exist;
1595 pdev->iface.isAlreadySend = libusb_udev_is_already_send;
1596 pdev->iface.isChannelClosed = libusb_udev_is_channel_closed;
1597 pdev->iface.setAlreadySend = libusb_udev_set_already_send;
1598 pdev->iface.setChannelClosed = libusb_udev_channel_closed;
1599 pdev->iface.markChannelClosed = libusb_udev_mark_channel_closed;
1600 pdev->iface.getPath = libusb_udev_get_path;
1601 /* Transfer */
1602 pdev->iface.isoch_transfer = libusb_udev_isoch_transfer;
1603 pdev->iface.control_transfer = libusb_udev_control_transfer;
1604 pdev->iface.bulk_or_interrupt_transfer = libusb_udev_bulk_or_interrupt_transfer;
1605 pdev->iface.select_interface = libusb_udev_select_interface;
1606 pdev->iface.select_configuration = libusb_udev_select_configuration;
1607 pdev->iface.complete_msconfig_setup = libusb_udev_complete_msconfig_setup;
1608 pdev->iface.control_pipe_request = libusb_udev_control_pipe_request;
1609 pdev->iface.control_query_device_text = libusb_udev_control_query_device_text;
1610 pdev->iface.os_feature_descriptor_request = libusb_udev_os_feature_descriptor_request;
1611 pdev->iface.cancel_all_transfer_request = libusb_udev_cancel_all_transfer_request;
1612 pdev->iface.cancel_transfer_request = libusb_udev_cancel_transfer_request;
1613 pdev->iface.query_device_descriptor = libusb_udev_query_device_descriptor;
1614 pdev->iface.detach_kernel_driver = libusb_udev_detach_kernel_driver;
1615 pdev->iface.attach_kernel_driver = libusb_udev_attach_kernel_driver;
1616 pdev->iface.query_device_port_status = libusb_udev_query_device_port_status;
1617 pdev->iface.free = udev_free;
1618}
1619
1620static int udev_get_device_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVICE* pdev,
1621 UINT16 bus_number, UINT16 dev_number)
1622{
1623 int error = -1;
1624 uint8_t port_numbers[16] = WINPR_C_ARRAY_INIT;
1625 LIBUSB_DEVICE** libusb_list = nullptr;
1626 const ssize_t total_device = libusb_get_device_list(ctx, &libusb_list);
1627
1628 WINPR_ASSERT(urbdrc);
1629
1630 /* Look for device. */
1631 for (ssize_t i = 0; i < total_device; i++)
1632 {
1633 LIBUSB_DEVICE* dev = libusb_list[i];
1634
1635 if ((bus_number != libusb_get_bus_number(dev)) ||
1636 (dev_number != libusb_get_device_address(dev)))
1637 libusb_unref_device(dev);
1638 else
1639 {
1640 error = libusb_open(dev, &pdev->libusb_handle);
1641
1642 if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error))
1643 {
1644 libusb_unref_device(dev);
1645 continue;
1646 }
1647
1648 /* get port number */
1649 error = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
1650 if (error < 1)
1651 {
1652 /* Prevent open hub, treat as error. */
1653 log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_get_port_numbers", error);
1654 libusb_unref_device(dev);
1655 continue;
1656 }
1657
1658 pdev->port_number = port_numbers[(error - 1)];
1659 error = 0;
1660 WLog_Print(urbdrc->log, WLOG_DEBUG, " Port: %" PRIu8, pdev->port_number);
1661 /* gen device path */
1662 (void)_snprintf(pdev->path, sizeof(pdev->path), "%" PRIu16 "-%d", bus_number,
1663 pdev->port_number);
1664
1665 WLog_Print(urbdrc->log, WLOG_DEBUG, " DevPath: %s", pdev->path);
1666 }
1667 }
1668 libusb_free_device_list(libusb_list, 0);
1669
1670 if (error < 0)
1671 return -1;
1672 return 0;
1673}
1674
1675static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVICE* pdev,
1676 UINT16 bus_number, WINPR_ATTR_UNUSED UINT16 dev_number)
1677{
1678 int error = -1;
1679 LIBUSB_DEVICE** libusb_list = nullptr;
1680 LIBUSB_DEVICE_HANDLE* handle = nullptr;
1681 const ssize_t total_device = libusb_get_device_list(ctx, &libusb_list);
1682
1683 WINPR_ASSERT(urbdrc);
1684
1685 /* Look for device hub. */
1686 for (ssize_t i = 0; i < total_device; i++)
1687 {
1688 LIBUSB_DEVICE* dev = libusb_list[i];
1689
1690 if ((bus_number != libusb_get_bus_number(dev)) ||
1691 (1 != libusb_get_device_address(dev))) /* Root hub always first on bus. */
1692 libusb_unref_device(dev);
1693 else
1694 {
1695 WLog_Print(urbdrc->log, WLOG_DEBUG, " Open hub: %" PRIu16 "", bus_number);
1696 error = libusb_open(dev, &handle);
1697
1698 if (!log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error))
1699 pdev->hub_handle = handle;
1700 else
1701 libusb_unref_device(dev);
1702 }
1703 }
1704
1705 libusb_free_device_list(libusb_list, 0);
1706
1707 if (error < 0)
1708 return -1;
1709
1710 return 0;
1711}
1712
1713static void request_free(void* value)
1714{
1715 ASYNC_TRANSFER_USER_DATA* user_data = nullptr;
1716 struct libusb_transfer* transfer = (struct libusb_transfer*)value;
1717 if (!transfer)
1718 return;
1719
1720 user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
1721 async_transfer_user_data_free(user_data);
1722 transfer->user_data = nullptr;
1723 libusb_free_transfer(transfer);
1724}
1725
1726static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUSB_DEVICE* device,
1727 BYTE bus_number, BYTE dev_number)
1728{
1729 UDEVICE* pdev = nullptr;
1730 int status = LIBUSB_ERROR_OTHER;
1731 LIBUSB_DEVICE_DESCRIPTOR* devDescriptor = nullptr;
1732 LIBUSB_CONFIG_DESCRIPTOR* config_temp = nullptr;
1733 LIBUSB_INTERFACE_DESCRIPTOR interface_temp;
1734
1735 WINPR_ASSERT(urbdrc);
1736
1737 pdev = (PUDEVICE)calloc(1, sizeof(UDEVICE));
1738
1739 if (!pdev)
1740 return nullptr;
1741
1742 pdev->urbdrc = urbdrc;
1743 udev_load_interface(pdev);
1744
1745 if (device)
1746 pdev->libusb_dev = device;
1747 else
1748 pdev->libusb_dev = udev_get_libusb_dev(context, bus_number, dev_number);
1749
1750 if (pdev->libusb_dev == nullptr)
1751 goto fail;
1752
1753 if (urbdrc->listener_callback)
1754 udev_set_channelManager(&pdev->iface, urbdrc->listener_callback->channel_mgr);
1755
1756 /* Get DEVICE handle */
1757 status = udev_get_device_handle(urbdrc, context, pdev, bus_number, dev_number);
1758 if (status != LIBUSB_SUCCESS)
1759 {
1760 struct libusb_device_descriptor desc;
1761 const uint8_t port = libusb_get_port_number(pdev->libusb_dev);
1762 libusb_get_device_descriptor(pdev->libusb_dev, &desc);
1763
1764 log_libusb_result(urbdrc->log, WLOG_ERROR,
1765 "libusb_open [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]", status,
1766 bus_number, port, dev_number, desc.idVendor, desc.idProduct);
1767 goto fail;
1768 }
1769
1770 /* Get HUB handle */
1771 status = udev_get_hub_handle(urbdrc, context, pdev, bus_number, dev_number);
1772
1773 if (status < 0)
1774 pdev->hub_handle = nullptr;
1775
1776 pdev->devDescriptor = udev_new_descript(urbdrc, pdev->libusb_dev);
1777
1778 if (!pdev->devDescriptor)
1779 goto fail;
1780
1781 status = libusb_get_active_config_descriptor(pdev->libusb_dev, &pdev->LibusbConfig);
1782
1783 if (status == LIBUSB_ERROR_NOT_FOUND)
1784 status = libusb_get_config_descriptor(pdev->libusb_dev, 0, &pdev->LibusbConfig);
1785
1786 if (status < 0)
1787 {
1788 log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_get_config_descriptor", status);
1789 goto fail;
1790 }
1791
1792 config_temp = pdev->LibusbConfig;
1793 /* get the first interface and first altsetting */
1794 interface_temp = config_temp->interface[0].altsetting[0];
1795 WLog_Print(urbdrc->log, WLOG_DEBUG,
1796 "Registered Device: Vid: 0x%04" PRIX16 " Pid: 0x%04" PRIX16 ""
1797 " InterfaceClass = %s",
1798 pdev->devDescriptor->idVendor, pdev->devDescriptor->idProduct,
1799 usb_interface_class_to_string(interface_temp.bInterfaceClass));
1800 /* Check composite device */
1801 devDescriptor = pdev->devDescriptor;
1802
1803 if ((devDescriptor->bNumConfigurations == 1) && (config_temp->bNumInterfaces > 1) &&
1804 (devDescriptor->bDeviceClass == LIBUSB_CLASS_PER_INTERFACE))
1805 {
1806 pdev->isCompositeDevice = 1;
1807 }
1808 else if ((devDescriptor->bDeviceClass == 0xef) &&
1809 (devDescriptor->bDeviceSubClass == LIBUSB_CLASS_COMM) &&
1810 (devDescriptor->bDeviceProtocol == 0x01))
1811 {
1812 pdev->isCompositeDevice = 1;
1813 }
1814 else
1815 pdev->isCompositeDevice = 0;
1816
1817 /* set device class to first interface class */
1818 devDescriptor->bDeviceClass = interface_temp.bInterfaceClass;
1819 devDescriptor->bDeviceSubClass = interface_temp.bInterfaceSubClass;
1820 devDescriptor->bDeviceProtocol = interface_temp.bInterfaceProtocol;
1821 /* initialize pdev */
1822 pdev->bus_number = bus_number;
1823 pdev->dev_number = dev_number;
1824 pdev->request_queue = ArrayList_New(TRUE);
1825
1826 if (!pdev->request_queue)
1827 goto fail;
1828
1829 ArrayList_Object(pdev->request_queue)->fnObjectFree = request_free;
1830
1831 /* set config of windows */
1832 pdev->MsConfig = msusb_msconfig_new();
1833
1834 if (!pdev->MsConfig)
1835 goto fail;
1836
1837 // deb_config_msg(pdev->libusb_dev, config_temp, devDescriptor->bNumConfigurations);
1838 return &pdev->iface;
1839fail:
1840 pdev->iface.free(&pdev->iface);
1841 return nullptr;
1842}
1843
1844size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendor, UINT16 idProduct,
1845 IUDEVICE*** devArray)
1846{
1847 WINPR_ASSERT(urbdrc);
1848 WINPR_ASSERT(devArray);
1849
1850 size_t num = 0;
1851 LIBUSB_DEVICE** libusb_list = nullptr;
1852
1853 *devArray = nullptr;
1854
1855 WLog_Print(urbdrc->log, WLOG_INFO, "VID: 0x%04" PRIX16 ", PID: 0x%04" PRIX16 "", idVendor,
1856 idProduct);
1857 const ssize_t total_device = libusb_get_device_list(ctx, &libusb_list);
1858 if (total_device < 0)
1859 {
1860 WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_get_device_list -> [%" PRIdz "]", total_device);
1861 return 0;
1862 }
1863 if (total_device == 0)
1864 {
1865 WLog_Print(urbdrc->log, WLOG_WARN, "libusb_get_device_list -> [%" PRIdz "]", total_device);
1866 return 0;
1867 }
1868
1869 UDEVICE** array = (UDEVICE**)calloc((size_t)total_device, sizeof(UDEVICE*));
1870
1871 if (!array)
1872 goto fail;
1873
1874 for (ssize_t i = 0; i < total_device; i++)
1875 {
1876 LIBUSB_DEVICE* dev = libusb_list[i];
1877 LIBUSB_DEVICE_DESCRIPTOR* descriptor = udev_new_descript(urbdrc, dev);
1878
1879 if ((descriptor->idVendor == idVendor) && (descriptor->idProduct == idProduct))
1880 {
1881 const uint8_t nr = libusb_get_bus_number(dev);
1882 const uint8_t addr = libusb_get_device_address(dev);
1883 array[num] = (PUDEVICE)udev_init(urbdrc, ctx, dev, nr, addr);
1884
1885 if (array[num] != nullptr)
1886 num++;
1887 else
1888 {
1889 WLog_Print(urbdrc->log, WLOG_WARN,
1890 "udev_init(nr=%" PRIu8 ", addr=%" PRIu8 ") failed", nr, addr);
1891 }
1892 }
1893 else
1894 libusb_unref_device(dev);
1895
1896 free(descriptor);
1897 }
1898
1899fail:
1900 libusb_free_device_list(libusb_list, 0);
1901 *devArray = (IUDEVICE**)array;
1902 return num;
1903}
1904
1905IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, libusb_context* context, BYTE bus_number,
1906 BYTE dev_number)
1907{
1908 WLog_Print(urbdrc->log, WLOG_DEBUG, "bus:%d dev:%d", bus_number, dev_number);
1909 return udev_init(urbdrc, context, nullptr, bus_number, dev_number);
1910}
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59