FreeRDP
Loading...
Searching...
No Matches
data_transfer.c
1
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <winpr/sysinfo.h>
26#include <winpr/cast.h>
27
28#include <urbdrc_helpers.h>
29
30#include "urbdrc_types.h"
31#include "data_transfer.h"
32#include "msusb.h"
33
34static void usb_process_get_port_status(IUDEVICE* pdev, wStream* out)
35{
36 int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
37
38 switch (bcdUSB)
39 {
40 case USB_v1_0:
41 Stream_Write_UINT32(out, 0x303);
42 break;
43
44 case USB_v1_1:
45 Stream_Write_UINT32(out, 0x103);
46 break;
47
48 case USB_v2_0:
49 default:
50 Stream_Write_UINT32(out, 0x503);
51 break;
52 }
53}
54
55/* [MS-RDPEUSB] 2.2.10.1.1TS_URB_RESULT_HEADER */
56static BOOL write_urb_result_header(wStream* s, UINT16 Size, UINT32 status)
57{
58 if (!Stream_EnsureRemainingCapacity(s, 8ULL + Size))
59 return FALSE;
60 Stream_Write_UINT16(s, Size);
61 Stream_Seek_UINT16(s);
62 Stream_Write_UINT32(s, status);
63 return TRUE;
64}
65
66/* [MS-RDPEUSB] 2.2.7.2 URB Completion (URB_COMPLETION)
67 * 2.2.7.3 URB Completion No Data (URB_COMPLETION_NO_DATA)
68 */
69static wStream* create_urb_completion_message(UINT32 InterfaceId, UINT32 MessageId,
70 UINT32 RequestId, UINT32 FunctionId)
71{
72 wStream* out =
73 create_shared_message_header_with_functionid(InterfaceId, MessageId, FunctionId, 4);
74 if (!out)
75 return nullptr;
76
77 Stream_Write_UINT32(out, RequestId);
78 return out;
79}
80
81static UINT send_urb_completion_message(GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
82 HRESULT hResult, UINT32 OutputSize, const void* data)
83{
84 WINPR_ASSERT(callback);
85 UINT status = ERROR_OUTOFMEMORY;
86
87 if (!Stream_EnsureRemainingCapacity(out, 8ULL + OutputSize))
88 goto fail;
89
90 Stream_Write_INT32(out, hResult);
91 Stream_Write_UINT32(out, OutputSize);
92 Stream_Write(out, data, OutputSize);
93 return stream_write_and_free(callback->plugin, callback->channel, out);
94
95fail:
96 Stream_Free(out, TRUE);
97 return status;
98}
99
100static UINT urb_write_completion(WINPR_ATTR_UNUSED IUDEVICE* pdev,
101 GENERIC_CHANNEL_CALLBACK* callback, BOOL noAck, wStream* out,
102 UINT32 InterfaceId, UINT32 MessageId, UINT32 RequestId,
103 UINT32 usbd_status, UINT32 OutputBufferSize)
104{
105 if (!out)
106 return ERROR_INVALID_PARAMETER;
107
108 if (Stream_Capacity(out) < OutputBufferSize + 36)
109 {
110 Stream_Free(out, TRUE);
111 return ERROR_INVALID_PARAMETER;
112 }
113
114 Stream_ResetPosition(out);
115
116 const UINT32 FunctionId = (OutputBufferSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
117 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
118 {
119 Stream_Free(out, TRUE);
120 return ERROR_OUTOFMEMORY;
121 }
122
123 Stream_Write_UINT32(out, RequestId);
124 Stream_Write_UINT32(out, 8);
126 if (!write_urb_result_header(out, 8, usbd_status))
127 {
128 Stream_Free(out, TRUE);
129 return ERROR_OUTOFMEMORY;
130 }
131
132 Stream_Write_UINT32(out, 0);
133 Stream_Write_UINT32(out, OutputBufferSize);
134 Stream_Seek(out, OutputBufferSize);
135
136 if (!noAck)
137 return stream_write_and_free(callback->plugin, callback->channel, out);
138 else
139 Stream_Free(out, TRUE);
140
141 return ERROR_SUCCESS;
142}
143
144static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
145 UINT32 OutputBufferSize)
146{
147 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
148
149#if UINT32_MAX >= SIZE_MAX
150 if (OutputBufferSize > UINT32_MAX - 28ull)
151 return nullptr;
152#endif
153
154 wStream* out = create_shared_message_header_with_functionid(
155 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
156 if (!out)
157 return nullptr;
158
159 Stream_Write_UINT32(out, RequestId);
160 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
161 Stream_Write_UINT32(out, OutputBufferSize);
162 Stream_Write_UINT32(out, OutputBufferSize);
163 return out;
164}
165
166static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
167 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
168 IUDEVMAN* udevman)
169{
170 UINT32 NumRequestCompletion = 0;
171 UINT32 RequestCompletion = 0;
172
173 if (!callback || !s || !udevman || !pdev)
174 return ERROR_INVALID_PARAMETER;
175
176 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
177
178 if (!urbdrc)
179 return ERROR_INVALID_PARAMETER;
180
181 WLog_Print(urbdrc->log, WLOG_DEBUG, "urbdrc_process_register_request_callback");
182
183 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
184 return ERROR_INVALID_DATA;
185
186 Stream_Read_UINT32(s, NumRequestCompletion);
188 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL * NumRequestCompletion))
189 return ERROR_INVALID_DATA;
190 for (uint32_t x = 0; x < NumRequestCompletion; x++)
191 {
194 Stream_Read_UINT32(s, RequestCompletion);
195 pdev->set_ReqCompletion(pdev, RequestCompletion);
196 }
197
198 return ERROR_SUCCESS;
199}
200
201static UINT urbdrc_process_cancel_request(IUDEVICE* pdev, wStream* s, IUDEVMAN* udevman)
202{
203 UINT32 CancelId = 0;
204 URBDRC_PLUGIN* urbdrc = nullptr;
205
206 if (!s || !udevman || !pdev)
207 return ERROR_INVALID_PARAMETER;
208
209 urbdrc = (URBDRC_PLUGIN*)udevman->plugin;
210
211 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
212 return ERROR_INVALID_DATA;
213
214 Stream_Read_UINT32(s, CancelId);
215 WLog_Print(urbdrc->log, WLOG_DEBUG, "CANCEL_REQUEST: CancelId=%08" PRIx32 "", CancelId);
216
217 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
218 return ERROR_INTERNAL_ERROR;
219
220 return ERROR_SUCCESS;
221}
222
223static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev, wStream* s,
224 IUDEVMAN* udevman)
225{
226 UINT32 Reason = 0;
227 URBDRC_PLUGIN* urbdrc = nullptr;
228
229 if (!s || !udevman)
230 return ERROR_INVALID_PARAMETER;
231
232 urbdrc = (URBDRC_PLUGIN*)udevman->plugin;
233
234 if (!urbdrc)
235 return ERROR_INVALID_PARAMETER;
236
237 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
238 return ERROR_INVALID_DATA;
239
240 Stream_Read_UINT32(s, Reason);
242 switch (Reason)
243 {
244 case UsbRetractReason_BlockedByPolicy:
245 WLog_Print(urbdrc->log, WLOG_DEBUG,
246 "UsbRetractReason_BlockedByPolicy: now it is not support");
247 return ERROR_ACCESS_DENIED;
248
249 default:
250 WLog_Print(urbdrc->log, WLOG_DEBUG,
251 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32 "", Reason);
252 return ERROR_ACCESS_DENIED;
253 }
254
255 return ERROR_SUCCESS;
256}
257
258static UINT urbdrc_process_io_control(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
259 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
260{
261 UINT32 InterfaceId = 0;
262 UINT32 IoControlCode = 0;
263 UINT32 InputBufferSize = 0;
264 UINT32 OutputBufferSize = 0;
265 UINT32 RequestId = 0;
266 UINT32 usbd_status = USBD_STATUS_SUCCESS;
267 wStream* out = nullptr;
268 int success = 0;
269 URBDRC_PLUGIN* urbdrc = nullptr;
270
271 if (!callback || !s || !udevman || !pdev)
272 return ERROR_INVALID_PARAMETER;
273
274 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
275
276 if (!urbdrc)
277 return ERROR_INVALID_PARAMETER;
278
279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
280 return ERROR_INVALID_DATA;
281
282 Stream_Read_UINT32(s, IoControlCode);
283 Stream_Read_UINT32(s, InputBufferSize);
284
285 if (!Stream_SafeSeek(s, InputBufferSize))
286 return ERROR_INVALID_DATA;
287 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
288 return ERROR_INVALID_DATA;
289
290 Stream_Read_UINT32(s, OutputBufferSize);
291 Stream_Read_UINT32(s, RequestId);
292
293 if (OutputBufferSize > UINT32_MAX - 4)
294 return ERROR_INVALID_DATA;
295
296 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
297 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
298
299 if (!out)
300 return ERROR_OUTOFMEMORY;
301
302 switch (IoControlCode)
303 {
304 case IOCTL_INTERNAL_USB_SUBMIT_URB:
305 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
306 WLog_Print(urbdrc->log, WLOG_ERROR,
307 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
308 break;
309
310 case IOCTL_INTERNAL_USB_RESET_PORT:
311 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
312 break;
313
314 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
315 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
316 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
317 Stream_Pointer(out));
318
319 if (success)
320 {
321 if (!Stream_SafeSeek(out, OutputBufferSize))
322 {
323 Stream_Free(out, TRUE);
324 return ERROR_INVALID_DATA;
325 }
326
327 if (pdev->isExist(pdev) == 0)
328 Stream_Write_UINT32(out, 0);
329 else
330 usb_process_get_port_status(pdev, out);
331 }
332
333 break;
334
335 case IOCTL_INTERNAL_USB_CYCLE_PORT:
336 WLog_Print(urbdrc->log, WLOG_DEBUG, "ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
337 WLog_Print(urbdrc->log, WLOG_ERROR,
338 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
339 break;
340
341 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
342 WLog_Print(urbdrc->log, WLOG_DEBUG,
343 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
344 WLog_Print(urbdrc->log, WLOG_ERROR,
345 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
346 break;
347
348 default:
349 WLog_Print(urbdrc->log, WLOG_DEBUG,
350 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32 "",
351 IoControlCode);
352 Stream_Free(out, TRUE);
353 return ERROR_INVALID_OPERATION;
354 }
355
356 return stream_write_and_free(callback->plugin, callback->channel, out);
357}
358
359static UINT urbdrc_process_internal_io_control(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
360 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
361{
362 if (!pdev || !callback || !s || !udevman)
363 return ERROR_INVALID_PARAMETER;
364
365 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
366 WINPR_ASSERT(urbdrc);
367
368 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
369 return ERROR_INVALID_DATA;
370
371 const UINT32 IoControlCode = Stream_Get_UINT32(s);
372 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
373 {
374 WLog_ERR(
375 TAG,
376 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
377 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
378 IoControlCode);
379 return ERROR_INVALID_DATA;
380 }
381 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
382
383 if (!Stream_SafeSeek(s, InputBufferSize))
384 return ERROR_INVALID_DATA;
385 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
386 return ERROR_INVALID_DATA;
387 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
388 const UINT32 RequestId = Stream_Get_UINT32(s);
389 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
390 // TODO: Implement control code.
392 const UINT32 frames = GetTickCount();
393
394 if (4 > OutputBufferSize)
395 {
396 WLog_Print(urbdrc->log, WLOG_DEBUG, "out_size %" PRIu32 " > OutputBufferSize %" PRIu32, 4u,
397 OutputBufferSize);
398 return ERROR_BAD_CONFIGURATION;
399 }
400 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
401
402 if (!out)
403 return ERROR_OUTOFMEMORY;
404
405 Stream_Write_UINT32(out, frames);
406 return stream_write_and_free(callback->plugin, callback->channel, out);
407}
408
409/* [MS-RDPEUSB] 2.2.6.6 Query Device Text Response Message (QUERY_DEVICE_TEXT_RSP) */
410static UINT urbdrc_send_query_device_text_response(GENERIC_CHANNEL_CALLBACK* callback,
411 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
412 const BYTE* text, uint8_t bytelen)
413{
414 WINPR_ASSERT(callback);
415
416 const uint8_t charlen = bytelen / sizeof(WCHAR);
417 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
418 8ULL + bytelen);
419
420 if (!out)
421 return ERROR_OUTOFMEMORY;
422
423 Stream_Write(out, text, bytelen); /* '\0' terminated unicode */
424 Stream_Write_INT32(out, hr);
425 return stream_write_and_free(callback->plugin, callback->channel, out);
426}
427
428static UINT urbdrc_process_query_device_text(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
429 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
430{
431 UINT32 TextType = 0;
432 UINT32 LocaleId = 0;
433 UINT8 bufferSize = 0xFF;
434 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
435
436 if (!pdev || !callback || !s || !udevman)
437 return ERROR_INVALID_PARAMETER;
438 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
439 return ERROR_INVALID_DATA;
440
441 Stream_Read_UINT32(s, TextType);
442 Stream_Read_UINT32(s, LocaleId);
443 if (LocaleId > UINT16_MAX)
444 return ERROR_INVALID_DATA;
445
446 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
447 &bufferSize, DeviceDescription);
448 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
449 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
450 DeviceDescription, bufferSize);
451}
452
453static void func_select_all_interface_for_msconfig(URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
454 MSUSB_CONFIG_DESCRIPTOR* MsConfig)
455{
456 WINPR_ASSERT(urbdrc);
457 WINPR_ASSERT(pdev);
458 WINPR_ASSERT(MsConfig);
459
460 MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces;
461 UINT32 NumInterfaces = MsConfig->NumInterfaces;
462
463 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
464 {
465 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
466 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
467 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
468 if (rc < 0)
469 {
470 WLog_Print(urbdrc->log, WLOG_WARN,
471 "select_interface %" PRIu8 " [%" PRIu8 "] failed [%d]", InterfaceNumber,
472 AlternateSetting, rc);
473 }
474 }
475}
476
477/* [MS-RDPEUSB] 2.2.10.2 TS_URB_SELECT_CONFIGURATION_RESULT */
478static UINT send_urb_select_configuration_result(GENERIC_CHANNEL_CALLBACK* callback,
479 UINT32 InterfaceId, UINT32 MessageId,
480 UINT32 RequestId, UINT32 UrbStatus,
481 const MSUSB_CONFIG_DESCRIPTOR* MsConfig)
482{
483 wStream* out =
484 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
485 if (!out)
486 return ERROR_OUTOFMEMORY;
487
488 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
489 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
490
491 if (!Stream_EnsureRemainingCapacity(out, 4))
492 goto fail;
493 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
494
495 if (!write_urb_result_header(out, usize, UrbStatus))
496 goto fail;
497
499 if (MsConfig)
500 {
501 if (!msusb_msconfig_write(MsConfig, out))
502 goto fail;
503 }
504 else
505 {
506 Stream_Write_UINT32(out, 0);
507 Stream_Write_UINT32(out, 0);
508 }
509
510 return send_urb_completion_message(callback, out, 0, 0, nullptr);
511
512fail:
513 Stream_Free(out, TRUE);
514 return ERROR_OUTOFMEMORY;
515}
516
517static UINT urb_select_configuration(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
518 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
519 int transferDir)
520{
521 MSUSB_CONFIG_DESCRIPTOR* MsConfig = nullptr;
522 UINT32 NumInterfaces = 0;
523 UINT32 usbd_status = 0;
524 BYTE ConfigurationDescriptorIsValid = 0;
525 URBDRC_PLUGIN* urbdrc = nullptr;
526 const BOOL noAck = (RequestField & 0x80000000U) != 0;
527 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
528
529 if (!callback || !s || !udevman || !pdev)
530 return ERROR_INVALID_PARAMETER;
531
532 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
533
534 if (!urbdrc)
535 return ERROR_INVALID_PARAMETER;
536
537 if (transferDir == 0)
538 {
539 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_configuration: unsupported transfer out");
540 return ERROR_INVALID_PARAMETER;
541 }
542
543 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
544 return ERROR_INVALID_DATA;
545
546 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
547 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
548 Stream_Seek(s, 3); /* Padding */
549 Stream_Read_UINT32(s, NumInterfaces);
550
552 if (ConfigurationDescriptorIsValid)
553 {
554 /* parser data for struct config */
555 MsConfig = msusb_msconfig_read(s, NumInterfaces);
556
557 if (!MsConfig)
558 return ERROR_INVALID_DATA;
559
560 /* select config */
561 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
562 if (lrc != 0)
563 {
564 msusb_msconfig_free(MsConfig);
565 MsConfig = nullptr;
566 return ERROR_INTERNAL_ERROR;
567 }
568
569 /* select all interface */
570 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
571 /* complete configuration setup */
572 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
573 {
574 msusb_msconfig_free(MsConfig);
575 MsConfig = nullptr;
576 }
577 }
578
579 if (noAck)
580 return CHANNEL_RC_OK;
581 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
582 usbd_status, MsConfig);
583}
584
585/* [MS-RDPEUSB[ 2.2.10.3 TS_URB_SELECT_INTERFACE_RESULT */
586static UINT urb_select_interface_result(GENERIC_CHANNEL_CALLBACK* callback, UINT32 RequestId,
587 UINT32 InterfaceId, UINT32 MessageId,
588 MSUSB_INTERFACE_DESCRIPTOR* MsInterface)
589{
590 WINPR_ASSERT(callback);
591 WINPR_ASSERT(MsInterface);
592
593 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
594 wStream* out =
595 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
596
597 if (!out)
598 return ERROR_OUTOFMEMORY;
599
600 const uint32_t size = 8U + interface_size;
601 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
602
603 if (!Stream_EnsureRemainingCapacity(out, 4))
604 goto fail;
605 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
606
607 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
608 goto fail;
609
610 if (!msusb_msinterface_write(MsInterface, out))
611 goto fail;
612
613 return send_urb_completion_message(callback, out, 0, 0, nullptr);
614
615fail:
616 Stream_Free(out, TRUE);
617
618 return ERROR_INTERNAL_ERROR;
619}
620
621static UINT urb_select_interface(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
622 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
623 int transferDir)
624{
625 const BOOL noAck = (RequestField & 0x80000000U) != 0;
626 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
627
628 if (!callback || !s || !udevman || !pdev)
629 return ERROR_INVALID_PARAMETER;
630
631 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
632
633 if (!urbdrc)
634 return ERROR_INVALID_PARAMETER;
635
636 if (transferDir == 0)
637 {
638 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_interface: not support transfer out");
639 return ERROR_INVALID_PARAMETER;
640 }
641
642 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
643 return ERROR_INVALID_DATA;
644
645 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
646 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
647 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = msusb_msinterface_read(s);
648
649 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
650 {
651 msusb_msinterface_free(MsInterface);
652 return ERROR_INVALID_DATA;
653 }
654
655 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
656 if (OutputBufferSize != 0)
657 {
658 WLog_Print(urbdrc->log, WLOG_ERROR,
659 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
660 "%" PRIu32,
661 OutputBufferSize);
662 msusb_msinterface_free(MsInterface);
663 return ERROR_INVALID_DATA;
664 }
665
666 const int lerr =
667 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
668 if (lerr != 0)
669 {
670 msusb_msinterface_free(MsInterface);
671 return ERROR_INTERNAL_ERROR;
672 }
673
674 /* replace device's MsInterface */
675 MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->get_MsConfig(pdev);
676 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
677 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
678 return ERROR_BAD_CONFIGURATION;
679
680 /* complete configuration setup */
681 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
682 return ERROR_BAD_CONFIGURATION;
683
684 if (noAck)
685 return CHANNEL_RC_OK;
686
687 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
688}
689
690static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
691 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
692 int transferDir, int External)
693{
694 UINT32 out_size = 0;
695 UINT32 InterfaceId = 0;
696 UINT32 EndpointAddress = 0;
697 UINT32 PipeHandle = 0;
698 UINT32 TransferFlags = 0;
699 UINT32 OutputBufferSize = 0;
700 UINT32 usbd_status = 0;
701 UINT32 Timeout = 0;
702 BYTE bmRequestType = 0;
703 BYTE Request = 0;
704 UINT16 Value = 0;
705 UINT16 Index = 0;
706 UINT16 length = 0;
707 BYTE* buffer = nullptr;
708 wStream* out = nullptr;
709 URBDRC_PLUGIN* urbdrc = nullptr;
710 const BOOL noAck = (RequestField & 0x80000000U) != 0;
711 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
712
713 if (!callback || !s || !udevman || !pdev)
714 return ERROR_INVALID_PARAMETER;
715
716 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
717
718 if (!urbdrc)
719 return ERROR_INVALID_PARAMETER;
720
721 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
722 return ERROR_INVALID_DATA;
723
724 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
725 Stream_Read_UINT32(s, PipeHandle);
726 Stream_Read_UINT32(s, TransferFlags);
727 EndpointAddress = (PipeHandle & 0x000000ff);
728 Timeout = 2000;
729
730 switch (External)
731 {
732 case URB_CONTROL_TRANSFER_EXTERNAL:
733 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
734 return ERROR_INVALID_DATA;
735
736 Stream_Read_UINT32(s, Timeout);
737 break;
738
739 case URB_CONTROL_TRANSFER_NONEXTERNAL:
740 break;
741 default:
742 break;
743 }
744
746 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
747 return ERROR_INVALID_DATA;
748
749 Stream_Read_UINT8(s, bmRequestType);
750 Stream_Read_UINT8(s, Request);
751 Stream_Read_UINT16(s, Value);
752 Stream_Read_UINT16(s, Index);
753 Stream_Read_UINT16(s, length);
754 Stream_Read_UINT32(s, OutputBufferSize);
755
756 if (length != OutputBufferSize)
757 {
758 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_control_transfer ERROR: buf != length");
759 return ERROR_INVALID_DATA;
760 }
761
762 out_size = 36 + OutputBufferSize;
763 out = Stream_New(nullptr, out_size);
764
765 if (!out)
766 return ERROR_OUTOFMEMORY;
767
768 Stream_Seek(out, 36);
770 buffer = Stream_Pointer(out);
771
772 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
773 {
774 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
775 {
776 Stream_Free(out, TRUE);
777 return ERROR_INVALID_DATA;
778 }
779 Stream_Copy(s, out, OutputBufferSize);
780 }
781
783 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
784 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
785 Timeout))
786 {
787 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
788 Stream_Free(out, TRUE);
789 return ERROR_INTERNAL_ERROR;
790 }
791
792 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
793 usbd_status, OutputBufferSize);
794}
795
796static void urb_bulk_transfer_cb(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
797 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
798 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
799 WINPR_ATTR_UNUSED UINT32 StartFrame,
800 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
801{
802 if (!pdev->isChannelClosed(pdev))
803 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
804 OutputBufferSize);
805 else
806 Stream_Free(out, TRUE);
807}
808
809static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
810 wStream* s, UINT32 RequestField, UINT32 MessageId,
811 IUDEVMAN* udevman, int transferDir)
812{
813 UINT32 EndpointAddress = 0;
814 UINT32 PipeHandle = 0;
815 UINT32 TransferFlags = 0;
816 UINT32 OutputBufferSize = 0;
817 const BOOL noAck = (RequestField & 0x80000000U) != 0;
818 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
819
820 if (!pdev || !callback || !s || !udevman)
821 return ERROR_INVALID_PARAMETER;
822
823 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
824 return ERROR_INVALID_DATA;
825
826 Stream_Read_UINT32(s, PipeHandle);
827 Stream_Read_UINT32(s, TransferFlags);
828 Stream_Read_UINT32(s, OutputBufferSize);
829 EndpointAddress = (PipeHandle & 0x000000ff);
830
831 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
832 {
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
834 {
835 return ERROR_INVALID_DATA;
836 }
837 }
838
840 const int rc = pdev->bulk_or_interrupt_transfer(
841 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
842 OutputBufferSize,
843 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
844 urb_bulk_transfer_cb, 10000);
845
846 return (uint32_t)rc;
847}
848
849static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
850 GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
851 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
852 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
853 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
854{
855 if (!noAck)
856 {
857 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
858 Stream_ResetPosition(out);
859
860 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
861 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
862 {
863 Stream_Free(out, TRUE);
864 return;
865 }
866
867 Stream_Write_UINT32(out, RequestId);
868 Stream_Write_UINT32(out, 20 + packetSize);
869 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
870 status))
871 {
872 Stream_Free(out, TRUE);
873 return;
874 }
875
876 Stream_Write_UINT32(out, StartFrame);
878 if (status == 0)
879 {
881 Stream_Write_UINT32(out, NumberOfPackets);
882 Stream_Write_UINT32(out, ErrorCount);
883 Stream_Seek(out, packetSize);
884 }
885 else
886 {
887 Stream_Write_UINT32(out, 0);
888 Stream_Write_UINT32(out, ErrorCount);
889 }
890
891 Stream_Write_UINT32(out, 0);
892 Stream_Write_UINT32(out, OutputBufferSize);
893 Stream_Seek(out, OutputBufferSize);
894
895 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
896 if (rc != CHANNEL_RC_OK)
897 WLog_WARN(TAG, "stream_write_and_free failed with %" PRIu32, rc);
898 }
899}
900
901static UINT urb_isoch_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
902 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
903 int transferDir)
904{
905 int rc = 0;
906 UINT32 EndpointAddress = 0;
907 UINT32 PipeHandle = 0;
908 UINT32 TransferFlags = 0;
909 UINT32 StartFrame = 0;
910 UINT32 NumberOfPackets = 0;
911 UINT32 ErrorCount = 0;
912 UINT32 OutputBufferSize = 0;
913 BYTE* packetDescriptorData = nullptr;
914 const BOOL noAck = (RequestField & 0x80000000U) != 0;
915 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
916
917 if (!pdev || !callback || !udevman)
918 return ERROR_INVALID_PARAMETER;
919
920 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
921 return ERROR_INVALID_DATA;
922
923 Stream_Read_UINT32(s, PipeHandle);
924 EndpointAddress = (PipeHandle & 0x000000ff);
925 Stream_Read_UINT32(s, TransferFlags);
926 Stream_Read_UINT32(s, StartFrame);
927 Stream_Read_UINT32(s, NumberOfPackets);
928 Stream_Read_UINT32(s, ErrorCount);
930 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
931 return ERROR_INVALID_DATA;
932
933 packetDescriptorData = Stream_Pointer(s);
934 Stream_Seek(s, 12ULL * NumberOfPackets);
935
936 if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UINT32)))
937 return ERROR_INVALID_DATA;
938 Stream_Read_UINT32(s, OutputBufferSize);
939
940 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
941 {
942 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
943 return ERROR_INVALID_DATA;
944 }
945
946 rc = pdev->isoch_transfer(
947 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
948 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
949 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
950 urb_isoch_transfer_cb, 2000);
951
952 if (rc < 0)
953 return ERROR_INTERNAL_ERROR;
954 return (UINT)rc;
955}
956
957static UINT urb_control_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
958 wStream* s, UINT32 RequestField, UINT32 MessageId,
959 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
960{
961 size_t out_size = 0;
962 UINT32 InterfaceId = 0;
963 UINT32 OutputBufferSize = 0;
964 UINT32 usbd_status = 0;
965 BYTE bmRequestType = 0;
966 BYTE desc_index = 0;
967 BYTE desc_type = 0;
968 UINT16 langId = 0;
969 wStream* out = nullptr;
970 URBDRC_PLUGIN* urbdrc = nullptr;
971 const BOOL noAck = (RequestField & 0x80000000U) != 0;
972 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
973
974 if (!callback || !s || !udevman || !pdev)
975 return ERROR_INVALID_PARAMETER;
976
977 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
978
979 if (!urbdrc)
980 return ERROR_INVALID_PARAMETER;
981
982 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
983 return ERROR_INVALID_DATA;
984
985 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
986 Stream_Read_UINT8(s, desc_index);
987 Stream_Read_UINT8(s, desc_type);
988 Stream_Read_UINT16(s, langId);
989 Stream_Read_UINT32(s, OutputBufferSize);
990 if (OutputBufferSize > UINT32_MAX - 36)
991 return ERROR_INVALID_DATA;
992 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
993 {
994 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
995 return ERROR_INVALID_DATA;
996 }
997
998 out_size = 36ULL + OutputBufferSize;
999 out = Stream_New(nullptr, out_size);
1000
1001 if (!out)
1002 return ERROR_OUTOFMEMORY;
1003
1004 Stream_Seek(out, 36);
1005 bmRequestType = func_recipient;
1006
1007 switch (transferDir)
1008 {
1009 case USBD_TRANSFER_DIRECTION_IN:
1010 bmRequestType |= 0x80;
1011 break;
1012
1013 case USBD_TRANSFER_DIRECTION_OUT:
1014 bmRequestType |= 0x00;
1015 Stream_Copy(s, out, OutputBufferSize);
1016 Stream_Rewind(out, OutputBufferSize);
1017 break;
1018
1019 default:
1020 WLog_Print(urbdrc->log, WLOG_DEBUG, "get error transferDir");
1021 OutputBufferSize = 0;
1022 usbd_status = USBD_STATUS_STALL_PID;
1023 break;
1024 }
1025
1027 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1028 0x06, /* REQUEST_GET_DESCRIPTOR */
1029 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1030 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1031 {
1032 WLog_Print(urbdrc->log, WLOG_ERROR, "get_descriptor failed");
1033 Stream_Free(out, TRUE);
1034 return ERROR_INTERNAL_ERROR;
1035 }
1036
1037 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1038 usbd_status, OutputBufferSize);
1039}
1040
1041static UINT urb_control_get_status_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1042 wStream* s, UINT32 RequestField, UINT32 MessageId,
1043 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1044{
1045 size_t out_size = 0;
1046 UINT32 InterfaceId = 0;
1047 UINT32 OutputBufferSize = 0;
1048 UINT32 usbd_status = 0;
1049 UINT16 Index = 0;
1050 BYTE bmRequestType = 0;
1051 wStream* out = nullptr;
1052 URBDRC_PLUGIN* urbdrc = nullptr;
1053 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1054 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1055
1056 if (!callback || !s || !udevman || !pdev)
1057 return ERROR_INVALID_PARAMETER;
1058
1059 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1060
1061 if (!urbdrc)
1062 return ERROR_INVALID_PARAMETER;
1063
1064 if (transferDir == 0)
1065 {
1066 WLog_Print(urbdrc->log, WLOG_DEBUG,
1067 "urb_control_get_status_request: transfer out not supported");
1068 return ERROR_INVALID_PARAMETER;
1069 }
1070
1071 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1072 return ERROR_INVALID_DATA;
1073
1074 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1075 Stream_Read_UINT16(s, Index);
1076 Stream_Seek(s, 2);
1077 Stream_Read_UINT32(s, OutputBufferSize);
1078 if (OutputBufferSize > UINT32_MAX - 36)
1079 return ERROR_INVALID_DATA;
1080 out_size = 36ULL + OutputBufferSize;
1081 out = Stream_New(nullptr, out_size);
1082
1083 if (!out)
1084 return ERROR_OUTOFMEMORY;
1085
1086 Stream_Seek(out, 36);
1087 bmRequestType = func_recipient | 0x80;
1088
1089 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00, /* REQUEST_GET_STATUS */
1090 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1091 1000))
1092 {
1093 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1094 Stream_Free(out, TRUE);
1095 return ERROR_INTERNAL_ERROR;
1096 }
1097
1098 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1099 usbd_status, OutputBufferSize);
1100}
1101
1102static UINT urb_control_vendor_or_class_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1103 wStream* s, UINT32 RequestField, UINT32 MessageId,
1104 IUDEVMAN* udevman, BYTE func_type,
1105 BYTE func_recipient, int transferDir)
1106{
1107 UINT32 out_size = 0;
1108 UINT32 InterfaceId = 0;
1109 UINT32 TransferFlags = 0;
1110 UINT32 usbd_status = 0;
1111 UINT32 OutputBufferSize = 0;
1112 BYTE ReqTypeReservedBits = 0;
1113 BYTE Request = 0;
1114 BYTE bmRequestType = 0;
1115 UINT16 Value = 0;
1116 UINT16 Index = 0;
1117 wStream* out = nullptr;
1118 URBDRC_PLUGIN* urbdrc = nullptr;
1119 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1120 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1121
1122 if (!callback || !s || !udevman || !pdev)
1123 return ERROR_INVALID_PARAMETER;
1124
1125 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1126
1127 if (!urbdrc)
1128 return ERROR_INVALID_PARAMETER;
1129
1130 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1131 return ERROR_INVALID_DATA;
1132
1133 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1134 Stream_Read_UINT32(s, TransferFlags);
1135 Stream_Read_UINT8(s, ReqTypeReservedBits);
1136 Stream_Read_UINT8(s, Request);
1137 Stream_Read_UINT16(s, Value);
1138 Stream_Read_UINT16(s, Index);
1139 Stream_Seek_UINT16(s);
1140 Stream_Read_UINT32(s, OutputBufferSize);
1141 if (OutputBufferSize > UINT32_MAX - 36)
1142 return ERROR_INVALID_DATA;
1143
1144 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1145 {
1146 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1147 return ERROR_INVALID_DATA;
1148 }
1149
1150 out_size = 36ULL + OutputBufferSize;
1151 out = Stream_New(nullptr, out_size);
1152
1153 if (!out)
1154 return ERROR_OUTOFMEMORY;
1155
1156 Stream_Seek(out, 36);
1157
1159 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1160 {
1161 Stream_Copy(s, out, OutputBufferSize);
1162 Stream_Rewind(out, OutputBufferSize);
1163 }
1164
1166 bmRequestType = func_type | func_recipient;
1167
1168 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1169 bmRequestType |= 0x80;
1170
1171 WLog_Print(urbdrc->log, WLOG_DEBUG,
1172 "RequestId 0x%" PRIx32 " TransferFlags: 0x%" PRIx32 " ReqTypeReservedBits: 0x%" PRIx8
1173 " "
1174 "Request:0x%" PRIx8 " Value: 0x%" PRIx16 " Index: 0x%" PRIx16
1175 " OutputBufferSize: 0x%" PRIx32 " bmRequestType: 0x%" PRIx8,
1176 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1177 OutputBufferSize, bmRequestType);
1178
1179 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1180 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1181 {
1182 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1183 Stream_Free(out, TRUE);
1184 return ERROR_INTERNAL_ERROR;
1185 }
1186
1187 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1188 usbd_status, OutputBufferSize);
1189}
1190
1191static UINT urb_os_feature_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1192 wStream* s, UINT32 RequestField, UINT32 MessageId,
1193 IUDEVMAN* udevman, int transferDir)
1194{
1195 size_t out_size = 0;
1196 UINT32 InterfaceId = 0;
1197 UINT32 OutputBufferSize = 0;
1198 UINT32 usbd_status = 0;
1199 BYTE Recipient = 0;
1200 BYTE InterfaceNumber = 0;
1201 BYTE Ms_PageIndex = 0;
1202 UINT16 Ms_featureDescIndex = 0;
1203 wStream* out = nullptr;
1204 int ret = 0;
1205 URBDRC_PLUGIN* urbdrc = nullptr;
1206 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1207 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1208
1209 if (!callback || !s || !udevman || !pdev)
1210 return ERROR_INVALID_PARAMETER;
1211
1212 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1213
1214 if (!urbdrc)
1215 return ERROR_INVALID_PARAMETER;
1216
1217 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1218 return ERROR_INVALID_DATA;
1219
1220 /* 2.2.9.15 TS_URB_OS_FEATURE_DESCRIPTOR_REQUEST */
1221 Stream_Read_UINT8(s, Recipient);
1222 Recipient = (Recipient & 0x1f); /* Mask out Padding1 */
1223 Stream_Read_UINT8(s, InterfaceNumber);
1224 Stream_Read_UINT8(s, Ms_PageIndex);
1225 Stream_Read_UINT16(s, Ms_featureDescIndex);
1226 Stream_Seek(s, 3); /* Padding 2 */
1227 Stream_Read_UINT32(s, OutputBufferSize);
1228 if (OutputBufferSize > UINT32_MAX - 36)
1229 return ERROR_INVALID_DATA;
1230
1231 switch (transferDir)
1232 {
1233 case USBD_TRANSFER_DIRECTION_OUT:
1234 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1235 return ERROR_INVALID_DATA;
1236
1237 break;
1238
1239 default:
1240 break;
1241 }
1242
1243 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1244 out_size = 36ULL + OutputBufferSize;
1245 out = Stream_New(nullptr, out_size);
1246
1247 if (!out)
1248 return ERROR_OUTOFMEMORY;
1249
1250 Stream_Seek(out, 36);
1251
1252 switch (transferDir)
1253 {
1254 case USBD_TRANSFER_DIRECTION_OUT:
1255 Stream_Copy(s, out, OutputBufferSize);
1256 Stream_Rewind(out, OutputBufferSize);
1257 break;
1258
1259 case USBD_TRANSFER_DIRECTION_IN:
1260 break;
1261 default:
1262 break;
1263 }
1264
1265 WLog_Print(urbdrc->log, WLOG_DEBUG,
1266 "Ms descriptor arg: Recipient:0x%" PRIx8 ", "
1267 "InterfaceNumber:0x%" PRIx8 ", Ms_PageIndex:0x%" PRIx8 ", "
1268 "Ms_featureDescIndex:0x%" PRIx16 ", OutputBufferSize:0x%" PRIx32 "",
1269 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1271 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1272 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1273 &OutputBufferSize, Stream_Pointer(out), 1000);
1274
1275 if (ret < 0)
1276 WLog_Print(urbdrc->log, WLOG_DEBUG, "os_feature_descriptor_request: error num %d", ret);
1277
1278 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1279 usbd_status, OutputBufferSize);
1280}
1281
1282static UINT urb_pipe_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1283 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1284 int transferDir, int action)
1285{
1286 UINT32 usbd_status = 0;
1287 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1288 int rc = 0;
1289 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1290 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1291
1292 if (!callback || !s || !udevman || !pdev)
1293 return ERROR_INVALID_PARAMETER;
1294
1295 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1296
1297 if (!urbdrc)
1298 return ERROR_INVALID_PARAMETER;
1299
1300 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1301 return ERROR_INVALID_DATA;
1302
1303 if (transferDir == 0)
1304 {
1305 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: not support transfer out");
1306 return ERROR_INVALID_PARAMETER;
1307 }
1308
1309 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1310 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1311 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1312 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1313
1314 if (OutputBufferSize != 0)
1315 {
1316 WLog_Print(urbdrc->log, WLOG_DEBUG,
1317 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32 " != 0",
1318 OutputBufferSize);
1319 return ERROR_BAD_CONFIGURATION;
1320 }
1321
1322 switch (action)
1323 {
1324 case PIPE_CANCEL:
1325 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1326 PIPE_CANCEL);
1327
1328 if (rc < 0)
1329 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE SET HALT: error %u", ret);
1330 else
1331 ret = USBD_STATUS_SUCCESS;
1332
1333 break;
1334
1335 case PIPE_RESET:
1336 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: PIPE_RESET ep 0x%" PRIx32 "",
1337 EndpointAddress);
1338 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1339 PIPE_RESET);
1340
1341 if (rc < 0)
1342 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE RESET: error %u", ret);
1343 else
1344 ret = USBD_STATUS_SUCCESS;
1345
1346 break;
1347
1348 default:
1349 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request action: %d not supported",
1350 action);
1351 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1352 break;
1353 }
1354
1357 wStream* out = Stream_New(nullptr, 36);
1358
1359 if (!out)
1360 return ERROR_OUTOFMEMORY;
1361
1362 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1363 0);
1364}
1365/* [MS-RDPEUSB] 2.2.10.4 TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT */
1366static UINT urb_send_current_frame_number_result(GENERIC_CHANNEL_CALLBACK* callback,
1367 UINT32 RequestId, UINT32 MessageId,
1368 UINT32 CompletionId, UINT32 FrameNumber)
1369{
1370 WINPR_ASSERT(callback);
1371
1372 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1373 wStream* out =
1374 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1375
1376 if (!out)
1377 return ERROR_OUTOFMEMORY;
1378
1379 Stream_Write_UINT32(out, 12);
1380 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1381 {
1382 Stream_Free(out, TRUE);
1383 return ERROR_OUTOFMEMORY;
1384 }
1385
1386 Stream_Write_UINT32(out, FrameNumber);
1387 return send_urb_completion_message(callback, out, 0, 0, nullptr);
1388}
1389
1390static UINT urb_get_current_frame_number(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1391 wStream* s, UINT32 RequestField, UINT32 MessageId,
1392 IUDEVMAN* udevman, int transferDir)
1393{
1394 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1395 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1396
1397 if (!callback || !s || !udevman || !pdev)
1398 return ERROR_INVALID_PARAMETER;
1399
1400 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1401
1402 if (!urbdrc)
1403 return ERROR_INVALID_PARAMETER;
1404
1405 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1406 return ERROR_INVALID_DATA;
1407
1408 if (transferDir == 0)
1409 {
1410 WLog_Print(urbdrc->log, WLOG_DEBUG,
1411 "urb_get_current_frame_number: not support transfer out");
1412 return ERROR_INVALID_PARAMETER;
1413 }
1414
1415 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1416 if (OutputBufferSize != 0)
1417 {
1418 WLog_Print(urbdrc->log, WLOG_WARN, "OutputBufferSize=%" PRIu32 ", expected 0",
1419 OutputBufferSize);
1420 }
1422 const UINT32 dummy_frames = GetTickCount();
1423 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1424
1425 if (noAck)
1426 return CHANNEL_RC_OK;
1427
1428 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1429 dummy_frames);
1430}
1431
1432/* Unused function for current server */
1433static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1434 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1435 UINT32 RequestField, UINT32 MessageId,
1436 IUDEVMAN* udevman, int transferDir)
1437{
1438 size_t out_size = 0;
1439 UINT32 InterfaceId = 0;
1440 UINT32 OutputBufferSize = 0;
1441 UINT32 usbd_status = 0;
1442 wStream* out = nullptr;
1443 URBDRC_PLUGIN* urbdrc = nullptr;
1444 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1445 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1446
1447 if (!callback || !s || !udevman || !pdev)
1448 return ERROR_INVALID_PARAMETER;
1449
1450 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1451
1452 if (!urbdrc)
1453 return ERROR_INVALID_PARAMETER;
1454
1455 if (transferDir == 0)
1456 {
1457 WLog_Print(urbdrc->log, WLOG_DEBUG,
1458 "urb_control_get_configuration_request:"
1459 " not support transfer out");
1460 return ERROR_INVALID_PARAMETER;
1461 }
1462
1463 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1464 return ERROR_INVALID_DATA;
1465
1466 Stream_Read_UINT32(s, OutputBufferSize);
1467 if (OutputBufferSize > UINT32_MAX - 36)
1468 return ERROR_INVALID_DATA;
1469 out_size = 36ULL + OutputBufferSize;
1470 out = Stream_New(nullptr, out_size);
1471
1472 if (!out)
1473 return ERROR_OUTOFMEMORY;
1474
1475 Stream_Seek(out, 36);
1476 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1477
1478 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1479 0x08, /* REQUEST_GET_CONFIGURATION */
1480 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1481 {
1482 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1483 Stream_Free(out, TRUE);
1484 return ERROR_INTERNAL_ERROR;
1485 }
1486
1487 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1488 usbd_status, OutputBufferSize);
1489}
1490
1491/* Unused function for current server */
1492static UINT urb_control_get_interface_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1493 wStream* s, UINT32 RequestField, UINT32 MessageId,
1494 IUDEVMAN* udevman, int transferDir)
1495{
1496 size_t out_size = 0;
1497 UINT32 InterfaceId = 0;
1498 UINT32 OutputBufferSize = 0;
1499 UINT32 usbd_status = 0;
1500 UINT16 InterfaceNr = 0;
1501 wStream* out = nullptr;
1502 URBDRC_PLUGIN* urbdrc = nullptr;
1503 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1504 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1505
1506 if (!callback || !s || !udevman || !pdev)
1507 return ERROR_INVALID_PARAMETER;
1508
1509 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1510
1511 if (!urbdrc)
1512 return ERROR_INVALID_PARAMETER;
1513
1514 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1515 return ERROR_INVALID_DATA;
1516
1517 if (transferDir == 0)
1518 {
1519 WLog_Print(urbdrc->log, WLOG_DEBUG,
1520 "urb_control_get_interface_request: not support transfer out");
1521 return ERROR_INVALID_PARAMETER;
1522 }
1523
1524 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1525 Stream_Read_UINT16(s, InterfaceNr);
1526 Stream_Seek(s, 2);
1527 Stream_Read_UINT32(s, OutputBufferSize);
1528 if (OutputBufferSize > UINT32_MAX - 36)
1529 return ERROR_INVALID_DATA;
1530 out_size = 36ULL + OutputBufferSize;
1531 out = Stream_New(nullptr, out_size);
1532
1533 if (!out)
1534 return ERROR_OUTOFMEMORY;
1535
1536 Stream_Seek(out, 36);
1537
1538 if (!pdev->control_transfer(
1539 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */
1540 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1541 {
1542 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1543 Stream_Free(out, TRUE);
1544 return ERROR_INTERNAL_ERROR;
1545 }
1546
1547 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1548 usbd_status, OutputBufferSize);
1549}
1550
1551static UINT urb_control_feature_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1552 wStream* s, UINT32 RequestField, UINT32 MessageId,
1553 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1554 int transferDir)
1555{
1556 UINT32 InterfaceId = 0;
1557 UINT32 OutputBufferSize = 0;
1558 UINT32 usbd_status = 0;
1559 UINT16 FeatureSelector = 0;
1560 UINT16 Index = 0;
1561 BYTE bmRequestType = 0;
1562 BYTE bmRequest = 0;
1563 wStream* out = nullptr;
1564 URBDRC_PLUGIN* urbdrc = nullptr;
1565 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1566 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1567
1568 if (!callback || !s || !udevman || !pdev)
1569 return ERROR_INVALID_PARAMETER;
1570
1571 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1572
1573 if (!urbdrc)
1574 return ERROR_INVALID_PARAMETER;
1575
1576 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1577 return ERROR_INVALID_DATA;
1578
1579 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1580 Stream_Read_UINT16(s, FeatureSelector);
1581 Stream_Read_UINT16(s, Index);
1582 Stream_Read_UINT32(s, OutputBufferSize);
1583 if (OutputBufferSize > UINT32_MAX - 36)
1584 return ERROR_INVALID_DATA;
1585 switch (transferDir)
1586 {
1587 case USBD_TRANSFER_DIRECTION_OUT:
1588 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1589 return ERROR_INVALID_DATA;
1590
1591 break;
1592
1593 default:
1594 break;
1595 }
1596
1597 out = Stream_New(nullptr, 36ULL + OutputBufferSize);
1598
1599 if (!out)
1600 return ERROR_OUTOFMEMORY;
1601
1602 Stream_Seek(out, 36);
1603 bmRequestType = func_recipient;
1604
1605 switch (transferDir)
1606 {
1607 case USBD_TRANSFER_DIRECTION_OUT:
1608 WLog_Print(urbdrc->log, WLOG_ERROR,
1609 "Function urb_control_feature_request: OUT Unchecked");
1610 Stream_Copy(s, out, OutputBufferSize);
1611 Stream_Rewind(out, OutputBufferSize);
1612 bmRequestType |= 0x00;
1613 break;
1614
1615 case USBD_TRANSFER_DIRECTION_IN:
1616 bmRequestType |= 0x80;
1617 break;
1618 default:
1619 break;
1620 }
1621
1622 switch (command)
1623 {
1624 case URB_SET_FEATURE:
1625 bmRequest = 0x03; /* REQUEST_SET_FEATURE */
1626 break;
1627
1628 case URB_CLEAR_FEATURE:
1629 bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */
1630 break;
1631
1632 default:
1633 WLog_Print(urbdrc->log, WLOG_ERROR,
1634 "urb_control_feature_request: Error Command 0x%02" PRIx8 "", command);
1635 Stream_Free(out, TRUE);
1636 return ERROR_INTERNAL_ERROR;
1637 }
1638
1639 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1640 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1641 {
1642 WLog_Print(urbdrc->log, WLOG_DEBUG, "feature control transfer failed");
1643 Stream_Free(out, TRUE);
1644 return ERROR_INTERNAL_ERROR;
1645 }
1646
1647 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1648 usbd_status, OutputBufferSize);
1649}
1650
1651static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1652 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1653 int transferDir)
1654{
1655 UINT32 CbTsUrb = 0;
1656 UINT16 Size = 0;
1657 UINT16 URB_Function = 0;
1658 UINT32 RequestId = 0;
1659 UINT error = ERROR_INTERNAL_ERROR;
1660 URBDRC_PLUGIN* urbdrc = nullptr;
1661
1662 if (!callback || !s || !udevman || !pdev)
1663 return ERROR_INVALID_PARAMETER;
1664
1665 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1666
1667 if (!urbdrc)
1668 return ERROR_INVALID_PARAMETER;
1669
1670 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1671 return ERROR_INVALID_DATA;
1672
1673 Stream_Read_UINT32(s, CbTsUrb);
1674 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1675 return ERROR_INVALID_DATA;
1676 Stream_Read_UINT16(s, Size);
1677 if (Size != CbTsUrb)
1678 {
1679 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1680 ? "2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1681 : "2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1682 WLog_ERR(TAG,
1683 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1684 " != %s::CbTsUrb 0x%08" PRIx32,
1685 Size, section, CbTsUrb);
1686 return ERROR_INVALID_DATA;
1687 }
1688 Stream_Read_UINT16(s, URB_Function);
1689 Stream_Read_UINT32(s, RequestId);
1690 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB %s[%" PRIu16 "]", urb_function_string(URB_Function),
1691 URB_Function);
1692
1693 switch (URB_Function)
1694 {
1695 case TS_URB_SELECT_CONFIGURATION:
1696 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1697 transferDir);
1698 break;
1699
1700 case TS_URB_SELECT_INTERFACE:
1701 error =
1702 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1703 break;
1704
1705 case TS_URB_PIPE_REQUEST:
1706 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1707 PIPE_CANCEL);
1708 break;
1709
1710 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1714 break;
1715
1716 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1720 break;
1721
1722 case TS_URB_GET_FRAME_LENGTH:
1726 break;
1727
1728 case TS_URB_SET_FRAME_LENGTH:
1732 break;
1733
1734 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1735 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1736 transferDir);
1737 break;
1738
1739 case TS_URB_CONTROL_TRANSFER:
1740 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1741 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1742 break;
1743
1744 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1745 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1746 transferDir);
1747 break;
1748
1749 case TS_URB_ISOCH_TRANSFER:
1750 error =
1751 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1752 break;
1753
1754 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1755 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1756 0x00, transferDir);
1757 break;
1758
1759 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1760 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1761 0x00, transferDir);
1762 break;
1763
1764 case TS_URB_SET_FEATURE_TO_DEVICE:
1765 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1766 0x00, URB_SET_FEATURE, transferDir);
1767 break;
1768
1769 case TS_URB_SET_FEATURE_TO_INTERFACE:
1770 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1771 0x01, URB_SET_FEATURE, transferDir);
1772 break;
1773
1774 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1775 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1776 0x02, URB_SET_FEATURE, transferDir);
1777 break;
1778
1779 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1780 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1781 0x00, URB_CLEAR_FEATURE, transferDir);
1782 break;
1783
1784 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1785 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1786 0x01, URB_CLEAR_FEATURE, transferDir);
1787 break;
1788
1789 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1790 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1791 0x02, URB_CLEAR_FEATURE, transferDir);
1792 break;
1793
1794 case TS_URB_GET_STATUS_FROM_DEVICE:
1795 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1796 0x00, transferDir);
1797 break;
1798
1799 case TS_URB_GET_STATUS_FROM_INTERFACE:
1800 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1801 0x01, transferDir);
1802 break;
1803
1804 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1805 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1806 0x02, transferDir);
1807 break;
1808
1809 case TS_URB_RESERVED_0X0016:
1810 break;
1811
1812 case TS_URB_VENDOR_DEVICE:
1813 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1814 udevman, (0x02u << 5), /* vendor type */
1815 0x00, transferDir);
1816 break;
1817
1818 case TS_URB_VENDOR_INTERFACE:
1819 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1820 udevman, (0x02u << 5), /* vendor type */
1821 0x01, transferDir);
1822 break;
1823
1824 case TS_URB_VENDOR_ENDPOINT:
1825 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1826 udevman, (0x02u << 5), /* vendor type */
1827 0x02, transferDir);
1828 break;
1829
1830 case TS_URB_CLASS_DEVICE:
1831 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1832 udevman, (0x01u << 5), /* class type */
1833 0x00, transferDir);
1834 break;
1835
1836 case TS_URB_CLASS_INTERFACE:
1837 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1838 udevman, (0x01u << 5), /* class type */
1839 0x01, transferDir);
1840 break;
1841
1842 case TS_URB_CLASS_ENDPOINT:
1843 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1844 udevman, (0x01u << 5), /* class type */
1845 0x02, transferDir);
1846 break;
1847
1848 case TS_URB_RESERVE_0X001D:
1849 break;
1850
1851 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1852 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1853 PIPE_RESET);
1854 break;
1855
1856 case TS_URB_CLASS_OTHER:
1857 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1858 udevman, (0x01u << 5), /* class type */
1859 0x03, transferDir);
1860 break;
1861
1862 case TS_URB_VENDOR_OTHER:
1863 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1864 udevman, (0x02u << 5), /* vendor type */
1865 0x03, transferDir);
1866 break;
1867
1868 case TS_URB_GET_STATUS_FROM_OTHER:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1870 0x03, transferDir);
1871 break;
1872
1873 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1874 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1875 0x03, URB_CLEAR_FEATURE, transferDir);
1876 break;
1877
1878 case TS_URB_SET_FEATURE_TO_OTHER:
1879 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1880 0x03, URB_SET_FEATURE, transferDir);
1881 break;
1882
1883 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1884 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1885 0x02, transferDir);
1886 break;
1887
1888 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1889 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1890 0x02, transferDir);
1891 break;
1892
1893 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1894 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1895 udevman, transferDir);
1896 break;
1897
1898 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1899 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1900 udevman, transferDir);
1901 break;
1902
1903 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1904 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1905 0x01, transferDir);
1906 break;
1907
1908 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1909 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1910 0x01, transferDir);
1911 break;
1912
1913 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1914 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1915 udevman, transferDir);
1916 break;
1917
1918 case TS_URB_RESERVE_0X002B:
1919 case TS_URB_RESERVE_0X002C:
1920 case TS_URB_RESERVE_0X002D:
1921 case TS_URB_RESERVE_0X002E:
1922 case TS_URB_RESERVE_0X002F:
1923 break;
1924
1926 case TS_URB_SYNC_RESET_PIPE:
1927 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1928 PIPE_RESET);
1929 break;
1930
1931 case TS_URB_SYNC_CLEAR_STALL:
1932 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1933 PIPE_RESET);
1934 break;
1935
1936 case TS_URB_CONTROL_TRANSFER_EX:
1937 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1938 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1939 break;
1940
1941 default:
1942 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB_Func: %" PRIx16 " is not found!",
1943 URB_Function);
1944 break;
1945 }
1946
1947 if (error)
1948 {
1949 WLog_Print(urbdrc->log, WLOG_WARN,
1950 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1951 urb_function_string(URB_Function), URB_Function, error);
1952 }
1953
1954 return error;
1955}
1956
1957UINT urbdrc_process_udev_data_transfer(GENERIC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
1958 IUDEVMAN* udevman, wStream* data)
1959{
1960 UINT32 InterfaceId = 0;
1961 UINT32 MessageId = 0;
1962 UINT32 FunctionId = 0;
1963 IUDEVICE* pdev = nullptr;
1964 UINT error = ERROR_INTERNAL_ERROR;
1965
1966 if (!urbdrc || !data || !callback || !udevman)
1967 goto fail;
1968
1969 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1970 goto fail;
1971
1972 Stream_Rewind_UINT32(data);
1973
1974 Stream_Read_UINT32(data, InterfaceId);
1975 Stream_Read_UINT32(data, MessageId);
1976 Stream_Read_UINT32(data, FunctionId);
1977
1978 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1979
1980 /* Device does not exist, ignore this request. */
1981 if (pdev == nullptr)
1982 {
1983 error = ERROR_SUCCESS;
1984 goto fail;
1985 }
1986
1987 /* Device has been removed, ignore this request. */
1988 if (pdev->isChannelClosed(pdev))
1989 {
1990 error = ERROR_SUCCESS;
1991 goto fail;
1992 }
1993
1994 /* USB kernel driver detach!! */
1995 if (!pdev->detach_kernel_driver(pdev))
1996 {
1997 error = ERROR_SUCCESS;
1998 goto fail;
1999 }
2000
2001 switch (FunctionId)
2002 {
2003 case CANCEL_REQUEST:
2004 error = urbdrc_process_cancel_request(pdev, data, udevman);
2005 break;
2006
2007 case REGISTER_REQUEST_CALLBACK:
2008 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2009 break;
2010
2011 case IO_CONTROL:
2012 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2013 break;
2014
2015 case INTERNAL_IO_CONTROL:
2016 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2017 break;
2018
2019 case QUERY_DEVICE_TEXT:
2020 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2021 break;
2022
2023 case TRANSFER_IN_REQUEST:
2024 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2025 USBD_TRANSFER_DIRECTION_IN);
2026 break;
2027
2028 case TRANSFER_OUT_REQUEST:
2029 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2030 USBD_TRANSFER_DIRECTION_OUT);
2031 break;
2032
2033 case RETRACT_DEVICE:
2034 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2035 break;
2036
2037 default:
2038 WLog_Print(urbdrc->log, WLOG_WARN,
2039 "urbdrc_process_udev_data_transfer:"
2040 " unknown FunctionId 0x%" PRIX32 "",
2041 FunctionId);
2042 break;
2043 }
2044
2045fail:
2046 if (error)
2047 {
2048 WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
2049 }
2050
2051 return error;
2052}