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 Stream_Write_UINT32(out, 12);
1434 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1435 {
1436 Stream_Free(out, TRUE);
1437 return ERROR_OUTOFMEMORY;
1438 }
1439
1440 Stream_Write_UINT32(out, FrameNumber);
1441 return send_urb_completion_message(callback, out, 0, 0, nullptr);
1442}
1443
1444static UINT urb_get_current_frame_number(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1445 wStream* s, UINT32 RequestField, UINT32 MessageId,
1446 IUDEVMAN* udevman, int transferDir)
1447{
1448 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1449 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1450
1451 if (!callback || !s || !udevman || !pdev)
1452 return ERROR_INVALID_PARAMETER;
1453
1454 URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1455
1456 if (!urbdrc)
1457 return ERROR_INVALID_PARAMETER;
1458
1459 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1460 return ERROR_INVALID_DATA;
1461
1462 if (transferDir == 0)
1463 {
1464 WLog_Print(urbdrc->log, WLOG_DEBUG,
1465 "urb_get_current_frame_number: not support transfer out");
1466 return ERROR_INVALID_PARAMETER;
1467 }
1468
1469 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1470 if (OutputBufferSize != 0)
1471 {
1472 WLog_Print(urbdrc->log, WLOG_WARN, "OutputBufferSize=%" PRIu32 ", expected 0",
1473 OutputBufferSize);
1474 }
1476 const UINT32 dummy_frames = GetTickCount();
1477 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1478
1479 if (noAck)
1480 return CHANNEL_RC_OK;
1481
1482 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1483 dummy_frames);
1484}
1485
1486/* Unused function for current server */
1487static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1488 GENERIC_CHANNEL_CALLBACK* callback, wStream* s,
1489 UINT32 RequestField, UINT32 MessageId,
1490 IUDEVMAN* udevman, int transferDir)
1491{
1492 size_t out_size = 0;
1493 UINT32 InterfaceId = 0;
1494 UINT32 OutputBufferSize = 0;
1495 UINT32 usbd_status = 0;
1496 wStream* out = nullptr;
1497 URBDRC_PLUGIN* urbdrc = nullptr;
1498 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1499 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1500
1501 if (!callback || !s || !udevman || !pdev)
1502 return ERROR_INVALID_PARAMETER;
1503
1504 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1505
1506 if (!urbdrc)
1507 return ERROR_INVALID_PARAMETER;
1508
1509 if (transferDir == 0)
1510 {
1511 WLog_Print(urbdrc->log, WLOG_DEBUG,
1512 "urb_control_get_configuration_request:"
1513 " not support transfer out");
1514 return ERROR_INVALID_PARAMETER;
1515 }
1516
1517 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1518 return ERROR_INVALID_DATA;
1519
1520 Stream_Read_UINT32(s, OutputBufferSize);
1521 if (OutputBufferSize > UINT32_MAX - 36)
1522 return ERROR_INVALID_DATA;
1523 out_size = 36ULL + OutputBufferSize;
1524 out = Stream_New(nullptr, out_size);
1525
1526 if (!out)
1527 return ERROR_OUTOFMEMORY;
1528
1529 Stream_Seek(out, 36);
1530 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1531
1532 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1533 0x08, /* REQUEST_GET_CONFIGURATION */
1534 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1535 {
1536 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1537 Stream_Free(out, TRUE);
1538 return ERROR_INTERNAL_ERROR;
1539 }
1540
1541 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1542 usbd_status, OutputBufferSize, transferDir);
1543}
1544
1545/* Unused function for current server */
1546static UINT urb_control_get_interface_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1547 wStream* s, UINT32 RequestField, UINT32 MessageId,
1548 IUDEVMAN* udevman, int transferDir)
1549{
1550 size_t out_size = 0;
1551 UINT32 InterfaceId = 0;
1552 UINT32 OutputBufferSize = 0;
1553 UINT32 usbd_status = 0;
1554 UINT16 InterfaceNr = 0;
1555 wStream* out = nullptr;
1556 URBDRC_PLUGIN* urbdrc = nullptr;
1557 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1558 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1559
1560 if (!callback || !s || !udevman || !pdev)
1561 return ERROR_INVALID_PARAMETER;
1562
1563 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1564
1565 if (!urbdrc)
1566 return ERROR_INVALID_PARAMETER;
1567
1568 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1569 return ERROR_INVALID_DATA;
1570
1571 if (transferDir == 0)
1572 {
1573 WLog_Print(urbdrc->log, WLOG_DEBUG,
1574 "urb_control_get_interface_request: not support transfer out");
1575 return ERROR_INVALID_PARAMETER;
1576 }
1577
1578 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1579 Stream_Read_UINT16(s, InterfaceNr);
1580 Stream_Seek(s, 2);
1581 Stream_Read_UINT32(s, OutputBufferSize);
1582 if (OutputBufferSize > UINT32_MAX - 36)
1583 return ERROR_INVALID_DATA;
1584 out_size = 36ULL + OutputBufferSize;
1585 out = Stream_New(nullptr, out_size);
1586
1587 if (!out)
1588 return ERROR_OUTOFMEMORY;
1589
1590 Stream_Seek(out, 36);
1591
1592 if (!pdev->control_transfer(
1593 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */
1594 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1595 {
1596 WLog_Print(urbdrc->log, WLOG_DEBUG, "control_transfer failed");
1597 Stream_Free(out, TRUE);
1598 return ERROR_INTERNAL_ERROR;
1599 }
1600
1601 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1602 usbd_status, OutputBufferSize, transferDir);
1603}
1604
1605static UINT urb_control_feature_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1606 wStream* s, UINT32 RequestField, UINT32 MessageId,
1607 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1608 int transferDir)
1609{
1610 UINT32 InterfaceId = 0;
1611 UINT32 OutputBufferSize = 0;
1612 UINT32 usbd_status = 0;
1613 UINT16 FeatureSelector = 0;
1614 UINT16 Index = 0;
1615 BYTE bmRequestType = 0;
1616 BYTE bmRequest = 0;
1617 wStream* out = nullptr;
1618 URBDRC_PLUGIN* urbdrc = nullptr;
1619 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1620 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1621
1622 if (!callback || !s || !udevman || !pdev)
1623 return ERROR_INVALID_PARAMETER;
1624
1625 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1626
1627 if (!urbdrc)
1628 return ERROR_INVALID_PARAMETER;
1629
1630 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1631 return ERROR_INVALID_DATA;
1632
1633 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1634 Stream_Read_UINT16(s, FeatureSelector);
1635 Stream_Read_UINT16(s, Index);
1636 Stream_Read_UINT32(s, OutputBufferSize);
1637 if (OutputBufferSize > UINT32_MAX - 36)
1638 return ERROR_INVALID_DATA;
1639 switch (transferDir)
1640 {
1641 case USBD_TRANSFER_DIRECTION_OUT:
1642 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1643 return ERROR_INVALID_DATA;
1644
1645 break;
1646
1647 default:
1648 break;
1649 }
1650
1651 out = Stream_New(nullptr, 36ULL + OutputBufferSize);
1652
1653 if (!out)
1654 return ERROR_OUTOFMEMORY;
1655
1656 Stream_Seek(out, 36);
1657 bmRequestType = func_recipient;
1658
1659 switch (transferDir)
1660 {
1661 case USBD_TRANSFER_DIRECTION_OUT:
1662 WLog_Print(urbdrc->log, WLOG_ERROR,
1663 "Function urb_control_feature_request: OUT Unchecked");
1664 Stream_Copy(s, out, OutputBufferSize);
1665 Stream_Rewind(out, OutputBufferSize);
1666 bmRequestType |= 0x00;
1667 break;
1668
1669 case USBD_TRANSFER_DIRECTION_IN:
1670 bmRequestType |= 0x80;
1671 break;
1672 default:
1673 break;
1674 }
1675
1676 switch (command)
1677 {
1678 case URB_SET_FEATURE:
1679 bmRequest = 0x03; /* REQUEST_SET_FEATURE */
1680 break;
1681
1682 case URB_CLEAR_FEATURE:
1683 bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */
1684 break;
1685
1686 default:
1687 WLog_Print(urbdrc->log, WLOG_ERROR,
1688 "urb_control_feature_request: Error Command 0x%02" PRIx8 "", command);
1689 Stream_Free(out, TRUE);
1690 return ERROR_INTERNAL_ERROR;
1691 }
1692
1693 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1694 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1695 {
1696 WLog_Print(urbdrc->log, WLOG_DEBUG, "feature control transfer failed");
1697 Stream_Free(out, TRUE);
1698 return ERROR_INTERNAL_ERROR;
1699 }
1700
1701 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1702 usbd_status, OutputBufferSize, transferDir);
1703}
1704
1705static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callback,
1706 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1707 int transferDir)
1708{
1709 UINT32 CbTsUrb = 0;
1710 UINT16 Size = 0;
1711 UINT16 URB_Function = 0;
1712 UINT32 RequestId = 0;
1713 UINT error = ERROR_INTERNAL_ERROR;
1714 URBDRC_PLUGIN* urbdrc = nullptr;
1715
1716 if (!callback || !s || !udevman || !pdev)
1717 return ERROR_INVALID_PARAMETER;
1718
1719 urbdrc = (URBDRC_PLUGIN*)callback->plugin;
1720
1721 if (!urbdrc)
1722 return ERROR_INVALID_PARAMETER;
1723
1724 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1725 return ERROR_INVALID_DATA;
1726
1727 Stream_Read_UINT32(s, CbTsUrb);
1728 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1729 return ERROR_INVALID_DATA;
1730 Stream_Read_UINT16(s, Size);
1731 if (Size != CbTsUrb)
1732 {
1733 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1734 ? "2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1735 : "2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1736 WLog_ERR(TAG,
1737 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1738 " != %s::CbTsUrb 0x%08" PRIx32,
1739 Size, section, CbTsUrb);
1740 return ERROR_INVALID_DATA;
1741 }
1742 Stream_Read_UINT16(s, URB_Function);
1743 Stream_Read_UINT32(s, RequestId);
1744 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB %s[%" PRIu16 "]", urb_function_string(URB_Function),
1745 URB_Function);
1746
1747 switch (URB_Function)
1748 {
1749 case TS_URB_SELECT_CONFIGURATION:
1750 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1751 transferDir);
1752 break;
1753
1754 case TS_URB_SELECT_INTERFACE:
1755 error =
1756 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1757 break;
1758
1759 case TS_URB_PIPE_REQUEST:
1760 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1761 PIPE_CANCEL);
1762 break;
1763
1764 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1768 break;
1769
1770 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1774 break;
1775
1776 case TS_URB_GET_FRAME_LENGTH:
1780 break;
1781
1782 case TS_URB_SET_FRAME_LENGTH:
1786 break;
1787
1788 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1789 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1790 transferDir);
1791 break;
1792
1793 case TS_URB_CONTROL_TRANSFER:
1794 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1795 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1796 break;
1797
1798 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1799 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1800 transferDir);
1801 break;
1802
1803 case TS_URB_ISOCH_TRANSFER:
1804 error =
1805 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1806 break;
1807
1808 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1809 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1810 0x00, transferDir);
1811 break;
1812
1813 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1814 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1815 0x00, transferDir);
1816 break;
1817
1818 case TS_URB_SET_FEATURE_TO_DEVICE:
1819 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1820 0x00, URB_SET_FEATURE, transferDir);
1821 break;
1822
1823 case TS_URB_SET_FEATURE_TO_INTERFACE:
1824 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1825 0x01, URB_SET_FEATURE, transferDir);
1826 break;
1827
1828 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1829 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1830 0x02, URB_SET_FEATURE, transferDir);
1831 break;
1832
1833 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1834 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1835 0x00, URB_CLEAR_FEATURE, transferDir);
1836 break;
1837
1838 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x01, URB_CLEAR_FEATURE, transferDir);
1841 break;
1842
1843 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x02, URB_CLEAR_FEATURE, transferDir);
1846 break;
1847
1848 case TS_URB_GET_STATUS_FROM_DEVICE:
1849 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1850 0x00, transferDir);
1851 break;
1852
1853 case TS_URB_GET_STATUS_FROM_INTERFACE:
1854 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 0x01, transferDir);
1856 break;
1857
1858 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1859 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1860 0x02, transferDir);
1861 break;
1862
1863 case TS_URB_RESERVED_0X0016:
1864 break;
1865
1866 case TS_URB_VENDOR_DEVICE:
1867 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1868 udevman, (0x02u << 5), /* vendor type */
1869 0x00, transferDir);
1870 break;
1871
1872 case TS_URB_VENDOR_INTERFACE:
1873 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1874 udevman, (0x02u << 5), /* vendor type */
1875 0x01, transferDir);
1876 break;
1877
1878 case TS_URB_VENDOR_ENDPOINT:
1879 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1880 udevman, (0x02u << 5), /* vendor type */
1881 0x02, transferDir);
1882 break;
1883
1884 case TS_URB_CLASS_DEVICE:
1885 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1886 udevman, (0x01u << 5), /* class type */
1887 0x00, transferDir);
1888 break;
1889
1890 case TS_URB_CLASS_INTERFACE:
1891 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1892 udevman, (0x01u << 5), /* class type */
1893 0x01, transferDir);
1894 break;
1895
1896 case TS_URB_CLASS_ENDPOINT:
1897 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1898 udevman, (0x01u << 5), /* class type */
1899 0x02, transferDir);
1900 break;
1901
1902 case TS_URB_RESERVE_0X001D:
1903 break;
1904
1905 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1906 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1907 PIPE_RESET);
1908 break;
1909
1910 case TS_URB_CLASS_OTHER:
1911 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1912 udevman, (0x01u << 5), /* class type */
1913 0x03, transferDir);
1914 break;
1915
1916 case TS_URB_VENDOR_OTHER:
1917 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1918 udevman, (0x02u << 5), /* vendor type */
1919 0x03, transferDir);
1920 break;
1921
1922 case TS_URB_GET_STATUS_FROM_OTHER:
1923 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1924 0x03, transferDir);
1925 break;
1926
1927 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1928 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1929 0x03, URB_CLEAR_FEATURE, transferDir);
1930 break;
1931
1932 case TS_URB_SET_FEATURE_TO_OTHER:
1933 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1934 0x03, URB_SET_FEATURE, transferDir);
1935 break;
1936
1937 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1938 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1939 0x02, transferDir);
1940 break;
1941
1942 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1943 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1944 0x02, transferDir);
1945 break;
1946
1947 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1948 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1949 udevman, transferDir);
1950 break;
1951
1952 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1953 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1954 udevman, transferDir);
1955 break;
1956
1957 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1958 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1959 0x01, transferDir);
1960 break;
1961
1962 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1963 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1964 0x01, transferDir);
1965 break;
1966
1967 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1968 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1969 udevman, transferDir);
1970 break;
1971
1972 case TS_URB_RESERVE_0X002B:
1973 case TS_URB_RESERVE_0X002C:
1974 case TS_URB_RESERVE_0X002D:
1975 case TS_URB_RESERVE_0X002E:
1976 case TS_URB_RESERVE_0X002F:
1977 break;
1978
1980 case TS_URB_SYNC_RESET_PIPE:
1981 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1982 PIPE_RESET);
1983 break;
1984
1985 case TS_URB_SYNC_CLEAR_STALL:
1986 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1987 PIPE_RESET);
1988 break;
1989
1990 case TS_URB_CONTROL_TRANSFER_EX:
1991 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1992 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1993 break;
1994
1995 default:
1996 WLog_Print(urbdrc->log, WLOG_DEBUG, "URB_Func: %" PRIx16 " is not found!",
1997 URB_Function);
1998 break;
1999 }
2000
2001 if (error)
2002 {
2003 WLog_Print(urbdrc->log, WLOG_WARN,
2004 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2005 urb_function_string(URB_Function), URB_Function, error);
2006 }
2007
2008 return error;
2009}
2010
2011UINT urbdrc_process_udev_data_transfer(GENERIC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
2012 IUDEVMAN* udevman, wStream* data)
2013{
2014 UINT32 InterfaceId = 0;
2015 UINT32 MessageId = 0;
2016 UINT32 FunctionId = 0;
2017 IUDEVICE* pdev = nullptr;
2018 UINT error = ERROR_INTERNAL_ERROR;
2019
2020 if (!urbdrc || !data || !callback || !udevman)
2021 goto fail;
2022
2023 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2024 goto fail;
2025
2026 Stream_Rewind_UINT32(data);
2027
2028 Stream_Read_UINT32(data, InterfaceId);
2029 Stream_Read_UINT32(data, MessageId);
2030 Stream_Read_UINT32(data, FunctionId);
2031
2032 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2033
2034 /* Device does not exist, ignore this request. */
2035 if (pdev == nullptr)
2036 {
2037 error = ERROR_SUCCESS;
2038 goto fail;
2039 }
2040
2041 /* Device has been removed, ignore this request. */
2042 if (pdev->isChannelClosed(pdev))
2043 {
2044 error = ERROR_SUCCESS;
2045 goto fail;
2046 }
2047
2048 /* USB kernel driver detach!! */
2049 if (!pdev->detach_kernel_driver(pdev))
2050 {
2051 error = ERROR_SUCCESS;
2052 goto fail;
2053 }
2054
2055 switch (FunctionId)
2056 {
2057 case CANCEL_REQUEST:
2058 error = urbdrc_process_cancel_request(pdev, data, udevman);
2059 break;
2060
2061 case REGISTER_REQUEST_CALLBACK:
2062 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2063 break;
2064
2065 case IO_CONTROL:
2066 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2067 break;
2068
2069 case INTERNAL_IO_CONTROL:
2070 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2071 break;
2072
2073 case QUERY_DEVICE_TEXT:
2074 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2075 break;
2076
2077 case TRANSFER_IN_REQUEST:
2078 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2079 USBD_TRANSFER_DIRECTION_IN);
2080 break;
2081
2082 case TRANSFER_OUT_REQUEST:
2083 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2084 USBD_TRANSFER_DIRECTION_OUT);
2085 break;
2086
2087 case RETRACT_DEVICE:
2088 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2089 break;
2090
2091 default:
2092 WLog_Print(urbdrc->log, WLOG_WARN,
2093 "urbdrc_process_udev_data_transfer:"
2094 " unknown FunctionId 0x%" PRIX32 "",
2095 FunctionId);
2096 break;
2097 }
2098
2099fail:
2100 if (error)
2101 {
2102 WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
2103 }
2104
2105 return error;
2106}