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_SetPosition(out, 0);
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, "select_interface %" PRIu8 " [%" PRIu8 "] failed",
471 InterfaceNumber, AlternateSetting);
472 }
473 }
474}
475
476/* [MS-RDPEUSB] 2.2.10.2 TS_URB_SELECT_CONFIGURATION_RESULT */
477static UINT send_urb_select_configuration_result(GENERIC_CHANNEL_CALLBACK* callback,
478 UINT32 InterfaceId, UINT32 MessageId,
479 UINT32 RequestId, UINT32 UrbStatus,
480 const MSUSB_CONFIG_DESCRIPTOR* MsConfig)
481{
482 wStream* out =
483 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
484 if (!out)
485 return ERROR_OUTOFMEMORY;
486
487 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
488 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
489
490 if (!Stream_EnsureRemainingCapacity(out, 4))
491 goto fail;
492 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
493
494 if (!write_urb_result_header(out, usize, UrbStatus))
495 goto fail;
496
498 if (MsConfig)
499 {
500 if (!msusb_msconfig_write(MsConfig, out))
501 goto fail;
502 }
503 else
504 {
505 Stream_Write_UINT32(out, 0);
506 Stream_Write_UINT32(out, 0);
507 }
508
509 return send_urb_completion_message(callback, out, 0, 0, nullptr);
510
511fail:
512 Stream_Free(out, TRUE);
513 return ERROR_OUTOFMEMORY;
514}
515
516static UINT urb_select_configuration(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
517 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
518 int transferDir)
519{
520 MSUSB_CONFIG_DESCRIPTOR* MsConfig = nullptr;
521 UINT32 NumInterfaces = 0;
522 UINT32 usbd_status = 0;
523 BYTE ConfigurationDescriptorIsValid = 0;
524 URBDRC_PLUGIN* urbdrc = nullptr;
525 const BOOL noAck = (RequestField & 0x80000000U) != 0;
526 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
527
528 if (!callback || !s || !udevman || !pdev)
529 return ERROR_INVALID_PARAMETER;
530
531 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
532
533 if (!urbdrc)
534 return ERROR_INVALID_PARAMETER;
535
536 if (transferDir == 0)
537 {
538 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_configuration: unsupported transfer out");
539 return ERROR_INVALID_PARAMETER;
540 }
541
542 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
543 return ERROR_INVALID_DATA;
544
545 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
546 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
547 Stream_Seek(s, 3); /* Padding */
548 Stream_Read_UINT32(s, NumInterfaces);
549
551 if (ConfigurationDescriptorIsValid)
552 {
553 /* parser data for struct config */
554 MsConfig = msusb_msconfig_read(s, NumInterfaces);
555
556 if (!MsConfig)
557 return ERROR_INVALID_DATA;
558
559 /* select config */
560 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
561 if (lrc != 0)
562 {
563 msusb_msconfig_free(MsConfig);
564 MsConfig = nullptr;
565 return ERROR_INTERNAL_ERROR;
566 }
567
568 /* select all interface */
569 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
570 /* complete configuration setup */
571 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
572 {
573 msusb_msconfig_free(MsConfig);
574 MsConfig = nullptr;
575 }
576 }
577
578 if (noAck)
579 return CHANNEL_RC_OK;
580 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
581 usbd_status, MsConfig);
582}
583
584/* [MS-RDPEUSB[ 2.2.10.3 TS_URB_SELECT_INTERFACE_RESULT */
585static UINT urb_select_interface_result(GENERIC_CHANNEL_CALLBACK* callback, UINT32 RequestId,
586 UINT32 InterfaceId, UINT32 MessageId,
587 MSUSB_INTERFACE_DESCRIPTOR* MsInterface)
588{
589 WINPR_ASSERT(callback);
590 WINPR_ASSERT(MsInterface);
591
592 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
593 wStream* out =
594 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
595
596 if (!out)
597 return ERROR_OUTOFMEMORY;
598
599 const uint32_t size = 8U + interface_size;
600 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
601
602 if (!Stream_EnsureRemainingCapacity(out, 4))
603 goto fail;
604 Stream_Write_UINT32(out, usize); /* CbTsUrbResult */
605
606 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
607 goto fail;
608
609 if (!msusb_msinterface_write(MsInterface, out))
610 goto fail;
611
612 return send_urb_completion_message(callback, out, 0, 0, nullptr);
613
614fail:
615 Stream_Free(out, TRUE);
616
617 return ERROR_INTERNAL_ERROR;
618}
619
620static UINT urb_select_interface(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
621 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
622 int transferDir)
623{
624 const BOOL noAck = (RequestField & 0x80000000U) != 0;
625 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
626
627 if (!callback || !s || !udevman || !pdev)
628 return ERROR_INVALID_PARAMETER;
629
630 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
631
632 if (!urbdrc)
633 return ERROR_INVALID_PARAMETER;
634
635 if (transferDir == 0)
636 {
637 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_select_interface: not support transfer out");
638 return ERROR_INVALID_PARAMETER;
639 }
640
641 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
642 return ERROR_INVALID_DATA;
643
644 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
645 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
646 MSUSB_INTERFACE_DESCRIPTOR* MsInterface = msusb_msinterface_read(s);
647
648 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
649 {
650 msusb_msinterface_free(MsInterface);
651 return ERROR_INVALID_DATA;
652 }
653
654 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
655 if (OutputBufferSize != 0)
656 {
657 WLog_Print(urbdrc->log, WLOG_ERROR,
658 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
659 "%" PRIu32,
660 OutputBufferSize);
661 msusb_msinterface_free(MsInterface);
662 return ERROR_INVALID_DATA;
663 }
664
665 const int lerr =
666 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
667 if (lerr != 0)
668 {
669 msusb_msinterface_free(MsInterface);
670 return ERROR_INTERNAL_ERROR;
671 }
672
673 /* replace device's MsInterface */
674 MSUSB_CONFIG_DESCRIPTOR* MsConfig = pdev->get_MsConfig(pdev);
675 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
676 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
677 return ERROR_BAD_CONFIGURATION;
678
679 /* complete configuration setup */
680 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
681 return ERROR_BAD_CONFIGURATION;
682
683 if (noAck)
684 return CHANNEL_RC_OK;
685
686 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
687}
688
689static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
690 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
691 int transferDir, int External)
692{
693 UINT32 out_size = 0;
694 UINT32 InterfaceId = 0;
695 UINT32 EndpointAddress = 0;
696 UINT32 PipeHandle = 0;
697 UINT32 TransferFlags = 0;
698 UINT32 OutputBufferSize = 0;
699 UINT32 usbd_status = 0;
700 UINT32 Timeout = 0;
701 BYTE bmRequestType = 0;
702 BYTE Request = 0;
703 UINT16 Value = 0;
704 UINT16 Index = 0;
705 UINT16 length = 0;
706 BYTE* buffer = nullptr;
707 wStream* out = nullptr;
708 URBDRC_PLUGIN* urbdrc = nullptr;
709 const BOOL noAck = (RequestField & 0x80000000U) != 0;
710 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
711
712 if (!callback || !s || !udevman || !pdev)
713 return ERROR_INVALID_PARAMETER;
714
715 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
716
717 if (!urbdrc)
718 return ERROR_INVALID_PARAMETER;
719
720 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
721 return ERROR_INVALID_DATA;
722
723 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
724 Stream_Read_UINT32(s, PipeHandle);
725 Stream_Read_UINT32(s, TransferFlags);
726 EndpointAddress = (PipeHandle & 0x000000ff);
727 Timeout = 2000;
728
729 switch (External)
730 {
731 case URB_CONTROL_TRANSFER_EXTERNAL:
732 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
733 return ERROR_INVALID_DATA;
734
735 Stream_Read_UINT32(s, Timeout);
736 break;
737
738 case URB_CONTROL_TRANSFER_NONEXTERNAL:
739 break;
740 default:
741 break;
742 }
743
745 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
746 return ERROR_INVALID_DATA;
747
748 Stream_Read_UINT8(s, bmRequestType);
749 Stream_Read_UINT8(s, Request);
750 Stream_Read_UINT16(s, Value);
751 Stream_Read_UINT16(s, Index);
752 Stream_Read_UINT16(s, length);
753 Stream_Read_UINT32(s, OutputBufferSize);
754
755 if (length != OutputBufferSize)
756 {
757 WLog_Print(urbdrc->log, WLOG_ERROR, "urb_control_transfer ERROR: buf != length");
758 return ERROR_INVALID_DATA;
759 }
760
761 out_size = 36 + OutputBufferSize;
762 out = Stream_New(nullptr, out_size);
763
764 if (!out)
765 return ERROR_OUTOFMEMORY;
766
767 Stream_Seek(out, 36);
769 buffer = Stream_Pointer(out);
770
771 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
772 {
773 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
774 {
775 Stream_Free(out, TRUE);
776 return ERROR_INVALID_DATA;
777 }
778 Stream_Copy(s, out, OutputBufferSize);
779 }
780
782 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
783 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
784 Timeout))
785 {
786 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
787 Stream_Free(out, TRUE);
788 return ERROR_INTERNAL_ERROR;
789 }
790
791 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
792 usbd_status, OutputBufferSize);
793}
794
795static void urb_bulk_transfer_cb(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
796 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
797 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
798 WINPR_ATTR_UNUSED UINT32 StartFrame,
799 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
800{
801 if (!pdev->isChannelClosed(pdev))
802 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
803 OutputBufferSize);
804 else
805 Stream_Free(out, TRUE);
806}
807
808static UINT urb_bulk_or_interrupt_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
809 wStream* s, UINT32 RequestField, UINT32 MessageId,
810 IUDEVMAN* udevman, int transferDir)
811{
812 UINT32 EndpointAddress = 0;
813 UINT32 PipeHandle = 0;
814 UINT32 TransferFlags = 0;
815 UINT32 OutputBufferSize = 0;
816 const BOOL noAck = (RequestField & 0x80000000U) != 0;
817 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
818
819 if (!pdev || !callback || !s || !udevman)
820 return ERROR_INVALID_PARAMETER;
821
822 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
823 return ERROR_INVALID_DATA;
824
825 Stream_Read_UINT32(s, PipeHandle);
826 Stream_Read_UINT32(s, TransferFlags);
827 Stream_Read_UINT32(s, OutputBufferSize);
828 EndpointAddress = (PipeHandle & 0x000000ff);
829
830 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
831 {
832 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
833 {
834 return ERROR_INVALID_DATA;
835 }
836 }
837
839 const int rc = pdev->bulk_or_interrupt_transfer(
840 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
841 OutputBufferSize,
842 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
843 urb_bulk_transfer_cb, 10000);
844
845 return (uint32_t)rc;
846}
847
848static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
849 GENERIC_CHANNEL_CALLBACK* callback, wStream* out,
850 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
851 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
852 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
853{
854 if (!noAck)
855 {
856 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
857 Stream_SetPosition(out, 0);
858
859 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
860 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
861 {
862 Stream_Free(out, TRUE);
863 return;
864 }
865
866 Stream_Write_UINT32(out, RequestId);
867 Stream_Write_UINT32(out, 20 + packetSize);
868 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
869 status))
870 {
871 Stream_Free(out, TRUE);
872 return;
873 }
874
875 Stream_Write_UINT32(out, StartFrame);
877 if (status == 0)
878 {
880 Stream_Write_UINT32(out, NumberOfPackets);
881 Stream_Write_UINT32(out, ErrorCount);
882 Stream_Seek(out, packetSize);
883 }
884 else
885 {
886 Stream_Write_UINT32(out, 0);
887 Stream_Write_UINT32(out, ErrorCount);
888 }
889
890 Stream_Write_UINT32(out, 0);
891 Stream_Write_UINT32(out, OutputBufferSize);
892 Stream_Seek(out, OutputBufferSize);
893
894 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
895 if (rc != CHANNEL_RC_OK)
896 WLog_WARN(TAG, "stream_write_and_free failed with %" PRIu32, rc);
897 }
898}
899
900static UINT urb_isoch_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
901 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
902 int transferDir)
903{
904 int rc = 0;
905 UINT32 EndpointAddress = 0;
906 UINT32 PipeHandle = 0;
907 UINT32 TransferFlags = 0;
908 UINT32 StartFrame = 0;
909 UINT32 NumberOfPackets = 0;
910 UINT32 ErrorCount = 0;
911 UINT32 OutputBufferSize = 0;
912 BYTE* packetDescriptorData = nullptr;
913 const BOOL noAck = (RequestField & 0x80000000U) != 0;
914 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
915
916 if (!pdev || !callback || !udevman)
917 return ERROR_INVALID_PARAMETER;
918
919 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
920 return ERROR_INVALID_DATA;
921
922 Stream_Read_UINT32(s, PipeHandle);
923 EndpointAddress = (PipeHandle & 0x000000ff);
924 Stream_Read_UINT32(s, TransferFlags);
925 Stream_Read_UINT32(s, StartFrame);
926 Stream_Read_UINT32(s, NumberOfPackets);
927 Stream_Read_UINT32(s, ErrorCount);
929 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
930 return ERROR_INVALID_DATA;
931
932 packetDescriptorData = Stream_Pointer(s);
933 Stream_Seek(s, 12ULL * NumberOfPackets);
934
935 if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UINT32)))
936 return ERROR_INVALID_DATA;
937 Stream_Read_UINT32(s, OutputBufferSize);
938
939 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
940 {
941 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
942 return ERROR_INVALID_DATA;
943 }
944
945 rc = pdev->isoch_transfer(
946 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
947 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
948 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
949 urb_isoch_transfer_cb, 2000);
950
951 if (rc < 0)
952 return ERROR_INTERNAL_ERROR;
953 return (UINT)rc;
954}
955
956static UINT urb_control_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
957 wStream* s, UINT32 RequestField, UINT32 MessageId,
958 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
959{
960 size_t out_size = 0;
961 UINT32 InterfaceId = 0;
962 UINT32 OutputBufferSize = 0;
963 UINT32 usbd_status = 0;
964 BYTE bmRequestType = 0;
965 BYTE desc_index = 0;
966 BYTE desc_type = 0;
967 UINT16 langId = 0;
968 wStream* out = nullptr;
969 URBDRC_PLUGIN* urbdrc = nullptr;
970 const BOOL noAck = (RequestField & 0x80000000U) != 0;
971 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
972
973 if (!callback || !s || !udevman || !pdev)
974 return ERROR_INVALID_PARAMETER;
975
976 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
977
978 if (!urbdrc)
979 return ERROR_INVALID_PARAMETER;
980
981 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
982 return ERROR_INVALID_DATA;
983
984 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
985 Stream_Read_UINT8(s, desc_index);
986 Stream_Read_UINT8(s, desc_type);
987 Stream_Read_UINT16(s, langId);
988 Stream_Read_UINT32(s, OutputBufferSize);
989 if (OutputBufferSize > UINT32_MAX - 36)
990 return ERROR_INVALID_DATA;
991 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
992 {
993 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
994 return ERROR_INVALID_DATA;
995 }
996
997 out_size = 36ULL + OutputBufferSize;
998 out = Stream_New(nullptr, out_size);
999
1000 if (!out)
1001 return ERROR_OUTOFMEMORY;
1002
1003 Stream_Seek(out, 36);
1004 bmRequestType = func_recipient;
1005
1006 switch (transferDir)
1007 {
1008 case USBD_TRANSFER_DIRECTION_IN:
1009 bmRequestType |= 0x80;
1010 break;
1011
1012 case USBD_TRANSFER_DIRECTION_OUT:
1013 bmRequestType |= 0x00;
1014 Stream_Copy(s, out, OutputBufferSize);
1015 Stream_Rewind(out, OutputBufferSize);
1016 break;
1017
1018 default:
1019 WLog_Print(urbdrc->log, WLOG_DEBUG, "get error transferDir");
1020 OutputBufferSize = 0;
1021 usbd_status = USBD_STATUS_STALL_PID;
1022 break;
1023 }
1024
1026 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1027 0x06, /* REQUEST_GET_DESCRIPTOR */
1028 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1029 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1030 {
1031 WLog_Print(urbdrc->log, WLOG_ERROR, "get_descriptor failed");
1032 Stream_Free(out, TRUE);
1033 return ERROR_INTERNAL_ERROR;
1034 }
1035
1036 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1037 usbd_status, OutputBufferSize);
1038}
1039
1040static UINT urb_control_get_status_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1041 wStream* s, UINT32 RequestField, UINT32 MessageId,
1042 IUDEVMAN* udevman, BYTE func_recipient, int transferDir)
1043{
1044 size_t out_size = 0;
1045 UINT32 InterfaceId = 0;
1046 UINT32 OutputBufferSize = 0;
1047 UINT32 usbd_status = 0;
1048 UINT16 Index = 0;
1049 BYTE bmRequestType = 0;
1050 wStream* out = nullptr;
1051 URBDRC_PLUGIN* urbdrc = nullptr;
1052 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1053 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1054
1055 if (!callback || !s || !udevman || !pdev)
1056 return ERROR_INVALID_PARAMETER;
1057
1058 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1059
1060 if (!urbdrc)
1061 return ERROR_INVALID_PARAMETER;
1062
1063 if (transferDir == 0)
1064 {
1065 WLog_Print(urbdrc->log, WLOG_DEBUG,
1066 "urb_control_get_status_request: transfer out not supported");
1067 return ERROR_INVALID_PARAMETER;
1068 }
1069
1070 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1071 return ERROR_INVALID_DATA;
1072
1073 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1074 Stream_Read_UINT16(s, Index);
1075 Stream_Seek(s, 2);
1076 Stream_Read_UINT32(s, OutputBufferSize);
1077 if (OutputBufferSize > UINT32_MAX - 36)
1078 return ERROR_INVALID_DATA;
1079 out_size = 36ULL + OutputBufferSize;
1080 out = Stream_New(nullptr, out_size);
1081
1082 if (!out)
1083 return ERROR_OUTOFMEMORY;
1084
1085 Stream_Seek(out, 36);
1086 bmRequestType = func_recipient | 0x80;
1087
1088 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00, /* REQUEST_GET_STATUS */
1089 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1090 1000))
1091 {
1092 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1093 Stream_Free(out, TRUE);
1094 return ERROR_INTERNAL_ERROR;
1095 }
1096
1097 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1098 usbd_status, OutputBufferSize);
1099}
1100
1101static UINT urb_control_vendor_or_class_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1102 wStream* s, UINT32 RequestField, UINT32 MessageId,
1103 IUDEVMAN* udevman, BYTE func_type,
1104 BYTE func_recipient, int transferDir)
1105{
1106 UINT32 out_size = 0;
1107 UINT32 InterfaceId = 0;
1108 UINT32 TransferFlags = 0;
1109 UINT32 usbd_status = 0;
1110 UINT32 OutputBufferSize = 0;
1111 BYTE ReqTypeReservedBits = 0;
1112 BYTE Request = 0;
1113 BYTE bmRequestType = 0;
1114 UINT16 Value = 0;
1115 UINT16 Index = 0;
1116 wStream* out = nullptr;
1117 URBDRC_PLUGIN* urbdrc = nullptr;
1118 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1119 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1120
1121 if (!callback || !s || !udevman || !pdev)
1122 return ERROR_INVALID_PARAMETER;
1123
1124 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1125
1126 if (!urbdrc)
1127 return ERROR_INVALID_PARAMETER;
1128
1129 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1130 return ERROR_INVALID_DATA;
1131
1132 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1133 Stream_Read_UINT32(s, TransferFlags);
1134 Stream_Read_UINT8(s, ReqTypeReservedBits);
1135 Stream_Read_UINT8(s, Request);
1136 Stream_Read_UINT16(s, Value);
1137 Stream_Read_UINT16(s, Index);
1138 Stream_Seek_UINT16(s);
1139 Stream_Read_UINT32(s, OutputBufferSize);
1140 if (OutputBufferSize > UINT32_MAX - 36)
1141 return ERROR_INVALID_DATA;
1142
1143 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1144 {
1145 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1146 return ERROR_INVALID_DATA;
1147 }
1148
1149 out_size = 36ULL + OutputBufferSize;
1150 out = Stream_New(nullptr, out_size);
1151
1152 if (!out)
1153 return ERROR_OUTOFMEMORY;
1154
1155 Stream_Seek(out, 36);
1156
1158 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1159 {
1160 Stream_Copy(s, out, OutputBufferSize);
1161 Stream_Rewind(out, OutputBufferSize);
1162 }
1163
1165 bmRequestType = func_type | func_recipient;
1166
1167 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1168 bmRequestType |= 0x80;
1169
1170 WLog_Print(urbdrc->log, WLOG_DEBUG,
1171 "RequestId 0x%" PRIx32 " TransferFlags: 0x%" PRIx32 " ReqTypeReservedBits: 0x%" PRIx8
1172 " "
1173 "Request:0x%" PRIx8 " Value: 0x%" PRIx16 " Index: 0x%" PRIx16
1174 " OutputBufferSize: 0x%" PRIx32 " bmRequestType: 0x%" PRIx8,
1175 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1176 OutputBufferSize, bmRequestType);
1177
1178 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1179 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1180 {
1181 WLog_Print(urbdrc->log, WLOG_ERROR, "control_transfer failed");
1182 Stream_Free(out, TRUE);
1183 return ERROR_INTERNAL_ERROR;
1184 }
1185
1186 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1187 usbd_status, OutputBufferSize);
1188}
1189
1190static UINT urb_os_feature_descriptor_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1191 wStream* s, UINT32 RequestField, UINT32 MessageId,
1192 IUDEVMAN* udevman, int transferDir)
1193{
1194 size_t out_size = 0;
1195 UINT32 InterfaceId = 0;
1196 UINT32 OutputBufferSize = 0;
1197 UINT32 usbd_status = 0;
1198 BYTE Recipient = 0;
1199 BYTE InterfaceNumber = 0;
1200 BYTE Ms_PageIndex = 0;
1201 UINT16 Ms_featureDescIndex = 0;
1202 wStream* out = nullptr;
1203 int ret = 0;
1204 URBDRC_PLUGIN* urbdrc = nullptr;
1205 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1206 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1207
1208 if (!callback || !s || !udevman || !pdev)
1209 return ERROR_INVALID_PARAMETER;
1210
1211 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1212
1213 if (!urbdrc)
1214 return ERROR_INVALID_PARAMETER;
1215
1216 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1217 return ERROR_INVALID_DATA;
1218
1219 /* 2.2.9.15 TS_URB_OS_FEATURE_DESCRIPTOR_REQUEST */
1220 Stream_Read_UINT8(s, Recipient);
1221 Recipient = (Recipient & 0x1f); /* Mask out Padding1 */
1222 Stream_Read_UINT8(s, InterfaceNumber);
1223 Stream_Read_UINT8(s, Ms_PageIndex);
1224 Stream_Read_UINT16(s, Ms_featureDescIndex);
1225 Stream_Seek(s, 3); /* Padding 2 */
1226 Stream_Read_UINT32(s, OutputBufferSize);
1227 if (OutputBufferSize > UINT32_MAX - 36)
1228 return ERROR_INVALID_DATA;
1229
1230 switch (transferDir)
1231 {
1232 case USBD_TRANSFER_DIRECTION_OUT:
1233 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1234 return ERROR_INVALID_DATA;
1235
1236 break;
1237
1238 default:
1239 break;
1240 }
1241
1242 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1243 out_size = 36ULL + OutputBufferSize;
1244 out = Stream_New(nullptr, out_size);
1245
1246 if (!out)
1247 return ERROR_OUTOFMEMORY;
1248
1249 Stream_Seek(out, 36);
1250
1251 switch (transferDir)
1252 {
1253 case USBD_TRANSFER_DIRECTION_OUT:
1254 Stream_Copy(s, out, OutputBufferSize);
1255 Stream_Rewind(out, OutputBufferSize);
1256 break;
1257
1258 case USBD_TRANSFER_DIRECTION_IN:
1259 break;
1260 default:
1261 break;
1262 }
1263
1264 WLog_Print(urbdrc->log, WLOG_DEBUG,
1265 "Ms descriptor arg: Recipient:0x%" PRIx8 ", "
1266 "InterfaceNumber:0x%" PRIx8 ", Ms_PageIndex:0x%" PRIx8 ", "
1267 "Ms_featureDescIndex:0x%" PRIx16 ", OutputBufferSize:0x%" PRIx32 "",
1268 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1270 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1271 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1272 &OutputBufferSize, Stream_Pointer(out), 1000);
1273
1274 if (ret < 0)
1275 WLog_Print(urbdrc->log, WLOG_DEBUG, "os_feature_descriptor_request: error num %d", ret);
1276
1277 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1278 usbd_status, OutputBufferSize);
1279}
1280
1281static UINT urb_pipe_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1282 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1283 int transferDir, int action)
1284{
1285 UINT32 usbd_status = 0;
1286 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1287 int rc = 0;
1288 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1289 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1290
1291 if (!callback || !s || !udevman || !pdev)
1292 return ERROR_INVALID_PARAMETER;
1293
1294 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1295
1296 if (!urbdrc)
1297 return ERROR_INVALID_PARAMETER;
1298
1299 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1300 return ERROR_INVALID_DATA;
1301
1302 if (transferDir == 0)
1303 {
1304 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: not support transfer out");
1305 return ERROR_INVALID_PARAMETER;
1306 }
1307
1308 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1309 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1310 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1311 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1312
1313 if (OutputBufferSize != 0)
1314 {
1315 WLog_Print(urbdrc->log, WLOG_DEBUG,
1316 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32 " != 0",
1317 OutputBufferSize);
1318 return ERROR_BAD_CONFIGURATION;
1319 }
1320
1321 switch (action)
1322 {
1323 case PIPE_CANCEL:
1324 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1325 PIPE_CANCEL);
1326
1327 if (rc < 0)
1328 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE SET HALT: error %u", ret);
1329 else
1330 ret = USBD_STATUS_SUCCESS;
1331
1332 break;
1333
1334 case PIPE_RESET:
1335 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request: PIPE_RESET ep 0x%" PRIx32 "",
1336 EndpointAddress);
1337 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1338 PIPE_RESET);
1339
1340 if (rc < 0)
1341 WLog_Print(urbdrc->log, WLOG_DEBUG, "PIPE RESET: error %u", ret);
1342 else
1343 ret = USBD_STATUS_SUCCESS;
1344
1345 break;
1346
1347 default:
1348 WLog_Print(urbdrc->log, WLOG_DEBUG, "urb_pipe_request action: %d not supported",
1349 action);
1350 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1351 break;
1352 }
1353
1356 wStream* out = Stream_New(nullptr, 36);
1357
1358 if (!out)
1359 return ERROR_OUTOFMEMORY;
1360
1361 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1362 0);
1363}
1364/* [MS-RDPEUSB] 2.2.10.4 TS_URB_GET_CURRENT_FRAME_NUMBER_RESULT */
1365static UINT urb_send_current_frame_number_result(GENERIC_CHANNEL_CALLBACK* callback,
1366 UINT32 RequestId, UINT32 MessageId,
1367 UINT32 CompletionId, UINT32 FrameNumber)
1368{
1369 WINPR_ASSERT(callback);
1370
1371 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1372 wStream* out =
1373 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1374
1375 if (!out)
1376 return ERROR_OUTOFMEMORY;
1377
1378 Stream_Write_UINT32(out, 12);
1379 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1380 {
1381 Stream_Free(out, TRUE);
1382 return ERROR_OUTOFMEMORY;
1383 }
1384
1385 Stream_Write_UINT32(out, FrameNumber);
1386 return send_urb_completion_message(callback, out, 0, 0, nullptr);
1387}
1388
1389static UINT urb_get_current_frame_number(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1390 wStream* s, UINT32 RequestField, UINT32 MessageId,
1391 IUDEVMAN* udevman, int transferDir)
1392{
1393 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1394 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1395
1396 if (!callback || !s || !udevman || !pdev)
1397 return ERROR_INVALID_PARAMETER;
1398
1399 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1400
1401 if (!urbdrc)
1402 return ERROR_INVALID_PARAMETER;
1403
1404 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1405 return ERROR_INVALID_DATA;
1406
1407 if (transferDir == 0)
1408 {
1409 WLog_Print(urbdrc->log, WLOG_DEBUG,
1410 "urb_get_current_frame_number: not support transfer out");
1411 return ERROR_INVALID_PARAMETER;
1412 }
1413
1414 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1415 if (OutputBufferSize != 0)
1416 {
1417 WLog_Print(urbdrc->log, WLOG_WARN, "OutputBufferSize=%" PRIu32 ", expected 0",
1418 OutputBufferSize);
1419 }
1421 const UINT32 dummy_frames = GetTickCount();
1422 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1423
1424 if (noAck)
1425 return CHANNEL_RC_OK;
1426
1427 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1428 dummy_frames);
1429}
1430
1431/* Unused function for current server */
1432static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1433 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1434 UINT32 RequestField, UINT32 MessageId,
1435 IUDEVMAN* udevman, int transferDir)
1436{
1437 size_t out_size = 0;
1438 UINT32 InterfaceId = 0;
1439 UINT32 OutputBufferSize = 0;
1440 UINT32 usbd_status = 0;
1441 wStream* out = nullptr;
1442 URBDRC_PLUGIN* urbdrc = nullptr;
1443 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1444 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1445
1446 if (!callback || !s || !udevman || !pdev)
1447 return ERROR_INVALID_PARAMETER;
1448
1449 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1450
1451 if (!urbdrc)
1452 return ERROR_INVALID_PARAMETER;
1453
1454 if (transferDir == 0)
1455 {
1456 WLog_Print(urbdrc->log, WLOG_DEBUG,
1457 "urb_control_get_configuration_request:"
1458 " not support transfer out");
1459 return ERROR_INVALID_PARAMETER;
1460 }
1461
1462 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1463 return ERROR_INVALID_DATA;
1464
1465 Stream_Read_UINT32(s, OutputBufferSize);
1466 if (OutputBufferSize > UINT32_MAX - 36)
1467 return ERROR_INVALID_DATA;
1468 out_size = 36ULL + OutputBufferSize;
1469 out = Stream_New(nullptr, out_size);
1470
1471 if (!out)
1472 return ERROR_OUTOFMEMORY;
1473
1474 Stream_Seek(out, 36);
1475 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1476
1477 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1478 0x08, /* REQUEST_GET_CONFIGURATION */
1479 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1480 {
1481 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1482 Stream_Free(out, TRUE);
1483 return ERROR_INTERNAL_ERROR;
1484 }
1485
1486 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1487 usbd_status, OutputBufferSize);
1488}
1489
1490/* Unused function for current server */
1491static UINT urb_control_get_interface_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1492 wStream* s, UINT32 RequestField, UINT32 MessageId,
1493 IUDEVMAN* udevman, int transferDir)
1494{
1495 size_t out_size = 0;
1496 UINT32 InterfaceId = 0;
1497 UINT32 OutputBufferSize = 0;
1498 UINT32 usbd_status = 0;
1499 UINT16 InterfaceNr = 0;
1500 wStream* out = nullptr;
1501 URBDRC_PLUGIN* urbdrc = nullptr;
1502 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1503 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1504
1505 if (!callback || !s || !udevman || !pdev)
1506 return ERROR_INVALID_PARAMETER;
1507
1508 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1509
1510 if (!urbdrc)
1511 return ERROR_INVALID_PARAMETER;
1512
1513 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1514 return ERROR_INVALID_DATA;
1515
1516 if (transferDir == 0)
1517 {
1518 WLog_Print(urbdrc->log, WLOG_DEBUG,
1519 "urb_control_get_interface_request: not support transfer out");
1520 return ERROR_INVALID_PARAMETER;
1521 }
1522
1523 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1524 Stream_Read_UINT16(s, InterfaceNr);
1525 Stream_Seek(s, 2);
1526 Stream_Read_UINT32(s, OutputBufferSize);
1527 if (OutputBufferSize > UINT32_MAX - 36)
1528 return ERROR_INVALID_DATA;
1529 out_size = 36ULL + OutputBufferSize;
1530 out = Stream_New(nullptr, out_size);
1531
1532 if (!out)
1533 return ERROR_OUTOFMEMORY;
1534
1535 Stream_Seek(out, 36);
1536
1537 if (!pdev->control_transfer(
1538 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */
1539 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1540 {
1541 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1542 Stream_Free(out, TRUE);
1543 return ERROR_INTERNAL_ERROR;
1544 }
1545
1546 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1547 usbd_status, OutputBufferSize);
1548}
1549
1550static UINT urb_control_feature_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1551 wStream* s, UINT32 RequestField, UINT32 MessageId,
1552 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1553 int transferDir)
1554{
1555 UINT32 InterfaceId = 0;
1556 UINT32 OutputBufferSize = 0;
1557 UINT32 usbd_status = 0;
1558 UINT16 FeatureSelector = 0;
1559 UINT16 Index = 0;
1560 BYTE bmRequestType = 0;
1561 BYTE bmRequest = 0;
1562 wStream* out = nullptr;
1563 URBDRC_PLUGIN* urbdrc = nullptr;
1564 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1565 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1566
1567 if (!callback || !s || !udevman || !pdev)
1568 return ERROR_INVALID_PARAMETER;
1569
1570 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1571
1572 if (!urbdrc)
1573 return ERROR_INVALID_PARAMETER;
1574
1575 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1576 return ERROR_INVALID_DATA;
1577
1578 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1579 Stream_Read_UINT16(s, FeatureSelector);
1580 Stream_Read_UINT16(s, Index);
1581 Stream_Read_UINT32(s, OutputBufferSize);
1582 if (OutputBufferSize > UINT32_MAX - 36)
1583 return ERROR_INVALID_DATA;
1584 switch (transferDir)
1585 {
1586 case USBD_TRANSFER_DIRECTION_OUT:
1587 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1588 return ERROR_INVALID_DATA;
1589
1590 break;
1591
1592 default:
1593 break;
1594 }
1595
1596 out = Stream_New(nullptr, 36ULL + OutputBufferSize);
1597
1598 if (!out)
1599 return ERROR_OUTOFMEMORY;
1600
1601 Stream_Seek(out, 36);
1602 bmRequestType = func_recipient;
1603
1604 switch (transferDir)
1605 {
1606 case USBD_TRANSFER_DIRECTION_OUT:
1607 WLog_Print(urbdrc->log, WLOG_ERROR,
1608 "Function urb_control_feature_request: OUT Unchecked");
1609 Stream_Copy(s, out, OutputBufferSize);
1610 Stream_Rewind(out, OutputBufferSize);
1611 bmRequestType |= 0x00;
1612 break;
1613
1614 case USBD_TRANSFER_DIRECTION_IN:
1615 bmRequestType |= 0x80;
1616 break;
1617 default:
1618 break;
1619 }
1620
1621 switch (command)
1622 {
1623 case URB_SET_FEATURE:
1624 bmRequest = 0x03; /* REQUEST_SET_FEATURE */
1625 break;
1626
1627 case URB_CLEAR_FEATURE:
1628 bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */
1629 break;
1630
1631 default:
1632 WLog_Print(urbdrc->log, WLOG_ERROR,
1633 "urb_control_feature_request: Error Command 0x%02" PRIx8 "", command);
1634 Stream_Free(out, TRUE);
1635 return ERROR_INTERNAL_ERROR;
1636 }
1637
1638 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1639 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1640 {
1641 WLog_Print(urbdrc->log, WLOG_DEBUG, "feature control transfer failed");
1642 Stream_Free(out, TRUE);
1643 return ERROR_INTERNAL_ERROR;
1644 }
1645
1646 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1647 usbd_status, OutputBufferSize);
1648}
1649
1650static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1651 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1652 int transferDir)
1653{
1654 UINT32 CbTsUrb = 0;
1655 UINT16 Size = 0;
1656 UINT16 URB_Function = 0;
1657 UINT32 RequestId = 0;
1658 UINT error = ERROR_INTERNAL_ERROR;
1659 URBDRC_PLUGIN* urbdrc = nullptr;
1660
1661 if (!callback || !s || !udevman || !pdev)
1662 return ERROR_INVALID_PARAMETER;
1663
1664 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1665
1666 if (!urbdrc)
1667 return ERROR_INVALID_PARAMETER;
1668
1669 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1670 return ERROR_INVALID_DATA;
1671
1672 Stream_Read_UINT32(s, CbTsUrb);
1673 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1674 return ERROR_INVALID_DATA;
1675 Stream_Read_UINT16(s, Size);
1676 if (Size != CbTsUrb)
1677 {
1678 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1679 ? "2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1680 : "2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1681 WLog_ERR(TAG,
1682 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1683 " != %s::CbTsUrb 0x%08" PRIx32,
1684 Size, section, CbTsUrb);
1685 return ERROR_INVALID_DATA;
1686 }
1687 Stream_Read_UINT16(s, URB_Function);
1688 Stream_Read_UINT32(s, RequestId);
1689 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB %s[%" PRIu16 "]", urb_function_string(URB_Function),
1690 URB_Function);
1691
1692 switch (URB_Function)
1693 {
1694 case TS_URB_SELECT_CONFIGURATION:
1695 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1696 transferDir);
1697 break;
1698
1699 case TS_URB_SELECT_INTERFACE:
1700 error =
1701 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1702 break;
1703
1704 case TS_URB_PIPE_REQUEST:
1705 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1706 PIPE_CANCEL);
1707 break;
1708
1709 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1713 break;
1714
1715 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1719 break;
1720
1721 case TS_URB_GET_FRAME_LENGTH:
1725 break;
1726
1727 case TS_URB_SET_FRAME_LENGTH:
1731 break;
1732
1733 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1734 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1735 transferDir);
1736 break;
1737
1738 case TS_URB_CONTROL_TRANSFER:
1739 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1740 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1741 break;
1742
1743 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1744 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1745 transferDir);
1746 break;
1747
1748 case TS_URB_ISOCH_TRANSFER:
1749 error =
1750 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1751 break;
1752
1753 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1754 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1755 0x00, transferDir);
1756 break;
1757
1758 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1759 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1760 0x00, transferDir);
1761 break;
1762
1763 case TS_URB_SET_FEATURE_TO_DEVICE:
1764 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1765 0x00, URB_SET_FEATURE, transferDir);
1766 break;
1767
1768 case TS_URB_SET_FEATURE_TO_INTERFACE:
1769 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1770 0x01, URB_SET_FEATURE, transferDir);
1771 break;
1772
1773 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1774 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1775 0x02, URB_SET_FEATURE, transferDir);
1776 break;
1777
1778 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1779 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1780 0x00, URB_CLEAR_FEATURE, transferDir);
1781 break;
1782
1783 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1784 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1785 0x01, URB_CLEAR_FEATURE, transferDir);
1786 break;
1787
1788 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1789 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1790 0x02, URB_CLEAR_FEATURE, transferDir);
1791 break;
1792
1793 case TS_URB_GET_STATUS_FROM_DEVICE:
1794 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1795 0x00, transferDir);
1796 break;
1797
1798 case TS_URB_GET_STATUS_FROM_INTERFACE:
1799 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1800 0x01, transferDir);
1801 break;
1802
1803 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1804 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1805 0x02, transferDir);
1806 break;
1807
1808 case TS_URB_RESERVED_0X0016:
1809 break;
1810
1811 case TS_URB_VENDOR_DEVICE:
1812 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1813 udevman, (0x02 << 5), /* vendor type */
1814 0x00, transferDir);
1815 break;
1816
1817 case TS_URB_VENDOR_INTERFACE:
1818 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1819 udevman, (0x02 << 5), /* vendor type */
1820 0x01, transferDir);
1821 break;
1822
1823 case TS_URB_VENDOR_ENDPOINT:
1824 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1825 udevman, (0x02 << 5), /* vendor type */
1826 0x02, transferDir);
1827 break;
1828
1829 case TS_URB_CLASS_DEVICE:
1830 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1831 udevman, (0x01 << 5), /* class type */
1832 0x00, transferDir);
1833 break;
1834
1835 case TS_URB_CLASS_INTERFACE:
1836 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1837 udevman, (0x01 << 5), /* class type */
1838 0x01, transferDir);
1839 break;
1840
1841 case TS_URB_CLASS_ENDPOINT:
1842 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1843 udevman, (0x01 << 5), /* class type */
1844 0x02, transferDir);
1845 break;
1846
1847 case TS_URB_RESERVE_0X001D:
1848 break;
1849
1850 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1851 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1852 PIPE_RESET);
1853 break;
1854
1855 case TS_URB_CLASS_OTHER:
1856 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1857 udevman, (0x01 << 5), /* class type */
1858 0x03, transferDir);
1859 break;
1860
1861 case TS_URB_VENDOR_OTHER:
1862 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1863 udevman, (0x02 << 5), /* vendor type */
1864 0x03, transferDir);
1865 break;
1866
1867 case TS_URB_GET_STATUS_FROM_OTHER:
1868 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1869 0x03, transferDir);
1870 break;
1871
1872 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1873 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1874 0x03, URB_CLEAR_FEATURE, transferDir);
1875 break;
1876
1877 case TS_URB_SET_FEATURE_TO_OTHER:
1878 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1879 0x03, URB_SET_FEATURE, transferDir);
1880 break;
1881
1882 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1883 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1884 0x02, transferDir);
1885 break;
1886
1887 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1888 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1889 0x02, transferDir);
1890 break;
1891
1892 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1893 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1894 udevman, transferDir);
1895 break;
1896
1897 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1898 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1899 udevman, transferDir);
1900 break;
1901
1902 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1903 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1904 0x01, transferDir);
1905 break;
1906
1907 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1908 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1909 0x01, transferDir);
1910 break;
1911
1912 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1913 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1914 udevman, transferDir);
1915 break;
1916
1917 case TS_URB_RESERVE_0X002B:
1918 case TS_URB_RESERVE_0X002C:
1919 case TS_URB_RESERVE_0X002D:
1920 case TS_URB_RESERVE_0X002E:
1921 case TS_URB_RESERVE_0X002F:
1922 break;
1923
1925 case TS_URB_SYNC_RESET_PIPE:
1926 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1927 PIPE_RESET);
1928 break;
1929
1930 case TS_URB_SYNC_CLEAR_STALL:
1931 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1932 PIPE_RESET);
1933 break;
1934
1935 case TS_URB_CONTROL_TRANSFER_EX:
1936 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1937 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1938 break;
1939
1940 default:
1941 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB_Func: %" PRIx16 " is not found!",
1942 URB_Function);
1943 break;
1944 }
1945
1946 if (error)
1947 {
1948 WLog_Print(urbdrc->log, WLOG_WARN,
1949 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1950 urb_function_string(URB_Function), URB_Function, error);
1951 }
1952
1953 return error;
1954}
1955
1956UINT urbdrc_process_udev_data_transfer(GENERIC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
1957 IUDEVMAN* udevman, wStream* data)
1958{
1959 UINT32 InterfaceId = 0;
1960 UINT32 MessageId = 0;
1961 UINT32 FunctionId = 0;
1962 IUDEVICE* pdev = nullptr;
1963 UINT error = ERROR_INTERNAL_ERROR;
1964
1965 if (!urbdrc || !data || !callback || !udevman)
1966 goto fail;
1967
1968 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1969 goto fail;
1970
1971 Stream_Rewind_UINT32(data);
1972
1973 Stream_Read_UINT32(data, InterfaceId);
1974 Stream_Read_UINT32(data, MessageId);
1975 Stream_Read_UINT32(data, FunctionId);
1976
1977 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1978
1979 /* Device does not exist, ignore this request. */
1980 if (pdev == nullptr)
1981 {
1982 error = ERROR_SUCCESS;
1983 goto fail;
1984 }
1985
1986 /* Device has been removed, ignore this request. */
1987 if (pdev->isChannelClosed(pdev))
1988 {
1989 error = ERROR_SUCCESS;
1990 goto fail;
1991 }
1992
1993 /* USB kernel driver detach!! */
1994 if (!pdev->detach_kernel_driver(pdev))
1995 {
1996 error = ERROR_SUCCESS;
1997 goto fail;
1998 }
1999
2000 switch (FunctionId)
2001 {
2002 case CANCEL_REQUEST:
2003 error = urbdrc_process_cancel_request(pdev, data, udevman);
2004 break;
2005
2006 case REGISTER_REQUEST_CALLBACK:
2007 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2008 break;
2009
2010 case IO_CONTROL:
2011 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2012 break;
2013
2014 case INTERNAL_IO_CONTROL:
2015 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2016 break;
2017
2018 case QUERY_DEVICE_TEXT:
2019 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2020 break;
2021
2022 case TRANSFER_IN_REQUEST:
2023 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2024 USBD_TRANSFER_DIRECTION_IN);
2025 break;
2026
2027 case TRANSFER_OUT_REQUEST:
2028 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2029 USBD_TRANSFER_DIRECTION_OUT);
2030 break;
2031
2032 case RETRACT_DEVICE:
2033 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2034 break;
2035
2036 default:
2037 WLog_Print(urbdrc->log, WLOG_WARN,
2038 "urbdrc_process_udev_data_transfer:"
2039 " unknown FunctionId 0x%" PRIX32 "",
2040 FunctionId);
2041 break;
2042 }
2043
2044fail:
2045 if (error)
2046 {
2047 WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
2048 }
2049
2050 return error;
2051}