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