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;
145 const UINT32 mask = 0x80000000ul;
146 const UINT32 masked = usbd_status & mask;
148 hr = HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
149 Stream_Write_INT32(out, hr);
150 Stream_Write_UINT32(out, OutputBufferSize);
151 Stream_Seek(out, payloadSize);
154 return stream_write_and_free(callback->plugin, callback->channel, out);
156 Stream_Free(out, TRUE);
158 return ERROR_SUCCESS;
161static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
162 UINT32 OutputBufferSize)
164 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
166#if UINT32_MAX >= SIZE_MAX
167 if (OutputBufferSize > UINT32_MAX - 28ull)
171 wStream* out = create_shared_message_header_with_functionid(
172 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
176 Stream_Write_UINT32(out, RequestId);
177 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
178 Stream_Write_UINT32(out, OutputBufferSize);
179 Stream_Write_UINT32(out, OutputBufferSize);
191static BOOL urb_finalize_iocompletion(
wStream* out)
195 const size_t header = 12ULL + 4ULL ;
196 const size_t offset = header + 4ULL ;
197 const size_t fixed = offset + 4ULL + 4ULL ;
198 const size_t end = Stream_GetPosition(out);
203 const size_t OutputBufferSize = end - fixed;
205 if (OutputBufferSize > UINT32_MAX)
208 const UINT32 size = WINPR_ASSERTING_INT_CAST(UINT32, OutputBufferSize);
210 if (!Stream_SetPosition(out, offset))
213 Stream_Write_UINT32(out, size);
214 Stream_Write_UINT32(out, size);
215 return Stream_SetPosition(out, end);
218static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
222 UINT32 NumRequestCompletion = 0;
223 UINT32 RequestCompletion = 0;
225 if (!callback || !s || !udevman || !pdev)
226 return ERROR_INVALID_PARAMETER;
231 return ERROR_INVALID_PARAMETER;
233 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urbdrc_process_register_request_callback");
235 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
236 return ERROR_INVALID_DATA;
238 Stream_Read_UINT32(s, NumRequestCompletion);
240 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL * NumRequestCompletion))
241 return ERROR_INVALID_DATA;
242 for (uint32_t x = 0; x < NumRequestCompletion; x++)
246 Stream_Read_UINT32(s, RequestCompletion);
247 pdev->set_ReqCompletion(pdev, RequestCompletion);
250 return ERROR_SUCCESS;
253static UINT urbdrc_process_cancel_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
258 if (!s || !udevman || !pdev)
259 return ERROR_INVALID_PARAMETER;
263 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
264 return ERROR_INVALID_DATA;
266 Stream_Read_UINT32(s, CancelId);
267 WLog_Print(urbdrc->log, WLOG_DEBUG,
"CANCEL_REQUEST: CancelId=%08" PRIx32
"", CancelId);
269 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
270 return ERROR_INTERNAL_ERROR;
272 return ERROR_SUCCESS;
275static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev,
wStream* s,
282 return ERROR_INVALID_PARAMETER;
287 return ERROR_INVALID_PARAMETER;
289 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
290 return ERROR_INVALID_DATA;
292 Stream_Read_UINT32(s, Reason);
296 case UsbRetractReason_BlockedByPolicy:
297 WLog_Print(urbdrc->log, WLOG_DEBUG,
298 "UsbRetractReason_BlockedByPolicy: now it is not support");
299 return ERROR_ACCESS_DENIED;
302 WLog_Print(urbdrc->log, WLOG_DEBUG,
303 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32
"", Reason);
304 return ERROR_ACCESS_DENIED;
307 return ERROR_SUCCESS;
311 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
313 UINT32 InterfaceId = 0;
314 UINT32 IoControlCode = 0;
315 UINT32 InputBufferSize = 0;
316 UINT32 OutputBufferSize = 0;
317 UINT32 RequestId = 0;
318 UINT32 usbd_status = USBD_STATUS_SUCCESS;
323 if (!callback || !s || !udevman || !pdev)
324 return ERROR_INVALID_PARAMETER;
329 return ERROR_INVALID_PARAMETER;
331 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
332 return ERROR_INVALID_DATA;
334 Stream_Read_UINT32(s, IoControlCode);
335 Stream_Read_UINT32(s, InputBufferSize);
337 if (!Stream_SafeSeek(s, InputBufferSize))
338 return ERROR_INVALID_DATA;
339 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
340 return ERROR_INVALID_DATA;
342 Stream_Read_UINT32(s, OutputBufferSize);
343 Stream_Read_UINT32(s, RequestId);
345 if (OutputBufferSize > UINT32_MAX - 4)
346 return ERROR_INVALID_DATA;
348 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
349 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
352 return ERROR_OUTOFMEMORY;
354 switch (IoControlCode)
356 case IOCTL_INTERNAL_USB_SUBMIT_URB:
357 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
358 WLog_Print(urbdrc->log, WLOG_ERROR,
359 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
362 case IOCTL_INTERNAL_USB_RESET_PORT:
363 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
364 success = pdev->reset_device(pdev);
367 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
368 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
369 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
370 Stream_Pointer(out));
374 if (!Stream_SafeSeek(out, OutputBufferSize))
376 Stream_Free(out, TRUE);
377 return ERROR_INVALID_DATA;
380 if (pdev->isExist(pdev) == 0)
381 Stream_Write_UINT32(out, 0);
383 usb_process_get_port_status(pdev, out);
388 case IOCTL_INTERNAL_USB_CYCLE_PORT:
389 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
390 WLog_Print(urbdrc->log, WLOG_ERROR,
391 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
394 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
395 WLog_Print(urbdrc->log, WLOG_DEBUG,
396 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
397 WLog_Print(urbdrc->log, WLOG_ERROR,
398 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
402 WLog_Print(urbdrc->log, WLOG_DEBUG,
403 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
405 Stream_Free(out, TRUE);
406 return ERROR_INVALID_OPERATION;
409 if (!urb_finalize_iocompletion(out))
411 Stream_Free(out, TRUE);
412 return ERROR_INTERNAL_ERROR;
415 return stream_write_and_free(callback->plugin, callback->channel, out);
419 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
421 if (!pdev || !callback || !s || !udevman)
422 return ERROR_INVALID_PARAMETER;
425 WINPR_ASSERT(urbdrc);
427 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
428 return ERROR_INVALID_DATA;
430 const UINT32 IoControlCode = Stream_Get_UINT32(s);
431 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
435 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
436 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
438 return ERROR_INVALID_DATA;
440 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
442 if (!Stream_SafeSeek(s, InputBufferSize))
443 return ERROR_INVALID_DATA;
444 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
445 return ERROR_INVALID_DATA;
446 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
447 const UINT32 RequestId = Stream_Get_UINT32(s);
448 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
451 const UINT32 frames = GetTickCount();
453 if (4 > OutputBufferSize)
455 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32, 4u,
457 return ERROR_BAD_CONFIGURATION;
459 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
462 return ERROR_OUTOFMEMORY;
464 Stream_Write_UINT32(out, frames);
465 return stream_write_and_free(callback->plugin, callback->channel, out);
470 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
471 const BYTE* text, uint8_t bytelen)
473 WINPR_ASSERT(callback);
475 const uint8_t charlen = bytelen /
sizeof(WCHAR);
476 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
480 return ERROR_OUTOFMEMORY;
482 Stream_Write(out, text, bytelen);
483 Stream_Write_INT32(out, hr);
484 return stream_write_and_free(callback->plugin, callback->channel, out);
488 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
492 UINT8 bufferSize = 0xFF;
493 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
495 if (!pdev || !callback || !s || !udevman)
496 return ERROR_INVALID_PARAMETER;
497 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
498 return ERROR_INVALID_DATA;
500 Stream_Read_UINT32(s, TextType);
501 Stream_Read_UINT32(s, LocaleId);
502 if (LocaleId > UINT16_MAX)
503 return ERROR_INVALID_DATA;
505 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
506 &bufferSize, DeviceDescription);
507 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
508 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
509 DeviceDescription, bufferSize);
512static void func_select_all_interface_for_msconfig(
URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
515 WINPR_ASSERT(urbdrc);
517 WINPR_ASSERT(MsConfig);
520 UINT32 NumInterfaces = MsConfig->NumInterfaces;
522 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
524 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
525 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
526 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
529 WLog_Print(urbdrc->log, WLOG_WARN,
530 "select_interface %" PRIu8
" [%" PRIu8
"] failed [%d]", InterfaceNumber,
531 AlternateSetting, rc);
538 UINT32 InterfaceId, UINT32 MessageId,
539 UINT32 RequestId, UINT32 UrbStatus,
543 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
545 return ERROR_OUTOFMEMORY;
547 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
548 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
550 if (!Stream_EnsureRemainingCapacity(out, 4))
552 Stream_Write_UINT32(out, usize);
554 if (!write_urb_result_header(out, usize, UrbStatus))
560 if (!msusb_msconfig_write(MsConfig, out))
565 Stream_Write_UINT32(out, 0);
566 Stream_Write_UINT32(out, 0);
569 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
572 Stream_Free(out, TRUE);
573 return ERROR_OUTOFMEMORY;
577 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
581 UINT32 NumInterfaces = 0;
582 UINT32 usbd_status = 0;
583 BYTE ConfigurationDescriptorIsValid = 0;
585 const BOOL noAck = (RequestField & 0x80000000U) != 0;
586 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
588 if (!callback || !s || !udevman || !pdev)
589 return ERROR_INVALID_PARAMETER;
594 return ERROR_INVALID_PARAMETER;
596 if (transferDir == 0)
598 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
599 return ERROR_INVALID_PARAMETER;
602 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
603 return ERROR_INVALID_DATA;
605 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
606 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
608 Stream_Read_UINT32(s, NumInterfaces);
611 if (ConfigurationDescriptorIsValid)
614 MsConfig = msusb_msconfig_read(s, NumInterfaces);
617 return ERROR_INVALID_DATA;
620 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
623 msusb_msconfig_free(MsConfig);
625 return ERROR_INTERNAL_ERROR;
629 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
631 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
633 msusb_msconfig_free(MsConfig);
639 return CHANNEL_RC_OK;
640 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
641 usbd_status, MsConfig);
646 UINT32 InterfaceId, UINT32 MessageId,
649 WINPR_ASSERT(callback);
650 WINPR_ASSERT(MsInterface);
652 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
654 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
657 return ERROR_OUTOFMEMORY;
659 const uint32_t size = 8U + interface_size;
660 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
662 if (!Stream_EnsureRemainingCapacity(out, 4))
664 Stream_Write_UINT32(out, usize);
666 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
669 if (!msusb_msinterface_write(MsInterface, out))
672 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
675 Stream_Free(out, TRUE);
677 return ERROR_INTERNAL_ERROR;
681 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
684 const BOOL noAck = (RequestField & 0x80000000U) != 0;
685 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
687 if (!callback || !s || !udevman || !pdev)
688 return ERROR_INVALID_PARAMETER;
693 return ERROR_INVALID_PARAMETER;
695 if (transferDir == 0)
697 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
698 return ERROR_INVALID_PARAMETER;
701 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
702 return ERROR_INVALID_DATA;
704 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
705 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
708 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
710 msusb_msinterface_free(MsInterface);
711 return ERROR_INVALID_DATA;
714 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
715 if (OutputBufferSize != 0)
717 WLog_Print(urbdrc->log, WLOG_ERROR,
718 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
721 msusb_msinterface_free(MsInterface);
722 return ERROR_INVALID_DATA;
726 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
729 msusb_msinterface_free(MsInterface);
730 return ERROR_INTERNAL_ERROR;
735 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
736 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
737 return ERROR_BAD_CONFIGURATION;
740 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
741 return ERROR_BAD_CONFIGURATION;
744 return CHANNEL_RC_OK;
746 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
750 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
751 int transferDir,
int External)
754 UINT32 InterfaceId = 0;
755 UINT32 EndpointAddress = 0;
756 UINT32 PipeHandle = 0;
757 UINT32 TransferFlags = 0;
758 UINT32 OutputBufferSize = 0;
759 UINT32 usbd_status = 0;
761 BYTE bmRequestType = 0;
766 BYTE* buffer =
nullptr;
769 const BOOL noAck = (RequestField & 0x80000000U) != 0;
770 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
772 if (!callback || !s || !udevman || !pdev)
773 return ERROR_INVALID_PARAMETER;
778 return ERROR_INVALID_PARAMETER;
780 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
781 return ERROR_INVALID_DATA;
783 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
784 Stream_Read_UINT32(s, PipeHandle);
785 Stream_Read_UINT32(s, TransferFlags);
786 EndpointAddress = (PipeHandle & 0x000000ff);
791 case URB_CONTROL_TRANSFER_EXTERNAL:
792 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
793 return ERROR_INVALID_DATA;
795 Stream_Read_UINT32(s, Timeout);
798 case URB_CONTROL_TRANSFER_NONEXTERNAL:
805 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
806 return ERROR_INVALID_DATA;
808 Stream_Read_UINT8(s, bmRequestType);
809 Stream_Read_UINT8(s, Request);
810 Stream_Read_UINT16(s, Value);
811 Stream_Read_UINT16(s, Index);
812 Stream_Read_UINT16(s, length);
813 Stream_Read_UINT32(s, OutputBufferSize);
815 if (length != OutputBufferSize)
817 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
818 return ERROR_INVALID_DATA;
821 out_size = 36 + OutputBufferSize;
822 out = Stream_New(
nullptr, out_size);
825 return ERROR_OUTOFMEMORY;
827 Stream_Seek(out, 36);
829 buffer = Stream_Pointer(out);
831 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
835 Stream_Free(out, TRUE);
836 return ERROR_INVALID_DATA;
838 Stream_Copy(s, out, OutputBufferSize);
842 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
843 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
846 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
847 Stream_Free(out, TRUE);
848 return ERROR_INTERNAL_ERROR;
851 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
852 usbd_status, OutputBufferSize, transferDir);
856 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
857 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
858 WINPR_ATTR_UNUSED UINT32 StartFrame,
859 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
862 if (!pdev->isChannelClosed(pdev))
863 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
864 OutputBufferSize, transferDir);
866 Stream_Free(out, TRUE);
870 wStream* s, UINT32 RequestField, UINT32 MessageId,
871 IUDEVMAN* udevman,
int transferDir)
873 UINT32 EndpointAddress = 0;
874 UINT32 PipeHandle = 0;
875 UINT32 TransferFlags = 0;
876 UINT32 OutputBufferSize = 0;
877 const BOOL noAck = (RequestField & 0x80000000U) != 0;
878 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
880 if (!pdev || !callback || !s || !udevman)
881 return ERROR_INVALID_PARAMETER;
883 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
884 return ERROR_INVALID_DATA;
886 Stream_Read_UINT32(s, PipeHandle);
887 Stream_Read_UINT32(s, TransferFlags);
888 Stream_Read_UINT32(s, OutputBufferSize);
889 EndpointAddress = (PipeHandle & 0x000000ff);
891 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
893 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
895 return ERROR_INVALID_DATA;
900 const int rc = pdev->bulk_or_interrupt_transfer(
901 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
903 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
904 urb_bulk_transfer_cb, 10000);
909static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
911 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
912 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
913 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
918 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
919 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
920 Stream_ResetPosition(out);
922 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
923 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
925 Stream_Free(out, TRUE);
929 Stream_Write_UINT32(out, RequestId);
930 Stream_Write_UINT32(out, 20 + packetSize);
931 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
934 Stream_Free(out, TRUE);
938 Stream_Write_UINT32(out, StartFrame);
943 Stream_Write_UINT32(out, NumberOfPackets);
944 Stream_Write_UINT32(out, ErrorCount);
945 Stream_Seek(out, packetSize);
949 Stream_Write_UINT32(out, 0);
950 Stream_Write_UINT32(out, ErrorCount);
953 Stream_Write_UINT32(out, 0);
954 Stream_Write_UINT32(out, OutputBufferSize);
955 Stream_Seek(out, payloadSize);
957 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
958 if (rc != CHANNEL_RC_OK)
959 WLog_WARN(TAG,
"stream_write_and_free failed with %" PRIu32, rc);
964 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
968 UINT32 EndpointAddress = 0;
969 UINT32 PipeHandle = 0;
970 UINT32 TransferFlags = 0;
971 UINT32 StartFrame = 0;
972 UINT32 NumberOfPackets = 0;
973 UINT32 ErrorCount = 0;
974 UINT32 OutputBufferSize = 0;
975 BYTE* packetDescriptorData =
nullptr;
976 const BOOL noAck = (RequestField & 0x80000000U) != 0;
977 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
979 if (!pdev || !callback || !udevman)
980 return ERROR_INVALID_PARAMETER;
982 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
983 return ERROR_INVALID_DATA;
985 Stream_Read_UINT32(s, PipeHandle);
986 EndpointAddress = (PipeHandle & 0x000000ff);
987 Stream_Read_UINT32(s, TransferFlags);
988 Stream_Read_UINT32(s, StartFrame);
989 Stream_Read_UINT32(s, NumberOfPackets);
990 Stream_Read_UINT32(s, ErrorCount);
992 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
993 return ERROR_INVALID_DATA;
995 packetDescriptorData = Stream_Pointer(s);
996 Stream_Seek(s, 12ULL * NumberOfPackets);
998 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
999 return ERROR_INVALID_DATA;
1000 Stream_Read_UINT32(s, OutputBufferSize);
1002 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1004 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1005 return ERROR_INVALID_DATA;
1008 rc = pdev->isoch_transfer(
1009 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1010 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1011 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1012 urb_isoch_transfer_cb, 2000);
1015 return ERROR_INTERNAL_ERROR;
1020 wStream* s, UINT32 RequestField, UINT32 MessageId,
1021 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1023 size_t out_size = 0;
1024 UINT32 InterfaceId = 0;
1025 UINT32 OutputBufferSize = 0;
1026 UINT32 usbd_status = 0;
1027 BYTE bmRequestType = 0;
1028 BYTE desc_index = 0;
1033 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1034 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1036 if (!callback || !s || !udevman || !pdev)
1037 return ERROR_INVALID_PARAMETER;
1042 return ERROR_INVALID_PARAMETER;
1044 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1045 return ERROR_INVALID_DATA;
1047 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1048 Stream_Read_UINT8(s, desc_index);
1049 Stream_Read_UINT8(s, desc_type);
1050 Stream_Read_UINT16(s, langId);
1051 Stream_Read_UINT32(s, OutputBufferSize);
1052 if (OutputBufferSize > UINT32_MAX - 36)
1053 return ERROR_INVALID_DATA;
1054 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1056 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1057 return ERROR_INVALID_DATA;
1060 out_size = 36ULL + OutputBufferSize;
1061 out = Stream_New(
nullptr, out_size);
1064 return ERROR_OUTOFMEMORY;
1066 Stream_Seek(out, 36);
1067 bmRequestType = func_recipient;
1069 switch (transferDir)
1071 case USBD_TRANSFER_DIRECTION_IN:
1072 bmRequestType |= 0x80;
1075 case USBD_TRANSFER_DIRECTION_OUT:
1076 bmRequestType |= 0x00;
1077 Stream_Copy(s, out, OutputBufferSize);
1078 Stream_Rewind(out, OutputBufferSize);
1082 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1083 OutputBufferSize = 0;
1084 usbd_status = USBD_STATUS_STALL_PID;
1089 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1091 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1092 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1094 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1095 Stream_Free(out, TRUE);
1096 return ERROR_INTERNAL_ERROR;
1099 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1100 usbd_status, OutputBufferSize, transferDir);
1104 wStream* s, UINT32 RequestField, UINT32 MessageId,
1105 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1107 size_t out_size = 0;
1108 UINT32 InterfaceId = 0;
1109 UINT32 OutputBufferSize = 0;
1110 UINT32 usbd_status = 0;
1112 BYTE bmRequestType = 0;
1115 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1116 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1118 if (!callback || !s || !udevman || !pdev)
1119 return ERROR_INVALID_PARAMETER;
1124 return ERROR_INVALID_PARAMETER;
1126 if (transferDir == 0)
1128 WLog_Print(urbdrc->log, WLOG_DEBUG,
1129 "urb_control_get_status_request: transfer out not supported");
1130 return ERROR_INVALID_PARAMETER;
1133 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1134 return ERROR_INVALID_DATA;
1136 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1137 Stream_Read_UINT16(s, Index);
1139 Stream_Read_UINT32(s, OutputBufferSize);
1140 if (OutputBufferSize > UINT32_MAX - 36)
1141 return ERROR_INVALID_DATA;
1142 out_size = 36ULL + OutputBufferSize;
1143 out = Stream_New(
nullptr, out_size);
1146 return ERROR_OUTOFMEMORY;
1148 Stream_Seek(out, 36);
1149 bmRequestType = func_recipient | 0x80;
1151 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1152 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1155 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1156 Stream_Free(out, TRUE);
1157 return ERROR_INTERNAL_ERROR;
1160 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1161 usbd_status, OutputBufferSize, transferDir);
1165 wStream* s, UINT32 RequestField, UINT32 MessageId,
1166 IUDEVMAN* udevman, BYTE func_type,
1167 BYTE func_recipient,
int transferDir)
1169 UINT32 out_size = 0;
1170 UINT32 InterfaceId = 0;
1171 UINT32 TransferFlags = 0;
1172 UINT32 usbd_status = 0;
1173 UINT32 OutputBufferSize = 0;
1174 BYTE ReqTypeReservedBits = 0;
1176 BYTE bmRequestType = 0;
1181 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1182 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1184 if (!callback || !s || !udevman || !pdev)
1185 return ERROR_INVALID_PARAMETER;
1190 return ERROR_INVALID_PARAMETER;
1192 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1193 return ERROR_INVALID_DATA;
1195 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1196 Stream_Read_UINT32(s, TransferFlags);
1197 Stream_Read_UINT8(s, ReqTypeReservedBits);
1198 Stream_Read_UINT8(s, Request);
1199 Stream_Read_UINT16(s, Value);
1200 Stream_Read_UINT16(s, Index);
1201 Stream_Seek_UINT16(s);
1202 Stream_Read_UINT32(s, OutputBufferSize);
1203 if (OutputBufferSize > UINT32_MAX - 36)
1204 return ERROR_INVALID_DATA;
1206 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1208 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1209 return ERROR_INVALID_DATA;
1212 out_size = 36ULL + OutputBufferSize;
1213 out = Stream_New(
nullptr, out_size);
1216 return ERROR_OUTOFMEMORY;
1218 Stream_Seek(out, 36);
1221 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1223 Stream_Copy(s, out, OutputBufferSize);
1224 Stream_Rewind(out, OutputBufferSize);
1228 bmRequestType = func_type | func_recipient;
1230 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1231 bmRequestType |= 0x80;
1233 WLog_Print(urbdrc->log, WLOG_DEBUG,
1234 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1236 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1237 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1238 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1239 OutputBufferSize, bmRequestType);
1241 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1242 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1244 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1245 Stream_Free(out, TRUE);
1246 return ERROR_INTERNAL_ERROR;
1249 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1250 usbd_status, OutputBufferSize, transferDir);
1254 wStream* s, UINT32 RequestField, UINT32 MessageId,
1255 IUDEVMAN* udevman,
int transferDir)
1257 size_t out_size = 0;
1258 UINT32 InterfaceId = 0;
1259 UINT32 OutputBufferSize = 0;
1260 UINT32 usbd_status = 0;
1262 BYTE InterfaceNumber = 0;
1263 BYTE Ms_PageIndex = 0;
1264 UINT16 Ms_featureDescIndex = 0;
1268 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1269 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1271 if (!callback || !s || !udevman || !pdev)
1272 return ERROR_INVALID_PARAMETER;
1277 return ERROR_INVALID_PARAMETER;
1279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1280 return ERROR_INVALID_DATA;
1283 Stream_Read_UINT8(s, Recipient);
1284 Recipient = (Recipient & 0x1f);
1285 Stream_Read_UINT8(s, InterfaceNumber);
1286 Stream_Read_UINT8(s, Ms_PageIndex);
1287 Stream_Read_UINT16(s, Ms_featureDescIndex);
1289 Stream_Read_UINT32(s, OutputBufferSize);
1290 if (OutputBufferSize > UINT32_MAX - 36)
1291 return ERROR_INVALID_DATA;
1293 switch (transferDir)
1295 case USBD_TRANSFER_DIRECTION_OUT:
1296 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1297 return ERROR_INVALID_DATA;
1305 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1306 out_size = 36ULL + OutputBufferSize;
1307 out = Stream_New(
nullptr, out_size);
1310 return ERROR_OUTOFMEMORY;
1312 Stream_Seek(out, 36);
1314 switch (transferDir)
1316 case USBD_TRANSFER_DIRECTION_OUT:
1317 Stream_Copy(s, out, OutputBufferSize);
1318 Stream_Rewind(out, OutputBufferSize);
1321 case USBD_TRANSFER_DIRECTION_IN:
1327 WLog_Print(urbdrc->log, WLOG_DEBUG,
1328 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1329 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1330 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1331 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1333 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1334 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1335 &OutputBufferSize, Stream_Pointer(out), 1000);
1338 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1340 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1341 usbd_status, OutputBufferSize, transferDir);
1345 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1346 int transferDir,
int action)
1348 UINT32 usbd_status = 0;
1349 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1351 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1352 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1354 if (!callback || !s || !udevman || !pdev)
1355 return ERROR_INVALID_PARAMETER;
1360 return ERROR_INVALID_PARAMETER;
1362 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1363 return ERROR_INVALID_DATA;
1365 if (transferDir == 0)
1367 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1368 return ERROR_INVALID_PARAMETER;
1371 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1372 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1373 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1374 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1376 if (OutputBufferSize != 0)
1378 WLog_Print(urbdrc->log, WLOG_DEBUG,
1379 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32
" != 0",
1381 return ERROR_BAD_CONFIGURATION;
1387 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1391 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1393 ret = USBD_STATUS_SUCCESS;
1398 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1400 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1404 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1406 ret = USBD_STATUS_SUCCESS;
1411 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1413 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1419 wStream* out = Stream_New(
nullptr, 36);
1422 return ERROR_OUTOFMEMORY;
1424 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1429 UINT32 RequestId, UINT32 MessageId,
1430 UINT32 CompletionId, UINT32 FrameNumber)
1432 WINPR_ASSERT(callback);
1434 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1436 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1439 return ERROR_OUTOFMEMORY;
1441 if (!Stream_EnsureRemainingCapacity(out, 4))
1443 Stream_Write_UINT32(out, 12);
1444 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1446 Stream_Write_UINT32(out, FrameNumber);
1447 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1450 Stream_Free(out, TRUE);
1451 return ERROR_OUTOFMEMORY;
1455 wStream* s, UINT32 RequestField, UINT32 MessageId,
1456 IUDEVMAN* udevman,
int transferDir)
1458 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1459 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1461 if (!callback || !s || !udevman || !pdev)
1462 return ERROR_INVALID_PARAMETER;
1467 return ERROR_INVALID_PARAMETER;
1469 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1470 return ERROR_INVALID_DATA;
1472 if (transferDir == 0)
1474 WLog_Print(urbdrc->log, WLOG_DEBUG,
1475 "urb_get_current_frame_number: not support transfer out");
1476 return ERROR_INVALID_PARAMETER;
1479 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1480 if (OutputBufferSize != 0)
1482 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1486 const UINT32 dummy_frames = GetTickCount();
1487 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1490 return CHANNEL_RC_OK;
1492 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1497static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1499 UINT32 RequestField, UINT32 MessageId,
1500 IUDEVMAN* udevman,
int transferDir)
1502 size_t out_size = 0;
1503 UINT32 InterfaceId = 0;
1504 UINT32 OutputBufferSize = 0;
1505 UINT32 usbd_status = 0;
1508 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1509 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1511 if (!callback || !s || !udevman || !pdev)
1512 return ERROR_INVALID_PARAMETER;
1517 return ERROR_INVALID_PARAMETER;
1519 if (transferDir == 0)
1521 WLog_Print(urbdrc->log, WLOG_DEBUG,
1522 "urb_control_get_configuration_request:"
1523 " not support transfer out");
1524 return ERROR_INVALID_PARAMETER;
1527 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1528 return ERROR_INVALID_DATA;
1530 Stream_Read_UINT32(s, OutputBufferSize);
1531 if (OutputBufferSize > UINT32_MAX - 36)
1532 return ERROR_INVALID_DATA;
1533 out_size = 36ULL + OutputBufferSize;
1534 out = Stream_New(
nullptr, out_size);
1537 return ERROR_OUTOFMEMORY;
1539 Stream_Seek(out, 36);
1540 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1542 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1544 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1546 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1547 Stream_Free(out, TRUE);
1548 return ERROR_INTERNAL_ERROR;
1551 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1552 usbd_status, OutputBufferSize, transferDir);
1557 wStream* s, UINT32 RequestField, UINT32 MessageId,
1558 IUDEVMAN* udevman,
int transferDir)
1560 size_t out_size = 0;
1561 UINT32 InterfaceId = 0;
1562 UINT32 OutputBufferSize = 0;
1563 UINT32 usbd_status = 0;
1564 UINT16 InterfaceNr = 0;
1567 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1568 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1570 if (!callback || !s || !udevman || !pdev)
1571 return ERROR_INVALID_PARAMETER;
1576 return ERROR_INVALID_PARAMETER;
1578 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1579 return ERROR_INVALID_DATA;
1581 if (transferDir == 0)
1583 WLog_Print(urbdrc->log, WLOG_DEBUG,
1584 "urb_control_get_interface_request: not support transfer out");
1585 return ERROR_INVALID_PARAMETER;
1588 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1589 Stream_Read_UINT16(s, InterfaceNr);
1591 Stream_Read_UINT32(s, OutputBufferSize);
1592 if (OutputBufferSize > UINT32_MAX - 36)
1593 return ERROR_INVALID_DATA;
1594 out_size = 36ULL + OutputBufferSize;
1595 out = Stream_New(
nullptr, out_size);
1598 return ERROR_OUTOFMEMORY;
1600 Stream_Seek(out, 36);
1602 if (!pdev->control_transfer(
1603 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1604 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1606 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1607 Stream_Free(out, TRUE);
1608 return ERROR_INTERNAL_ERROR;
1611 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1612 usbd_status, OutputBufferSize, transferDir);
1616 wStream* s, UINT32 RequestField, UINT32 MessageId,
1617 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1620 UINT32 InterfaceId = 0;
1621 UINT32 OutputBufferSize = 0;
1622 UINT32 usbd_status = 0;
1623 UINT16 FeatureSelector = 0;
1625 BYTE bmRequestType = 0;
1629 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1630 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1632 if (!callback || !s || !udevman || !pdev)
1633 return ERROR_INVALID_PARAMETER;
1638 return ERROR_INVALID_PARAMETER;
1640 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1641 return ERROR_INVALID_DATA;
1643 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1644 Stream_Read_UINT16(s, FeatureSelector);
1645 Stream_Read_UINT16(s, Index);
1646 Stream_Read_UINT32(s, OutputBufferSize);
1647 if (OutputBufferSize > UINT32_MAX - 36)
1648 return ERROR_INVALID_DATA;
1649 switch (transferDir)
1651 case USBD_TRANSFER_DIRECTION_OUT:
1652 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1653 return ERROR_INVALID_DATA;
1661 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1664 return ERROR_OUTOFMEMORY;
1666 Stream_Seek(out, 36);
1667 bmRequestType = func_recipient;
1669 switch (transferDir)
1671 case USBD_TRANSFER_DIRECTION_OUT:
1672 WLog_Print(urbdrc->log, WLOG_ERROR,
1673 "Function urb_control_feature_request: OUT Unchecked");
1674 Stream_Copy(s, out, OutputBufferSize);
1675 Stream_Rewind(out, OutputBufferSize);
1676 bmRequestType |= 0x00;
1679 case USBD_TRANSFER_DIRECTION_IN:
1680 bmRequestType |= 0x80;
1688 case URB_SET_FEATURE:
1692 case URB_CLEAR_FEATURE:
1697 WLog_Print(urbdrc->log, WLOG_ERROR,
1698 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1699 Stream_Free(out, TRUE);
1700 return ERROR_INTERNAL_ERROR;
1703 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1704 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1706 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1707 Stream_Free(out, TRUE);
1708 return ERROR_INTERNAL_ERROR;
1711 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1712 usbd_status, OutputBufferSize, transferDir);
1716 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1721 UINT16 URB_Function = 0;
1722 UINT32 RequestId = 0;
1723 UINT error = ERROR_INTERNAL_ERROR;
1726 if (!callback || !s || !udevman || !pdev)
1727 return ERROR_INVALID_PARAMETER;
1732 return ERROR_INVALID_PARAMETER;
1734 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1735 return ERROR_INVALID_DATA;
1737 Stream_Read_UINT32(s, CbTsUrb);
1738 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1739 return ERROR_INVALID_DATA;
1740 Stream_Read_UINT16(s, Size);
1741 if (Size != CbTsUrb)
1743 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1744 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1745 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1747 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1748 " != %s::CbTsUrb 0x%08" PRIx32,
1749 Size, section, CbTsUrb);
1750 return ERROR_INVALID_DATA;
1752 Stream_Read_UINT16(s, URB_Function);
1753 Stream_Read_UINT32(s, RequestId);
1754 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1757 switch (URB_Function)
1759 case TS_URB_SELECT_CONFIGURATION:
1760 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1764 case TS_URB_SELECT_INTERFACE:
1766 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1769 case TS_URB_PIPE_REQUEST:
1770 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1774 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1780 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1786 case TS_URB_GET_FRAME_LENGTH:
1792 case TS_URB_SET_FRAME_LENGTH:
1798 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1799 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1803 case TS_URB_CONTROL_TRANSFER:
1804 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1805 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1808 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1809 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1813 case TS_URB_ISOCH_TRANSFER:
1815 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1818 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1819 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1823 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1824 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1828 case TS_URB_SET_FEATURE_TO_DEVICE:
1829 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1830 0x00, URB_SET_FEATURE, transferDir);
1833 case TS_URB_SET_FEATURE_TO_INTERFACE:
1834 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1835 0x01, URB_SET_FEATURE, transferDir);
1838 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x02, URB_SET_FEATURE, transferDir);
1843 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x00, URB_CLEAR_FEATURE, transferDir);
1848 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1849 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1850 0x01, URB_CLEAR_FEATURE, transferDir);
1853 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1854 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 0x02, URB_CLEAR_FEATURE, transferDir);
1858 case TS_URB_GET_STATUS_FROM_DEVICE:
1859 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1863 case TS_URB_GET_STATUS_FROM_INTERFACE:
1864 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1868 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1873 case TS_URB_RESERVED_0X0016:
1876 case TS_URB_VENDOR_DEVICE:
1877 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1878 udevman, (0x02u << 5),
1882 case TS_URB_VENDOR_INTERFACE:
1883 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1884 udevman, (0x02u << 5),
1888 case TS_URB_VENDOR_ENDPOINT:
1889 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1890 udevman, (0x02u << 5),
1894 case TS_URB_CLASS_DEVICE:
1895 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1896 udevman, (0x01u << 5),
1900 case TS_URB_CLASS_INTERFACE:
1901 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1902 udevman, (0x01u << 5),
1906 case TS_URB_CLASS_ENDPOINT:
1907 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1908 udevman, (0x01u << 5),
1912 case TS_URB_RESERVE_0X001D:
1915 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1916 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1920 case TS_URB_CLASS_OTHER:
1921 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1922 udevman, (0x01u << 5),
1926 case TS_URB_VENDOR_OTHER:
1927 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1928 udevman, (0x02u << 5),
1932 case TS_URB_GET_STATUS_FROM_OTHER:
1933 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1937 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1938 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1939 0x03, URB_CLEAR_FEATURE, transferDir);
1942 case TS_URB_SET_FEATURE_TO_OTHER:
1943 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1944 0x03, URB_SET_FEATURE, transferDir);
1947 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1948 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1952 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1953 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1957 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1958 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1959 udevman, transferDir);
1962 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1963 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1964 udevman, transferDir);
1967 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1968 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1972 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1973 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1977 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1978 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1979 udevman, transferDir);
1982 case TS_URB_RESERVE_0X002B:
1983 case TS_URB_RESERVE_0X002C:
1984 case TS_URB_RESERVE_0X002D:
1985 case TS_URB_RESERVE_0X002E:
1986 case TS_URB_RESERVE_0X002F:
1990 case TS_URB_SYNC_RESET_PIPE:
1991 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1995 case TS_URB_SYNC_CLEAR_STALL:
1996 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
2000 case TS_URB_CONTROL_TRANSFER_EX:
2001 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
2002 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
2006 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
2013 WLog_Print(urbdrc->log, WLOG_WARN,
2014 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2015 urb_function_string(URB_Function), URB_Function, error);
2022 IUDEVMAN* udevman,
wStream* data)
2024 UINT32 InterfaceId = 0;
2025 UINT32 MessageId = 0;
2026 UINT32 FunctionId = 0;
2027 IUDEVICE* pdev =
nullptr;
2028 UINT error = ERROR_INTERNAL_ERROR;
2030 if (!urbdrc || !data || !callback || !udevman)
2033 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2036 Stream_Rewind_UINT32(data);
2038 Stream_Read_UINT32(data, InterfaceId);
2039 Stream_Read_UINT32(data, MessageId);
2040 Stream_Read_UINT32(data, FunctionId);
2042 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2045 if (pdev ==
nullptr)
2047 error = ERROR_SUCCESS;
2052 if (pdev->isChannelClosed(pdev))
2054 error = ERROR_SUCCESS;
2059 if (!pdev->detach_kernel_driver(pdev))
2061 error = ERROR_SUCCESS;
2067 case CANCEL_REQUEST:
2068 error = urbdrc_process_cancel_request(pdev, data, udevman);
2071 case REGISTER_REQUEST_CALLBACK:
2072 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2076 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2079 case INTERNAL_IO_CONTROL:
2080 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2083 case QUERY_DEVICE_TEXT:
2084 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2087 case TRANSFER_IN_REQUEST:
2088 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2089 USBD_TRANSFER_DIRECTION_IN);
2092 case TRANSFER_OUT_REQUEST:
2093 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2094 USBD_TRANSFER_DIRECTION_OUT);
2097 case RETRACT_DEVICE:
2098 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2102 WLog_Print(urbdrc->log, WLOG_WARN,
2103 "urbdrc_process_udev_data_transfer:"
2104 " unknown FunctionId 0x%" PRIX32
"",
2112 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);