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");
366 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
367 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
368 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
369 Stream_Pointer(out));
373 if (!Stream_SafeSeek(out, OutputBufferSize))
375 Stream_Free(out, TRUE);
376 return ERROR_INVALID_DATA;
379 if (pdev->isExist(pdev) == 0)
380 Stream_Write_UINT32(out, 0);
382 usb_process_get_port_status(pdev, out);
387 case IOCTL_INTERNAL_USB_CYCLE_PORT:
388 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
389 WLog_Print(urbdrc->log, WLOG_ERROR,
390 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
393 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
394 WLog_Print(urbdrc->log, WLOG_DEBUG,
395 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
396 WLog_Print(urbdrc->log, WLOG_ERROR,
397 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
401 WLog_Print(urbdrc->log, WLOG_DEBUG,
402 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
404 Stream_Free(out, TRUE);
405 return ERROR_INVALID_OPERATION;
408 if (!urb_finalize_iocompletion(out))
410 Stream_Free(out, TRUE);
411 return ERROR_INTERNAL_ERROR;
414 return stream_write_and_free(callback->plugin, callback->channel, out);
418 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
420 if (!pdev || !callback || !s || !udevman)
421 return ERROR_INVALID_PARAMETER;
424 WINPR_ASSERT(urbdrc);
426 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
427 return ERROR_INVALID_DATA;
429 const UINT32 IoControlCode = Stream_Get_UINT32(s);
430 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
434 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
435 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
437 return ERROR_INVALID_DATA;
439 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
441 if (!Stream_SafeSeek(s, InputBufferSize))
442 return ERROR_INVALID_DATA;
443 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
444 return ERROR_INVALID_DATA;
445 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
446 const UINT32 RequestId = Stream_Get_UINT32(s);
447 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
450 const UINT32 frames = GetTickCount();
452 if (4 > OutputBufferSize)
454 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32, 4u,
456 return ERROR_BAD_CONFIGURATION;
458 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
461 return ERROR_OUTOFMEMORY;
463 Stream_Write_UINT32(out, frames);
464 return stream_write_and_free(callback->plugin, callback->channel, out);
469 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
470 const BYTE* text, uint8_t bytelen)
472 WINPR_ASSERT(callback);
474 const uint8_t charlen = bytelen /
sizeof(WCHAR);
475 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
479 return ERROR_OUTOFMEMORY;
481 Stream_Write(out, text, bytelen);
482 Stream_Write_INT32(out, hr);
483 return stream_write_and_free(callback->plugin, callback->channel, out);
487 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
491 UINT8 bufferSize = 0xFF;
492 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
494 if (!pdev || !callback || !s || !udevman)
495 return ERROR_INVALID_PARAMETER;
496 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
497 return ERROR_INVALID_DATA;
499 Stream_Read_UINT32(s, TextType);
500 Stream_Read_UINT32(s, LocaleId);
501 if (LocaleId > UINT16_MAX)
502 return ERROR_INVALID_DATA;
504 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
505 &bufferSize, DeviceDescription);
506 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
507 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
508 DeviceDescription, bufferSize);
511static void func_select_all_interface_for_msconfig(
URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
514 WINPR_ASSERT(urbdrc);
516 WINPR_ASSERT(MsConfig);
519 UINT32 NumInterfaces = MsConfig->NumInterfaces;
521 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
523 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
524 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
525 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
528 WLog_Print(urbdrc->log, WLOG_WARN,
529 "select_interface %" PRIu8
" [%" PRIu8
"] failed [%d]", InterfaceNumber,
530 AlternateSetting, rc);
537 UINT32 InterfaceId, UINT32 MessageId,
538 UINT32 RequestId, UINT32 UrbStatus,
542 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
544 return ERROR_OUTOFMEMORY;
546 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
547 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
549 if (!Stream_EnsureRemainingCapacity(out, 4))
551 Stream_Write_UINT32(out, usize);
553 if (!write_urb_result_header(out, usize, UrbStatus))
559 if (!msusb_msconfig_write(MsConfig, out))
564 Stream_Write_UINT32(out, 0);
565 Stream_Write_UINT32(out, 0);
568 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
571 Stream_Free(out, TRUE);
572 return ERROR_OUTOFMEMORY;
576 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
580 UINT32 NumInterfaces = 0;
581 UINT32 usbd_status = 0;
582 BYTE ConfigurationDescriptorIsValid = 0;
584 const BOOL noAck = (RequestField & 0x80000000U) != 0;
585 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
587 if (!callback || !s || !udevman || !pdev)
588 return ERROR_INVALID_PARAMETER;
593 return ERROR_INVALID_PARAMETER;
595 if (transferDir == 0)
597 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
598 return ERROR_INVALID_PARAMETER;
601 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
602 return ERROR_INVALID_DATA;
604 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
605 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
607 Stream_Read_UINT32(s, NumInterfaces);
610 if (ConfigurationDescriptorIsValid)
613 MsConfig = msusb_msconfig_read(s, NumInterfaces);
616 return ERROR_INVALID_DATA;
619 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
622 msusb_msconfig_free(MsConfig);
624 return ERROR_INTERNAL_ERROR;
628 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
630 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
632 msusb_msconfig_free(MsConfig);
638 return CHANNEL_RC_OK;
639 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
640 usbd_status, MsConfig);
645 UINT32 InterfaceId, UINT32 MessageId,
648 WINPR_ASSERT(callback);
649 WINPR_ASSERT(MsInterface);
651 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
653 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
656 return ERROR_OUTOFMEMORY;
658 const uint32_t size = 8U + interface_size;
659 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
661 if (!Stream_EnsureRemainingCapacity(out, 4))
663 Stream_Write_UINT32(out, usize);
665 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
668 if (!msusb_msinterface_write(MsInterface, out))
671 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
674 Stream_Free(out, TRUE);
676 return ERROR_INTERNAL_ERROR;
680 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
683 const BOOL noAck = (RequestField & 0x80000000U) != 0;
684 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
686 if (!callback || !s || !udevman || !pdev)
687 return ERROR_INVALID_PARAMETER;
692 return ERROR_INVALID_PARAMETER;
694 if (transferDir == 0)
696 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
697 return ERROR_INVALID_PARAMETER;
700 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
701 return ERROR_INVALID_DATA;
703 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
706 Stream_Seek_UINT32(s);
709 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
711 msusb_msinterface_free(MsInterface);
712 return ERROR_INVALID_DATA;
715 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
716 if (OutputBufferSize != 0)
718 WLog_Print(urbdrc->log, WLOG_ERROR,
719 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
722 msusb_msinterface_free(MsInterface);
723 return ERROR_INVALID_DATA;
727 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
730 msusb_msinterface_free(MsInterface);
731 return ERROR_INTERNAL_ERROR;
736 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
737 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
739 msusb_msinterface_free(MsInterface);
740 return ERROR_BAD_CONFIGURATION;
744 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
745 return ERROR_BAD_CONFIGURATION;
748 return CHANNEL_RC_OK;
750 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
754 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
755 int transferDir,
int External)
758 UINT32 InterfaceId = 0;
759 UINT32 EndpointAddress = 0;
760 UINT32 PipeHandle = 0;
761 UINT32 TransferFlags = 0;
762 UINT32 OutputBufferSize = 0;
763 UINT32 usbd_status = 0;
765 BYTE bmRequestType = 0;
770 BYTE* buffer =
nullptr;
773 const BOOL noAck = (RequestField & 0x80000000U) != 0;
774 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
776 if (!callback || !s || !udevman || !pdev)
777 return ERROR_INVALID_PARAMETER;
782 return ERROR_INVALID_PARAMETER;
784 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
785 return ERROR_INVALID_DATA;
787 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
788 Stream_Read_UINT32(s, PipeHandle);
789 Stream_Read_UINT32(s, TransferFlags);
790 EndpointAddress = (PipeHandle & 0x000000ff);
795 case URB_CONTROL_TRANSFER_EXTERNAL:
796 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
797 return ERROR_INVALID_DATA;
799 Stream_Read_UINT32(s, Timeout);
802 case URB_CONTROL_TRANSFER_NONEXTERNAL:
809 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
810 return ERROR_INVALID_DATA;
812 Stream_Read_UINT8(s, bmRequestType);
813 Stream_Read_UINT8(s, Request);
814 Stream_Read_UINT16(s, Value);
815 Stream_Read_UINT16(s, Index);
816 Stream_Read_UINT16(s, length);
817 Stream_Read_UINT32(s, OutputBufferSize);
819 if (length != OutputBufferSize)
821 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
822 return ERROR_INVALID_DATA;
825 out_size = 36 + OutputBufferSize;
826 out = Stream_New(
nullptr, out_size);
829 return ERROR_OUTOFMEMORY;
831 Stream_Seek(out, 36);
833 buffer = Stream_Pointer(out);
835 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
837 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
839 Stream_Free(out, TRUE);
840 return ERROR_INVALID_DATA;
842 Stream_Copy(s, out, OutputBufferSize);
846 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
847 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
850 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
851 Stream_Free(out, TRUE);
852 return ERROR_INTERNAL_ERROR;
855 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
856 usbd_status, OutputBufferSize, transferDir);
860 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
861 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
862 WINPR_ATTR_UNUSED UINT32 StartFrame,
863 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
866 if (!pdev->isChannelClosed(pdev))
867 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
868 OutputBufferSize, transferDir);
870 Stream_Free(out, TRUE);
874 wStream* s, UINT32 RequestField, UINT32 MessageId,
875 IUDEVMAN* udevman,
int transferDir)
877 UINT32 EndpointAddress = 0;
878 UINT32 PipeHandle = 0;
879 UINT32 TransferFlags = 0;
880 UINT32 OutputBufferSize = 0;
881 const BOOL noAck = (RequestField & 0x80000000U) != 0;
882 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
884 if (!pdev || !callback || !s || !udevman)
885 return ERROR_INVALID_PARAMETER;
887 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
888 return ERROR_INVALID_DATA;
890 Stream_Read_UINT32(s, PipeHandle);
891 Stream_Read_UINT32(s, TransferFlags);
892 Stream_Read_UINT32(s, OutputBufferSize);
893 EndpointAddress = (PipeHandle & 0x000000ff);
895 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
897 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
899 return ERROR_INVALID_DATA;
904 const int rc = pdev->bulk_or_interrupt_transfer(
905 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
907 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
908 urb_bulk_transfer_cb, 10000);
914 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
915 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
916 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
920 if (pdev->isChannelClosed(pdev))
922 Stream_Free(out, TRUE);
928 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
929 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
930 Stream_ResetPosition(out);
932 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
933 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
935 Stream_Free(out, TRUE);
939 Stream_Write_UINT32(out, RequestId);
940 Stream_Write_UINT32(out, 20 + packetSize);
941 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
944 Stream_Free(out, TRUE);
948 Stream_Write_UINT32(out, StartFrame);
953 Stream_Write_UINT32(out, NumberOfPackets);
954 Stream_Write_UINT32(out, ErrorCount);
955 Stream_Seek(out, packetSize);
959 Stream_Write_UINT32(out, 0);
960 Stream_Write_UINT32(out, ErrorCount);
963 Stream_Write_UINT32(out, 0);
964 Stream_Write_UINT32(out, OutputBufferSize);
965 Stream_Seek(out, payloadSize);
967 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
968 if (rc != CHANNEL_RC_OK)
969 WLog_WARN(TAG,
"stream_write_and_free failed with %" PRIu32, rc);
974 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
978 UINT32 EndpointAddress = 0;
979 UINT32 PipeHandle = 0;
980 UINT32 TransferFlags = 0;
981 UINT32 StartFrame = 0;
982 UINT32 NumberOfPackets = 0;
983 UINT32 ErrorCount = 0;
984 UINT32 OutputBufferSize = 0;
985 BYTE* packetDescriptorData =
nullptr;
986 const BOOL noAck = (RequestField & 0x80000000U) != 0;
987 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
989 if (!pdev || !callback || !udevman)
990 return ERROR_INVALID_PARAMETER;
992 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
993 return ERROR_INVALID_DATA;
995 Stream_Read_UINT32(s, PipeHandle);
996 EndpointAddress = (PipeHandle & 0x000000ff);
997 Stream_Read_UINT32(s, TransferFlags);
998 Stream_Read_UINT32(s, StartFrame);
999 Stream_Read_UINT32(s, NumberOfPackets);
1000 Stream_Read_UINT32(s, ErrorCount);
1002 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
1003 return ERROR_INVALID_DATA;
1005 packetDescriptorData = Stream_Pointer(s);
1006 Stream_Seek(s, 12ULL * NumberOfPackets);
1008 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
1009 return ERROR_INVALID_DATA;
1010 Stream_Read_UINT32(s, OutputBufferSize);
1012 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1014 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1015 return ERROR_INVALID_DATA;
1018 rc = pdev->isoch_transfer(
1019 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1020 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1021 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1022 urb_isoch_transfer_cb, 2000);
1025 return ERROR_INTERNAL_ERROR;
1030 wStream* s, UINT32 RequestField, UINT32 MessageId,
1031 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1033 size_t out_size = 0;
1034 UINT32 InterfaceId = 0;
1035 UINT32 OutputBufferSize = 0;
1036 UINT32 usbd_status = 0;
1037 BYTE bmRequestType = 0;
1038 BYTE desc_index = 0;
1043 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1044 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1046 if (!callback || !s || !udevman || !pdev)
1047 return ERROR_INVALID_PARAMETER;
1052 return ERROR_INVALID_PARAMETER;
1054 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1055 return ERROR_INVALID_DATA;
1057 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1058 Stream_Read_UINT8(s, desc_index);
1059 Stream_Read_UINT8(s, desc_type);
1060 Stream_Read_UINT16(s, langId);
1061 Stream_Read_UINT32(s, OutputBufferSize);
1062 if (OutputBufferSize > UINT32_MAX - 36)
1063 return ERROR_INVALID_DATA;
1064 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1066 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1067 return ERROR_INVALID_DATA;
1070 out_size = 36ULL + OutputBufferSize;
1071 out = Stream_New(
nullptr, out_size);
1074 return ERROR_OUTOFMEMORY;
1076 Stream_Seek(out, 36);
1077 bmRequestType = func_recipient;
1079 switch (transferDir)
1081 case USBD_TRANSFER_DIRECTION_IN:
1082 bmRequestType |= 0x80;
1085 case USBD_TRANSFER_DIRECTION_OUT:
1086 bmRequestType |= 0x00;
1087 Stream_Copy(s, out, OutputBufferSize);
1088 Stream_Rewind(out, OutputBufferSize);
1092 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1093 OutputBufferSize = 0;
1094 usbd_status = USBD_STATUS_STALL_PID;
1099 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1101 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1102 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1104 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1105 Stream_Free(out, TRUE);
1106 return ERROR_INTERNAL_ERROR;
1109 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1110 usbd_status, OutputBufferSize, transferDir);
1114 wStream* s, UINT32 RequestField, UINT32 MessageId,
1115 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1117 size_t out_size = 0;
1118 UINT32 InterfaceId = 0;
1119 UINT32 OutputBufferSize = 0;
1120 UINT32 usbd_status = 0;
1122 BYTE bmRequestType = 0;
1125 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1126 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1128 if (!callback || !s || !udevman || !pdev)
1129 return ERROR_INVALID_PARAMETER;
1134 return ERROR_INVALID_PARAMETER;
1136 if (transferDir == 0)
1138 WLog_Print(urbdrc->log, WLOG_DEBUG,
1139 "urb_control_get_status_request: transfer out not supported");
1140 return ERROR_INVALID_PARAMETER;
1143 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1144 return ERROR_INVALID_DATA;
1146 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1147 Stream_Read_UINT16(s, Index);
1149 Stream_Read_UINT32(s, OutputBufferSize);
1150 if (OutputBufferSize > UINT32_MAX - 36)
1151 return ERROR_INVALID_DATA;
1152 out_size = 36ULL + OutputBufferSize;
1153 out = Stream_New(
nullptr, out_size);
1156 return ERROR_OUTOFMEMORY;
1158 Stream_Seek(out, 36);
1159 bmRequestType = func_recipient | 0x80;
1161 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1162 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1165 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1166 Stream_Free(out, TRUE);
1167 return ERROR_INTERNAL_ERROR;
1170 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1171 usbd_status, OutputBufferSize, transferDir);
1175 wStream* s, UINT32 RequestField, UINT32 MessageId,
1176 IUDEVMAN* udevman, BYTE func_type,
1177 BYTE func_recipient,
int transferDir)
1179 UINT32 out_size = 0;
1180 UINT32 InterfaceId = 0;
1181 UINT32 TransferFlags = 0;
1182 UINT32 usbd_status = 0;
1183 UINT32 OutputBufferSize = 0;
1184 BYTE ReqTypeReservedBits = 0;
1186 BYTE bmRequestType = 0;
1191 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1192 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1194 if (!callback || !s || !udevman || !pdev)
1195 return ERROR_INVALID_PARAMETER;
1200 return ERROR_INVALID_PARAMETER;
1202 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1203 return ERROR_INVALID_DATA;
1205 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1206 Stream_Read_UINT32(s, TransferFlags);
1207 Stream_Read_UINT8(s, ReqTypeReservedBits);
1208 Stream_Read_UINT8(s, Request);
1209 Stream_Read_UINT16(s, Value);
1210 Stream_Read_UINT16(s, Index);
1211 Stream_Seek_UINT16(s);
1212 Stream_Read_UINT32(s, OutputBufferSize);
1213 if (OutputBufferSize > UINT32_MAX - 36)
1214 return ERROR_INVALID_DATA;
1216 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1218 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1219 return ERROR_INVALID_DATA;
1222 out_size = 36ULL + OutputBufferSize;
1223 out = Stream_New(
nullptr, out_size);
1226 return ERROR_OUTOFMEMORY;
1228 Stream_Seek(out, 36);
1231 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1233 Stream_Copy(s, out, OutputBufferSize);
1234 Stream_Rewind(out, OutputBufferSize);
1238 bmRequestType = func_type | func_recipient;
1240 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1241 bmRequestType |= 0x80;
1243 WLog_Print(urbdrc->log, WLOG_DEBUG,
1244 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1246 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1247 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1248 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1249 OutputBufferSize, bmRequestType);
1251 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1252 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1254 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1255 Stream_Free(out, TRUE);
1256 return ERROR_INTERNAL_ERROR;
1259 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1260 usbd_status, OutputBufferSize, transferDir);
1264 wStream* s, UINT32 RequestField, UINT32 MessageId,
1265 IUDEVMAN* udevman,
int transferDir)
1267 size_t out_size = 0;
1268 UINT32 InterfaceId = 0;
1269 UINT32 OutputBufferSize = 0;
1270 UINT32 usbd_status = 0;
1272 BYTE InterfaceNumber = 0;
1273 BYTE Ms_PageIndex = 0;
1274 UINT16 Ms_featureDescIndex = 0;
1278 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1279 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1281 if (!callback || !s || !udevman || !pdev)
1282 return ERROR_INVALID_PARAMETER;
1287 return ERROR_INVALID_PARAMETER;
1289 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1290 return ERROR_INVALID_DATA;
1293 Stream_Read_UINT8(s, Recipient);
1294 Recipient = (Recipient & 0x1f);
1295 Stream_Read_UINT8(s, InterfaceNumber);
1296 Stream_Read_UINT8(s, Ms_PageIndex);
1297 Stream_Read_UINT16(s, Ms_featureDescIndex);
1299 Stream_Read_UINT32(s, OutputBufferSize);
1300 if (OutputBufferSize > UINT32_MAX - 36)
1301 return ERROR_INVALID_DATA;
1303 switch (transferDir)
1305 case USBD_TRANSFER_DIRECTION_OUT:
1306 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1307 return ERROR_INVALID_DATA;
1315 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1316 out_size = 36ULL + OutputBufferSize;
1317 out = Stream_New(
nullptr, out_size);
1320 return ERROR_OUTOFMEMORY;
1322 Stream_Seek(out, 36);
1324 switch (transferDir)
1326 case USBD_TRANSFER_DIRECTION_OUT:
1327 Stream_Copy(s, out, OutputBufferSize);
1328 Stream_Rewind(out, OutputBufferSize);
1331 case USBD_TRANSFER_DIRECTION_IN:
1337 WLog_Print(urbdrc->log, WLOG_DEBUG,
1338 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1339 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1340 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1341 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1343 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1344 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1345 &OutputBufferSize, Stream_Pointer(out), 1000);
1348 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1350 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1351 usbd_status, OutputBufferSize, transferDir);
1355 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1356 int transferDir,
int action)
1358 UINT32 usbd_status = 0;
1359 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1361 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1362 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1364 if (!callback || !s || !udevman || !pdev)
1365 return ERROR_INVALID_PARAMETER;
1370 return ERROR_INVALID_PARAMETER;
1372 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1373 return ERROR_INVALID_DATA;
1375 if (transferDir == 0)
1377 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1378 return ERROR_INVALID_PARAMETER;
1381 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1382 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1383 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1384 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1386 if (OutputBufferSize != 0)
1388 WLog_Print(urbdrc->log, WLOG_DEBUG,
1389 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32
" != 0",
1391 return ERROR_BAD_CONFIGURATION;
1397 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1401 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1403 ret = USBD_STATUS_SUCCESS;
1408 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1410 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1414 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1416 ret = USBD_STATUS_SUCCESS;
1421 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1423 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1429 wStream* out = Stream_New(
nullptr, 36);
1432 return ERROR_OUTOFMEMORY;
1434 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1439 UINT32 RequestId, UINT32 MessageId,
1440 UINT32 CompletionId, UINT32 FrameNumber)
1442 WINPR_ASSERT(callback);
1444 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1446 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1449 return ERROR_OUTOFMEMORY;
1451 if (!Stream_EnsureRemainingCapacity(out, 4))
1453 Stream_Write_UINT32(out, 12);
1454 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1456 Stream_Write_UINT32(out, FrameNumber);
1457 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1460 Stream_Free(out, TRUE);
1461 return ERROR_OUTOFMEMORY;
1465 wStream* s, UINT32 RequestField, UINT32 MessageId,
1466 IUDEVMAN* udevman,
int transferDir)
1468 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1469 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1471 if (!callback || !s || !udevman || !pdev)
1472 return ERROR_INVALID_PARAMETER;
1477 return ERROR_INVALID_PARAMETER;
1479 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1480 return ERROR_INVALID_DATA;
1482 if (transferDir == 0)
1484 WLog_Print(urbdrc->log, WLOG_DEBUG,
1485 "urb_get_current_frame_number: not support transfer out");
1486 return ERROR_INVALID_PARAMETER;
1489 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1490 if (OutputBufferSize != 0)
1492 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1496 const UINT32 dummy_frames = GetTickCount();
1497 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1500 return CHANNEL_RC_OK;
1502 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1507static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1509 UINT32 RequestField, UINT32 MessageId,
1510 IUDEVMAN* udevman,
int transferDir)
1512 size_t out_size = 0;
1513 UINT32 InterfaceId = 0;
1514 UINT32 OutputBufferSize = 0;
1515 UINT32 usbd_status = 0;
1518 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1519 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1521 if (!callback || !s || !udevman || !pdev)
1522 return ERROR_INVALID_PARAMETER;
1527 return ERROR_INVALID_PARAMETER;
1529 if (transferDir == 0)
1531 WLog_Print(urbdrc->log, WLOG_DEBUG,
1532 "urb_control_get_configuration_request:"
1533 " not support transfer out");
1534 return ERROR_INVALID_PARAMETER;
1537 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1538 return ERROR_INVALID_DATA;
1540 Stream_Read_UINT32(s, OutputBufferSize);
1541 if (OutputBufferSize > UINT32_MAX - 36)
1542 return ERROR_INVALID_DATA;
1543 out_size = 36ULL + OutputBufferSize;
1544 out = Stream_New(
nullptr, out_size);
1547 return ERROR_OUTOFMEMORY;
1549 Stream_Seek(out, 36);
1550 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1552 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1554 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1556 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1557 Stream_Free(out, TRUE);
1558 return ERROR_INTERNAL_ERROR;
1561 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1562 usbd_status, OutputBufferSize, transferDir);
1567 wStream* s, UINT32 RequestField, UINT32 MessageId,
1568 IUDEVMAN* udevman,
int transferDir)
1570 size_t out_size = 0;
1571 UINT32 InterfaceId = 0;
1572 UINT32 OutputBufferSize = 0;
1573 UINT32 usbd_status = 0;
1574 UINT16 InterfaceNr = 0;
1577 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1578 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1580 if (!callback || !s || !udevman || !pdev)
1581 return ERROR_INVALID_PARAMETER;
1586 return ERROR_INVALID_PARAMETER;
1588 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1589 return ERROR_INVALID_DATA;
1591 if (transferDir == 0)
1593 WLog_Print(urbdrc->log, WLOG_DEBUG,
1594 "urb_control_get_interface_request: not support transfer out");
1595 return ERROR_INVALID_PARAMETER;
1598 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1599 Stream_Read_UINT16(s, InterfaceNr);
1601 Stream_Read_UINT32(s, OutputBufferSize);
1602 if (OutputBufferSize > UINT32_MAX - 36)
1603 return ERROR_INVALID_DATA;
1604 out_size = 36ULL + OutputBufferSize;
1605 out = Stream_New(
nullptr, out_size);
1608 return ERROR_OUTOFMEMORY;
1610 Stream_Seek(out, 36);
1612 if (!pdev->control_transfer(
1613 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1614 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1616 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1617 Stream_Free(out, TRUE);
1618 return ERROR_INTERNAL_ERROR;
1621 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1622 usbd_status, OutputBufferSize, transferDir);
1626 wStream* s, UINT32 RequestField, UINT32 MessageId,
1627 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1630 UINT32 InterfaceId = 0;
1631 UINT32 OutputBufferSize = 0;
1632 UINT32 usbd_status = 0;
1633 UINT16 FeatureSelector = 0;
1635 BYTE bmRequestType = 0;
1639 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1640 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1642 if (!callback || !s || !udevman || !pdev)
1643 return ERROR_INVALID_PARAMETER;
1648 return ERROR_INVALID_PARAMETER;
1650 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1651 return ERROR_INVALID_DATA;
1653 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1654 Stream_Read_UINT16(s, FeatureSelector);
1655 Stream_Read_UINT16(s, Index);
1656 Stream_Read_UINT32(s, OutputBufferSize);
1657 if (OutputBufferSize > UINT32_MAX - 36)
1658 return ERROR_INVALID_DATA;
1659 switch (transferDir)
1661 case USBD_TRANSFER_DIRECTION_OUT:
1662 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1663 return ERROR_INVALID_DATA;
1671 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1674 return ERROR_OUTOFMEMORY;
1676 Stream_Seek(out, 36);
1677 bmRequestType = func_recipient;
1679 switch (transferDir)
1681 case USBD_TRANSFER_DIRECTION_OUT:
1682 WLog_Print(urbdrc->log, WLOG_ERROR,
1683 "Function urb_control_feature_request: OUT Unchecked");
1684 Stream_Copy(s, out, OutputBufferSize);
1685 Stream_Rewind(out, OutputBufferSize);
1686 bmRequestType |= 0x00;
1689 case USBD_TRANSFER_DIRECTION_IN:
1690 bmRequestType |= 0x80;
1698 case URB_SET_FEATURE:
1702 case URB_CLEAR_FEATURE:
1707 WLog_Print(urbdrc->log, WLOG_ERROR,
1708 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1709 Stream_Free(out, TRUE);
1710 return ERROR_INTERNAL_ERROR;
1713 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1714 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1716 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1717 Stream_Free(out, TRUE);
1718 return ERROR_INTERNAL_ERROR;
1721 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1722 usbd_status, OutputBufferSize, transferDir);
1726 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1731 UINT16 URB_Function = 0;
1732 UINT32 RequestId = 0;
1733 UINT error = ERROR_INTERNAL_ERROR;
1736 if (!callback || !s || !udevman || !pdev)
1737 return ERROR_INVALID_PARAMETER;
1742 return ERROR_INVALID_PARAMETER;
1744 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1745 return ERROR_INVALID_DATA;
1747 Stream_Read_UINT32(s, CbTsUrb);
1748 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1749 return ERROR_INVALID_DATA;
1750 Stream_Read_UINT16(s, Size);
1751 if (Size != CbTsUrb)
1753 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1754 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1755 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1757 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1758 " != %s::CbTsUrb 0x%08" PRIx32,
1759 Size, section, CbTsUrb);
1760 return ERROR_INVALID_DATA;
1762 Stream_Read_UINT16(s, URB_Function);
1763 Stream_Read_UINT32(s, RequestId);
1764 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1767 switch (URB_Function)
1769 case TS_URB_SELECT_CONFIGURATION:
1770 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1774 case TS_URB_SELECT_INTERFACE:
1776 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1779 case TS_URB_PIPE_REQUEST:
1780 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1784 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1790 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1796 case TS_URB_GET_FRAME_LENGTH:
1802 case TS_URB_SET_FRAME_LENGTH:
1808 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1809 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1813 case TS_URB_CONTROL_TRANSFER:
1814 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1815 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1818 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1819 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1823 case TS_URB_ISOCH_TRANSFER:
1825 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1828 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1829 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1833 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1834 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1838 case TS_URB_SET_FEATURE_TO_DEVICE:
1839 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1840 0x00, URB_SET_FEATURE, transferDir);
1843 case TS_URB_SET_FEATURE_TO_INTERFACE:
1844 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1845 0x01, URB_SET_FEATURE, transferDir);
1848 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1849 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1850 0x02, URB_SET_FEATURE, transferDir);
1853 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1854 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1855 0x00, URB_CLEAR_FEATURE, transferDir);
1858 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1859 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1860 0x01, URB_CLEAR_FEATURE, transferDir);
1863 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1864 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1865 0x02, URB_CLEAR_FEATURE, transferDir);
1868 case TS_URB_GET_STATUS_FROM_DEVICE:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1873 case TS_URB_GET_STATUS_FROM_INTERFACE:
1874 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1878 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1879 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1883 case TS_URB_RESERVED_0X0016:
1886 case TS_URB_VENDOR_DEVICE:
1887 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1888 udevman, (0x02u << 5),
1892 case TS_URB_VENDOR_INTERFACE:
1893 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1894 udevman, (0x02u << 5),
1898 case TS_URB_VENDOR_ENDPOINT:
1899 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1900 udevman, (0x02u << 5),
1904 case TS_URB_CLASS_DEVICE:
1905 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1906 udevman, (0x01u << 5),
1910 case TS_URB_CLASS_INTERFACE:
1911 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1912 udevman, (0x01u << 5),
1916 case TS_URB_CLASS_ENDPOINT:
1917 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1918 udevman, (0x01u << 5),
1922 case TS_URB_RESERVE_0X001D:
1925 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1926 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1930 case TS_URB_CLASS_OTHER:
1931 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1932 udevman, (0x01u << 5),
1936 case TS_URB_VENDOR_OTHER:
1937 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1938 udevman, (0x02u << 5),
1942 case TS_URB_GET_STATUS_FROM_OTHER:
1943 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1947 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1948 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1949 0x03, URB_CLEAR_FEATURE, transferDir);
1952 case TS_URB_SET_FEATURE_TO_OTHER:
1953 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1954 0x03, URB_SET_FEATURE, transferDir);
1957 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1958 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1962 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1963 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1967 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1968 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1969 udevman, transferDir);
1972 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1973 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1974 udevman, transferDir);
1977 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1978 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1982 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1983 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1987 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1988 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1989 udevman, transferDir);
1992 case TS_URB_RESERVE_0X002B:
1993 case TS_URB_RESERVE_0X002C:
1994 case TS_URB_RESERVE_0X002D:
1995 case TS_URB_RESERVE_0X002E:
1996 case TS_URB_RESERVE_0X002F:
2000 case TS_URB_SYNC_RESET_PIPE:
2001 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
2005 case TS_URB_SYNC_CLEAR_STALL:
2006 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
2010 case TS_URB_CONTROL_TRANSFER_EX:
2011 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
2012 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
2016 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
2023 WLog_Print(urbdrc->log, WLOG_WARN,
2024 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2025 urb_function_string(URB_Function), URB_Function, error);
2032 IUDEVMAN* udevman,
wStream* data)
2034 UINT32 InterfaceId = 0;
2035 UINT32 MessageId = 0;
2036 UINT32 FunctionId = 0;
2037 IUDEVICE* pdev =
nullptr;
2038 UINT error = ERROR_INTERNAL_ERROR;
2040 if (!urbdrc || !data || !callback || !udevman)
2043 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2046 Stream_Rewind_UINT32(data);
2048 Stream_Read_UINT32(data, InterfaceId);
2049 Stream_Read_UINT32(data, MessageId);
2050 Stream_Read_UINT32(data, FunctionId);
2052 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2055 if (pdev ==
nullptr)
2057 error = ERROR_SUCCESS;
2062 if (pdev->isChannelClosed(pdev))
2064 error = ERROR_SUCCESS;
2071 callback = pdev->get_channelCallback(pdev);
2074 if (callback ==
nullptr)
2076 error = ERROR_SUCCESS;
2081 if (!pdev->detach_kernel_driver(pdev))
2083 error = ERROR_SUCCESS;
2089 case CANCEL_REQUEST:
2090 error = urbdrc_process_cancel_request(pdev, data, udevman);
2093 case REGISTER_REQUEST_CALLBACK:
2094 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2098 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2101 case INTERNAL_IO_CONTROL:
2102 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2105 case QUERY_DEVICE_TEXT:
2106 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2109 case TRANSFER_IN_REQUEST:
2110 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2111 USBD_TRANSFER_DIRECTION_IN);
2114 case TRANSFER_OUT_REQUEST:
2115 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2116 USBD_TRANSFER_DIRECTION_OUT);
2119 case RETRACT_DEVICE:
2120 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2124 WLog_Print(urbdrc->log, WLOG_WARN,
2125 "urbdrc_process_udev_data_transfer:"
2126 " unknown FunctionId 0x%" PRIX32
"",
2134 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);