25#include <winpr/sysinfo.h>
26#include <winpr/cast.h>
28#include <urbdrc_helpers.h>
30#include "urbdrc_types.h"
31#include "data_transfer.h"
34static void usb_process_get_port_status(IUDEVICE* pdev,
wStream* out)
36 int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
41 Stream_Write_UINT32(out, 0x303);
45 Stream_Write_UINT32(out, 0x103);
50 Stream_Write_UINT32(out, 0x503);
56static BOOL write_urb_result_header(
wStream* s, UINT16 Size, UINT32 status)
58 if (!Stream_EnsureRemainingCapacity(s, 8ULL + Size))
60 Stream_Write_UINT16(s, Size);
61 Stream_Seek_UINT16(s);
62 Stream_Write_UINT32(s, status);
69static wStream* create_urb_completion_message(UINT32 InterfaceId, UINT32 MessageId,
70 UINT32 RequestId, UINT32 FunctionId)
73 create_shared_message_header_with_functionid(InterfaceId, MessageId, FunctionId, 4);
77 Stream_Write_UINT32(out, RequestId);
82 HRESULT hResult, UINT32 OutputSize,
const void* data)
84 WINPR_ASSERT(callback);
85 UINT status = ERROR_OUTOFMEMORY;
87 if (!Stream_EnsureRemainingCapacity(out, 8ULL + OutputSize))
90 Stream_Write_INT32(out, hResult);
91 Stream_Write_UINT32(out, OutputSize);
92 Stream_Write(out, data, OutputSize);
93 return stream_write_and_free(callback->plugin, callback->channel, out);
96 Stream_Free(out, TRUE);
100static UINT urb_write_completion(WINPR_ATTR_UNUSED IUDEVICE* pdev,
102 UINT32 InterfaceId, UINT32 MessageId, UINT32 RequestId,
103 UINT32 usbd_status, UINT32 OutputBufferSize)
106 return ERROR_INVALID_PARAMETER;
108 if (Stream_Capacity(out) < OutputBufferSize + 36)
110 Stream_Free(out, TRUE);
111 return ERROR_INVALID_PARAMETER;
114 Stream_ResetPosition(out);
116 const UINT32 FunctionId = (OutputBufferSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
117 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
119 Stream_Free(out, TRUE);
120 return ERROR_OUTOFMEMORY;
123 Stream_Write_UINT32(out, RequestId);
124 Stream_Write_UINT32(out, 8);
126 if (!write_urb_result_header(out, 8, usbd_status))
128 Stream_Free(out, TRUE);
129 return ERROR_OUTOFMEMORY;
132 Stream_Write_UINT32(out, 0);
133 Stream_Write_UINT32(out, OutputBufferSize);
134 Stream_Seek(out, OutputBufferSize);
137 return stream_write_and_free(callback->plugin, callback->channel, out);
139 Stream_Free(out, TRUE);
141 return ERROR_SUCCESS;
144static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
145 UINT32 OutputBufferSize)
147 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
149#if UINT32_MAX >= SIZE_MAX
150 if (OutputBufferSize > UINT32_MAX - 28ull)
154 wStream* out = create_shared_message_header_with_functionid(
155 InterfaceId, MessageId, IOCONTROL_COMPLETION, OutputBufferSize + 16ull);
159 Stream_Write_UINT32(out, RequestId);
160 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
161 Stream_Write_UINT32(out, OutputBufferSize);
162 Stream_Write_UINT32(out, OutputBufferSize);
166static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
170 UINT32 NumRequestCompletion = 0;
171 UINT32 RequestCompletion = 0;
173 if (!callback || !s || !udevman || !pdev)
174 return ERROR_INVALID_PARAMETER;
179 return ERROR_INVALID_PARAMETER;
181 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urbdrc_process_register_request_callback");
183 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL))
184 return ERROR_INVALID_DATA;
186 Stream_Read_UINT32(s, NumRequestCompletion);
188 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL * NumRequestCompletion))
189 return ERROR_INVALID_DATA;
190 for (uint32_t x = 0; x < NumRequestCompletion; x++)
194 Stream_Read_UINT32(s, RequestCompletion);
195 pdev->set_ReqCompletion(pdev, RequestCompletion);
198 return ERROR_SUCCESS;
201static UINT urbdrc_process_cancel_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
206 if (!s || !udevman || !pdev)
207 return ERROR_INVALID_PARAMETER;
211 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
212 return ERROR_INVALID_DATA;
214 Stream_Read_UINT32(s, CancelId);
215 WLog_Print(urbdrc->log, WLOG_DEBUG,
"CANCEL_REQUEST: CancelId=%08" PRIx32
"", CancelId);
217 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
218 return ERROR_INTERNAL_ERROR;
220 return ERROR_SUCCESS;
223static UINT urbdrc_process_retract_device_request(WINPR_ATTR_UNUSED IUDEVICE* pdev,
wStream* s,
230 return ERROR_INVALID_PARAMETER;
235 return ERROR_INVALID_PARAMETER;
237 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
238 return ERROR_INVALID_DATA;
240 Stream_Read_UINT32(s, Reason);
244 case UsbRetractReason_BlockedByPolicy:
245 WLog_Print(urbdrc->log, WLOG_DEBUG,
246 "UsbRetractReason_BlockedByPolicy: now it is not support");
247 return ERROR_ACCESS_DENIED;
250 WLog_Print(urbdrc->log, WLOG_DEBUG,
251 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32
"", Reason);
252 return ERROR_ACCESS_DENIED;
255 return ERROR_SUCCESS;
259 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
261 UINT32 InterfaceId = 0;
262 UINT32 IoControlCode = 0;
263 UINT32 InputBufferSize = 0;
264 UINT32 OutputBufferSize = 0;
265 UINT32 RequestId = 0;
266 UINT32 usbd_status = USBD_STATUS_SUCCESS;
271 if (!callback || !s || !udevman || !pdev)
272 return ERROR_INVALID_PARAMETER;
277 return ERROR_INVALID_PARAMETER;
279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
280 return ERROR_INVALID_DATA;
282 Stream_Read_UINT32(s, IoControlCode);
283 Stream_Read_UINT32(s, InputBufferSize);
285 if (!Stream_SafeSeek(s, InputBufferSize))
286 return ERROR_INVALID_DATA;
287 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
288 return ERROR_INVALID_DATA;
290 Stream_Read_UINT32(s, OutputBufferSize);
291 Stream_Read_UINT32(s, RequestId);
293 if (OutputBufferSize > UINT32_MAX - 4)
294 return ERROR_INVALID_DATA;
296 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
297 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
300 return ERROR_OUTOFMEMORY;
302 switch (IoControlCode)
304 case IOCTL_INTERNAL_USB_SUBMIT_URB:
305 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
306 WLog_Print(urbdrc->log, WLOG_ERROR,
307 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
310 case IOCTL_INTERNAL_USB_RESET_PORT:
311 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
314 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
315 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
316 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
317 Stream_Pointer(out));
321 if (!Stream_SafeSeek(out, OutputBufferSize))
323 Stream_Free(out, TRUE);
324 return ERROR_INVALID_DATA;
327 if (pdev->isExist(pdev) == 0)
328 Stream_Write_UINT32(out, 0);
330 usb_process_get_port_status(pdev, out);
335 case IOCTL_INTERNAL_USB_CYCLE_PORT:
336 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
337 WLog_Print(urbdrc->log, WLOG_ERROR,
338 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
341 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
342 WLog_Print(urbdrc->log, WLOG_DEBUG,
343 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
344 WLog_Print(urbdrc->log, WLOG_ERROR,
345 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
349 WLog_Print(urbdrc->log, WLOG_DEBUG,
350 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
352 Stream_Free(out, TRUE);
353 return ERROR_INVALID_OPERATION;
356 return stream_write_and_free(callback->plugin, callback->channel, out);
360 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
362 if (!pdev || !callback || !s || !udevman)
363 return ERROR_INVALID_PARAMETER;
366 WINPR_ASSERT(urbdrc);
368 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
369 return ERROR_INVALID_DATA;
371 const UINT32 IoControlCode = Stream_Get_UINT32(s);
372 if (IoControlCode != IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME)
376 "Invalid [MS-RDPEUSB] 2.2.13 USB Internal IO Control Code::IoControlCode0x%08" PRIx32
377 ", must be IOCTL_TSUSBGD_IOCTL_USBDI_QUERY_BUS_TIME [0x00224000]",
379 return ERROR_INVALID_DATA;
381 const UINT32 InputBufferSize = Stream_Get_UINT32(s);
383 if (!Stream_SafeSeek(s, InputBufferSize))
384 return ERROR_INVALID_DATA;
385 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
386 return ERROR_INVALID_DATA;
387 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
388 const UINT32 RequestId = Stream_Get_UINT32(s);
389 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
392 const UINT32 frames = GetTickCount();
394 if (4 > OutputBufferSize)
396 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32, 4u,
398 return ERROR_BAD_CONFIGURATION;
400 wStream* out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
403 return ERROR_OUTOFMEMORY;
405 Stream_Write_UINT32(out, frames);
406 return stream_write_and_free(callback->plugin, callback->channel, out);
411 UINT32 InterfaceId, UINT32 MessageId, HRESULT hr,
412 const BYTE* text, uint8_t bytelen)
414 WINPR_ASSERT(callback);
416 const uint8_t charlen = bytelen /
sizeof(WCHAR);
417 wStream* out = create_shared_message_header_with_functionid(InterfaceId, MessageId, charlen,
421 return ERROR_OUTOFMEMORY;
423 Stream_Write(out, text, bytelen);
424 Stream_Write_INT32(out, hr);
425 return stream_write_and_free(callback->plugin, callback->channel, out);
429 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
433 UINT8 bufferSize = 0xFF;
434 BYTE DeviceDescription[0x100] = WINPR_C_ARRAY_INIT;
436 if (!pdev || !callback || !s || !udevman)
437 return ERROR_INVALID_PARAMETER;
438 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
439 return ERROR_INVALID_DATA;
441 Stream_Read_UINT32(s, TextType);
442 Stream_Read_UINT32(s, LocaleId);
443 if (LocaleId > UINT16_MAX)
444 return ERROR_INVALID_DATA;
446 HRESULT hr = (HRESULT)pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId,
447 &bufferSize, DeviceDescription);
448 const UINT32 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
449 return urbdrc_send_query_device_text_response(callback, InterfaceId, MessageId, hr,
450 DeviceDescription, bufferSize);
453static void func_select_all_interface_for_msconfig(
URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
456 WINPR_ASSERT(urbdrc);
458 WINPR_ASSERT(MsConfig);
461 UINT32 NumInterfaces = MsConfig->NumInterfaces;
463 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
465 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
466 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
467 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
470 WLog_Print(urbdrc->log, WLOG_WARN,
471 "select_interface %" PRIu8
" [%" PRIu8
"] failed [%d]", InterfaceNumber,
472 AlternateSetting, rc);
479 UINT32 InterfaceId, UINT32 MessageId,
480 UINT32 RequestId, UINT32 UrbStatus,
484 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
486 return ERROR_OUTOFMEMORY;
488 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
489 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
491 if (!Stream_EnsureRemainingCapacity(out, 4))
493 Stream_Write_UINT32(out, usize);
495 if (!write_urb_result_header(out, usize, UrbStatus))
501 if (!msusb_msconfig_write(MsConfig, out))
506 Stream_Write_UINT32(out, 0);
507 Stream_Write_UINT32(out, 0);
510 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
513 Stream_Free(out, TRUE);
514 return ERROR_OUTOFMEMORY;
518 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
522 UINT32 NumInterfaces = 0;
523 UINT32 usbd_status = 0;
524 BYTE ConfigurationDescriptorIsValid = 0;
526 const BOOL noAck = (RequestField & 0x80000000U) != 0;
527 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
529 if (!callback || !s || !udevman || !pdev)
530 return ERROR_INVALID_PARAMETER;
535 return ERROR_INVALID_PARAMETER;
537 if (transferDir == 0)
539 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
540 return ERROR_INVALID_PARAMETER;
543 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
544 return ERROR_INVALID_DATA;
546 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
547 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
549 Stream_Read_UINT32(s, NumInterfaces);
552 if (ConfigurationDescriptorIsValid)
555 MsConfig = msusb_msconfig_read(s, NumInterfaces);
558 return ERROR_INVALID_DATA;
561 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
564 msusb_msconfig_free(MsConfig);
566 return ERROR_INTERNAL_ERROR;
570 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
572 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
574 msusb_msconfig_free(MsConfig);
580 return CHANNEL_RC_OK;
581 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
582 usbd_status, MsConfig);
587 UINT32 InterfaceId, UINT32 MessageId,
590 WINPR_ASSERT(callback);
591 WINPR_ASSERT(MsInterface);
593 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
595 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
598 return ERROR_OUTOFMEMORY;
600 const uint32_t size = 8U + interface_size;
601 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
603 if (!Stream_EnsureRemainingCapacity(out, 4))
605 Stream_Write_UINT32(out, usize);
607 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
610 if (!msusb_msinterface_write(MsInterface, out))
613 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
616 Stream_Free(out, TRUE);
618 return ERROR_INTERNAL_ERROR;
622 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
625 const BOOL noAck = (RequestField & 0x80000000U) != 0;
626 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
628 if (!callback || !s || !udevman || !pdev)
629 return ERROR_INVALID_PARAMETER;
634 return ERROR_INVALID_PARAMETER;
636 if (transferDir == 0)
638 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
639 return ERROR_INVALID_PARAMETER;
642 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
643 return ERROR_INVALID_DATA;
645 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
646 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
649 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
651 msusb_msinterface_free(MsInterface);
652 return ERROR_INVALID_DATA;
655 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
656 if (OutputBufferSize != 0)
658 WLog_Print(urbdrc->log, WLOG_ERROR,
659 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
662 msusb_msinterface_free(MsInterface);
663 return ERROR_INVALID_DATA;
667 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
670 msusb_msinterface_free(MsInterface);
671 return ERROR_INTERNAL_ERROR;
676 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
677 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
678 return ERROR_BAD_CONFIGURATION;
681 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
682 return ERROR_BAD_CONFIGURATION;
685 return CHANNEL_RC_OK;
687 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
691 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
692 int transferDir,
int External)
695 UINT32 InterfaceId = 0;
696 UINT32 EndpointAddress = 0;
697 UINT32 PipeHandle = 0;
698 UINT32 TransferFlags = 0;
699 UINT32 OutputBufferSize = 0;
700 UINT32 usbd_status = 0;
702 BYTE bmRequestType = 0;
707 BYTE* buffer =
nullptr;
710 const BOOL noAck = (RequestField & 0x80000000U) != 0;
711 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
713 if (!callback || !s || !udevman || !pdev)
714 return ERROR_INVALID_PARAMETER;
719 return ERROR_INVALID_PARAMETER;
721 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
722 return ERROR_INVALID_DATA;
724 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
725 Stream_Read_UINT32(s, PipeHandle);
726 Stream_Read_UINT32(s, TransferFlags);
727 EndpointAddress = (PipeHandle & 0x000000ff);
732 case URB_CONTROL_TRANSFER_EXTERNAL:
733 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
734 return ERROR_INVALID_DATA;
736 Stream_Read_UINT32(s, Timeout);
739 case URB_CONTROL_TRANSFER_NONEXTERNAL:
746 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
747 return ERROR_INVALID_DATA;
749 Stream_Read_UINT8(s, bmRequestType);
750 Stream_Read_UINT8(s, Request);
751 Stream_Read_UINT16(s, Value);
752 Stream_Read_UINT16(s, Index);
753 Stream_Read_UINT16(s, length);
754 Stream_Read_UINT32(s, OutputBufferSize);
756 if (length != OutputBufferSize)
758 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
759 return ERROR_INVALID_DATA;
762 out_size = 36 + OutputBufferSize;
763 out = Stream_New(
nullptr, out_size);
766 return ERROR_OUTOFMEMORY;
768 Stream_Seek(out, 36);
770 buffer = Stream_Pointer(out);
772 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
774 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
776 Stream_Free(out, TRUE);
777 return ERROR_INVALID_DATA;
779 Stream_Copy(s, out, OutputBufferSize);
783 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
784 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
787 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
788 Stream_Free(out, TRUE);
789 return ERROR_INTERNAL_ERROR;
792 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
793 usbd_status, OutputBufferSize);
797 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
798 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
799 WINPR_ATTR_UNUSED UINT32 StartFrame,
800 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
802 if (!pdev->isChannelClosed(pdev))
803 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
806 Stream_Free(out, TRUE);
810 wStream* s, UINT32 RequestField, UINT32 MessageId,
811 IUDEVMAN* udevman,
int transferDir)
813 UINT32 EndpointAddress = 0;
814 UINT32 PipeHandle = 0;
815 UINT32 TransferFlags = 0;
816 UINT32 OutputBufferSize = 0;
817 const BOOL noAck = (RequestField & 0x80000000U) != 0;
818 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
820 if (!pdev || !callback || !s || !udevman)
821 return ERROR_INVALID_PARAMETER;
823 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
824 return ERROR_INVALID_DATA;
826 Stream_Read_UINT32(s, PipeHandle);
827 Stream_Read_UINT32(s, TransferFlags);
828 Stream_Read_UINT32(s, OutputBufferSize);
829 EndpointAddress = (PipeHandle & 0x000000ff);
831 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
833 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
835 return ERROR_INVALID_DATA;
840 const int rc = pdev->bulk_or_interrupt_transfer(
841 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
843 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
844 urb_bulk_transfer_cb, 10000);
849static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
851 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
852 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
853 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
857 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
858 Stream_ResetPosition(out);
860 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
861 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
863 Stream_Free(out, TRUE);
867 Stream_Write_UINT32(out, RequestId);
868 Stream_Write_UINT32(out, 20 + packetSize);
869 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
872 Stream_Free(out, TRUE);
876 Stream_Write_UINT32(out, StartFrame);
881 Stream_Write_UINT32(out, NumberOfPackets);
882 Stream_Write_UINT32(out, ErrorCount);
883 Stream_Seek(out, packetSize);
887 Stream_Write_UINT32(out, 0);
888 Stream_Write_UINT32(out, ErrorCount);
891 Stream_Write_UINT32(out, 0);
892 Stream_Write_UINT32(out, OutputBufferSize);
893 Stream_Seek(out, OutputBufferSize);
895 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
896 if (rc != CHANNEL_RC_OK)
897 WLog_WARN(TAG,
"stream_write_and_free failed with %" PRIu32, rc);
902 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
906 UINT32 EndpointAddress = 0;
907 UINT32 PipeHandle = 0;
908 UINT32 TransferFlags = 0;
909 UINT32 StartFrame = 0;
910 UINT32 NumberOfPackets = 0;
911 UINT32 ErrorCount = 0;
912 UINT32 OutputBufferSize = 0;
913 BYTE* packetDescriptorData =
nullptr;
914 const BOOL noAck = (RequestField & 0x80000000U) != 0;
915 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
917 if (!pdev || !callback || !udevman)
918 return ERROR_INVALID_PARAMETER;
920 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
921 return ERROR_INVALID_DATA;
923 Stream_Read_UINT32(s, PipeHandle);
924 EndpointAddress = (PipeHandle & 0x000000ff);
925 Stream_Read_UINT32(s, TransferFlags);
926 Stream_Read_UINT32(s, StartFrame);
927 Stream_Read_UINT32(s, NumberOfPackets);
928 Stream_Read_UINT32(s, ErrorCount);
930 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
931 return ERROR_INVALID_DATA;
933 packetDescriptorData = Stream_Pointer(s);
934 Stream_Seek(s, 12ULL * NumberOfPackets);
936 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
937 return ERROR_INVALID_DATA;
938 Stream_Read_UINT32(s, OutputBufferSize);
940 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
942 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
943 return ERROR_INVALID_DATA;
946 rc = pdev->isoch_transfer(
947 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
948 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
949 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr,
950 urb_isoch_transfer_cb, 2000);
953 return ERROR_INTERNAL_ERROR;
958 wStream* s, UINT32 RequestField, UINT32 MessageId,
959 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
962 UINT32 InterfaceId = 0;
963 UINT32 OutputBufferSize = 0;
964 UINT32 usbd_status = 0;
965 BYTE bmRequestType = 0;
971 const BOOL noAck = (RequestField & 0x80000000U) != 0;
972 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
974 if (!callback || !s || !udevman || !pdev)
975 return ERROR_INVALID_PARAMETER;
980 return ERROR_INVALID_PARAMETER;
982 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
983 return ERROR_INVALID_DATA;
985 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
986 Stream_Read_UINT8(s, desc_index);
987 Stream_Read_UINT8(s, desc_type);
988 Stream_Read_UINT16(s, langId);
989 Stream_Read_UINT32(s, OutputBufferSize);
990 if (OutputBufferSize > UINT32_MAX - 36)
991 return ERROR_INVALID_DATA;
992 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
994 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
995 return ERROR_INVALID_DATA;
998 out_size = 36ULL + OutputBufferSize;
999 out = Stream_New(
nullptr, out_size);
1002 return ERROR_OUTOFMEMORY;
1004 Stream_Seek(out, 36);
1005 bmRequestType = func_recipient;
1007 switch (transferDir)
1009 case USBD_TRANSFER_DIRECTION_IN:
1010 bmRequestType |= 0x80;
1013 case USBD_TRANSFER_DIRECTION_OUT:
1014 bmRequestType |= 0x00;
1015 Stream_Copy(s, out, OutputBufferSize);
1016 Stream_Rewind(out, OutputBufferSize);
1020 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1021 OutputBufferSize = 0;
1022 usbd_status = USBD_STATUS_STALL_PID;
1027 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1029 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1030 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1032 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1033 Stream_Free(out, TRUE);
1034 return ERROR_INTERNAL_ERROR;
1037 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1038 usbd_status, OutputBufferSize);
1042 wStream* s, UINT32 RequestField, UINT32 MessageId,
1043 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1045 size_t out_size = 0;
1046 UINT32 InterfaceId = 0;
1047 UINT32 OutputBufferSize = 0;
1048 UINT32 usbd_status = 0;
1050 BYTE bmRequestType = 0;
1053 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1054 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1056 if (!callback || !s || !udevman || !pdev)
1057 return ERROR_INVALID_PARAMETER;
1062 return ERROR_INVALID_PARAMETER;
1064 if (transferDir == 0)
1066 WLog_Print(urbdrc->log, WLOG_DEBUG,
1067 "urb_control_get_status_request: transfer out not supported");
1068 return ERROR_INVALID_PARAMETER;
1071 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1072 return ERROR_INVALID_DATA;
1074 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1075 Stream_Read_UINT16(s, Index);
1077 Stream_Read_UINT32(s, OutputBufferSize);
1078 if (OutputBufferSize > UINT32_MAX - 36)
1079 return ERROR_INVALID_DATA;
1080 out_size = 36ULL + OutputBufferSize;
1081 out = Stream_New(
nullptr, out_size);
1084 return ERROR_OUTOFMEMORY;
1086 Stream_Seek(out, 36);
1087 bmRequestType = func_recipient | 0x80;
1089 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1090 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1093 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1094 Stream_Free(out, TRUE);
1095 return ERROR_INTERNAL_ERROR;
1098 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1099 usbd_status, OutputBufferSize);
1103 wStream* s, UINT32 RequestField, UINT32 MessageId,
1104 IUDEVMAN* udevman, BYTE func_type,
1105 BYTE func_recipient,
int transferDir)
1107 UINT32 out_size = 0;
1108 UINT32 InterfaceId = 0;
1109 UINT32 TransferFlags = 0;
1110 UINT32 usbd_status = 0;
1111 UINT32 OutputBufferSize = 0;
1112 BYTE ReqTypeReservedBits = 0;
1114 BYTE bmRequestType = 0;
1119 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1120 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1122 if (!callback || !s || !udevman || !pdev)
1123 return ERROR_INVALID_PARAMETER;
1128 return ERROR_INVALID_PARAMETER;
1130 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1131 return ERROR_INVALID_DATA;
1133 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1134 Stream_Read_UINT32(s, TransferFlags);
1135 Stream_Read_UINT8(s, ReqTypeReservedBits);
1136 Stream_Read_UINT8(s, Request);
1137 Stream_Read_UINT16(s, Value);
1138 Stream_Read_UINT16(s, Index);
1139 Stream_Seek_UINT16(s);
1140 Stream_Read_UINT32(s, OutputBufferSize);
1141 if (OutputBufferSize > UINT32_MAX - 36)
1142 return ERROR_INVALID_DATA;
1144 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1146 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1147 return ERROR_INVALID_DATA;
1150 out_size = 36ULL + OutputBufferSize;
1151 out = Stream_New(
nullptr, out_size);
1154 return ERROR_OUTOFMEMORY;
1156 Stream_Seek(out, 36);
1159 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1161 Stream_Copy(s, out, OutputBufferSize);
1162 Stream_Rewind(out, OutputBufferSize);
1166 bmRequestType = func_type | func_recipient;
1168 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1169 bmRequestType |= 0x80;
1171 WLog_Print(urbdrc->log, WLOG_DEBUG,
1172 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1174 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1175 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1176 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1177 OutputBufferSize, bmRequestType);
1179 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1180 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1182 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1183 Stream_Free(out, TRUE);
1184 return ERROR_INTERNAL_ERROR;
1187 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1188 usbd_status, OutputBufferSize);
1192 wStream* s, UINT32 RequestField, UINT32 MessageId,
1193 IUDEVMAN* udevman,
int transferDir)
1195 size_t out_size = 0;
1196 UINT32 InterfaceId = 0;
1197 UINT32 OutputBufferSize = 0;
1198 UINT32 usbd_status = 0;
1200 BYTE InterfaceNumber = 0;
1201 BYTE Ms_PageIndex = 0;
1202 UINT16 Ms_featureDescIndex = 0;
1206 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1207 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1209 if (!callback || !s || !udevman || !pdev)
1210 return ERROR_INVALID_PARAMETER;
1215 return ERROR_INVALID_PARAMETER;
1217 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1218 return ERROR_INVALID_DATA;
1221 Stream_Read_UINT8(s, Recipient);
1222 Recipient = (Recipient & 0x1f);
1223 Stream_Read_UINT8(s, InterfaceNumber);
1224 Stream_Read_UINT8(s, Ms_PageIndex);
1225 Stream_Read_UINT16(s, Ms_featureDescIndex);
1227 Stream_Read_UINT32(s, OutputBufferSize);
1228 if (OutputBufferSize > UINT32_MAX - 36)
1229 return ERROR_INVALID_DATA;
1231 switch (transferDir)
1233 case USBD_TRANSFER_DIRECTION_OUT:
1234 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1235 return ERROR_INVALID_DATA;
1243 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1244 out_size = 36ULL + OutputBufferSize;
1245 out = Stream_New(
nullptr, out_size);
1248 return ERROR_OUTOFMEMORY;
1250 Stream_Seek(out, 36);
1252 switch (transferDir)
1254 case USBD_TRANSFER_DIRECTION_OUT:
1255 Stream_Copy(s, out, OutputBufferSize);
1256 Stream_Rewind(out, OutputBufferSize);
1259 case USBD_TRANSFER_DIRECTION_IN:
1265 WLog_Print(urbdrc->log, WLOG_DEBUG,
1266 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1267 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1268 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1269 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1271 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1272 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1273 &OutputBufferSize, Stream_Pointer(out), 1000);
1276 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1278 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1279 usbd_status, OutputBufferSize);
1283 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1284 int transferDir,
int action)
1286 UINT32 usbd_status = 0;
1287 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1289 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1290 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1292 if (!callback || !s || !udevman || !pdev)
1293 return ERROR_INVALID_PARAMETER;
1298 return ERROR_INVALID_PARAMETER;
1300 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1301 return ERROR_INVALID_DATA;
1303 if (transferDir == 0)
1305 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1306 return ERROR_INVALID_PARAMETER;
1309 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1310 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1311 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1312 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1314 if (OutputBufferSize != 0)
1316 WLog_Print(urbdrc->log, WLOG_DEBUG,
1317 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32
" != 0",
1319 return ERROR_BAD_CONFIGURATION;
1325 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1329 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1331 ret = USBD_STATUS_SUCCESS;
1336 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1338 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1342 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1344 ret = USBD_STATUS_SUCCESS;
1349 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1351 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1357 wStream* out = Stream_New(
nullptr, 36);
1360 return ERROR_OUTOFMEMORY;
1362 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1367 UINT32 RequestId, UINT32 MessageId,
1368 UINT32 CompletionId, UINT32 FrameNumber)
1370 WINPR_ASSERT(callback);
1372 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1374 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1377 return ERROR_OUTOFMEMORY;
1379 Stream_Write_UINT32(out, 12);
1380 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1382 Stream_Free(out, TRUE);
1383 return ERROR_OUTOFMEMORY;
1386 Stream_Write_UINT32(out, FrameNumber);
1387 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1391 wStream* s, UINT32 RequestField, UINT32 MessageId,
1392 IUDEVMAN* udevman,
int transferDir)
1394 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1395 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1397 if (!callback || !s || !udevman || !pdev)
1398 return ERROR_INVALID_PARAMETER;
1403 return ERROR_INVALID_PARAMETER;
1405 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1406 return ERROR_INVALID_DATA;
1408 if (transferDir == 0)
1410 WLog_Print(urbdrc->log, WLOG_DEBUG,
1411 "urb_get_current_frame_number: not support transfer out");
1412 return ERROR_INVALID_PARAMETER;
1415 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1416 if (OutputBufferSize != 0)
1418 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1422 const UINT32 dummy_frames = GetTickCount();
1423 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1426 return CHANNEL_RC_OK;
1428 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1433static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1435 UINT32 RequestField, UINT32 MessageId,
1436 IUDEVMAN* udevman,
int transferDir)
1438 size_t out_size = 0;
1439 UINT32 InterfaceId = 0;
1440 UINT32 OutputBufferSize = 0;
1441 UINT32 usbd_status = 0;
1444 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1445 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1447 if (!callback || !s || !udevman || !pdev)
1448 return ERROR_INVALID_PARAMETER;
1453 return ERROR_INVALID_PARAMETER;
1455 if (transferDir == 0)
1457 WLog_Print(urbdrc->log, WLOG_DEBUG,
1458 "urb_control_get_configuration_request:"
1459 " not support transfer out");
1460 return ERROR_INVALID_PARAMETER;
1463 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1464 return ERROR_INVALID_DATA;
1466 Stream_Read_UINT32(s, OutputBufferSize);
1467 if (OutputBufferSize > UINT32_MAX - 36)
1468 return ERROR_INVALID_DATA;
1469 out_size = 36ULL + OutputBufferSize;
1470 out = Stream_New(
nullptr, out_size);
1473 return ERROR_OUTOFMEMORY;
1475 Stream_Seek(out, 36);
1476 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1478 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1480 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1482 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1483 Stream_Free(out, TRUE);
1484 return ERROR_INTERNAL_ERROR;
1487 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1488 usbd_status, OutputBufferSize);
1493 wStream* s, UINT32 RequestField, UINT32 MessageId,
1494 IUDEVMAN* udevman,
int transferDir)
1496 size_t out_size = 0;
1497 UINT32 InterfaceId = 0;
1498 UINT32 OutputBufferSize = 0;
1499 UINT32 usbd_status = 0;
1500 UINT16 InterfaceNr = 0;
1503 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1504 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1506 if (!callback || !s || !udevman || !pdev)
1507 return ERROR_INVALID_PARAMETER;
1512 return ERROR_INVALID_PARAMETER;
1514 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1515 return ERROR_INVALID_DATA;
1517 if (transferDir == 0)
1519 WLog_Print(urbdrc->log, WLOG_DEBUG,
1520 "urb_control_get_interface_request: not support transfer out");
1521 return ERROR_INVALID_PARAMETER;
1524 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1525 Stream_Read_UINT16(s, InterfaceNr);
1527 Stream_Read_UINT32(s, OutputBufferSize);
1528 if (OutputBufferSize > UINT32_MAX - 36)
1529 return ERROR_INVALID_DATA;
1530 out_size = 36ULL + OutputBufferSize;
1531 out = Stream_New(
nullptr, out_size);
1534 return ERROR_OUTOFMEMORY;
1536 Stream_Seek(out, 36);
1538 if (!pdev->control_transfer(
1539 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1540 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1542 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1543 Stream_Free(out, TRUE);
1544 return ERROR_INTERNAL_ERROR;
1547 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1548 usbd_status, OutputBufferSize);
1552 wStream* s, UINT32 RequestField, UINT32 MessageId,
1553 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1556 UINT32 InterfaceId = 0;
1557 UINT32 OutputBufferSize = 0;
1558 UINT32 usbd_status = 0;
1559 UINT16 FeatureSelector = 0;
1561 BYTE bmRequestType = 0;
1565 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1566 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1568 if (!callback || !s || !udevman || !pdev)
1569 return ERROR_INVALID_PARAMETER;
1574 return ERROR_INVALID_PARAMETER;
1576 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1577 return ERROR_INVALID_DATA;
1579 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1580 Stream_Read_UINT16(s, FeatureSelector);
1581 Stream_Read_UINT16(s, Index);
1582 Stream_Read_UINT32(s, OutputBufferSize);
1583 if (OutputBufferSize > UINT32_MAX - 36)
1584 return ERROR_INVALID_DATA;
1585 switch (transferDir)
1587 case USBD_TRANSFER_DIRECTION_OUT:
1588 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1589 return ERROR_INVALID_DATA;
1597 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1600 return ERROR_OUTOFMEMORY;
1602 Stream_Seek(out, 36);
1603 bmRequestType = func_recipient;
1605 switch (transferDir)
1607 case USBD_TRANSFER_DIRECTION_OUT:
1608 WLog_Print(urbdrc->log, WLOG_ERROR,
1609 "Function urb_control_feature_request: OUT Unchecked");
1610 Stream_Copy(s, out, OutputBufferSize);
1611 Stream_Rewind(out, OutputBufferSize);
1612 bmRequestType |= 0x00;
1615 case USBD_TRANSFER_DIRECTION_IN:
1616 bmRequestType |= 0x80;
1624 case URB_SET_FEATURE:
1628 case URB_CLEAR_FEATURE:
1633 WLog_Print(urbdrc->log, WLOG_ERROR,
1634 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1635 Stream_Free(out, TRUE);
1636 return ERROR_INTERNAL_ERROR;
1639 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1640 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1642 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1643 Stream_Free(out, TRUE);
1644 return ERROR_INTERNAL_ERROR;
1647 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1648 usbd_status, OutputBufferSize);
1652 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1657 UINT16 URB_Function = 0;
1658 UINT32 RequestId = 0;
1659 UINT error = ERROR_INTERNAL_ERROR;
1662 if (!callback || !s || !udevman || !pdev)
1663 return ERROR_INVALID_PARAMETER;
1668 return ERROR_INVALID_PARAMETER;
1670 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1671 return ERROR_INVALID_DATA;
1673 Stream_Read_UINT32(s, CbTsUrb);
1674 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1675 return ERROR_INVALID_DATA;
1676 Stream_Read_UINT16(s, Size);
1677 if (Size != CbTsUrb)
1679 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1680 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1681 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1683 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1684 " != %s::CbTsUrb 0x%08" PRIx32,
1685 Size, section, CbTsUrb);
1686 return ERROR_INVALID_DATA;
1688 Stream_Read_UINT16(s, URB_Function);
1689 Stream_Read_UINT32(s, RequestId);
1690 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1693 switch (URB_Function)
1695 case TS_URB_SELECT_CONFIGURATION:
1696 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1700 case TS_URB_SELECT_INTERFACE:
1702 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1705 case TS_URB_PIPE_REQUEST:
1706 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1710 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1716 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1722 case TS_URB_GET_FRAME_LENGTH:
1728 case TS_URB_SET_FRAME_LENGTH:
1734 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1735 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1739 case TS_URB_CONTROL_TRANSFER:
1740 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1741 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1744 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1745 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1749 case TS_URB_ISOCH_TRANSFER:
1751 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1754 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1755 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1759 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1760 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1764 case TS_URB_SET_FEATURE_TO_DEVICE:
1765 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1766 0x00, URB_SET_FEATURE, transferDir);
1769 case TS_URB_SET_FEATURE_TO_INTERFACE:
1770 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1771 0x01, URB_SET_FEATURE, transferDir);
1774 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1775 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1776 0x02, URB_SET_FEATURE, transferDir);
1779 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1780 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1781 0x00, URB_CLEAR_FEATURE, transferDir);
1784 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1785 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1786 0x01, URB_CLEAR_FEATURE, transferDir);
1789 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1790 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1791 0x02, URB_CLEAR_FEATURE, transferDir);
1794 case TS_URB_GET_STATUS_FROM_DEVICE:
1795 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1799 case TS_URB_GET_STATUS_FROM_INTERFACE:
1800 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1804 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1805 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1809 case TS_URB_RESERVED_0X0016:
1812 case TS_URB_VENDOR_DEVICE:
1813 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1814 udevman, (0x02u << 5),
1818 case TS_URB_VENDOR_INTERFACE:
1819 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1820 udevman, (0x02u << 5),
1824 case TS_URB_VENDOR_ENDPOINT:
1825 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1826 udevman, (0x02u << 5),
1830 case TS_URB_CLASS_DEVICE:
1831 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1832 udevman, (0x01u << 5),
1836 case TS_URB_CLASS_INTERFACE:
1837 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1838 udevman, (0x01u << 5),
1842 case TS_URB_CLASS_ENDPOINT:
1843 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1844 udevman, (0x01u << 5),
1848 case TS_URB_RESERVE_0X001D:
1851 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1852 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1856 case TS_URB_CLASS_OTHER:
1857 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1858 udevman, (0x01u << 5),
1862 case TS_URB_VENDOR_OTHER:
1863 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1864 udevman, (0x02u << 5),
1868 case TS_URB_GET_STATUS_FROM_OTHER:
1869 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1873 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1874 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1875 0x03, URB_CLEAR_FEATURE, transferDir);
1878 case TS_URB_SET_FEATURE_TO_OTHER:
1879 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1880 0x03, URB_SET_FEATURE, transferDir);
1883 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1884 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1888 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1889 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1893 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1894 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1895 udevman, transferDir);
1898 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1899 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1900 udevman, transferDir);
1903 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1904 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1908 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1909 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1913 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1914 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1915 udevman, transferDir);
1918 case TS_URB_RESERVE_0X002B:
1919 case TS_URB_RESERVE_0X002C:
1920 case TS_URB_RESERVE_0X002D:
1921 case TS_URB_RESERVE_0X002E:
1922 case TS_URB_RESERVE_0X002F:
1926 case TS_URB_SYNC_RESET_PIPE:
1927 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1931 case TS_URB_SYNC_CLEAR_STALL:
1932 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1936 case TS_URB_CONTROL_TRANSFER_EX:
1937 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1938 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1942 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
1949 WLog_Print(urbdrc->log, WLOG_WARN,
1950 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1951 urb_function_string(URB_Function), URB_Function, error);
1958 IUDEVMAN* udevman,
wStream* data)
1960 UINT32 InterfaceId = 0;
1961 UINT32 MessageId = 0;
1962 UINT32 FunctionId = 0;
1963 IUDEVICE* pdev =
nullptr;
1964 UINT error = ERROR_INTERNAL_ERROR;
1966 if (!urbdrc || !data || !callback || !udevman)
1969 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1972 Stream_Rewind_UINT32(data);
1974 Stream_Read_UINT32(data, InterfaceId);
1975 Stream_Read_UINT32(data, MessageId);
1976 Stream_Read_UINT32(data, FunctionId);
1978 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1981 if (pdev ==
nullptr)
1983 error = ERROR_SUCCESS;
1988 if (pdev->isChannelClosed(pdev))
1990 error = ERROR_SUCCESS;
1995 if (!pdev->detach_kernel_driver(pdev))
1997 error = ERROR_SUCCESS;
2003 case CANCEL_REQUEST:
2004 error = urbdrc_process_cancel_request(pdev, data, udevman);
2007 case REGISTER_REQUEST_CALLBACK:
2008 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2012 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2015 case INTERNAL_IO_CONTROL:
2016 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2019 case QUERY_DEVICE_TEXT:
2020 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2023 case TRANSFER_IN_REQUEST:
2024 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2025 USBD_TRANSFER_DIRECTION_IN);
2028 case TRANSFER_OUT_REQUEST:
2029 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2030 USBD_TRANSFER_DIRECTION_OUT);
2033 case RETRACT_DEVICE:
2034 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2038 WLog_Print(urbdrc->log, WLOG_WARN,
2039 "urbdrc_process_udev_data_transfer:"
2040 " unknown FunctionId 0x%" PRIX32
"",
2048 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);