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