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);
104static UINT32 urb_completion_payload_size(
int transferDir, UINT32 outputBufferSize)
106 return (transferDir == USBD_TRANSFER_DIRECTION_IN) ? outputBufferSize : 0;
109static UINT urb_write_completion(WINPR_ATTR_UNUSED IUDEVICE* pdev,
111 UINT32 InterfaceId, UINT32 MessageId, UINT32 RequestId,
112 UINT32 usbd_status, UINT32 OutputBufferSize,
int transferDir)
115 return ERROR_INVALID_PARAMETER;
117 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
118 if (Stream_Capacity(out) < payloadSize + 36ULL)
120 Stream_Free(out, TRUE);
121 return ERROR_INVALID_PARAMETER;
124 Stream_ResetPosition(out);
126 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
127 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
129 Stream_Free(out, TRUE);
130 return ERROR_OUTOFMEMORY;
133 Stream_Write_UINT32(out, RequestId);
134 Stream_Write_UINT32(out, 8);
136 if (!write_urb_result_header(out, 8, usbd_status))
138 Stream_Free(out, TRUE);
139 return ERROR_OUTOFMEMORY;
142 Stream_Write_UINT32(out, 0);
143 Stream_Write_UINT32(out, OutputBufferSize);
144 Stream_Seek(out, payloadSize);
147 return stream_write_and_free(callback->plugin, callback->channel, out);
149 Stream_Free(out, TRUE);
151 return ERROR_SUCCESS;
154static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
155 UINT32 OutputBufferSize)
157 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
159#if UINT32_MAX >= SIZE_MAX
160 if (OutputBufferSize > UINT32_MAX - 28ull)
164 wStream* out = create_shared_message_header_with_functionid(
165 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
169 Stream_Write_UINT32(out, RequestId);
170 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
171 Stream_Write_UINT32(out, OutputBufferSize);
172 Stream_Write_UINT32(out, OutputBufferSize);
184static BOOL urb_finalize_iocompletion(
wStream* out)
188 const size_t header = 12ULL + 4ULL ;
189 const size_t offset = header + 4ULL ;
190 const size_t fixed = offset + 4ULL + 4ULL ;
191 const size_t end = Stream_GetPosition(out);
196 const size_t OutputBufferSize = end - fixed;
198 if (OutputBufferSize > UINT32_MAX)
201 const UINT32 size = WINPR_ASSERTING_INT_CAST(UINT32, OutputBufferSize);
203 if (!Stream_SetPosition(out, offset))
206 Stream_Write_UINT32(out, size);
207 Stream_Write_UINT32(out, size);
208 return Stream_SetPosition(out, end);
211static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
215 UINT32 NumRequestCompletion = 0;
216 UINT32 RequestCompletion = 0;
218 if (!callback || !s || !udevman || !pdev)
219 return ERROR_INVALID_PARAMETER;
224 return ERROR_INVALID_PARAMETER;
226 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urbdrc_process_register_request_callback");
228 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
229 return ERROR_INVALID_DATA;
231 Stream_Read_UINT32(s, NumRequestCompletion);
233 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL * NumRequestCompletion))
234 return ERROR_INVALID_DATA;
235 for (uint32_t x = 0; x < NumRequestCompletion; x++)
239 Stream_Read_UINT32(s, RequestCompletion);
240 pdev->set_ReqCompletion(pdev, RequestCompletion);
243 return ERROR_SUCCESS;
246static UINT urbdrc_process_cancel_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
251 if (!s || !udevman || !pdev)
252 return ERROR_INVALID_PARAMETER;
256 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
257 return ERROR_INVALID_DATA;
259 Stream_Read_UINT32(s, CancelId);
260 WLog_Print(urbdrc->log, WLOG_DEBUG,
"CANCEL_REQUEST: CancelId=%08" PRIx32
"", CancelId);
262 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
263 return ERROR_INTERNAL_ERROR;
265 return ERROR_SUCCESS;
268static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev,
wStream* s,
275 return ERROR_INVALID_PARAMETER;
280 return ERROR_INVALID_PARAMETER;
282 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
283 return ERROR_INVALID_DATA;
285 Stream_Read_UINT32(s, Reason);
289 case UsbRetractReason_BlockedByPolicy:
290 WLog_Print(urbdrc->log, WLOG_DEBUG,
291 "UsbRetractReason_BlockedByPolicy: now it is not support");
292 return ERROR_ACCESS_DENIED;
295 WLog_Print(urbdrc->log, WLOG_DEBUG,
296 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32
"", Reason);
297 return ERROR_ACCESS_DENIED;
300 return ERROR_SUCCESS;
304 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
306 UINT32 InterfaceId = 0;
307 UINT32 IoControlCode = 0;
308 UINT32 InputBufferSize = 0;
309 UINT32 OutputBufferSize = 0;
310 UINT32 RequestId = 0;
311 UINT32 usbd_status = USBD_STATUS_SUCCESS;
316 if (!callback || !s || !udevman || !pdev)
317 return ERROR_INVALID_PARAMETER;
322 return ERROR_INVALID_PARAMETER;
324 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
325 return ERROR_INVALID_DATA;
327 Stream_Read_UINT32(s, IoControlCode);
328 Stream_Read_UINT32(s, InputBufferSize);
330 if (!Stream_SafeSeek(s, InputBufferSize))
331 return ERROR_INVALID_DATA;
332 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
333 return ERROR_INVALID_DATA;
335 Stream_Read_UINT32(s, OutputBufferSize);
336 Stream_Read_UINT32(s, RequestId);
338 if (OutputBufferSize > UINT32_MAX - 4)
339 return ERROR_INVALID_DATA;
341 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
342 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
345 return ERROR_OUTOFMEMORY;
347 switch (IoControlCode)
349 case IOCTL_INTERNAL_USB_SUBMIT_URB:
350 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
351 WLog_Print(urbdrc->log, WLOG_ERROR,
352 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
355 case IOCTL_INTERNAL_USB_RESET_PORT:
356 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
359 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
360 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
361 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
362 Stream_Pointer(out));
366 if (!Stream_SafeSeek(out, OutputBufferSize))
368 Stream_Free(out, TRUE);
369 return ERROR_INVALID_DATA;
372 if (pdev->isExist(pdev) == 0)
373 Stream_Write_UINT32(out, 0);
375 usb_process_get_port_status(pdev, out);
380 case IOCTL_INTERNAL_USB_CYCLE_PORT:
381 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
382 WLog_Print(urbdrc->log, WLOG_ERROR,
383 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
386 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
387 WLog_Print(urbdrc->log, WLOG_DEBUG,
388 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
389 WLog_Print(urbdrc->log, WLOG_ERROR,
390 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
394 WLog_Print(urbdrc->log, WLOG_DEBUG,
395 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
397 Stream_Free(out, TRUE);
398 return ERROR_INVALID_OPERATION;
401 if (!urb_finalize_iocompletion(out))
403 Stream_Free(out, TRUE);
404 return ERROR_INTERNAL_ERROR;
407 return stream_write_and_free(callback->plugin, callback->channel, out);
411 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
413 if (!pdev || !callback || !s || !udevman)
414 return ERROR_INVALID_PARAMETER;
417 WINPR_ASSERT(urbdrc);
419 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
420 return ERROR_INVALID_DATA;
422 const UINT32 IoControlCode = Stream_Get_UINT32(s);
423 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
427 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
428 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
430 return ERROR_INVALID_DATA;
432 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
434 if (!Stream_SafeSeek(s, InputBufferSize))
435 return ERROR_INVALID_DATA;
436 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
437 return ERROR_INVALID_DATA;
438 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
439 const UINT32 RequestId = Stream_Get_UINT32(s);
440 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
443 const UINT32 frames = GetTickCount();
445 if (4 > OutputBufferSize)
447 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32, 4u,
449 return ERROR_BAD_CONFIGURATION;
451 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
454 return ERROR_OUTOFMEMORY;
456 Stream_Write_UINT32(out, frames);
457 return stream_write_and_free(callback->plugin, callback->channel, out);
462 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
463 const BYTE* text, uint8_t bytelen)
465 WINPR_ASSERT(callback);
467 const uint8_t charlen = bytelen /
sizeof(WCHAR);
468 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
472 return ERROR_OUTOFMEMORY;
474 Stream_Write(out, text, bytelen);
475 Stream_Write_INT32(out, hr);
476 return stream_write_and_free(callback->plugin, callback->channel, out);
480 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
484 UINT8 bufferSize = 0xFF;
485 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
487 if (!pdev || !callback || !s || !udevman)
488 return ERROR_INVALID_PARAMETER;
489 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
490 return ERROR_INVALID_DATA;
492 Stream_Read_UINT32(s, TextType);
493 Stream_Read_UINT32(s, LocaleId);
494 if (LocaleId > UINT16_MAX)
495 return ERROR_INVALID_DATA;
497 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
498 &bufferSize, DeviceDescription);
499 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
500 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
501 DeviceDescription, bufferSize);
504static void func_select_all_interface_for_msconfig(
URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
507 WINPR_ASSERT(urbdrc);
509 WINPR_ASSERT(MsConfig);
512 UINT32 NumInterfaces = MsConfig->NumInterfaces;
514 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
516 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
517 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
518 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
521 WLog_Print(urbdrc->log, WLOG_WARN,
522 "select_interface %" PRIu8
" [%" PRIu8
"] failed [%d]", InterfaceNumber,
523 AlternateSetting, rc);
530 UINT32 InterfaceId, UINT32 MessageId,
531 UINT32 RequestId, UINT32 UrbStatus,
535 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
537 return ERROR_OUTOFMEMORY;
539 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
540 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
542 if (!Stream_EnsureRemainingCapacity(out, 4))
544 Stream_Write_UINT32(out, usize);
546 if (!write_urb_result_header(out, usize, UrbStatus))
552 if (!msusb_msconfig_write(MsConfig, out))
557 Stream_Write_UINT32(out, 0);
558 Stream_Write_UINT32(out, 0);
561 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
564 Stream_Free(out, TRUE);
565 return ERROR_OUTOFMEMORY;
569 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
573 UINT32 NumInterfaces = 0;
574 UINT32 usbd_status = 0;
575 BYTE ConfigurationDescriptorIsValid = 0;
577 const BOOL noAck = (RequestField & 0x80000000U) != 0;
578 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
580 if (!callback || !s || !udevman || !pdev)
581 return ERROR_INVALID_PARAMETER;
586 return ERROR_INVALID_PARAMETER;
588 if (transferDir == 0)
590 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
591 return ERROR_INVALID_PARAMETER;
594 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
595 return ERROR_INVALID_DATA;
597 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
598 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
600 Stream_Read_UINT32(s, NumInterfaces);
603 if (ConfigurationDescriptorIsValid)
606 MsConfig = msusb_msconfig_read(s, NumInterfaces);
609 return ERROR_INVALID_DATA;
612 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
615 msusb_msconfig_free(MsConfig);
617 return ERROR_INTERNAL_ERROR;
621 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
623 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
625 msusb_msconfig_free(MsConfig);
631 return CHANNEL_RC_OK;
632 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
633 usbd_status, MsConfig);
638 UINT32 InterfaceId, UINT32 MessageId,
641 WINPR_ASSERT(callback);
642 WINPR_ASSERT(MsInterface);
644 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
646 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
649 return ERROR_OUTOFMEMORY;
651 const uint32_t size = 8U + interface_size;
652 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
654 if (!Stream_EnsureRemainingCapacity(out, 4))
656 Stream_Write_UINT32(out, usize);
658 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
661 if (!msusb_msinterface_write(MsInterface, out))
664 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
667 Stream_Free(out, TRUE);
669 return ERROR_INTERNAL_ERROR;
673 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
676 const BOOL noAck = (RequestField & 0x80000000U) != 0;
677 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
679 if (!callback || !s || !udevman || !pdev)
680 return ERROR_INVALID_PARAMETER;
685 return ERROR_INVALID_PARAMETER;
687 if (transferDir == 0)
689 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
690 return ERROR_INVALID_PARAMETER;
693 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
694 return ERROR_INVALID_DATA;
696 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
697 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
700 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
702 msusb_msinterface_free(MsInterface);
703 return ERROR_INVALID_DATA;
706 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
707 if (OutputBufferSize != 0)
709 WLog_Print(urbdrc->log, WLOG_ERROR,
710 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
713 msusb_msinterface_free(MsInterface);
714 return ERROR_INVALID_DATA;
718 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
721 msusb_msinterface_free(MsInterface);
722 return ERROR_INTERNAL_ERROR;
727 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
728 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
729 return ERROR_BAD_CONFIGURATION;
732 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
733 return ERROR_BAD_CONFIGURATION;
736 return CHANNEL_RC_OK;
738 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
742 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
743 int transferDir,
int External)
746 UINT32 InterfaceId = 0;
747 UINT32 EndpointAddress = 0;
748 UINT32 PipeHandle = 0;
749 UINT32 TransferFlags = 0;
750 UINT32 OutputBufferSize = 0;
751 UINT32 usbd_status = 0;
753 BYTE bmRequestType = 0;
758 BYTE* buffer =
nullptr;
761 const BOOL noAck = (RequestField & 0x80000000U) != 0;
762 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
764 if (!callback || !s || !udevman || !pdev)
765 return ERROR_INVALID_PARAMETER;
770 return ERROR_INVALID_PARAMETER;
772 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
773 return ERROR_INVALID_DATA;
775 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
776 Stream_Read_UINT32(s, PipeHandle);
777 Stream_Read_UINT32(s, TransferFlags);
778 EndpointAddress = (PipeHandle & 0x000000ff);
783 case URB_CONTROL_TRANSFER_EXTERNAL:
784 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
785 return ERROR_INVALID_DATA;
787 Stream_Read_UINT32(s, Timeout);
790 case URB_CONTROL_TRANSFER_NONEXTERNAL:
797 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
798 return ERROR_INVALID_DATA;
800 Stream_Read_UINT8(s, bmRequestType);
801 Stream_Read_UINT8(s, Request);
802 Stream_Read_UINT16(s, Value);
803 Stream_Read_UINT16(s, Index);
804 Stream_Read_UINT16(s, length);
805 Stream_Read_UINT32(s, OutputBufferSize);
807 if (length != OutputBufferSize)
809 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
810 return ERROR_INVALID_DATA;
813 out_size = 36 + OutputBufferSize;
814 out = Stream_New(
nullptr, out_size);
817 return ERROR_OUTOFMEMORY;
819 Stream_Seek(out, 36);
821 buffer = Stream_Pointer(out);
823 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
825 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
827 Stream_Free(out, TRUE);
828 return ERROR_INVALID_DATA;
830 Stream_Copy(s, out, OutputBufferSize);
834 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
835 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
838 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
839 Stream_Free(out, TRUE);
840 return ERROR_INTERNAL_ERROR;
843 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
844 usbd_status, OutputBufferSize, transferDir);
848 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
849 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
850 WINPR_ATTR_UNUSED UINT32 StartFrame,
851 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
854 if (!pdev->isChannelClosed(pdev))
855 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
856 OutputBufferSize, transferDir);
858 Stream_Free(out, TRUE);
862 wStream* s, UINT32 RequestField, UINT32 MessageId,
863 IUDEVMAN* udevman,
int transferDir)
865 UINT32 EndpointAddress = 0;
866 UINT32 PipeHandle = 0;
867 UINT32 TransferFlags = 0;
868 UINT32 OutputBufferSize = 0;
869 const BOOL noAck = (RequestField & 0x80000000U) != 0;
870 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
872 if (!pdev || !callback || !s || !udevman)
873 return ERROR_INVALID_PARAMETER;
875 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
876 return ERROR_INVALID_DATA;
878 Stream_Read_UINT32(s, PipeHandle);
879 Stream_Read_UINT32(s, TransferFlags);
880 Stream_Read_UINT32(s, OutputBufferSize);
881 EndpointAddress = (PipeHandle & 0x000000ff);
883 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
885 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
887 return ERROR_INVALID_DATA;
892 const int rc = pdev->bulk_or_interrupt_transfer(
893 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
895 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
896 urb_bulk_transfer_cb, 10000);
901static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
903 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
904 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
905 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
910 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
911 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
912 Stream_ResetPosition(out);
914 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
915 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
917 Stream_Free(out, TRUE);
921 Stream_Write_UINT32(out, RequestId);
922 Stream_Write_UINT32(out, 20 + packetSize);
923 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
926 Stream_Free(out, TRUE);
930 Stream_Write_UINT32(out, StartFrame);
935 Stream_Write_UINT32(out, NumberOfPackets);
936 Stream_Write_UINT32(out, ErrorCount);
937 Stream_Seek(out, packetSize);
941 Stream_Write_UINT32(out, 0);
942 Stream_Write_UINT32(out, ErrorCount);
945 Stream_Write_UINT32(out, 0);
946 Stream_Write_UINT32(out, OutputBufferSize);
947 Stream_Seek(out, payloadSize);
949 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
950 if (rc != CHANNEL_RC_OK)
951 WLog_WARN(TAG,
"stream_write_and_free failed with %" PRIu32, rc);
956 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
960 UINT32 EndpointAddress = 0;
961 UINT32 PipeHandle = 0;
962 UINT32 TransferFlags = 0;
963 UINT32 StartFrame = 0;
964 UINT32 NumberOfPackets = 0;
965 UINT32 ErrorCount = 0;
966 UINT32 OutputBufferSize = 0;
967 BYTE* packetDescriptorData =
nullptr;
968 const BOOL noAck = (RequestField & 0x80000000U) != 0;
969 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
971 if (!pdev || !callback || !udevman)
972 return ERROR_INVALID_PARAMETER;
974 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
975 return ERROR_INVALID_DATA;
977 Stream_Read_UINT32(s, PipeHandle);
978 EndpointAddress = (PipeHandle & 0x000000ff);
979 Stream_Read_UINT32(s, TransferFlags);
980 Stream_Read_UINT32(s, StartFrame);
981 Stream_Read_UINT32(s, NumberOfPackets);
982 Stream_Read_UINT32(s, ErrorCount);
984 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
985 return ERROR_INVALID_DATA;
987 packetDescriptorData = Stream_Pointer(s);
988 Stream_Seek(s, 12ULL * NumberOfPackets);
990 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
991 return ERROR_INVALID_DATA;
992 Stream_Read_UINT32(s, OutputBufferSize);
994 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
996 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
997 return ERROR_INVALID_DATA;
1000 rc = pdev->isoch_transfer(
1001 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1002 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1003 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1004 urb_isoch_transfer_cb, 2000);
1007 return ERROR_INTERNAL_ERROR;
1012 wStream* s, UINT32 RequestField, UINT32 MessageId,
1013 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1015 size_t out_size = 0;
1016 UINT32 InterfaceId = 0;
1017 UINT32 OutputBufferSize = 0;
1018 UINT32 usbd_status = 0;
1019 BYTE bmRequestType = 0;
1020 BYTE desc_index = 0;
1025 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1026 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1028 if (!callback || !s || !udevman || !pdev)
1029 return ERROR_INVALID_PARAMETER;
1034 return ERROR_INVALID_PARAMETER;
1036 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1037 return ERROR_INVALID_DATA;
1039 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1040 Stream_Read_UINT8(s, desc_index);
1041 Stream_Read_UINT8(s, desc_type);
1042 Stream_Read_UINT16(s, langId);
1043 Stream_Read_UINT32(s, OutputBufferSize);
1044 if (OutputBufferSize > UINT32_MAX - 36)
1045 return ERROR_INVALID_DATA;
1046 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1048 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1049 return ERROR_INVALID_DATA;
1052 out_size = 36ULL + OutputBufferSize;
1053 out = Stream_New(
nullptr, out_size);
1056 return ERROR_OUTOFMEMORY;
1058 Stream_Seek(out, 36);
1059 bmRequestType = func_recipient;
1061 switch (transferDir)
1063 case USBD_TRANSFER_DIRECTION_IN:
1064 bmRequestType |= 0x80;
1067 case USBD_TRANSFER_DIRECTION_OUT:
1068 bmRequestType |= 0x00;
1069 Stream_Copy(s, out, OutputBufferSize);
1070 Stream_Rewind(out, OutputBufferSize);
1074 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1075 OutputBufferSize = 0;
1076 usbd_status = USBD_STATUS_STALL_PID;
1081 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1083 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1084 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1086 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1087 Stream_Free(out, TRUE);
1088 return ERROR_INTERNAL_ERROR;
1091 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1092 usbd_status, OutputBufferSize, transferDir);
1096 wStream* s, UINT32 RequestField, UINT32 MessageId,
1097 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1099 size_t out_size = 0;
1100 UINT32 InterfaceId = 0;
1101 UINT32 OutputBufferSize = 0;
1102 UINT32 usbd_status = 0;
1104 BYTE bmRequestType = 0;
1107 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1108 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1110 if (!callback || !s || !udevman || !pdev)
1111 return ERROR_INVALID_PARAMETER;
1116 return ERROR_INVALID_PARAMETER;
1118 if (transferDir == 0)
1120 WLog_Print(urbdrc->log, WLOG_DEBUG,
1121 "urb_control_get_status_request: transfer out not supported");
1122 return ERROR_INVALID_PARAMETER;
1125 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1126 return ERROR_INVALID_DATA;
1128 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1129 Stream_Read_UINT16(s, Index);
1131 Stream_Read_UINT32(s, OutputBufferSize);
1132 if (OutputBufferSize > UINT32_MAX - 36)
1133 return ERROR_INVALID_DATA;
1134 out_size = 36ULL + OutputBufferSize;
1135 out = Stream_New(
nullptr, out_size);
1138 return ERROR_OUTOFMEMORY;
1140 Stream_Seek(out, 36);
1141 bmRequestType = func_recipient | 0x80;
1143 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1144 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1147 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1148 Stream_Free(out, TRUE);
1149 return ERROR_INTERNAL_ERROR;
1152 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1153 usbd_status, OutputBufferSize, transferDir);
1157 wStream* s, UINT32 RequestField, UINT32 MessageId,
1158 IUDEVMAN* udevman, BYTE func_type,
1159 BYTE func_recipient,
int transferDir)
1161 UINT32 out_size = 0;
1162 UINT32 InterfaceId = 0;
1163 UINT32 TransferFlags = 0;
1164 UINT32 usbd_status = 0;
1165 UINT32 OutputBufferSize = 0;
1166 BYTE ReqTypeReservedBits = 0;
1168 BYTE bmRequestType = 0;
1173 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1174 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1176 if (!callback || !s || !udevman || !pdev)
1177 return ERROR_INVALID_PARAMETER;
1182 return ERROR_INVALID_PARAMETER;
1184 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1185 return ERROR_INVALID_DATA;
1187 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1188 Stream_Read_UINT32(s, TransferFlags);
1189 Stream_Read_UINT8(s, ReqTypeReservedBits);
1190 Stream_Read_UINT8(s, Request);
1191 Stream_Read_UINT16(s, Value);
1192 Stream_Read_UINT16(s, Index);
1193 Stream_Seek_UINT16(s);
1194 Stream_Read_UINT32(s, OutputBufferSize);
1195 if (OutputBufferSize > UINT32_MAX - 36)
1196 return ERROR_INVALID_DATA;
1198 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1200 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1201 return ERROR_INVALID_DATA;
1204 out_size = 36ULL + OutputBufferSize;
1205 out = Stream_New(
nullptr, out_size);
1208 return ERROR_OUTOFMEMORY;
1210 Stream_Seek(out, 36);
1213 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1215 Stream_Copy(s, out, OutputBufferSize);
1216 Stream_Rewind(out, OutputBufferSize);
1220 bmRequestType = func_type | func_recipient;
1222 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1223 bmRequestType |= 0x80;
1225 WLog_Print(urbdrc->log, WLOG_DEBUG,
1226 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1228 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1229 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1230 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1231 OutputBufferSize, bmRequestType);
1233 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1234 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1236 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1237 Stream_Free(out, TRUE);
1238 return ERROR_INTERNAL_ERROR;
1241 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1242 usbd_status, OutputBufferSize, transferDir);
1246 wStream* s, UINT32 RequestField, UINT32 MessageId,
1247 IUDEVMAN* udevman,
int transferDir)
1249 size_t out_size = 0;
1250 UINT32 InterfaceId = 0;
1251 UINT32 OutputBufferSize = 0;
1252 UINT32 usbd_status = 0;
1254 BYTE InterfaceNumber = 0;
1255 BYTE Ms_PageIndex = 0;
1256 UINT16 Ms_featureDescIndex = 0;
1260 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1261 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1263 if (!callback || !s || !udevman || !pdev)
1264 return ERROR_INVALID_PARAMETER;
1269 return ERROR_INVALID_PARAMETER;
1271 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1272 return ERROR_INVALID_DATA;
1275 Stream_Read_UINT8(s, Recipient);
1276 Recipient = (Recipient & 0x1f);
1277 Stream_Read_UINT8(s, InterfaceNumber);
1278 Stream_Read_UINT8(s, Ms_PageIndex);
1279 Stream_Read_UINT16(s, Ms_featureDescIndex);
1281 Stream_Read_UINT32(s, OutputBufferSize);
1282 if (OutputBufferSize > UINT32_MAX - 36)
1283 return ERROR_INVALID_DATA;
1285 switch (transferDir)
1287 case USBD_TRANSFER_DIRECTION_OUT:
1288 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1289 return ERROR_INVALID_DATA;
1297 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1298 out_size = 36ULL + OutputBufferSize;
1299 out = Stream_New(
nullptr, out_size);
1302 return ERROR_OUTOFMEMORY;
1304 Stream_Seek(out, 36);
1306 switch (transferDir)
1308 case USBD_TRANSFER_DIRECTION_OUT:
1309 Stream_Copy(s, out, OutputBufferSize);
1310 Stream_Rewind(out, OutputBufferSize);
1313 case USBD_TRANSFER_DIRECTION_IN:
1319 WLog_Print(urbdrc->log, WLOG_DEBUG,
1320 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1321 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1322 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1323 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1325 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1326 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1327 &OutputBufferSize, Stream_Pointer(out), 1000);
1330 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1332 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1333 usbd_status, OutputBufferSize, transferDir);
1337 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1338 int transferDir,
int action)
1340 UINT32 usbd_status = 0;
1341 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1343 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1344 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1346 if (!callback || !s || !udevman || !pdev)
1347 return ERROR_INVALID_PARAMETER;
1352 return ERROR_INVALID_PARAMETER;
1354 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1355 return ERROR_INVALID_DATA;
1357 if (transferDir == 0)
1359 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1360 return ERROR_INVALID_PARAMETER;
1363 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1364 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1365 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1366 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1368 if (OutputBufferSize != 0)
1370 WLog_Print(urbdrc->log, WLOG_DEBUG,
1371 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32
" != 0",
1373 return ERROR_BAD_CONFIGURATION;
1379 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1383 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1385 ret = USBD_STATUS_SUCCESS;
1390 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1392 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1396 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1398 ret = USBD_STATUS_SUCCESS;
1403 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1405 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1411 wStream* out = Stream_New(
nullptr, 36);
1414 return ERROR_OUTOFMEMORY;
1416 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1421 UINT32 RequestId, UINT32 MessageId,
1422 UINT32 CompletionId, UINT32 FrameNumber)
1424 WINPR_ASSERT(callback);
1426 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1428 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1431 return ERROR_OUTOFMEMORY;
1433 Stream_Write_UINT32(out, 12);
1434 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1436 Stream_Free(out, TRUE);
1437 return ERROR_OUTOFMEMORY;
1440 Stream_Write_UINT32(out, FrameNumber);
1441 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1445 wStream* s, UINT32 RequestField, UINT32 MessageId,
1446 IUDEVMAN* udevman,
int transferDir)
1448 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1449 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1451 if (!callback || !s || !udevman || !pdev)
1452 return ERROR_INVALID_PARAMETER;
1457 return ERROR_INVALID_PARAMETER;
1459 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1460 return ERROR_INVALID_DATA;
1462 if (transferDir == 0)
1464 WLog_Print(urbdrc->log, WLOG_DEBUG,
1465 "urb_get_current_frame_number: not support transfer out");
1466 return ERROR_INVALID_PARAMETER;
1469 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1470 if (OutputBufferSize != 0)
1472 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1476 const UINT32 dummy_frames = GetTickCount();
1477 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1480 return CHANNEL_RC_OK;
1482 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1487static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1489 UINT32 RequestField, UINT32 MessageId,
1490 IUDEVMAN* udevman,
int transferDir)
1492 size_t out_size = 0;
1493 UINT32 InterfaceId = 0;
1494 UINT32 OutputBufferSize = 0;
1495 UINT32 usbd_status = 0;
1498 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1499 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1501 if (!callback || !s || !udevman || !pdev)
1502 return ERROR_INVALID_PARAMETER;
1507 return ERROR_INVALID_PARAMETER;
1509 if (transferDir == 0)
1511 WLog_Print(urbdrc->log, WLOG_DEBUG,
1512 "urb_control_get_configuration_request:"
1513 " not support transfer out");
1514 return ERROR_INVALID_PARAMETER;
1517 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1518 return ERROR_INVALID_DATA;
1520 Stream_Read_UINT32(s, OutputBufferSize);
1521 if (OutputBufferSize > UINT32_MAX - 36)
1522 return ERROR_INVALID_DATA;
1523 out_size = 36ULL + OutputBufferSize;
1524 out = Stream_New(
nullptr, out_size);
1527 return ERROR_OUTOFMEMORY;
1529 Stream_Seek(out, 36);
1530 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1532 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1534 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1536 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1537 Stream_Free(out, TRUE);
1538 return ERROR_INTERNAL_ERROR;
1541 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1542 usbd_status, OutputBufferSize, transferDir);
1547 wStream* s, UINT32 RequestField, UINT32 MessageId,
1548 IUDEVMAN* udevman,
int transferDir)
1550 size_t out_size = 0;
1551 UINT32 InterfaceId = 0;
1552 UINT32 OutputBufferSize = 0;
1553 UINT32 usbd_status = 0;
1554 UINT16 InterfaceNr = 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 if (transferDir == 0)
1573 WLog_Print(urbdrc->log, WLOG_DEBUG,
1574 "urb_control_get_interface_request: not support transfer out");
1575 return ERROR_INVALID_PARAMETER;
1578 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1579 Stream_Read_UINT16(s, InterfaceNr);
1581 Stream_Read_UINT32(s, OutputBufferSize);
1582 if (OutputBufferSize > UINT32_MAX - 36)
1583 return ERROR_INVALID_DATA;
1584 out_size = 36ULL + OutputBufferSize;
1585 out = Stream_New(
nullptr, out_size);
1588 return ERROR_OUTOFMEMORY;
1590 Stream_Seek(out, 36);
1592 if (!pdev->control_transfer(
1593 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1594 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1596 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1597 Stream_Free(out, TRUE);
1598 return ERROR_INTERNAL_ERROR;
1601 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1602 usbd_status, OutputBufferSize, transferDir);
1606 wStream* s, UINT32 RequestField, UINT32 MessageId,
1607 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1610 UINT32 InterfaceId = 0;
1611 UINT32 OutputBufferSize = 0;
1612 UINT32 usbd_status = 0;
1613 UINT16 FeatureSelector = 0;
1615 BYTE bmRequestType = 0;
1619 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1620 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1622 if (!callback || !s || !udevman || !pdev)
1623 return ERROR_INVALID_PARAMETER;
1628 return ERROR_INVALID_PARAMETER;
1630 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1631 return ERROR_INVALID_DATA;
1633 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1634 Stream_Read_UINT16(s, FeatureSelector);
1635 Stream_Read_UINT16(s, Index);
1636 Stream_Read_UINT32(s, OutputBufferSize);
1637 if (OutputBufferSize > UINT32_MAX - 36)
1638 return ERROR_INVALID_DATA;
1639 switch (transferDir)
1641 case USBD_TRANSFER_DIRECTION_OUT:
1642 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1643 return ERROR_INVALID_DATA;
1651 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1654 return ERROR_OUTOFMEMORY;
1656 Stream_Seek(out, 36);
1657 bmRequestType = func_recipient;
1659 switch (transferDir)
1661 case USBD_TRANSFER_DIRECTION_OUT:
1662 WLog_Print(urbdrc->log, WLOG_ERROR,
1663 "Function urb_control_feature_request: OUT Unchecked");
1664 Stream_Copy(s, out, OutputBufferSize);
1665 Stream_Rewind(out, OutputBufferSize);
1666 bmRequestType |= 0x00;
1669 case USBD_TRANSFER_DIRECTION_IN:
1670 bmRequestType |= 0x80;
1678 case URB_SET_FEATURE:
1682 case URB_CLEAR_FEATURE:
1687 WLog_Print(urbdrc->log, WLOG_ERROR,
1688 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1689 Stream_Free(out, TRUE);
1690 return ERROR_INTERNAL_ERROR;
1693 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1694 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1696 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1697 Stream_Free(out, TRUE);
1698 return ERROR_INTERNAL_ERROR;
1701 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1702 usbd_status, OutputBufferSize, transferDir);
1706 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1711 UINT16 URB_Function = 0;
1712 UINT32 RequestId = 0;
1713 UINT error = ERROR_INTERNAL_ERROR;
1716 if (!callback || !s || !udevman || !pdev)
1717 return ERROR_INVALID_PARAMETER;
1722 return ERROR_INVALID_PARAMETER;
1724 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1725 return ERROR_INVALID_DATA;
1727 Stream_Read_UINT32(s, CbTsUrb);
1728 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1729 return ERROR_INVALID_DATA;
1730 Stream_Read_UINT16(s, Size);
1731 if (Size != CbTsUrb)
1733 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1734 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1735 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1737 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1738 " != %s::CbTsUrb 0x%08" PRIx32,
1739 Size, section, CbTsUrb);
1740 return ERROR_INVALID_DATA;
1742 Stream_Read_UINT16(s, URB_Function);
1743 Stream_Read_UINT32(s, RequestId);
1744 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1747 switch (URB_Function)
1749 case TS_URB_SELECT_CONFIGURATION:
1750 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1754 case TS_URB_SELECT_INTERFACE:
1756 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1759 case TS_URB_PIPE_REQUEST:
1760 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1764 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1770 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1776 case TS_URB_GET_FRAME_LENGTH:
1782 case TS_URB_SET_FRAME_LENGTH:
1788 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1789 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1793 case TS_URB_CONTROL_TRANSFER:
1794 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1795 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1798 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1799 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1803 case TS_URB_ISOCH_TRANSFER:
1805 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1808 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1809 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1813 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1814 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1818 case TS_URB_SET_FEATURE_TO_DEVICE:
1819 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1820 0x00, URB_SET_FEATURE, transferDir);
1823 case TS_URB_SET_FEATURE_TO_INTERFACE:
1824 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1825 0x01, URB_SET_FEATURE, transferDir);
1828 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1829 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1830 0x02, URB_SET_FEATURE, transferDir);
1833 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1834 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1835 0x00, URB_CLEAR_FEATURE, transferDir);
1838 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x01, URB_CLEAR_FEATURE, transferDir);
1843 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x02, URB_CLEAR_FEATURE, transferDir);
1848 case TS_URB_GET_STATUS_FROM_DEVICE:
1849 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1853 case TS_URB_GET_STATUS_FROM_INTERFACE:
1854 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1858 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1859 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1863 case TS_URB_RESERVED_0X0016:
1866 case TS_URB_VENDOR_DEVICE:
1867 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1868 udevman, (0x02u << 5),
1872 case TS_URB_VENDOR_INTERFACE:
1873 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1874 udevman, (0x02u << 5),
1878 case TS_URB_VENDOR_ENDPOINT:
1879 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1880 udevman, (0x02u << 5),
1884 case TS_URB_CLASS_DEVICE:
1885 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1886 udevman, (0x01u << 5),
1890 case TS_URB_CLASS_INTERFACE:
1891 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1892 udevman, (0x01u << 5),
1896 case TS_URB_CLASS_ENDPOINT:
1897 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1898 udevman, (0x01u << 5),
1902 case TS_URB_RESERVE_0X001D:
1905 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1906 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1910 case TS_URB_CLASS_OTHER:
1911 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1912 udevman, (0x01u << 5),
1916 case TS_URB_VENDOR_OTHER:
1917 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1918 udevman, (0x02u << 5),
1922 case TS_URB_GET_STATUS_FROM_OTHER:
1923 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1927 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1928 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1929 0x03, URB_CLEAR_FEATURE, transferDir);
1932 case TS_URB_SET_FEATURE_TO_OTHER:
1933 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1934 0x03, URB_SET_FEATURE, transferDir);
1937 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1938 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1942 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1943 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1947 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1948 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1949 udevman, transferDir);
1952 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1953 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1954 udevman, transferDir);
1957 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1958 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1962 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1963 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1967 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1968 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1969 udevman, transferDir);
1972 case TS_URB_RESERVE_0X002B:
1973 case TS_URB_RESERVE_0X002C:
1974 case TS_URB_RESERVE_0X002D:
1975 case TS_URB_RESERVE_0X002E:
1976 case TS_URB_RESERVE_0X002F:
1980 case TS_URB_SYNC_RESET_PIPE:
1981 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1985 case TS_URB_SYNC_CLEAR_STALL:
1986 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1990 case TS_URB_CONTROL_TRANSFER_EX:
1991 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1992 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1996 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
2003 WLog_Print(urbdrc->log, WLOG_WARN,
2004 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2005 urb_function_string(URB_Function), URB_Function, error);
2012 IUDEVMAN* udevman,
wStream* data)
2014 UINT32 InterfaceId = 0;
2015 UINT32 MessageId = 0;
2016 UINT32 FunctionId = 0;
2017 IUDEVICE* pdev =
nullptr;
2018 UINT error = ERROR_INTERNAL_ERROR;
2020 if (!urbdrc || !data || !callback || !udevman)
2023 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2026 Stream_Rewind_UINT32(data);
2028 Stream_Read_UINT32(data, InterfaceId);
2029 Stream_Read_UINT32(data, MessageId);
2030 Stream_Read_UINT32(data, FunctionId);
2032 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2035 if (pdev ==
nullptr)
2037 error = ERROR_SUCCESS;
2042 if (pdev->isChannelClosed(pdev))
2044 error = ERROR_SUCCESS;
2049 if (!pdev->detach_kernel_driver(pdev))
2051 error = ERROR_SUCCESS;
2057 case CANCEL_REQUEST:
2058 error = urbdrc_process_cancel_request(pdev, data, udevman);
2061 case REGISTER_REQUEST_CALLBACK:
2062 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2066 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2069 case INTERNAL_IO_CONTROL:
2070 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2073 case QUERY_DEVICE_TEXT:
2074 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2077 case TRANSFER_IN_REQUEST:
2078 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2079 USBD_TRANSFER_DIRECTION_IN);
2082 case TRANSFER_OUT_REQUEST:
2083 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2084 USBD_TRANSFER_DIRECTION_OUT);
2087 case RETRACT_DEVICE:
2088 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2092 WLog_Print(urbdrc->log, WLOG_WARN,
2093 "urbdrc_process_udev_data_transfer:"
2094 " unknown FunctionId 0x%" PRIX32
"",
2102 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);