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_SetPosition(out, 0);
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] = { 0 };
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(IUDEVICE* pdev,
457 UINT32 NumInterfaces = MsConfig->NumInterfaces;
459 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
461 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
462 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
463 pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
469 UINT32 InterfaceId, UINT32 MessageId,
470 UINT32 RequestId, UINT32 UrbStatus,
474 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
476 return ERROR_OUTOFMEMORY;
478 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
479 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
481 if (!Stream_EnsureRemainingCapacity(out, 4))
483 Stream_Write_UINT32(out, usize);
485 if (!write_urb_result_header(out, usize, UrbStatus))
490 msusb_msconfig_write(MsConfig, out);
493 Stream_Write_UINT32(out, 0);
494 Stream_Write_UINT32(out, 0);
497 return send_urb_completion_message(callback, out, 0, 0, NULL);
500 Stream_Free(out, TRUE);
501 return ERROR_OUTOFMEMORY;
505 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
509 UINT32 NumInterfaces = 0;
510 UINT32 usbd_status = 0;
511 BYTE ConfigurationDescriptorIsValid = 0;
513 const BOOL noAck = (RequestField & 0x80000000U) != 0;
514 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
516 if (!callback || !s || !udevman || !pdev)
517 return ERROR_INVALID_PARAMETER;
522 return ERROR_INVALID_PARAMETER;
524 if (transferDir == 0)
526 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
527 return ERROR_INVALID_PARAMETER;
530 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
531 return ERROR_INVALID_DATA;
533 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
534 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
536 Stream_Read_UINT32(s, NumInterfaces);
539 if (ConfigurationDescriptorIsValid)
542 MsConfig = msusb_msconfig_read(s, NumInterfaces);
545 return ERROR_INVALID_DATA;
548 pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
550 func_select_all_interface_for_msconfig(pdev, MsConfig);
552 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
554 msusb_msconfig_free(MsConfig);
560 return CHANNEL_RC_OK;
561 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
562 usbd_status, MsConfig);
567 UINT32 InterfaceId, UINT32 MessageId,
569 UINT32 ConfigurationHandle)
571 WINPR_ASSERT(callback);
572 WINPR_ASSERT(MsInterface);
574 const UINT32 NumInterfaces = 1;
575 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
577 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
580 return ERROR_OUTOFMEMORY;
582 const uint32_t size = 8U + interface_size;
583 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
585 if (!Stream_EnsureRemainingCapacity(out, 4))
587 Stream_Write_UINT32(out, usize);
589 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
592 if (!msusb_msinterface_write(MsInterface, out))
595 if (!Stream_EnsureRemainingCapacity(out, 8))
597 Stream_Write_UINT32(out, ConfigurationHandle);
598 Stream_Write_UINT32(out, NumInterfaces);
600 for (
size_t x = 0; x < NumInterfaces; x++)
603 if (!msusb_msinterface_write(ifc, out))
607 return send_urb_completion_message(callback, out, 0, 0, NULL);
610 Stream_Free(out, TRUE);
612 return ERROR_INTERNAL_ERROR;
616 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
619 const BOOL noAck = (RequestField & 0x80000000U) != 0;
620 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
622 if (!callback || !s || !udevman || !pdev)
623 return ERROR_INVALID_PARAMETER;
628 return ERROR_INVALID_PARAMETER;
630 if (transferDir == 0)
632 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
633 return ERROR_INVALID_PARAMETER;
636 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
637 return ERROR_INVALID_DATA;
639 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
640 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
643 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
645 msusb_msinterface_free(MsInterface);
646 return ERROR_INVALID_DATA;
649 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
650 if (OutputBufferSize != 0)
652 WLog_Print(urbdrc->log, WLOG_ERROR,
653 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
656 msusb_msinterface_free(MsInterface);
657 return ERROR_INVALID_DATA;
660 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
663 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
664 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
665 return ERROR_BAD_CONFIGURATION;
668 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
669 return ERROR_BAD_CONFIGURATION;
672 return CHANNEL_RC_OK;
674 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface,
675 ConfigurationHandle);
679 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
680 int transferDir,
int External)
683 UINT32 InterfaceId = 0;
684 UINT32 EndpointAddress = 0;
685 UINT32 PipeHandle = 0;
686 UINT32 TransferFlags = 0;
687 UINT32 OutputBufferSize = 0;
688 UINT32 usbd_status = 0;
690 BYTE bmRequestType = 0;
698 const BOOL noAck = (RequestField & 0x80000000U) != 0;
699 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
701 if (!callback || !s || !udevman || !pdev)
702 return ERROR_INVALID_PARAMETER;
707 return ERROR_INVALID_PARAMETER;
709 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
710 return ERROR_INVALID_DATA;
712 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
713 Stream_Read_UINT32(s, PipeHandle);
714 Stream_Read_UINT32(s, TransferFlags);
715 EndpointAddress = (PipeHandle & 0x000000ff);
720 case URB_CONTROL_TRANSFER_EXTERNAL:
721 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
722 return ERROR_INVALID_DATA;
724 Stream_Read_UINT32(s, Timeout);
727 case URB_CONTROL_TRANSFER_NONEXTERNAL:
734 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
735 return ERROR_INVALID_DATA;
737 Stream_Read_UINT8(s, bmRequestType);
738 Stream_Read_UINT8(s, Request);
739 Stream_Read_UINT16(s, Value);
740 Stream_Read_UINT16(s, Index);
741 Stream_Read_UINT16(s, length);
742 Stream_Read_UINT32(s, OutputBufferSize);
744 if (length != OutputBufferSize)
746 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
747 return ERROR_INVALID_DATA;
750 out_size = 36 + OutputBufferSize;
751 out = Stream_New(NULL, out_size);
754 return ERROR_OUTOFMEMORY;
756 Stream_Seek(out, 36);
758 buffer = Stream_Pointer(out);
760 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
762 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
764 Stream_Free(out, TRUE);
765 return ERROR_INVALID_DATA;
767 Stream_Copy(s, out, OutputBufferSize);
771 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
772 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
775 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
776 Stream_Free(out, TRUE);
777 return ERROR_INTERNAL_ERROR;
780 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
781 usbd_status, OutputBufferSize);
785 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
786 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
787 WINPR_ATTR_UNUSED UINT32 StartFrame,
788 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
790 if (!pdev->isChannelClosed(pdev))
791 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
794 Stream_Free(out, TRUE);
798 wStream* s, UINT32 RequestField, UINT32 MessageId,
799 IUDEVMAN* udevman,
int transferDir)
801 UINT32 EndpointAddress = 0;
802 UINT32 PipeHandle = 0;
803 UINT32 TransferFlags = 0;
804 UINT32 OutputBufferSize = 0;
805 const BOOL noAck = (RequestField & 0x80000000U) != 0;
806 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
808 if (!pdev || !callback || !s || !udevman)
809 return ERROR_INVALID_PARAMETER;
811 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
812 return ERROR_INVALID_DATA;
814 Stream_Read_UINT32(s, PipeHandle);
815 Stream_Read_UINT32(s, TransferFlags);
816 Stream_Read_UINT32(s, OutputBufferSize);
817 EndpointAddress = (PipeHandle & 0x000000ff);
819 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
821 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
823 return ERROR_INVALID_DATA;
828 const int rc = pdev->bulk_or_interrupt_transfer(
829 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
830 OutputBufferSize, (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
831 urb_bulk_transfer_cb, 10000);
836static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
838 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
839 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
840 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
844 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
845 Stream_SetPosition(out, 0);
847 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
848 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
850 Stream_Free(out, TRUE);
854 Stream_Write_UINT32(out, RequestId);
855 Stream_Write_UINT32(out, 20 + packetSize);
856 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
859 Stream_Free(out, TRUE);
863 Stream_Write_UINT32(out, StartFrame);
868 Stream_Write_UINT32(out, NumberOfPackets);
869 Stream_Write_UINT32(out, ErrorCount);
870 Stream_Seek(out, packetSize);
874 Stream_Write_UINT32(out, 0);
875 Stream_Write_UINT32(out, ErrorCount);
878 Stream_Write_UINT32(out, 0);
879 Stream_Write_UINT32(out, OutputBufferSize);
880 Stream_Seek(out, OutputBufferSize);
882 stream_write_and_free(callback->plugin, callback->channel, out);
887 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
891 UINT32 EndpointAddress = 0;
892 UINT32 PipeHandle = 0;
893 UINT32 TransferFlags = 0;
894 UINT32 StartFrame = 0;
895 UINT32 NumberOfPackets = 0;
896 UINT32 ErrorCount = 0;
897 UINT32 OutputBufferSize = 0;
898 BYTE* packetDescriptorData = NULL;
899 const BOOL noAck = (RequestField & 0x80000000U) != 0;
900 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
902 if (!pdev || !callback || !udevman)
903 return ERROR_INVALID_PARAMETER;
905 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
906 return ERROR_INVALID_DATA;
908 Stream_Read_UINT32(s, PipeHandle);
909 EndpointAddress = (PipeHandle & 0x000000ff);
910 Stream_Read_UINT32(s, TransferFlags);
911 Stream_Read_UINT32(s, StartFrame);
912 Stream_Read_UINT32(s, NumberOfPackets);
913 Stream_Read_UINT32(s, ErrorCount);
915 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
916 return ERROR_INVALID_DATA;
918 packetDescriptorData = Stream_Pointer(s);
919 Stream_Seek(s, 12ULL * NumberOfPackets);
921 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
922 return ERROR_INVALID_DATA;
923 Stream_Read_UINT32(s, OutputBufferSize);
925 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
927 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
928 return ERROR_INVALID_DATA;
931 rc = pdev->isoch_transfer(
932 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
933 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
934 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
935 urb_isoch_transfer_cb, 2000);
938 return ERROR_INTERNAL_ERROR;
943 wStream* s, UINT32 RequestField, UINT32 MessageId,
944 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
947 UINT32 InterfaceId = 0;
948 UINT32 OutputBufferSize = 0;
949 UINT32 usbd_status = 0;
950 BYTE bmRequestType = 0;
956 const BOOL noAck = (RequestField & 0x80000000U) != 0;
957 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
959 if (!callback || !s || !udevman || !pdev)
960 return ERROR_INVALID_PARAMETER;
965 return ERROR_INVALID_PARAMETER;
967 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
968 return ERROR_INVALID_DATA;
970 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
971 Stream_Read_UINT8(s, desc_index);
972 Stream_Read_UINT8(s, desc_type);
973 Stream_Read_UINT16(s, langId);
974 Stream_Read_UINT32(s, OutputBufferSize);
975 if (OutputBufferSize > UINT32_MAX - 36)
976 return ERROR_INVALID_DATA;
977 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
979 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
980 return ERROR_INVALID_DATA;
983 out_size = 36ULL + OutputBufferSize;
984 out = Stream_New(NULL, out_size);
987 return ERROR_OUTOFMEMORY;
989 Stream_Seek(out, 36);
990 bmRequestType = func_recipient;
994 case USBD_TRANSFER_DIRECTION_IN:
995 bmRequestType |= 0x80;
998 case USBD_TRANSFER_DIRECTION_OUT:
999 bmRequestType |= 0x00;
1000 Stream_Copy(s, out, OutputBufferSize);
1001 Stream_Rewind(out, OutputBufferSize);
1005 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1006 OutputBufferSize = 0;
1007 usbd_status = USBD_STATUS_STALL_PID;
1012 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1014 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1015 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1017 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1018 Stream_Free(out, TRUE);
1019 return ERROR_INTERNAL_ERROR;
1022 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1023 usbd_status, OutputBufferSize);
1027 wStream* s, UINT32 RequestField, UINT32 MessageId,
1028 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1030 size_t out_size = 0;
1031 UINT32 InterfaceId = 0;
1032 UINT32 OutputBufferSize = 0;
1033 UINT32 usbd_status = 0;
1035 BYTE bmRequestType = 0;
1038 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1039 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1041 if (!callback || !s || !udevman || !pdev)
1042 return ERROR_INVALID_PARAMETER;
1047 return ERROR_INVALID_PARAMETER;
1049 if (transferDir == 0)
1051 WLog_Print(urbdrc->log, WLOG_DEBUG,
1052 "urb_control_get_status_request: transfer out not supported");
1053 return ERROR_INVALID_PARAMETER;
1056 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1057 return ERROR_INVALID_DATA;
1059 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1060 Stream_Read_UINT16(s, Index);
1062 Stream_Read_UINT32(s, OutputBufferSize);
1063 if (OutputBufferSize > UINT32_MAX - 36)
1064 return ERROR_INVALID_DATA;
1065 out_size = 36ULL + OutputBufferSize;
1066 out = Stream_New(NULL, out_size);
1069 return ERROR_OUTOFMEMORY;
1071 Stream_Seek(out, 36);
1072 bmRequestType = func_recipient | 0x80;
1074 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1075 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1078 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1079 Stream_Free(out, TRUE);
1080 return ERROR_INTERNAL_ERROR;
1083 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1084 usbd_status, OutputBufferSize);
1088 wStream* s, UINT32 RequestField, UINT32 MessageId,
1089 IUDEVMAN* udevman, BYTE func_type,
1090 BYTE func_recipient,
int transferDir)
1092 UINT32 out_size = 0;
1093 UINT32 InterfaceId = 0;
1094 UINT32 TransferFlags = 0;
1095 UINT32 usbd_status = 0;
1096 UINT32 OutputBufferSize = 0;
1097 BYTE ReqTypeReservedBits = 0;
1099 BYTE bmRequestType = 0;
1104 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1105 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1107 if (!callback || !s || !udevman || !pdev)
1108 return ERROR_INVALID_PARAMETER;
1113 return ERROR_INVALID_PARAMETER;
1115 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1116 return ERROR_INVALID_DATA;
1118 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1119 Stream_Read_UINT32(s, TransferFlags);
1120 Stream_Read_UINT8(s, ReqTypeReservedBits);
1121 Stream_Read_UINT8(s, Request);
1122 Stream_Read_UINT16(s, Value);
1123 Stream_Read_UINT16(s, Index);
1124 Stream_Seek_UINT16(s);
1125 Stream_Read_UINT32(s, OutputBufferSize);
1126 if (OutputBufferSize > UINT32_MAX - 36)
1127 return ERROR_INVALID_DATA;
1129 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1131 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1132 return ERROR_INVALID_DATA;
1135 out_size = 36ULL + OutputBufferSize;
1136 out = Stream_New(NULL, out_size);
1139 return ERROR_OUTOFMEMORY;
1141 Stream_Seek(out, 36);
1144 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1146 Stream_Copy(s, out, OutputBufferSize);
1147 Stream_Rewind(out, OutputBufferSize);
1151 bmRequestType = func_type | func_recipient;
1153 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1154 bmRequestType |= 0x80;
1156 WLog_Print(urbdrc->log, WLOG_DEBUG,
1157 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1159 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1160 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1161 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1162 OutputBufferSize, bmRequestType);
1164 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1165 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1167 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1168 Stream_Free(out, TRUE);
1169 return ERROR_INTERNAL_ERROR;
1172 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1173 usbd_status, OutputBufferSize);
1177 wStream* s, UINT32 RequestField, UINT32 MessageId,
1178 IUDEVMAN* udevman,
int transferDir)
1180 size_t out_size = 0;
1181 UINT32 InterfaceId = 0;
1182 UINT32 OutputBufferSize = 0;
1183 UINT32 usbd_status = 0;
1185 BYTE InterfaceNumber = 0;
1186 BYTE Ms_PageIndex = 0;
1187 UINT16 Ms_featureDescIndex = 0;
1191 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1192 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1194 if (!callback || !s || !udevman || !pdev)
1195 return ERROR_INVALID_PARAMETER;
1200 return ERROR_INVALID_PARAMETER;
1202 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1203 return ERROR_INVALID_DATA;
1206 Stream_Read_UINT8(s, Recipient);
1207 Recipient = (Recipient & 0x1f);
1208 Stream_Read_UINT8(s, InterfaceNumber);
1209 Stream_Read_UINT8(s, Ms_PageIndex);
1210 Stream_Read_UINT16(s, Ms_featureDescIndex);
1212 Stream_Read_UINT32(s, OutputBufferSize);
1213 if (OutputBufferSize > UINT32_MAX - 36)
1214 return ERROR_INVALID_DATA;
1216 switch (transferDir)
1218 case USBD_TRANSFER_DIRECTION_OUT:
1219 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1220 return ERROR_INVALID_DATA;
1228 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1229 out_size = 36ULL + OutputBufferSize;
1230 out = Stream_New(NULL, out_size);
1233 return ERROR_OUTOFMEMORY;
1235 Stream_Seek(out, 36);
1237 switch (transferDir)
1239 case USBD_TRANSFER_DIRECTION_OUT:
1240 Stream_Copy(s, out, OutputBufferSize);
1241 Stream_Rewind(out, OutputBufferSize);
1244 case USBD_TRANSFER_DIRECTION_IN:
1250 WLog_Print(urbdrc->log, WLOG_DEBUG,
1251 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1252 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1253 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1254 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1256 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1257 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1258 &OutputBufferSize, Stream_Pointer(out), 1000);
1261 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1263 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1264 usbd_status, OutputBufferSize);
1268 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1269 int transferDir,
int action)
1271 UINT32 out_size = 0;
1272 UINT32 InterfaceId = 0;
1273 UINT32 PipeHandle = 0;
1274 UINT32 EndpointAddress = 0;
1275 UINT32 OutputBufferSize = 0;
1276 UINT32 usbd_status = 0;
1278 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1281 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1282 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1284 if (!callback || !s || !udevman || !pdev)
1285 return ERROR_INVALID_PARAMETER;
1290 return ERROR_INVALID_PARAMETER;
1292 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1293 return ERROR_INVALID_DATA;
1295 if (transferDir == 0)
1297 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1298 return ERROR_INVALID_PARAMETER;
1301 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1302 Stream_Read_UINT32(s, PipeHandle);
1303 Stream_Read_UINT32(s, OutputBufferSize);
1304 EndpointAddress = (PipeHandle & 0x000000ff);
1309 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1313 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1315 ret = USBD_STATUS_SUCCESS;
1320 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1322 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1326 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1328 ret = USBD_STATUS_SUCCESS;
1333 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1335 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1341 if (out_size > OutputBufferSize)
1343 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32,
1344 out_size, OutputBufferSize);
1345 return ERROR_BAD_CONFIGURATION;
1347 out = Stream_New(NULL, out_size);
1350 return ERROR_OUTOFMEMORY;
1352 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1357 UINT32 RequestId, UINT32 MessageId,
1358 UINT32 CompletionId, UINT32 FrameNumber)
1360 WINPR_ASSERT(callback);
1362 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1364 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1367 return ERROR_OUTOFMEMORY;
1369 Stream_Write_UINT32(out, 12);
1370 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1372 Stream_Free(out, TRUE);
1373 return ERROR_OUTOFMEMORY;
1376 Stream_Write_UINT32(out, FrameNumber);
1377 return send_urb_completion_message(callback, out, 0, 0, NULL);
1381 wStream* s, UINT32 RequestField, UINT32 MessageId,
1382 IUDEVMAN* udevman,
int transferDir)
1384 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1385 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1387 if (!callback || !s || !udevman || !pdev)
1388 return ERROR_INVALID_PARAMETER;
1393 return ERROR_INVALID_PARAMETER;
1395 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1396 return ERROR_INVALID_DATA;
1398 if (transferDir == 0)
1400 WLog_Print(urbdrc->log, WLOG_DEBUG,
1401 "urb_get_current_frame_number: not support transfer out");
1402 return ERROR_INVALID_PARAMETER;
1405 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1406 if (OutputBufferSize != 0)
1408 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1412 const UINT32 dummy_frames = GetTickCount();
1413 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1416 return CHANNEL_RC_OK;
1418 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1423static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1425 UINT32 RequestField, UINT32 MessageId,
1426 IUDEVMAN* udevman,
int transferDir)
1428 size_t out_size = 0;
1429 UINT32 InterfaceId = 0;
1430 UINT32 OutputBufferSize = 0;
1431 UINT32 usbd_status = 0;
1434 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1435 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1437 if (!callback || !s || !udevman || !pdev)
1438 return ERROR_INVALID_PARAMETER;
1443 return ERROR_INVALID_PARAMETER;
1445 if (transferDir == 0)
1447 WLog_Print(urbdrc->log, WLOG_DEBUG,
1448 "urb_control_get_configuration_request:"
1449 " not support transfer out");
1450 return ERROR_INVALID_PARAMETER;
1453 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1454 return ERROR_INVALID_DATA;
1456 Stream_Read_UINT32(s, OutputBufferSize);
1457 if (OutputBufferSize > UINT32_MAX - 36)
1458 return ERROR_INVALID_DATA;
1459 out_size = 36ULL + OutputBufferSize;
1460 out = Stream_New(NULL, out_size);
1463 return ERROR_OUTOFMEMORY;
1465 Stream_Seek(out, 36);
1466 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1468 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1470 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1472 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1473 Stream_Free(out, TRUE);
1474 return ERROR_INTERNAL_ERROR;
1477 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1478 usbd_status, OutputBufferSize);
1483 wStream* s, UINT32 RequestField, UINT32 MessageId,
1484 IUDEVMAN* udevman,
int transferDir)
1486 size_t out_size = 0;
1487 UINT32 InterfaceId = 0;
1488 UINT32 OutputBufferSize = 0;
1489 UINT32 usbd_status = 0;
1490 UINT16 InterfaceNr = 0;
1493 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1494 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1496 if (!callback || !s || !udevman || !pdev)
1497 return ERROR_INVALID_PARAMETER;
1502 return ERROR_INVALID_PARAMETER;
1504 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1505 return ERROR_INVALID_DATA;
1507 if (transferDir == 0)
1509 WLog_Print(urbdrc->log, WLOG_DEBUG,
1510 "urb_control_get_interface_request: not support transfer out");
1511 return ERROR_INVALID_PARAMETER;
1514 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1515 Stream_Read_UINT16(s, InterfaceNr);
1517 Stream_Read_UINT32(s, OutputBufferSize);
1518 if (OutputBufferSize > UINT32_MAX - 36)
1519 return ERROR_INVALID_DATA;
1520 out_size = 36ULL + OutputBufferSize;
1521 out = Stream_New(NULL, out_size);
1524 return ERROR_OUTOFMEMORY;
1526 Stream_Seek(out, 36);
1528 if (!pdev->control_transfer(
1529 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1530 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1532 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1533 Stream_Free(out, TRUE);
1534 return ERROR_INTERNAL_ERROR;
1537 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1538 usbd_status, OutputBufferSize);
1542 wStream* s, UINT32 RequestField, UINT32 MessageId,
1543 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1546 UINT32 InterfaceId = 0;
1547 UINT32 OutputBufferSize = 0;
1548 UINT32 usbd_status = 0;
1549 UINT16 FeatureSelector = 0;
1551 BYTE bmRequestType = 0;
1555 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1556 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1558 if (!callback || !s || !udevman || !pdev)
1559 return ERROR_INVALID_PARAMETER;
1564 return ERROR_INVALID_PARAMETER;
1566 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1567 return ERROR_INVALID_DATA;
1569 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1570 Stream_Read_UINT16(s, FeatureSelector);
1571 Stream_Read_UINT16(s, Index);
1572 Stream_Read_UINT32(s, OutputBufferSize);
1573 if (OutputBufferSize > UINT32_MAX - 36)
1574 return ERROR_INVALID_DATA;
1575 switch (transferDir)
1577 case USBD_TRANSFER_DIRECTION_OUT:
1578 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1579 return ERROR_INVALID_DATA;
1587 out = Stream_New(NULL, 36ULL + OutputBufferSize);
1590 return ERROR_OUTOFMEMORY;
1592 Stream_Seek(out, 36);
1593 bmRequestType = func_recipient;
1595 switch (transferDir)
1597 case USBD_TRANSFER_DIRECTION_OUT:
1598 WLog_Print(urbdrc->log, WLOG_ERROR,
1599 "Function urb_control_feature_request: OUT Unchecked");
1600 Stream_Copy(s, out, OutputBufferSize);
1601 Stream_Rewind(out, OutputBufferSize);
1602 bmRequestType |= 0x00;
1605 case USBD_TRANSFER_DIRECTION_IN:
1606 bmRequestType |= 0x80;
1614 case URB_SET_FEATURE:
1618 case URB_CLEAR_FEATURE:
1623 WLog_Print(urbdrc->log, WLOG_ERROR,
1624 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1625 Stream_Free(out, TRUE);
1626 return ERROR_INTERNAL_ERROR;
1629 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1630 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1632 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1633 Stream_Free(out, TRUE);
1634 return ERROR_INTERNAL_ERROR;
1637 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1638 usbd_status, OutputBufferSize);
1642 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1647 UINT16 URB_Function = 0;
1648 UINT32 RequestId = 0;
1649 UINT error = ERROR_INTERNAL_ERROR;
1652 if (!callback || !s || !udevman || !pdev)
1653 return ERROR_INVALID_PARAMETER;
1658 return ERROR_INVALID_PARAMETER;
1660 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1661 return ERROR_INVALID_DATA;
1663 Stream_Read_UINT32(s, CbTsUrb);
1664 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1665 return ERROR_INVALID_DATA;
1666 Stream_Read_UINT16(s, Size);
1667 if (Size != CbTsUrb)
1669 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1670 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1671 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1673 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1674 " != %s::CbTsUrb 0x%08" PRIx32,
1675 Size, section, CbTsUrb);
1676 return ERROR_INVALID_DATA;
1678 Stream_Read_UINT16(s, URB_Function);
1679 Stream_Read_UINT32(s, RequestId);
1680 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1683 switch (URB_Function)
1685 case TS_URB_SELECT_CONFIGURATION:
1686 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1690 case TS_URB_SELECT_INTERFACE:
1692 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1695 case TS_URB_PIPE_REQUEST:
1696 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1700 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1706 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1712 case TS_URB_GET_FRAME_LENGTH:
1718 case TS_URB_SET_FRAME_LENGTH:
1724 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1725 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1729 case TS_URB_CONTROL_TRANSFER:
1730 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1731 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1734 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1735 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1739 case TS_URB_ISOCH_TRANSFER:
1741 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1744 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1745 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1749 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1750 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1754 case TS_URB_SET_FEATURE_TO_DEVICE:
1755 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1756 0x00, URB_SET_FEATURE, transferDir);
1759 case TS_URB_SET_FEATURE_TO_INTERFACE:
1760 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1761 0x01, URB_SET_FEATURE, transferDir);
1764 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1765 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1766 0x02, URB_SET_FEATURE, transferDir);
1769 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1770 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1771 0x00, URB_CLEAR_FEATURE, transferDir);
1774 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1775 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1776 0x01, URB_CLEAR_FEATURE, transferDir);
1779 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1780 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1781 0x02, URB_CLEAR_FEATURE, transferDir);
1784 case TS_URB_GET_STATUS_FROM_DEVICE:
1785 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1789 case TS_URB_GET_STATUS_FROM_INTERFACE:
1790 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1794 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1795 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1799 case TS_URB_RESERVED_0X0016:
1802 case TS_URB_VENDOR_DEVICE:
1803 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1804 udevman, (0x02 << 5),
1808 case TS_URB_VENDOR_INTERFACE:
1809 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1810 udevman, (0x02 << 5),
1814 case TS_URB_VENDOR_ENDPOINT:
1815 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1816 udevman, (0x02 << 5),
1820 case TS_URB_CLASS_DEVICE:
1821 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1822 udevman, (0x01 << 5),
1826 case TS_URB_CLASS_INTERFACE:
1827 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1828 udevman, (0x01 << 5),
1832 case TS_URB_CLASS_ENDPOINT:
1833 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1834 udevman, (0x01 << 5),
1838 case TS_URB_RESERVE_0X001D:
1841 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1842 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1846 case TS_URB_CLASS_OTHER:
1847 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1848 udevman, (0x01 << 5),
1852 case TS_URB_VENDOR_OTHER:
1853 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1854 udevman, (0x02 << 5),
1858 case TS_URB_GET_STATUS_FROM_OTHER:
1859 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1863 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1864 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1865 0x03, URB_CLEAR_FEATURE, transferDir);
1868 case TS_URB_SET_FEATURE_TO_OTHER:
1869 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1870 0x03, URB_SET_FEATURE, transferDir);
1873 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1874 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1878 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1879 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1883 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1884 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1885 udevman, transferDir);
1888 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1889 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1890 udevman, transferDir);
1893 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1894 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1898 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1899 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1903 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1904 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1905 udevman, transferDir);
1908 case TS_URB_RESERVE_0X002B:
1909 case TS_URB_RESERVE_0X002C:
1910 case TS_URB_RESERVE_0X002D:
1911 case TS_URB_RESERVE_0X002E:
1912 case TS_URB_RESERVE_0X002F:
1916 case TS_URB_SYNC_RESET_PIPE:
1917 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1921 case TS_URB_SYNC_CLEAR_STALL:
1922 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1926 case TS_URB_CONTROL_TRANSFER_EX:
1927 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1928 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1932 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
1939 WLog_Print(urbdrc->log, WLOG_WARN,
1940 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1941 urb_function_string(URB_Function), URB_Function, error);
1948 IUDEVMAN* udevman,
wStream* data)
1950 UINT32 InterfaceId = 0;
1951 UINT32 MessageId = 0;
1952 UINT32 FunctionId = 0;
1953 IUDEVICE* pdev = NULL;
1954 UINT error = ERROR_INTERNAL_ERROR;
1956 if (!urbdrc || !data || !callback || !udevman)
1959 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1962 Stream_Rewind_UINT32(data);
1964 Stream_Read_UINT32(data, InterfaceId);
1965 Stream_Read_UINT32(data, MessageId);
1966 Stream_Read_UINT32(data, FunctionId);
1968 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1973 error = ERROR_SUCCESS;
1978 if (pdev->isChannelClosed(pdev))
1980 error = ERROR_SUCCESS;
1985 pdev->detach_kernel_driver(pdev);
1989 case CANCEL_REQUEST:
1990 error = urbdrc_process_cancel_request(pdev, data, udevman);
1993 case REGISTER_REQUEST_CALLBACK:
1994 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
1998 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2001 case INTERNAL_IO_CONTROL:
2002 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2005 case QUERY_DEVICE_TEXT:
2006 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2009 case TRANSFER_IN_REQUEST:
2010 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2011 USBD_TRANSFER_DIRECTION_IN);
2014 case TRANSFER_OUT_REQUEST:
2015 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2016 USBD_TRANSFER_DIRECTION_OUT);
2019 case RETRACT_DEVICE:
2020 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2024 WLog_Print(urbdrc->log, WLOG_WARN,
2025 "urbdrc_process_udev_data_transfer:"
2026 " unknown FunctionId 0x%" PRIX32
"",
2034 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);