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