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