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