25#include <winpr/sysinfo.h>
26#include <winpr/cast.h>
28#include <urbdrc_helpers.h>
30#include "urbdrc_types.h"
31#include "data_transfer.h"
34static void usb_process_get_port_status(IUDEVICE* pdev,
wStream* out)
36 int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
41 Stream_Write_UINT32(out, 0x303);
45 Stream_Write_UINT32(out, 0x103);
50 Stream_Write_UINT32(out, 0x503);
56static BOOL write_urb_result_header(
wStream* s, UINT16 Size, UINT32 status)
58 if (!Stream_EnsureRemainingCapacity(s, 8ULL + Size))
60 Stream_Write_UINT16(s, Size);
61 Stream_Seek_UINT16(s);
62 Stream_Write_UINT32(s, status);
69static wStream* create_urb_completion_message(UINT32 InterfaceId, UINT32 MessageId,
70 UINT32 RequestId, UINT32 FunctionId)
73 create_shared_message_header_with_functionid(InterfaceId, MessageId, FunctionId, 4);
77 Stream_Write_UINT32(out, RequestId);
82 HRESULT hResult, UINT32 OutputSize,
const void* data)
84 WINPR_ASSERT(callback);
85 UINT status = ERROR_OUTOFMEMORY;
87 if (!Stream_EnsureRemainingCapacity(out, 8ULL + OutputSize))
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);
96 Stream_Free(out, TRUE);
100static UINT urb_write_completion(WINPR_ATTR_UNUSED IUDEVICE* pdev,
102 UINT32 InterfaceId, UINT32 MessageId, UINT32 RequestId,
103 UINT32 usbd_status, UINT32 OutputBufferSize)
106 return ERROR_INVALID_PARAMETER;
108 if (Stream_Capacity(out) < OutputBufferSize + 36)
110 Stream_Free(out, TRUE);
111 return ERROR_INVALID_PARAMETER;
114 Stream_SetPosition(out, 0);
116 const UINT32 FunctionId = (OutputBufferSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
117 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
119 Stream_Free(out, TRUE);
120 return ERROR_OUTOFMEMORY;
123 Stream_Write_UINT32(out, RequestId);
124 Stream_Write_UINT32(out, 8);
126 if (!write_urb_result_header(out, 8, usbd_status))
128 Stream_Free(out, TRUE);
129 return ERROR_OUTOFMEMORY;
132 Stream_Write_UINT32(out, 0);
133 Stream_Write_UINT32(out, OutputBufferSize);
134 Stream_Seek(out, OutputBufferSize);
137 return stream_write_and_free(callback->plugin, callback->channel, out);
139 Stream_Free(out, TRUE);
141 return ERROR_SUCCESS;
144static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
145 UINT32 OutputBufferSize)
147 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
149#if UINT32_MAX >= SIZE_MAX
150 if (OutputBufferSize > UINT32_MAX - 28ull)
154 wStream* out = create_shared_message_header_with_functionid(
155 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
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);
166static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
170 UINT32 NumRequestCompletion = 0;
171 UINT32 RequestCompletion = 0;
173 if (!callback || !s || !udevman || !pdev)
174 return ERROR_INVALID_PARAMETER;
179 return ERROR_INVALID_PARAMETER;
181 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urbdrc_process_register_request_callback");
183 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
184 return ERROR_INVALID_DATA;
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++)
194 Stream_Read_UINT32(s, RequestCompletion);
195 pdev->set_ReqCompletion(pdev, RequestCompletion);
198 return ERROR_SUCCESS;
201static UINT urbdrc_process_cancel_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
206 if (!s || !udevman || !pdev)
207 return ERROR_INVALID_PARAMETER;
211 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
212 return ERROR_INVALID_DATA;
214 Stream_Read_UINT32(s, CancelId);
215 WLog_Print(urbdrc->log, WLOG_DEBUG,
"CANCEL_REQUEST: CancelId=%08" PRIx32
"", CancelId);
217 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
218 return ERROR_INTERNAL_ERROR;
220 return ERROR_SUCCESS;
223static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev,
wStream* s,
230 return ERROR_INVALID_PARAMETER;
235 return ERROR_INVALID_PARAMETER;
237 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
238 return ERROR_INVALID_DATA;
240 Stream_Read_UINT32(s, Reason);
244 case UsbRetractReason_BlockedByPolicy:
245 WLog_Print(urbdrc->log, WLOG_DEBUG,
246 "UsbRetractReason_BlockedByPolicy: now it is not support");
247 return ERROR_ACCESS_DENIED;
250 WLog_Print(urbdrc->log, WLOG_DEBUG,
251 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32
"", Reason);
252 return ERROR_ACCESS_DENIED;
255 return ERROR_SUCCESS;
259 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
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;
271 if (!callback || !s || !udevman || !pdev)
272 return ERROR_INVALID_PARAMETER;
277 return ERROR_INVALID_PARAMETER;
279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
280 return ERROR_INVALID_DATA;
282 Stream_Read_UINT32(s, IoControlCode);
283 Stream_Read_UINT32(s, InputBufferSize);
285 if (!Stream_SafeSeek(s, InputBufferSize))
286 return ERROR_INVALID_DATA;
287 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
288 return ERROR_INVALID_DATA;
290 Stream_Read_UINT32(s, OutputBufferSize);
291 Stream_Read_UINT32(s, RequestId);
293 if (OutputBufferSize > UINT32_MAX - 4)
294 return ERROR_INVALID_DATA;
296 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
297 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
300 return ERROR_OUTOFMEMORY;
302 switch (IoControlCode)
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");
310 case IOCTL_INTERNAL_USB_RESET_PORT:
311 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
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));
321 if (!Stream_SafeSeek(out, OutputBufferSize))
323 Stream_Free(out, TRUE);
324 return ERROR_INVALID_DATA;
327 if (pdev->isExist(pdev) == 0)
328 Stream_Write_UINT32(out, 0);
330 usb_process_get_port_status(pdev, out);
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");
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");
349 WLog_Print(urbdrc->log, WLOG_DEBUG,
350 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
352 Stream_Free(out, TRUE);
353 return ERROR_INVALID_OPERATION;
356 return stream_write_and_free(callback->plugin, callback->channel, out);
360 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
362 if (!pdev || !callback || !s || !udevman)
363 return ERROR_INVALID_PARAMETER;
366 WINPR_ASSERT(urbdrc);
368 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
369 return ERROR_INVALID_DATA;
371 const UINT32 IoControlCode = Stream_Get_UINT32(s);
372 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
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]",
379 return ERROR_INVALID_DATA;
381 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
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));
392 const UINT32 frames = GetTickCount();
394 if (4 > OutputBufferSize)
396 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32, 4u,
398 return ERROR_BAD_CONFIGURATION;
400 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
403 return ERROR_OUTOFMEMORY;
405 Stream_Write_UINT32(out, frames);
406 return stream_write_and_free(callback->plugin, callback->channel, out);
411 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
412 const BYTE* text, uint8_t bytelen)
414 WINPR_ASSERT(callback);
416 const uint8_t charlen = bytelen /
sizeof(WCHAR);
417 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
421 return ERROR_OUTOFMEMORY;
423 Stream_Write(out, text, bytelen);
424 Stream_Write_INT32(out, hr);
425 return stream_write_and_free(callback->plugin, callback->channel, out);
429 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
433 UINT8 bufferSize = 0xFF;
434 BYTE DeviceDescription[0x100] = { 0 };
436 if (!pdev || !callback || !s || !udevman)
437 return ERROR_INVALID_PARAMETER;
438 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
439 return ERROR_INVALID_DATA;
441 Stream_Read_UINT32(s, TextType);
442 Stream_Read_UINT32(s, LocaleId);
443 if (LocaleId > UINT16_MAX)
444 return ERROR_INVALID_DATA;
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);
453static void func_select_all_interface_for_msconfig(IUDEVICE* pdev,
457 UINT32 NumInterfaces = MsConfig->NumInterfaces;
459 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
461 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
462 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
463 pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
469 UINT32 InterfaceId, UINT32 MessageId,
470 UINT32 RequestId, UINT32 UrbStatus,
474 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
476 return ERROR_OUTOFMEMORY;
478 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
479 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
481 if (!Stream_EnsureRemainingCapacity(out, 4))
483 Stream_Write_UINT32(out, usize);
485 if (!write_urb_result_header(out, usize, UrbStatus))
490 msusb_msconfig_write(MsConfig, out);
493 Stream_Write_UINT32(out, 0);
494 Stream_Write_UINT32(out, 0);
497 return send_urb_completion_message(callback, out, 0, 0, NULL);
500 Stream_Free(out, TRUE);
501 return ERROR_OUTOFMEMORY;
505 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
509 UINT32 NumInterfaces = 0;
510 UINT32 usbd_status = 0;
511 BYTE ConfigurationDescriptorIsValid = 0;
513 const BOOL noAck = (RequestField & 0x80000000U) != 0;
514 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
516 if (!callback || !s || !udevman || !pdev)
517 return ERROR_INVALID_PARAMETER;
522 return ERROR_INVALID_PARAMETER;
524 if (transferDir == 0)
526 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
527 return ERROR_INVALID_PARAMETER;
530 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
531 return ERROR_INVALID_DATA;
533 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
534 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
536 Stream_Read_UINT32(s, NumInterfaces);
539 if (ConfigurationDescriptorIsValid)
542 MsConfig = msusb_msconfig_read(s, NumInterfaces);
545 return ERROR_INVALID_DATA;
548 pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
550 func_select_all_interface_for_msconfig(pdev, MsConfig);
552 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
554 msusb_msconfig_free(MsConfig);
560 return CHANNEL_RC_OK;
561 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
562 usbd_status, MsConfig);
567 UINT32 InterfaceId, UINT32 MessageId,
569 UINT32 ConfigurationHandle)
571 WINPR_ASSERT(callback);
572 WINPR_ASSERT(MsInterface);
574 const UINT32 NumInterfaces = 1;
575 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
577 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
580 return ERROR_OUTOFMEMORY;
582 const uint32_t size = 8U + interface_size;
583 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
585 if (!Stream_EnsureRemainingCapacity(out, 4))
587 Stream_Write_UINT32(out, usize);
589 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
592 if (!msusb_msinterface_write(MsInterface, out))
595 if (!Stream_EnsureRemainingCapacity(out, 8))
597 Stream_Write_UINT32(out, ConfigurationHandle);
598 Stream_Write_UINT32(out, NumInterfaces);
600 for (
size_t x = 0; x < NumInterfaces; x++)
603 if (!msusb_msinterface_write(ifc, out))
607 return send_urb_completion_message(callback, out, 0, 0, NULL);
610 Stream_Free(out, TRUE);
612 return ERROR_INTERNAL_ERROR;
616 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
619 const BOOL noAck = (RequestField & 0x80000000U) != 0;
620 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
622 if (!callback || !s || !udevman || !pdev)
623 return ERROR_INVALID_PARAMETER;
628 return ERROR_INVALID_PARAMETER;
630 if (transferDir == 0)
632 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
633 return ERROR_INVALID_PARAMETER;
636 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
637 return ERROR_INVALID_DATA;
639 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
640 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
643 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
645 msusb_msinterface_free(MsInterface);
646 return ERROR_INVALID_DATA;
649 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
650 if (OutputBufferSize != 0)
652 WLog_Print(urbdrc->log, WLOG_ERROR,
653 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
656 msusb_msinterface_free(MsInterface);
657 return ERROR_INVALID_DATA;
660 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
663 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
664 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
666 msusb_msconfig_free(MsConfig);
667 return ERROR_BAD_CONFIGURATION;
670 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
671 return ERROR_BAD_CONFIGURATION;
674 return CHANNEL_RC_OK;
676 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface,
677 ConfigurationHandle);
681 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
682 int transferDir,
int External)
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;
692 BYTE bmRequestType = 0;
700 const BOOL noAck = (RequestField & 0x80000000U) != 0;
701 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
703 if (!callback || !s || !udevman || !pdev)
704 return ERROR_INVALID_PARAMETER;
709 return ERROR_INVALID_PARAMETER;
711 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
712 return ERROR_INVALID_DATA;
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);
722 case URB_CONTROL_TRANSFER_EXTERNAL:
723 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
724 return ERROR_INVALID_DATA;
726 Stream_Read_UINT32(s, Timeout);
729 case URB_CONTROL_TRANSFER_NONEXTERNAL:
736 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
737 return ERROR_INVALID_DATA;
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);
746 if (length != OutputBufferSize)
748 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
749 return ERROR_INVALID_DATA;
752 out_size = 36 + OutputBufferSize;
753 out = Stream_New(NULL, out_size);
756 return ERROR_OUTOFMEMORY;
758 Stream_Seek(out, 36);
760 buffer = Stream_Pointer(out);
762 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
764 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
766 Stream_Free(out, TRUE);
767 return ERROR_INVALID_DATA;
769 Stream_Copy(s, out, OutputBufferSize);
773 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
774 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
777 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
778 Stream_Free(out, TRUE);
779 return ERROR_INTERNAL_ERROR;
782 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
783 usbd_status, OutputBufferSize);
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)
792 if (!pdev->isChannelClosed(pdev))
793 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
796 Stream_Free(out, TRUE);
800 wStream* s, UINT32 RequestField, UINT32 MessageId,
801 IUDEVMAN* udevman,
int transferDir)
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;
810 if (!pdev || !callback || !s || !udevman)
811 return ERROR_INVALID_PARAMETER;
813 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
814 return ERROR_INVALID_DATA;
816 Stream_Read_UINT32(s, PipeHandle);
817 Stream_Read_UINT32(s, TransferFlags);
818 Stream_Read_UINT32(s, OutputBufferSize);
819 EndpointAddress = (PipeHandle & 0x000000ff);
821 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
823 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
825 return ERROR_INVALID_DATA;
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);
838static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
840 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
841 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
842 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
846 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
847 Stream_SetPosition(out, 0);
849 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
850 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
852 Stream_Free(out, TRUE);
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),
861 Stream_Free(out, TRUE);
865 Stream_Write_UINT32(out, StartFrame);
870 Stream_Write_UINT32(out, NumberOfPackets);
871 Stream_Write_UINT32(out, ErrorCount);
872 Stream_Seek(out, packetSize);
876 Stream_Write_UINT32(out, 0);
877 Stream_Write_UINT32(out, ErrorCount);
880 Stream_Write_UINT32(out, 0);
881 Stream_Write_UINT32(out, OutputBufferSize);
882 Stream_Seek(out, OutputBufferSize);
884 stream_write_and_free(callback->plugin, callback->channel, out);
889 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
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;
904 if (!pdev || !callback || !udevman)
905 return ERROR_INVALID_PARAMETER;
907 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
908 return ERROR_INVALID_DATA;
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;
920 packetDescriptorData = Stream_Pointer(s);
921 Stream_Seek(s, 12ULL * NumberOfPackets);
923 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
924 return ERROR_INVALID_DATA;
925 Stream_Read_UINT32(s, OutputBufferSize);
927 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
929 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
930 return ERROR_INVALID_DATA;
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);
940 return ERROR_INTERNAL_ERROR;
945 wStream* s, UINT32 RequestField, UINT32 MessageId,
946 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
949 UINT32 InterfaceId = 0;
950 UINT32 OutputBufferSize = 0;
951 UINT32 usbd_status = 0;
952 BYTE bmRequestType = 0;
958 const BOOL noAck = (RequestField & 0x80000000U) != 0;
959 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
961 if (!callback || !s || !udevman || !pdev)
962 return ERROR_INVALID_PARAMETER;
967 return ERROR_INVALID_PARAMETER;
969 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
970 return ERROR_INVALID_DATA;
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)
981 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
982 return ERROR_INVALID_DATA;
985 out_size = 36ULL + OutputBufferSize;
986 out = Stream_New(NULL, out_size);
989 return ERROR_OUTOFMEMORY;
991 Stream_Seek(out, 36);
992 bmRequestType = func_recipient;
996 case USBD_TRANSFER_DIRECTION_IN:
997 bmRequestType |= 0x80;
1000 case USBD_TRANSFER_DIRECTION_OUT:
1001 bmRequestType |= 0x00;
1002 Stream_Copy(s, out, OutputBufferSize);
1003 Stream_Rewind(out, OutputBufferSize);
1007 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1008 OutputBufferSize = 0;
1009 usbd_status = USBD_STATUS_STALL_PID;
1014 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1016 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1017 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1019 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1020 Stream_Free(out, TRUE);
1021 return ERROR_INTERNAL_ERROR;
1024 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1025 usbd_status, OutputBufferSize);
1029 wStream* s, UINT32 RequestField, UINT32 MessageId,
1030 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1032 size_t out_size = 0;
1033 UINT32 InterfaceId = 0;
1034 UINT32 OutputBufferSize = 0;
1035 UINT32 usbd_status = 0;
1037 BYTE bmRequestType = 0;
1040 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1041 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1043 if (!callback || !s || !udevman || !pdev)
1044 return ERROR_INVALID_PARAMETER;
1049 return ERROR_INVALID_PARAMETER;
1051 if (transferDir == 0)
1053 WLog_Print(urbdrc->log, WLOG_DEBUG,
1054 "urb_control_get_status_request: transfer out not supported");
1055 return ERROR_INVALID_PARAMETER;
1058 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1059 return ERROR_INVALID_DATA;
1061 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1062 Stream_Read_UINT16(s, Index);
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);
1071 return ERROR_OUTOFMEMORY;
1073 Stream_Seek(out, 36);
1074 bmRequestType = func_recipient | 0x80;
1076 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1077 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1080 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1081 Stream_Free(out, TRUE);
1082 return ERROR_INTERNAL_ERROR;
1085 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1086 usbd_status, OutputBufferSize);
1090 wStream* s, UINT32 RequestField, UINT32 MessageId,
1091 IUDEVMAN* udevman, BYTE func_type,
1092 BYTE func_recipient,
int transferDir)
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;
1101 BYTE bmRequestType = 0;
1106 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1107 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1109 if (!callback || !s || !udevman || !pdev)
1110 return ERROR_INVALID_PARAMETER;
1115 return ERROR_INVALID_PARAMETER;
1117 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1118 return ERROR_INVALID_DATA;
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;
1131 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1133 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1134 return ERROR_INVALID_DATA;
1137 out_size = 36ULL + OutputBufferSize;
1138 out = Stream_New(NULL, out_size);
1141 return ERROR_OUTOFMEMORY;
1143 Stream_Seek(out, 36);
1146 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1148 Stream_Copy(s, out, OutputBufferSize);
1149 Stream_Rewind(out, OutputBufferSize);
1153 bmRequestType = func_type | func_recipient;
1155 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1156 bmRequestType |= 0x80;
1158 WLog_Print(urbdrc->log, WLOG_DEBUG,
1159 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
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);
1166 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1167 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1169 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1170 Stream_Free(out, TRUE);
1171 return ERROR_INTERNAL_ERROR;
1174 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1175 usbd_status, OutputBufferSize);
1179 wStream* s, UINT32 RequestField, UINT32 MessageId,
1180 IUDEVMAN* udevman,
int transferDir)
1182 size_t out_size = 0;
1183 UINT32 InterfaceId = 0;
1184 UINT32 OutputBufferSize = 0;
1185 UINT32 usbd_status = 0;
1187 BYTE InterfaceNumber = 0;
1188 BYTE Ms_PageIndex = 0;
1189 UINT16 Ms_featureDescIndex = 0;
1193 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1194 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1196 if (!callback || !s || !udevman || !pdev)
1197 return ERROR_INVALID_PARAMETER;
1202 return ERROR_INVALID_PARAMETER;
1204 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1205 return ERROR_INVALID_DATA;
1208 Stream_Read_UINT8(s, Recipient);
1209 Recipient = (Recipient & 0x1f);
1210 Stream_Read_UINT8(s, InterfaceNumber);
1211 Stream_Read_UINT8(s, Ms_PageIndex);
1212 Stream_Read_UINT16(s, Ms_featureDescIndex);
1214 Stream_Read_UINT32(s, OutputBufferSize);
1215 if (OutputBufferSize > UINT32_MAX - 36)
1216 return ERROR_INVALID_DATA;
1218 switch (transferDir)
1220 case USBD_TRANSFER_DIRECTION_OUT:
1221 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1222 return ERROR_INVALID_DATA;
1230 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1231 out_size = 36ULL + OutputBufferSize;
1232 out = Stream_New(NULL, out_size);
1235 return ERROR_OUTOFMEMORY;
1237 Stream_Seek(out, 36);
1239 switch (transferDir)
1241 case USBD_TRANSFER_DIRECTION_OUT:
1242 Stream_Copy(s, out, OutputBufferSize);
1243 Stream_Rewind(out, OutputBufferSize);
1246 case USBD_TRANSFER_DIRECTION_IN:
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);
1263 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1265 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1266 usbd_status, OutputBufferSize);
1270 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1271 int transferDir,
int action)
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;
1280 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1283 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1284 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1286 if (!callback || !s || !udevman || !pdev)
1287 return ERROR_INVALID_PARAMETER;
1292 return ERROR_INVALID_PARAMETER;
1294 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1295 return ERROR_INVALID_DATA;
1297 if (transferDir == 0)
1299 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1300 return ERROR_INVALID_PARAMETER;
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);
1311 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1315 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1317 ret = USBD_STATUS_SUCCESS;
1322 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1324 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1328 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1330 ret = USBD_STATUS_SUCCESS;
1335 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1337 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1343 if (out_size > OutputBufferSize)
1345 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32,
1346 out_size, OutputBufferSize);
1347 return ERROR_BAD_CONFIGURATION;
1349 out = Stream_New(NULL, out_size);
1352 return ERROR_OUTOFMEMORY;
1354 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1359 UINT32 RequestId, UINT32 MessageId,
1360 UINT32 CompletionId, UINT32 FrameNumber)
1362 WINPR_ASSERT(callback);
1364 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1366 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1369 return ERROR_OUTOFMEMORY;
1371 Stream_Write_UINT32(out, 12);
1372 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1374 Stream_Free(out, TRUE);
1375 return ERROR_OUTOFMEMORY;
1378 Stream_Write_UINT32(out, FrameNumber);
1379 return send_urb_completion_message(callback, out, 0, 0, NULL);
1383 wStream* s, UINT32 RequestField, UINT32 MessageId,
1384 IUDEVMAN* udevman,
int transferDir)
1386 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1387 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1389 if (!callback || !s || !udevman || !pdev)
1390 return ERROR_INVALID_PARAMETER;
1395 return ERROR_INVALID_PARAMETER;
1397 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1398 return ERROR_INVALID_DATA;
1400 if (transferDir == 0)
1402 WLog_Print(urbdrc->log, WLOG_DEBUG,
1403 "urb_get_current_frame_number: not support transfer out");
1404 return ERROR_INVALID_PARAMETER;
1407 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1408 if (OutputBufferSize != 0)
1410 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1414 const UINT32 dummy_frames = GetTickCount();
1415 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1418 return CHANNEL_RC_OK;
1420 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1425static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1427 UINT32 RequestField, UINT32 MessageId,
1428 IUDEVMAN* udevman,
int transferDir)
1430 size_t out_size = 0;
1431 UINT32 InterfaceId = 0;
1432 UINT32 OutputBufferSize = 0;
1433 UINT32 usbd_status = 0;
1436 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1437 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1439 if (!callback || !s || !udevman || !pdev)
1440 return ERROR_INVALID_PARAMETER;
1445 return ERROR_INVALID_PARAMETER;
1447 if (transferDir == 0)
1449 WLog_Print(urbdrc->log, WLOG_DEBUG,
1450 "urb_control_get_configuration_request:"
1451 " not support transfer out");
1452 return ERROR_INVALID_PARAMETER;
1455 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1456 return ERROR_INVALID_DATA;
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);
1465 return ERROR_OUTOFMEMORY;
1467 Stream_Seek(out, 36);
1468 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1470 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1472 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1474 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1475 Stream_Free(out, TRUE);
1476 return ERROR_INTERNAL_ERROR;
1479 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1480 usbd_status, OutputBufferSize);
1485 wStream* s, UINT32 RequestField, UINT32 MessageId,
1486 IUDEVMAN* udevman,
int transferDir)
1488 size_t out_size = 0;
1489 UINT32 InterfaceId = 0;
1490 UINT32 OutputBufferSize = 0;
1491 UINT32 usbd_status = 0;
1492 UINT16 InterfaceNr = 0;
1495 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1496 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1498 if (!callback || !s || !udevman || !pdev)
1499 return ERROR_INVALID_PARAMETER;
1504 return ERROR_INVALID_PARAMETER;
1506 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1507 return ERROR_INVALID_DATA;
1509 if (transferDir == 0)
1511 WLog_Print(urbdrc->log, WLOG_DEBUG,
1512 "urb_control_get_interface_request: not support transfer out");
1513 return ERROR_INVALID_PARAMETER;
1516 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1517 Stream_Read_UINT16(s, InterfaceNr);
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);
1526 return ERROR_OUTOFMEMORY;
1528 Stream_Seek(out, 36);
1530 if (!pdev->control_transfer(
1531 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1532 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1534 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1535 Stream_Free(out, TRUE);
1536 return ERROR_INTERNAL_ERROR;
1539 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1540 usbd_status, OutputBufferSize);
1544 wStream* s, UINT32 RequestField, UINT32 MessageId,
1545 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1548 UINT32 InterfaceId = 0;
1549 UINT32 OutputBufferSize = 0;
1550 UINT32 usbd_status = 0;
1551 UINT16 FeatureSelector = 0;
1553 BYTE bmRequestType = 0;
1557 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1558 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1560 if (!callback || !s || !udevman || !pdev)
1561 return ERROR_INVALID_PARAMETER;
1566 return ERROR_INVALID_PARAMETER;
1568 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1569 return ERROR_INVALID_DATA;
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)
1579 case USBD_TRANSFER_DIRECTION_OUT:
1580 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1581 return ERROR_INVALID_DATA;
1589 out = Stream_New(NULL, 36ULL + OutputBufferSize);
1592 return ERROR_OUTOFMEMORY;
1594 Stream_Seek(out, 36);
1595 bmRequestType = func_recipient;
1597 switch (transferDir)
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;
1607 case USBD_TRANSFER_DIRECTION_IN:
1608 bmRequestType |= 0x80;
1616 case URB_SET_FEATURE:
1620 case URB_CLEAR_FEATURE:
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;
1631 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1632 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1634 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1635 Stream_Free(out, TRUE);
1636 return ERROR_INTERNAL_ERROR;
1639 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1640 usbd_status, OutputBufferSize);
1644 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1649 UINT16 URB_Function = 0;
1650 UINT32 RequestId = 0;
1651 UINT error = ERROR_INTERNAL_ERROR;
1654 if (!callback || !s || !udevman || !pdev)
1655 return ERROR_INVALID_PARAMETER;
1660 return ERROR_INVALID_PARAMETER;
1662 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1663 return ERROR_INVALID_DATA;
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)
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)";
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;
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),
1685 switch (URB_Function)
1687 case TS_URB_SELECT_CONFIGURATION:
1688 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1692 case TS_URB_SELECT_INTERFACE:
1694 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1697 case TS_URB_PIPE_REQUEST:
1698 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1702 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1708 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1714 case TS_URB_GET_FRAME_LENGTH:
1720 case TS_URB_SET_FRAME_LENGTH:
1726 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1727 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1731 case TS_URB_CONTROL_TRANSFER:
1732 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1733 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1736 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1737 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1741 case TS_URB_ISOCH_TRANSFER:
1743 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1746 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1747 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1751 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1752 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
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);
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);
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);
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);
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);
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);
1786 case TS_URB_GET_STATUS_FROM_DEVICE:
1787 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1791 case TS_URB_GET_STATUS_FROM_INTERFACE:
1792 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1796 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1797 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1801 case TS_URB_RESERVED_0X0016:
1804 case TS_URB_VENDOR_DEVICE:
1805 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1806 udevman, (0x02 << 5),
1810 case TS_URB_VENDOR_INTERFACE:
1811 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1812 udevman, (0x02 << 5),
1816 case TS_URB_VENDOR_ENDPOINT:
1817 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1818 udevman, (0x02 << 5),
1822 case TS_URB_CLASS_DEVICE:
1823 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1824 udevman, (0x01 << 5),
1828 case TS_URB_CLASS_INTERFACE:
1829 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1830 udevman, (0x01 << 5),
1834 case TS_URB_CLASS_ENDPOINT:
1835 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1836 udevman, (0x01 << 5),
1840 case TS_URB_RESERVE_0X001D:
1843 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1844 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1848 case TS_URB_CLASS_OTHER:
1849 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1850 udevman, (0x01 << 5),
1854 case TS_URB_VENDOR_OTHER:
1855 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1856 udevman, (0x02 << 5),
1860 case TS_URB_GET_STATUS_FROM_OTHER:
1861 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
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);
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);
1875 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1876 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1880 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1881 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1885 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1886 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1887 udevman, transferDir);
1890 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1891 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1892 udevman, transferDir);
1895 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1896 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1900 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1901 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1905 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1906 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1907 udevman, transferDir);
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:
1918 case TS_URB_SYNC_RESET_PIPE:
1919 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1923 case TS_URB_SYNC_CLEAR_STALL:
1924 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1928 case TS_URB_CONTROL_TRANSFER_EX:
1929 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1930 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1934 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
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);
1950 IUDEVMAN* udevman,
wStream* data)
1952 UINT32 InterfaceId = 0;
1953 UINT32 MessageId = 0;
1954 UINT32 FunctionId = 0;
1955 IUDEVICE* pdev = NULL;
1956 UINT error = ERROR_INTERNAL_ERROR;
1958 if (!urbdrc || !data || !callback || !udevman)
1961 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1964 Stream_Rewind_UINT32(data);
1966 Stream_Read_UINT32(data, InterfaceId);
1967 Stream_Read_UINT32(data, MessageId);
1968 Stream_Read_UINT32(data, FunctionId);
1970 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1975 error = ERROR_SUCCESS;
1980 if (pdev->isChannelClosed(pdev))
1982 error = ERROR_SUCCESS;
1987 pdev->detach_kernel_driver(pdev);
1991 case CANCEL_REQUEST:
1992 error = urbdrc_process_cancel_request(pdev, data, udevman);
1995 case REGISTER_REQUEST_CALLBACK:
1996 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2000 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2003 case INTERNAL_IO_CONTROL:
2004 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2007 case QUERY_DEVICE_TEXT:
2008 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2011 case TRANSFER_IN_REQUEST:
2012 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2013 USBD_TRANSFER_DIRECTION_IN);
2016 case TRANSFER_OUT_REQUEST:
2017 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2018 USBD_TRANSFER_DIRECTION_OUT);
2021 case RETRACT_DEVICE:
2022 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2026 WLog_Print(urbdrc->log, WLOG_WARN,
2027 "urbdrc_process_udev_data_transfer:"
2028 " unknown FunctionId 0x%" PRIX32
"",
2036 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);