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 if (!Stream_EnsureRemainingCapacity(out, 4))
1435 Stream_Write_UINT32(out, 12);
1436 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1438 Stream_Write_UINT32(out, FrameNumber);
1439 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1442 Stream_Free(out, TRUE);
1443 return ERROR_OUTOFMEMORY;
1447 wStream* s, UINT32 RequestField, UINT32 MessageId,
1448 IUDEVMAN* udevman,
int transferDir)
1450 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1451 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1453 if (!callback || !s || !udevman || !pdev)
1454 return ERROR_INVALID_PARAMETER;
1459 return ERROR_INVALID_PARAMETER;
1461 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1462 return ERROR_INVALID_DATA;
1464 if (transferDir == 0)
1466 WLog_Print(urbdrc->log, WLOG_DEBUG,
1467 "urb_get_current_frame_number: not support transfer out");
1468 return ERROR_INVALID_PARAMETER;
1471 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1472 if (OutputBufferSize != 0)
1474 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1478 const UINT32 dummy_frames = GetTickCount();
1479 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1482 return CHANNEL_RC_OK;
1484 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1489static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1491 UINT32 RequestField, UINT32 MessageId,
1492 IUDEVMAN* udevman,
int transferDir)
1494 size_t out_size = 0;
1495 UINT32 InterfaceId = 0;
1496 UINT32 OutputBufferSize = 0;
1497 UINT32 usbd_status = 0;
1500 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1501 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1503 if (!callback || !s || !udevman || !pdev)
1504 return ERROR_INVALID_PARAMETER;
1509 return ERROR_INVALID_PARAMETER;
1511 if (transferDir == 0)
1513 WLog_Print(urbdrc->log, WLOG_DEBUG,
1514 "urb_control_get_configuration_request:"
1515 " not support transfer out");
1516 return ERROR_INVALID_PARAMETER;
1519 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1520 return ERROR_INVALID_DATA;
1522 Stream_Read_UINT32(s, OutputBufferSize);
1523 if (OutputBufferSize > UINT32_MAX - 36)
1524 return ERROR_INVALID_DATA;
1525 out_size = 36ULL + OutputBufferSize;
1526 out = Stream_New(
nullptr, out_size);
1529 return ERROR_OUTOFMEMORY;
1531 Stream_Seek(out, 36);
1532 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1534 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1536 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1538 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1539 Stream_Free(out, TRUE);
1540 return ERROR_INTERNAL_ERROR;
1543 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1544 usbd_status, OutputBufferSize, transferDir);
1549 wStream* s, UINT32 RequestField, UINT32 MessageId,
1550 IUDEVMAN* udevman,
int transferDir)
1552 size_t out_size = 0;
1553 UINT32 InterfaceId = 0;
1554 UINT32 OutputBufferSize = 0;
1555 UINT32 usbd_status = 0;
1556 UINT16 InterfaceNr = 0;
1559 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1560 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1562 if (!callback || !s || !udevman || !pdev)
1563 return ERROR_INVALID_PARAMETER;
1568 return ERROR_INVALID_PARAMETER;
1570 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1571 return ERROR_INVALID_DATA;
1573 if (transferDir == 0)
1575 WLog_Print(urbdrc->log, WLOG_DEBUG,
1576 "urb_control_get_interface_request: not support transfer out");
1577 return ERROR_INVALID_PARAMETER;
1580 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1581 Stream_Read_UINT16(s, InterfaceNr);
1583 Stream_Read_UINT32(s, OutputBufferSize);
1584 if (OutputBufferSize > UINT32_MAX - 36)
1585 return ERROR_INVALID_DATA;
1586 out_size = 36ULL + OutputBufferSize;
1587 out = Stream_New(
nullptr, out_size);
1590 return ERROR_OUTOFMEMORY;
1592 Stream_Seek(out, 36);
1594 if (!pdev->control_transfer(
1595 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1596 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1598 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1599 Stream_Free(out, TRUE);
1600 return ERROR_INTERNAL_ERROR;
1603 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1604 usbd_status, OutputBufferSize, transferDir);
1608 wStream* s, UINT32 RequestField, UINT32 MessageId,
1609 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1612 UINT32 InterfaceId = 0;
1613 UINT32 OutputBufferSize = 0;
1614 UINT32 usbd_status = 0;
1615 UINT16 FeatureSelector = 0;
1617 BYTE bmRequestType = 0;
1621 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1622 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1624 if (!callback || !s || !udevman || !pdev)
1625 return ERROR_INVALID_PARAMETER;
1630 return ERROR_INVALID_PARAMETER;
1632 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1633 return ERROR_INVALID_DATA;
1635 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1636 Stream_Read_UINT16(s, FeatureSelector);
1637 Stream_Read_UINT16(s, Index);
1638 Stream_Read_UINT32(s, OutputBufferSize);
1639 if (OutputBufferSize > UINT32_MAX - 36)
1640 return ERROR_INVALID_DATA;
1641 switch (transferDir)
1643 case USBD_TRANSFER_DIRECTION_OUT:
1644 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1645 return ERROR_INVALID_DATA;
1653 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1656 return ERROR_OUTOFMEMORY;
1658 Stream_Seek(out, 36);
1659 bmRequestType = func_recipient;
1661 switch (transferDir)
1663 case USBD_TRANSFER_DIRECTION_OUT:
1664 WLog_Print(urbdrc->log, WLOG_ERROR,
1665 "Function urb_control_feature_request: OUT Unchecked");
1666 Stream_Copy(s, out, OutputBufferSize);
1667 Stream_Rewind(out, OutputBufferSize);
1668 bmRequestType |= 0x00;
1671 case USBD_TRANSFER_DIRECTION_IN:
1672 bmRequestType |= 0x80;
1680 case URB_SET_FEATURE:
1684 case URB_CLEAR_FEATURE:
1689 WLog_Print(urbdrc->log, WLOG_ERROR,
1690 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1691 Stream_Free(out, TRUE);
1692 return ERROR_INTERNAL_ERROR;
1695 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1696 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1698 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1699 Stream_Free(out, TRUE);
1700 return ERROR_INTERNAL_ERROR;
1703 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1704 usbd_status, OutputBufferSize, transferDir);
1708 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1713 UINT16 URB_Function = 0;
1714 UINT32 RequestId = 0;
1715 UINT error = ERROR_INTERNAL_ERROR;
1718 if (!callback || !s || !udevman || !pdev)
1719 return ERROR_INVALID_PARAMETER;
1724 return ERROR_INVALID_PARAMETER;
1726 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1727 return ERROR_INVALID_DATA;
1729 Stream_Read_UINT32(s, CbTsUrb);
1730 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1731 return ERROR_INVALID_DATA;
1732 Stream_Read_UINT16(s, Size);
1733 if (Size != CbTsUrb)
1735 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1736 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1737 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1739 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1740 " != %s::CbTsUrb 0x%08" PRIx32,
1741 Size, section, CbTsUrb);
1742 return ERROR_INVALID_DATA;
1744 Stream_Read_UINT16(s, URB_Function);
1745 Stream_Read_UINT32(s, RequestId);
1746 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1749 switch (URB_Function)
1751 case TS_URB_SELECT_CONFIGURATION:
1752 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1756 case TS_URB_SELECT_INTERFACE:
1758 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1761 case TS_URB_PIPE_REQUEST:
1762 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1766 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1772 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1778 case TS_URB_GET_FRAME_LENGTH:
1784 case TS_URB_SET_FRAME_LENGTH:
1790 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1791 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1795 case TS_URB_CONTROL_TRANSFER:
1796 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1797 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1800 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1801 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1805 case TS_URB_ISOCH_TRANSFER:
1807 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1810 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1811 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1815 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1816 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1820 case TS_URB_SET_FEATURE_TO_DEVICE:
1821 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1822 0x00, URB_SET_FEATURE, transferDir);
1825 case TS_URB_SET_FEATURE_TO_INTERFACE:
1826 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1827 0x01, URB_SET_FEATURE, transferDir);
1830 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1831 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1832 0x02, URB_SET_FEATURE, transferDir);
1835 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1836 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1837 0x00, URB_CLEAR_FEATURE, transferDir);
1840 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1841 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1842 0x01, URB_CLEAR_FEATURE, transferDir);
1845 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1846 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1847 0x02, URB_CLEAR_FEATURE, transferDir);
1850 case TS_URB_GET_STATUS_FROM_DEVICE:
1851 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 case TS_URB_GET_STATUS_FROM_INTERFACE:
1856 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1860 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1861 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1865 case TS_URB_RESERVED_0X0016:
1868 case TS_URB_VENDOR_DEVICE:
1869 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1870 udevman, (0x02u << 5),
1874 case TS_URB_VENDOR_INTERFACE:
1875 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1876 udevman, (0x02u << 5),
1880 case TS_URB_VENDOR_ENDPOINT:
1881 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1882 udevman, (0x02u << 5),
1886 case TS_URB_CLASS_DEVICE:
1887 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1888 udevman, (0x01u << 5),
1892 case TS_URB_CLASS_INTERFACE:
1893 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1894 udevman, (0x01u << 5),
1898 case TS_URB_CLASS_ENDPOINT:
1899 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1900 udevman, (0x01u << 5),
1904 case TS_URB_RESERVE_0X001D:
1907 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1908 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1912 case TS_URB_CLASS_OTHER:
1913 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1914 udevman, (0x01u << 5),
1918 case TS_URB_VENDOR_OTHER:
1919 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1920 udevman, (0x02u << 5),
1924 case TS_URB_GET_STATUS_FROM_OTHER:
1925 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1929 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1930 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1931 0x03, URB_CLEAR_FEATURE, transferDir);
1934 case TS_URB_SET_FEATURE_TO_OTHER:
1935 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1936 0x03, URB_SET_FEATURE, transferDir);
1939 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1940 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1944 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1945 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1949 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1950 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1951 udevman, transferDir);
1954 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1955 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1956 udevman, transferDir);
1959 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1960 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1964 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1965 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1969 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1970 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1971 udevman, transferDir);
1974 case TS_URB_RESERVE_0X002B:
1975 case TS_URB_RESERVE_0X002C:
1976 case TS_URB_RESERVE_0X002D:
1977 case TS_URB_RESERVE_0X002E:
1978 case TS_URB_RESERVE_0X002F:
1982 case TS_URB_SYNC_RESET_PIPE:
1983 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1987 case TS_URB_SYNC_CLEAR_STALL:
1988 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1992 case TS_URB_CONTROL_TRANSFER_EX:
1993 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1994 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1998 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
2005 WLog_Print(urbdrc->log, WLOG_WARN,
2006 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2007 urb_function_string(URB_Function), URB_Function, error);
2014 IUDEVMAN* udevman,
wStream* data)
2016 UINT32 InterfaceId = 0;
2017 UINT32 MessageId = 0;
2018 UINT32 FunctionId = 0;
2019 IUDEVICE* pdev =
nullptr;
2020 UINT error = ERROR_INTERNAL_ERROR;
2022 if (!urbdrc || !data || !callback || !udevman)
2025 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2028 Stream_Rewind_UINT32(data);
2030 Stream_Read_UINT32(data, InterfaceId);
2031 Stream_Read_UINT32(data, MessageId);
2032 Stream_Read_UINT32(data, FunctionId);
2034 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2037 if (pdev ==
nullptr)
2039 error = ERROR_SUCCESS;
2044 if (pdev->isChannelClosed(pdev))
2046 error = ERROR_SUCCESS;
2051 if (!pdev->detach_kernel_driver(pdev))
2053 error = ERROR_SUCCESS;
2059 case CANCEL_REQUEST:
2060 error = urbdrc_process_cancel_request(pdev, data, udevman);
2063 case REGISTER_REQUEST_CALLBACK:
2064 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2068 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2071 case INTERNAL_IO_CONTROL:
2072 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2075 case QUERY_DEVICE_TEXT:
2076 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2079 case TRANSFER_IN_REQUEST:
2080 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2081 USBD_TRANSFER_DIRECTION_IN);
2084 case TRANSFER_OUT_REQUEST:
2085 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2086 USBD_TRANSFER_DIRECTION_OUT);
2089 case RETRACT_DEVICE:
2090 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2094 WLog_Print(urbdrc->log, WLOG_WARN,
2095 "urbdrc_process_udev_data_transfer:"
2096 " unknown FunctionId 0x%" PRIX32
"",
2104 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);