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));
704 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
707 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
709 msusb_msinterface_free(MsInterface);
710 return ERROR_INVALID_DATA;
713 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
714 if (OutputBufferSize != 0)
716 WLog_Print(urbdrc->log, WLOG_ERROR,
717 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
720 msusb_msinterface_free(MsInterface);
721 return ERROR_INVALID_DATA;
725 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
728 msusb_msinterface_free(MsInterface);
729 return ERROR_INTERNAL_ERROR;
734 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
735 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
736 return ERROR_BAD_CONFIGURATION;
739 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
740 return ERROR_BAD_CONFIGURATION;
743 return CHANNEL_RC_OK;
745 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface);
749 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
750 int transferDir,
int External)
753 UINT32 InterfaceId = 0;
754 UINT32 EndpointAddress = 0;
755 UINT32 PipeHandle = 0;
756 UINT32 TransferFlags = 0;
757 UINT32 OutputBufferSize = 0;
758 UINT32 usbd_status = 0;
760 BYTE bmRequestType = 0;
765 BYTE* buffer =
nullptr;
768 const BOOL noAck = (RequestField & 0x80000000U) != 0;
769 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
771 if (!callback || !s || !udevman || !pdev)
772 return ERROR_INVALID_PARAMETER;
777 return ERROR_INVALID_PARAMETER;
779 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
780 return ERROR_INVALID_DATA;
782 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
783 Stream_Read_UINT32(s, PipeHandle);
784 Stream_Read_UINT32(s, TransferFlags);
785 EndpointAddress = (PipeHandle & 0x000000ff);
790 case URB_CONTROL_TRANSFER_EXTERNAL:
791 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
792 return ERROR_INVALID_DATA;
794 Stream_Read_UINT32(s, Timeout);
797 case URB_CONTROL_TRANSFER_NONEXTERNAL:
804 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
805 return ERROR_INVALID_DATA;
807 Stream_Read_UINT8(s, bmRequestType);
808 Stream_Read_UINT8(s, Request);
809 Stream_Read_UINT16(s, Value);
810 Stream_Read_UINT16(s, Index);
811 Stream_Read_UINT16(s, length);
812 Stream_Read_UINT32(s, OutputBufferSize);
814 if (length != OutputBufferSize)
816 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
817 return ERROR_INVALID_DATA;
820 out_size = 36 + OutputBufferSize;
821 out = Stream_New(
nullptr, out_size);
824 return ERROR_OUTOFMEMORY;
826 Stream_Seek(out, 36);
828 buffer = Stream_Pointer(out);
830 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
832 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
834 Stream_Free(out, TRUE);
835 return ERROR_INVALID_DATA;
837 Stream_Copy(s, out, OutputBufferSize);
841 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
842 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
845 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
846 Stream_Free(out, TRUE);
847 return ERROR_INTERNAL_ERROR;
850 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
851 usbd_status, OutputBufferSize, transferDir);
855 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
856 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
857 WINPR_ATTR_UNUSED UINT32 StartFrame,
858 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize,
861 if (!pdev->isChannelClosed(pdev))
862 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
863 OutputBufferSize, transferDir);
865 Stream_Free(out, TRUE);
869 wStream* s, UINT32 RequestField, UINT32 MessageId,
870 IUDEVMAN* udevman,
int transferDir)
872 UINT32 EndpointAddress = 0;
873 UINT32 PipeHandle = 0;
874 UINT32 TransferFlags = 0;
875 UINT32 OutputBufferSize = 0;
876 const BOOL noAck = (RequestField & 0x80000000U) != 0;
877 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
879 if (!pdev || !callback || !s || !udevman)
880 return ERROR_INVALID_PARAMETER;
882 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
883 return ERROR_INVALID_DATA;
885 Stream_Read_UINT32(s, PipeHandle);
886 Stream_Read_UINT32(s, TransferFlags);
887 Stream_Read_UINT32(s, OutputBufferSize);
888 EndpointAddress = (PipeHandle & 0x000000ff);
890 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
892 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
894 return ERROR_INVALID_DATA;
899 const int rc = pdev->bulk_or_interrupt_transfer(
900 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
902 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
903 urb_bulk_transfer_cb, 10000);
908static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
910 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
911 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
912 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize,
917 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
918 const UINT32 payloadSize = urb_completion_payload_size(transferDir, OutputBufferSize);
919 Stream_ResetPosition(out);
921 const UINT32 FunctionId = (payloadSize != 0) ? URB_COMPLETION : URB_COMPLETION_NO_DATA;
922 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
924 Stream_Free(out, TRUE);
928 Stream_Write_UINT32(out, RequestId);
929 Stream_Write_UINT32(out, 20 + packetSize);
930 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
933 Stream_Free(out, TRUE);
937 Stream_Write_UINT32(out, StartFrame);
942 Stream_Write_UINT32(out, NumberOfPackets);
943 Stream_Write_UINT32(out, ErrorCount);
944 Stream_Seek(out, packetSize);
948 Stream_Write_UINT32(out, 0);
949 Stream_Write_UINT32(out, ErrorCount);
952 Stream_Write_UINT32(out, 0);
953 Stream_Write_UINT32(out, OutputBufferSize);
954 Stream_Seek(out, payloadSize);
956 const UINT rc = stream_write_and_free(callback->plugin, callback->channel, out);
957 if (rc != CHANNEL_RC_OK)
958 WLog_WARN(TAG,
"stream_write_and_free failed with %" PRIu32, rc);
963 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
967 UINT32 EndpointAddress = 0;
968 UINT32 PipeHandle = 0;
969 UINT32 TransferFlags = 0;
970 UINT32 StartFrame = 0;
971 UINT32 NumberOfPackets = 0;
972 UINT32 ErrorCount = 0;
973 UINT32 OutputBufferSize = 0;
974 BYTE* packetDescriptorData =
nullptr;
975 const BOOL noAck = (RequestField & 0x80000000U) != 0;
976 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
978 if (!pdev || !callback || !udevman)
979 return ERROR_INVALID_PARAMETER;
981 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
982 return ERROR_INVALID_DATA;
984 Stream_Read_UINT32(s, PipeHandle);
985 EndpointAddress = (PipeHandle & 0x000000ff);
986 Stream_Read_UINT32(s, TransferFlags);
987 Stream_Read_UINT32(s, StartFrame);
988 Stream_Read_UINT32(s, NumberOfPackets);
989 Stream_Read_UINT32(s, ErrorCount);
991 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
992 return ERROR_INVALID_DATA;
994 packetDescriptorData = Stream_Pointer(s);
995 Stream_Seek(s, 12ULL * NumberOfPackets);
997 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
998 return ERROR_INVALID_DATA;
999 Stream_Read_UINT32(s, OutputBufferSize);
1001 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1003 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1004 return ERROR_INVALID_DATA;
1007 rc = pdev->isoch_transfer(
1008 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
1009 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
1010 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : nullptr, transferDir,
1011 urb_isoch_transfer_cb, 2000);
1014 return ERROR_INTERNAL_ERROR;
1019 wStream* s, UINT32 RequestField, UINT32 MessageId,
1020 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1022 size_t out_size = 0;
1023 UINT32 InterfaceId = 0;
1024 UINT32 OutputBufferSize = 0;
1025 UINT32 usbd_status = 0;
1026 BYTE bmRequestType = 0;
1027 BYTE desc_index = 0;
1032 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1033 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1035 if (!callback || !s || !udevman || !pdev)
1036 return ERROR_INVALID_PARAMETER;
1041 return ERROR_INVALID_PARAMETER;
1043 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1044 return ERROR_INVALID_DATA;
1046 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1047 Stream_Read_UINT8(s, desc_index);
1048 Stream_Read_UINT8(s, desc_type);
1049 Stream_Read_UINT16(s, langId);
1050 Stream_Read_UINT32(s, OutputBufferSize);
1051 if (OutputBufferSize > UINT32_MAX - 36)
1052 return ERROR_INVALID_DATA;
1053 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1055 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1056 return ERROR_INVALID_DATA;
1059 out_size = 36ULL + OutputBufferSize;
1060 out = Stream_New(
nullptr, out_size);
1063 return ERROR_OUTOFMEMORY;
1065 Stream_Seek(out, 36);
1066 bmRequestType = func_recipient;
1068 switch (transferDir)
1070 case USBD_TRANSFER_DIRECTION_IN:
1071 bmRequestType |= 0x80;
1074 case USBD_TRANSFER_DIRECTION_OUT:
1075 bmRequestType |= 0x00;
1076 Stream_Copy(s, out, OutputBufferSize);
1077 Stream_Rewind(out, OutputBufferSize);
1081 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1082 OutputBufferSize = 0;
1083 usbd_status = USBD_STATUS_STALL_PID;
1088 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1090 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1091 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1093 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor 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, transferDir);
1103 wStream* s, UINT32 RequestField, UINT32 MessageId,
1104 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1106 size_t out_size = 0;
1107 UINT32 InterfaceId = 0;
1108 UINT32 OutputBufferSize = 0;
1109 UINT32 usbd_status = 0;
1111 BYTE bmRequestType = 0;
1114 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1115 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1117 if (!callback || !s || !udevman || !pdev)
1118 return ERROR_INVALID_PARAMETER;
1123 return ERROR_INVALID_PARAMETER;
1125 if (transferDir == 0)
1127 WLog_Print(urbdrc->log, WLOG_DEBUG,
1128 "urb_control_get_status_request: transfer out not supported");
1129 return ERROR_INVALID_PARAMETER;
1132 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1133 return ERROR_INVALID_DATA;
1135 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1136 Stream_Read_UINT16(s, Index);
1138 Stream_Read_UINT32(s, OutputBufferSize);
1139 if (OutputBufferSize > UINT32_MAX - 36)
1140 return ERROR_INVALID_DATA;
1141 out_size = 36ULL + OutputBufferSize;
1142 out = Stream_New(
nullptr, out_size);
1145 return ERROR_OUTOFMEMORY;
1147 Stream_Seek(out, 36);
1148 bmRequestType = func_recipient | 0x80;
1150 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1151 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1154 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1155 Stream_Free(out, TRUE);
1156 return ERROR_INTERNAL_ERROR;
1159 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1160 usbd_status, OutputBufferSize, transferDir);
1164 wStream* s, UINT32 RequestField, UINT32 MessageId,
1165 IUDEVMAN* udevman, BYTE func_type,
1166 BYTE func_recipient,
int transferDir)
1168 UINT32 out_size = 0;
1169 UINT32 InterfaceId = 0;
1170 UINT32 TransferFlags = 0;
1171 UINT32 usbd_status = 0;
1172 UINT32 OutputBufferSize = 0;
1173 BYTE ReqTypeReservedBits = 0;
1175 BYTE bmRequestType = 0;
1180 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1181 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1183 if (!callback || !s || !udevman || !pdev)
1184 return ERROR_INVALID_PARAMETER;
1189 return ERROR_INVALID_PARAMETER;
1191 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1192 return ERROR_INVALID_DATA;
1194 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1195 Stream_Read_UINT32(s, TransferFlags);
1196 Stream_Read_UINT8(s, ReqTypeReservedBits);
1197 Stream_Read_UINT8(s, Request);
1198 Stream_Read_UINT16(s, Value);
1199 Stream_Read_UINT16(s, Index);
1200 Stream_Seek_UINT16(s);
1201 Stream_Read_UINT32(s, OutputBufferSize);
1202 if (OutputBufferSize > UINT32_MAX - 36)
1203 return ERROR_INVALID_DATA;
1205 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1207 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1208 return ERROR_INVALID_DATA;
1211 out_size = 36ULL + OutputBufferSize;
1212 out = Stream_New(
nullptr, out_size);
1215 return ERROR_OUTOFMEMORY;
1217 Stream_Seek(out, 36);
1220 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1222 Stream_Copy(s, out, OutputBufferSize);
1223 Stream_Rewind(out, OutputBufferSize);
1227 bmRequestType = func_type | func_recipient;
1229 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1230 bmRequestType |= 0x80;
1232 WLog_Print(urbdrc->log, WLOG_DEBUG,
1233 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1235 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1236 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1237 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1238 OutputBufferSize, bmRequestType);
1240 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1241 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1243 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1244 Stream_Free(out, TRUE);
1245 return ERROR_INTERNAL_ERROR;
1248 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1249 usbd_status, OutputBufferSize, transferDir);
1253 wStream* s, UINT32 RequestField, UINT32 MessageId,
1254 IUDEVMAN* udevman,
int transferDir)
1256 size_t out_size = 0;
1257 UINT32 InterfaceId = 0;
1258 UINT32 OutputBufferSize = 0;
1259 UINT32 usbd_status = 0;
1261 BYTE InterfaceNumber = 0;
1262 BYTE Ms_PageIndex = 0;
1263 UINT16 Ms_featureDescIndex = 0;
1267 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1268 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1270 if (!callback || !s || !udevman || !pdev)
1271 return ERROR_INVALID_PARAMETER;
1276 return ERROR_INVALID_PARAMETER;
1278 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1279 return ERROR_INVALID_DATA;
1282 Stream_Read_UINT8(s, Recipient);
1283 Recipient = (Recipient & 0x1f);
1284 Stream_Read_UINT8(s, InterfaceNumber);
1285 Stream_Read_UINT8(s, Ms_PageIndex);
1286 Stream_Read_UINT16(s, Ms_featureDescIndex);
1288 Stream_Read_UINT32(s, OutputBufferSize);
1289 if (OutputBufferSize > UINT32_MAX - 36)
1290 return ERROR_INVALID_DATA;
1292 switch (transferDir)
1294 case USBD_TRANSFER_DIRECTION_OUT:
1295 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1296 return ERROR_INVALID_DATA;
1304 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1305 out_size = 36ULL + OutputBufferSize;
1306 out = Stream_New(
nullptr, out_size);
1309 return ERROR_OUTOFMEMORY;
1311 Stream_Seek(out, 36);
1313 switch (transferDir)
1315 case USBD_TRANSFER_DIRECTION_OUT:
1316 Stream_Copy(s, out, OutputBufferSize);
1317 Stream_Rewind(out, OutputBufferSize);
1320 case USBD_TRANSFER_DIRECTION_IN:
1326 WLog_Print(urbdrc->log, WLOG_DEBUG,
1327 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1328 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1329 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1330 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1332 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1333 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1334 &OutputBufferSize, Stream_Pointer(out), 1000);
1337 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1339 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1340 usbd_status, OutputBufferSize, transferDir);
1344 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1345 int transferDir,
int action)
1347 UINT32 usbd_status = 0;
1348 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1350 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1351 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1353 if (!callback || !s || !udevman || !pdev)
1354 return ERROR_INVALID_PARAMETER;
1359 return ERROR_INVALID_PARAMETER;
1361 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1362 return ERROR_INVALID_DATA;
1364 if (transferDir == 0)
1366 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1367 return ERROR_INVALID_PARAMETER;
1370 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1371 const UINT32 PipeHandle = Stream_Get_UINT32(s);
1372 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1373 const UINT32 EndpointAddress = (PipeHandle & 0x000000ff);
1375 if (OutputBufferSize != 0)
1377 WLog_Print(urbdrc->log, WLOG_DEBUG,
1378 "2.2.9.4 TS_URB_PIPE_REQUEST OutputBufferSize %" PRIu32
" != 0",
1380 return ERROR_BAD_CONFIGURATION;
1386 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1390 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1392 ret = USBD_STATUS_SUCCESS;
1397 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1399 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1403 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1405 ret = USBD_STATUS_SUCCESS;
1410 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1412 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1418 wStream* out = Stream_New(
nullptr, 36);
1421 return ERROR_OUTOFMEMORY;
1423 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1428 UINT32 RequestId, UINT32 MessageId,
1429 UINT32 CompletionId, UINT32 FrameNumber)
1431 WINPR_ASSERT(callback);
1433 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1435 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1438 return ERROR_OUTOFMEMORY;
1440 if (!Stream_EnsureRemainingCapacity(out, 4))
1442 Stream_Write_UINT32(out, 12);
1443 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1445 Stream_Write_UINT32(out, FrameNumber);
1446 return send_urb_completion_message(callback, out, 0, 0,
nullptr);
1449 Stream_Free(out, TRUE);
1450 return ERROR_OUTOFMEMORY;
1454 wStream* s, UINT32 RequestField, UINT32 MessageId,
1455 IUDEVMAN* udevman,
int transferDir)
1457 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1458 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1460 if (!callback || !s || !udevman || !pdev)
1461 return ERROR_INVALID_PARAMETER;
1466 return ERROR_INVALID_PARAMETER;
1468 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1469 return ERROR_INVALID_DATA;
1471 if (transferDir == 0)
1473 WLog_Print(urbdrc->log, WLOG_DEBUG,
1474 "urb_get_current_frame_number: not support transfer out");
1475 return ERROR_INVALID_PARAMETER;
1478 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1479 if (OutputBufferSize != 0)
1481 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1485 const UINT32 dummy_frames = GetTickCount();
1486 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1489 return CHANNEL_RC_OK;
1491 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1496static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1498 UINT32 RequestField, UINT32 MessageId,
1499 IUDEVMAN* udevman,
int transferDir)
1501 size_t out_size = 0;
1502 UINT32 InterfaceId = 0;
1503 UINT32 OutputBufferSize = 0;
1504 UINT32 usbd_status = 0;
1507 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1508 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1510 if (!callback || !s || !udevman || !pdev)
1511 return ERROR_INVALID_PARAMETER;
1516 return ERROR_INVALID_PARAMETER;
1518 if (transferDir == 0)
1520 WLog_Print(urbdrc->log, WLOG_DEBUG,
1521 "urb_control_get_configuration_request:"
1522 " not support transfer out");
1523 return ERROR_INVALID_PARAMETER;
1526 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1527 return ERROR_INVALID_DATA;
1529 Stream_Read_UINT32(s, OutputBufferSize);
1530 if (OutputBufferSize > UINT32_MAX - 36)
1531 return ERROR_INVALID_DATA;
1532 out_size = 36ULL + OutputBufferSize;
1533 out = Stream_New(
nullptr, out_size);
1536 return ERROR_OUTOFMEMORY;
1538 Stream_Seek(out, 36);
1539 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1541 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1543 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1545 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1546 Stream_Free(out, TRUE);
1547 return ERROR_INTERNAL_ERROR;
1550 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1551 usbd_status, OutputBufferSize, transferDir);
1556 wStream* s, UINT32 RequestField, UINT32 MessageId,
1557 IUDEVMAN* udevman,
int transferDir)
1559 size_t out_size = 0;
1560 UINT32 InterfaceId = 0;
1561 UINT32 OutputBufferSize = 0;
1562 UINT32 usbd_status = 0;
1563 UINT16 InterfaceNr = 0;
1566 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1567 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1569 if (!callback || !s || !udevman || !pdev)
1570 return ERROR_INVALID_PARAMETER;
1575 return ERROR_INVALID_PARAMETER;
1577 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1578 return ERROR_INVALID_DATA;
1580 if (transferDir == 0)
1582 WLog_Print(urbdrc->log, WLOG_DEBUG,
1583 "urb_control_get_interface_request: not support transfer out");
1584 return ERROR_INVALID_PARAMETER;
1587 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1588 Stream_Read_UINT16(s, InterfaceNr);
1590 Stream_Read_UINT32(s, OutputBufferSize);
1591 if (OutputBufferSize > UINT32_MAX - 36)
1592 return ERROR_INVALID_DATA;
1593 out_size = 36ULL + OutputBufferSize;
1594 out = Stream_New(
nullptr, out_size);
1597 return ERROR_OUTOFMEMORY;
1599 Stream_Seek(out, 36);
1601 if (!pdev->control_transfer(
1602 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1603 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1605 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1606 Stream_Free(out, TRUE);
1607 return ERROR_INTERNAL_ERROR;
1610 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1611 usbd_status, OutputBufferSize, transferDir);
1615 wStream* s, UINT32 RequestField, UINT32 MessageId,
1616 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1619 UINT32 InterfaceId = 0;
1620 UINT32 OutputBufferSize = 0;
1621 UINT32 usbd_status = 0;
1622 UINT16 FeatureSelector = 0;
1624 BYTE bmRequestType = 0;
1628 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1629 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1631 if (!callback || !s || !udevman || !pdev)
1632 return ERROR_INVALID_PARAMETER;
1637 return ERROR_INVALID_PARAMETER;
1639 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1640 return ERROR_INVALID_DATA;
1642 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1643 Stream_Read_UINT16(s, FeatureSelector);
1644 Stream_Read_UINT16(s, Index);
1645 Stream_Read_UINT32(s, OutputBufferSize);
1646 if (OutputBufferSize > UINT32_MAX - 36)
1647 return ERROR_INVALID_DATA;
1648 switch (transferDir)
1650 case USBD_TRANSFER_DIRECTION_OUT:
1651 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1652 return ERROR_INVALID_DATA;
1660 out = Stream_New(
nullptr, 36ULL + OutputBufferSize);
1663 return ERROR_OUTOFMEMORY;
1665 Stream_Seek(out, 36);
1666 bmRequestType = func_recipient;
1668 switch (transferDir)
1670 case USBD_TRANSFER_DIRECTION_OUT:
1671 WLog_Print(urbdrc->log, WLOG_ERROR,
1672 "Function urb_control_feature_request: OUT Unchecked");
1673 Stream_Copy(s, out, OutputBufferSize);
1674 Stream_Rewind(out, OutputBufferSize);
1675 bmRequestType |= 0x00;
1678 case USBD_TRANSFER_DIRECTION_IN:
1679 bmRequestType |= 0x80;
1687 case URB_SET_FEATURE:
1691 case URB_CLEAR_FEATURE:
1696 WLog_Print(urbdrc->log, WLOG_ERROR,
1697 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1698 Stream_Free(out, TRUE);
1699 return ERROR_INTERNAL_ERROR;
1702 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1703 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1705 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1706 Stream_Free(out, TRUE);
1707 return ERROR_INTERNAL_ERROR;
1710 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1711 usbd_status, OutputBufferSize, transferDir);
1715 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1720 UINT16 URB_Function = 0;
1721 UINT32 RequestId = 0;
1722 UINT error = ERROR_INTERNAL_ERROR;
1725 if (!callback || !s || !udevman || !pdev)
1726 return ERROR_INVALID_PARAMETER;
1731 return ERROR_INVALID_PARAMETER;
1733 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1734 return ERROR_INVALID_DATA;
1736 Stream_Read_UINT32(s, CbTsUrb);
1737 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1738 return ERROR_INVALID_DATA;
1739 Stream_Read_UINT16(s, Size);
1740 if (Size != CbTsUrb)
1742 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1743 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1744 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1746 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1747 " != %s::CbTsUrb 0x%08" PRIx32,
1748 Size, section, CbTsUrb);
1749 return ERROR_INVALID_DATA;
1751 Stream_Read_UINT16(s, URB_Function);
1752 Stream_Read_UINT32(s, RequestId);
1753 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1756 switch (URB_Function)
1758 case TS_URB_SELECT_CONFIGURATION:
1759 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1763 case TS_URB_SELECT_INTERFACE:
1765 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1768 case TS_URB_PIPE_REQUEST:
1769 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1773 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1779 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1785 case TS_URB_GET_FRAME_LENGTH:
1791 case TS_URB_SET_FRAME_LENGTH:
1797 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1798 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1802 case TS_URB_CONTROL_TRANSFER:
1803 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1804 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1807 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1808 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1812 case TS_URB_ISOCH_TRANSFER:
1814 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1817 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1818 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1822 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1823 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1827 case TS_URB_SET_FEATURE_TO_DEVICE:
1828 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1829 0x00, URB_SET_FEATURE, transferDir);
1832 case TS_URB_SET_FEATURE_TO_INTERFACE:
1833 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1834 0x01, URB_SET_FEATURE, transferDir);
1837 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1838 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1839 0x02, URB_SET_FEATURE, transferDir);
1842 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1843 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1844 0x00, URB_CLEAR_FEATURE, transferDir);
1847 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1848 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1849 0x01, URB_CLEAR_FEATURE, transferDir);
1852 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1853 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1854 0x02, URB_CLEAR_FEATURE, transferDir);
1857 case TS_URB_GET_STATUS_FROM_DEVICE:
1858 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1862 case TS_URB_GET_STATUS_FROM_INTERFACE:
1863 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1867 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1868 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1872 case TS_URB_RESERVED_0X0016:
1875 case TS_URB_VENDOR_DEVICE:
1876 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1877 udevman, (0x02u << 5),
1881 case TS_URB_VENDOR_INTERFACE:
1882 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1883 udevman, (0x02u << 5),
1887 case TS_URB_VENDOR_ENDPOINT:
1888 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1889 udevman, (0x02u << 5),
1893 case TS_URB_CLASS_DEVICE:
1894 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1895 udevman, (0x01u << 5),
1899 case TS_URB_CLASS_INTERFACE:
1900 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1901 udevman, (0x01u << 5),
1905 case TS_URB_CLASS_ENDPOINT:
1906 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1907 udevman, (0x01u << 5),
1911 case TS_URB_RESERVE_0X001D:
1914 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1915 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1919 case TS_URB_CLASS_OTHER:
1920 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1921 udevman, (0x01u << 5),
1925 case TS_URB_VENDOR_OTHER:
1926 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1927 udevman, (0x02u << 5),
1931 case TS_URB_GET_STATUS_FROM_OTHER:
1932 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1936 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1937 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1938 0x03, URB_CLEAR_FEATURE, transferDir);
1941 case TS_URB_SET_FEATURE_TO_OTHER:
1942 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1943 0x03, URB_SET_FEATURE, transferDir);
1946 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1947 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1951 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1952 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1956 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1957 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1958 udevman, transferDir);
1961 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1962 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1963 udevman, transferDir);
1966 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1967 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1971 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1972 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1976 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1977 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1978 udevman, transferDir);
1981 case TS_URB_RESERVE_0X002B:
1982 case TS_URB_RESERVE_0X002C:
1983 case TS_URB_RESERVE_0X002D:
1984 case TS_URB_RESERVE_0X002E:
1985 case TS_URB_RESERVE_0X002F:
1989 case TS_URB_SYNC_RESET_PIPE:
1990 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1994 case TS_URB_SYNC_CLEAR_STALL:
1995 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1999 case TS_URB_CONTROL_TRANSFER_EX:
2000 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
2001 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
2005 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
2012 WLog_Print(urbdrc->log, WLOG_WARN,
2013 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
2014 urb_function_string(URB_Function), URB_Function, error);
2021 IUDEVMAN* udevman,
wStream* data)
2023 UINT32 InterfaceId = 0;
2024 UINT32 MessageId = 0;
2025 UINT32 FunctionId = 0;
2026 IUDEVICE* pdev =
nullptr;
2027 UINT error = ERROR_INTERNAL_ERROR;
2029 if (!urbdrc || !data || !callback || !udevman)
2032 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
2035 Stream_Rewind_UINT32(data);
2037 Stream_Read_UINT32(data, InterfaceId);
2038 Stream_Read_UINT32(data, MessageId);
2039 Stream_Read_UINT32(data, FunctionId);
2041 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
2044 if (pdev ==
nullptr)
2046 error = ERROR_SUCCESS;
2051 if (pdev->isChannelClosed(pdev))
2053 error = ERROR_SUCCESS;
2058 if (!pdev->detach_kernel_driver(pdev))
2060 error = ERROR_SUCCESS;
2066 case CANCEL_REQUEST:
2067 error = urbdrc_process_cancel_request(pdev, data, udevman);
2070 case REGISTER_REQUEST_CALLBACK:
2071 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2075 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2078 case INTERNAL_IO_CONTROL:
2079 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2082 case QUERY_DEVICE_TEXT:
2083 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2086 case TRANSFER_IN_REQUEST:
2087 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2088 USBD_TRANSFER_DIRECTION_IN);
2091 case TRANSFER_OUT_REQUEST:
2092 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2093 USBD_TRANSFER_DIRECTION_OUT);
2096 case RETRACT_DEVICE:
2097 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2101 WLog_Print(urbdrc->log, WLOG_WARN,
2102 "urbdrc_process_udev_data_transfer:"
2103 " unknown FunctionId 0x%" PRIX32
"",
2111 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);