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(
URBDRC_PLUGIN* urbdrc, IUDEVICE* pdev,
456 WINPR_ASSERT(urbdrc);
458 WINPR_ASSERT(MsConfig);
461 UINT32 NumInterfaces = MsConfig->NumInterfaces;
463 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
465 const BYTE InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
466 const BYTE AlternateSetting = MsInterfaces[inum]->AlternateSetting;
467 const int rc = pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
470 WLog_Print(urbdrc->log, WLOG_WARN,
"select_interface %" PRIu8
" [%" PRIu8
"] failed",
471 InterfaceNumber, AlternateSetting);
478 UINT32 InterfaceId, UINT32 MessageId,
479 UINT32 RequestId, UINT32 UrbStatus,
483 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
485 return ERROR_OUTOFMEMORY;
487 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
488 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
490 if (!Stream_EnsureRemainingCapacity(out, 4))
492 Stream_Write_UINT32(out, usize);
494 if (!write_urb_result_header(out, usize, UrbStatus))
499 msusb_msconfig_write(MsConfig, out);
502 Stream_Write_UINT32(out, 0);
503 Stream_Write_UINT32(out, 0);
506 return send_urb_completion_message(callback, out, 0, 0, NULL);
509 Stream_Free(out, TRUE);
510 return ERROR_OUTOFMEMORY;
514 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
518 UINT32 NumInterfaces = 0;
519 UINT32 usbd_status = 0;
520 BYTE ConfigurationDescriptorIsValid = 0;
522 const BOOL noAck = (RequestField & 0x80000000U) != 0;
523 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
525 if (!callback || !s || !udevman || !pdev)
526 return ERROR_INVALID_PARAMETER;
531 return ERROR_INVALID_PARAMETER;
533 if (transferDir == 0)
535 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
536 return ERROR_INVALID_PARAMETER;
539 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
540 return ERROR_INVALID_DATA;
542 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
543 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
545 Stream_Read_UINT32(s, NumInterfaces);
548 if (ConfigurationDescriptorIsValid)
551 MsConfig = msusb_msconfig_read(s, NumInterfaces);
554 return ERROR_INVALID_DATA;
557 const int lrc = pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
560 msusb_msconfig_free(MsConfig);
562 return ERROR_INTERNAL_ERROR;
566 func_select_all_interface_for_msconfig(urbdrc, pdev, MsConfig);
568 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
570 msusb_msconfig_free(MsConfig);
576 return CHANNEL_RC_OK;
577 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
578 usbd_status, MsConfig);
583 UINT32 InterfaceId, UINT32 MessageId,
585 UINT32 ConfigurationHandle)
587 WINPR_ASSERT(callback);
588 WINPR_ASSERT(MsInterface);
590 const UINT32 NumInterfaces = 1;
591 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
593 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
596 return ERROR_OUTOFMEMORY;
598 const uint32_t size = 8U + interface_size;
599 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
601 if (!Stream_EnsureRemainingCapacity(out, 4))
603 Stream_Write_UINT32(out, usize);
605 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
608 if (!msusb_msinterface_write(MsInterface, out))
611 if (!Stream_EnsureRemainingCapacity(out, 8))
613 Stream_Write_UINT32(out, ConfigurationHandle);
614 Stream_Write_UINT32(out, NumInterfaces);
616 for (
size_t x = 0; x < NumInterfaces; x++)
619 if (!msusb_msinterface_write(ifc, out))
623 return send_urb_completion_message(callback, out, 0, 0, NULL);
626 Stream_Free(out, TRUE);
628 return ERROR_INTERNAL_ERROR;
632 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
635 const BOOL noAck = (RequestField & 0x80000000U) != 0;
636 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
638 if (!callback || !s || !udevman || !pdev)
639 return ERROR_INVALID_PARAMETER;
644 return ERROR_INVALID_PARAMETER;
646 if (transferDir == 0)
648 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
649 return ERROR_INVALID_PARAMETER;
652 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
653 return ERROR_INVALID_DATA;
655 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
656 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
659 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
661 msusb_msinterface_free(MsInterface);
662 return ERROR_INVALID_DATA;
665 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
666 if (OutputBufferSize != 0)
668 WLog_Print(urbdrc->log, WLOG_ERROR,
669 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
672 msusb_msinterface_free(MsInterface);
673 return ERROR_INVALID_DATA;
677 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
680 msusb_msinterface_free(MsInterface);
681 return ERROR_INTERNAL_ERROR;
686 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
687 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
688 return ERROR_BAD_CONFIGURATION;
691 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
692 return ERROR_BAD_CONFIGURATION;
695 return CHANNEL_RC_OK;
697 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface,
698 ConfigurationHandle);
702 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
703 int transferDir,
int External)
706 UINT32 InterfaceId = 0;
707 UINT32 EndpointAddress = 0;
708 UINT32 PipeHandle = 0;
709 UINT32 TransferFlags = 0;
710 UINT32 OutputBufferSize = 0;
711 UINT32 usbd_status = 0;
713 BYTE bmRequestType = 0;
721 const BOOL noAck = (RequestField & 0x80000000U) != 0;
722 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
724 if (!callback || !s || !udevman || !pdev)
725 return ERROR_INVALID_PARAMETER;
730 return ERROR_INVALID_PARAMETER;
732 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
733 return ERROR_INVALID_DATA;
735 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
736 Stream_Read_UINT32(s, PipeHandle);
737 Stream_Read_UINT32(s, TransferFlags);
738 EndpointAddress = (PipeHandle & 0x000000ff);
743 case URB_CONTROL_TRANSFER_EXTERNAL:
744 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
745 return ERROR_INVALID_DATA;
747 Stream_Read_UINT32(s, Timeout);
750 case URB_CONTROL_TRANSFER_NONEXTERNAL:
757 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
758 return ERROR_INVALID_DATA;
760 Stream_Read_UINT8(s, bmRequestType);
761 Stream_Read_UINT8(s, Request);
762 Stream_Read_UINT16(s, Value);
763 Stream_Read_UINT16(s, Index);
764 Stream_Read_UINT16(s, length);
765 Stream_Read_UINT32(s, OutputBufferSize);
767 if (length != OutputBufferSize)
769 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
770 return ERROR_INVALID_DATA;
773 out_size = 36 + OutputBufferSize;
774 out = Stream_New(NULL, out_size);
777 return ERROR_OUTOFMEMORY;
779 Stream_Seek(out, 36);
781 buffer = Stream_Pointer(out);
783 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
785 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
787 Stream_Free(out, TRUE);
788 return ERROR_INVALID_DATA;
790 Stream_Copy(s, out, OutputBufferSize);
794 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
795 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
798 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
799 Stream_Free(out, TRUE);
800 return ERROR_INTERNAL_ERROR;
803 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
804 usbd_status, OutputBufferSize);
808 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
809 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
810 WINPR_ATTR_UNUSED UINT32 StartFrame,
811 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
813 if (!pdev->isChannelClosed(pdev))
814 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
817 Stream_Free(out, TRUE);
821 wStream* s, UINT32 RequestField, UINT32 MessageId,
822 IUDEVMAN* udevman,
int transferDir)
824 UINT32 EndpointAddress = 0;
825 UINT32 PipeHandle = 0;
826 UINT32 TransferFlags = 0;
827 UINT32 OutputBufferSize = 0;
828 const BOOL noAck = (RequestField & 0x80000000U) != 0;
829 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
831 if (!pdev || !callback || !s || !udevman)
832 return ERROR_INVALID_PARAMETER;
834 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
835 return ERROR_INVALID_DATA;
837 Stream_Read_UINT32(s, PipeHandle);
838 Stream_Read_UINT32(s, TransferFlags);
839 Stream_Read_UINT32(s, OutputBufferSize);
840 EndpointAddress = (PipeHandle & 0x000000ff);
842 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
844 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
846 return ERROR_INVALID_DATA;
851 const int rc = pdev->bulk_or_interrupt_transfer(
852 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
853 OutputBufferSize, (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
854 urb_bulk_transfer_cb, 10000);
859static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
861 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
862 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
863 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
867 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
868 Stream_SetPosition(out, 0);
870 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
871 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
873 Stream_Free(out, TRUE);
877 Stream_Write_UINT32(out, RequestId);
878 Stream_Write_UINT32(out, 20 + packetSize);
879 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
882 Stream_Free(out, TRUE);
886 Stream_Write_UINT32(out, StartFrame);
891 Stream_Write_UINT32(out, NumberOfPackets);
892 Stream_Write_UINT32(out, ErrorCount);
893 Stream_Seek(out, packetSize);
897 Stream_Write_UINT32(out, 0);
898 Stream_Write_UINT32(out, ErrorCount);
901 Stream_Write_UINT32(out, 0);
902 Stream_Write_UINT32(out, OutputBufferSize);
903 Stream_Seek(out, OutputBufferSize);
905 stream_write_and_free(callback->plugin, callback->channel, out);
910 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
914 UINT32 EndpointAddress = 0;
915 UINT32 PipeHandle = 0;
916 UINT32 TransferFlags = 0;
917 UINT32 StartFrame = 0;
918 UINT32 NumberOfPackets = 0;
919 UINT32 ErrorCount = 0;
920 UINT32 OutputBufferSize = 0;
921 BYTE* packetDescriptorData = NULL;
922 const BOOL noAck = (RequestField & 0x80000000U) != 0;
923 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
925 if (!pdev || !callback || !udevman)
926 return ERROR_INVALID_PARAMETER;
928 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
929 return ERROR_INVALID_DATA;
931 Stream_Read_UINT32(s, PipeHandle);
932 EndpointAddress = (PipeHandle & 0x000000ff);
933 Stream_Read_UINT32(s, TransferFlags);
934 Stream_Read_UINT32(s, StartFrame);
935 Stream_Read_UINT32(s, NumberOfPackets);
936 Stream_Read_UINT32(s, ErrorCount);
938 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
939 return ERROR_INVALID_DATA;
941 packetDescriptorData = Stream_Pointer(s);
942 Stream_Seek(s, 12ULL * NumberOfPackets);
944 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
945 return ERROR_INVALID_DATA;
946 Stream_Read_UINT32(s, OutputBufferSize);
948 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
950 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
951 return ERROR_INVALID_DATA;
954 rc = pdev->isoch_transfer(
955 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
956 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
957 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
958 urb_isoch_transfer_cb, 2000);
961 return ERROR_INTERNAL_ERROR;
966 wStream* s, UINT32 RequestField, UINT32 MessageId,
967 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
970 UINT32 InterfaceId = 0;
971 UINT32 OutputBufferSize = 0;
972 UINT32 usbd_status = 0;
973 BYTE bmRequestType = 0;
979 const BOOL noAck = (RequestField & 0x80000000U) != 0;
980 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
982 if (!callback || !s || !udevman || !pdev)
983 return ERROR_INVALID_PARAMETER;
988 return ERROR_INVALID_PARAMETER;
990 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
991 return ERROR_INVALID_DATA;
993 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
994 Stream_Read_UINT8(s, desc_index);
995 Stream_Read_UINT8(s, desc_type);
996 Stream_Read_UINT16(s, langId);
997 Stream_Read_UINT32(s, OutputBufferSize);
998 if (OutputBufferSize > UINT32_MAX - 36)
999 return ERROR_INVALID_DATA;
1000 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1002 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1003 return ERROR_INVALID_DATA;
1006 out_size = 36ULL + OutputBufferSize;
1007 out = Stream_New(NULL, out_size);
1010 return ERROR_OUTOFMEMORY;
1012 Stream_Seek(out, 36);
1013 bmRequestType = func_recipient;
1015 switch (transferDir)
1017 case USBD_TRANSFER_DIRECTION_IN:
1018 bmRequestType |= 0x80;
1021 case USBD_TRANSFER_DIRECTION_OUT:
1022 bmRequestType |= 0x00;
1023 Stream_Copy(s, out, OutputBufferSize);
1024 Stream_Rewind(out, OutputBufferSize);
1028 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1029 OutputBufferSize = 0;
1030 usbd_status = USBD_STATUS_STALL_PID;
1035 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1037 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1038 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1040 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1041 Stream_Free(out, TRUE);
1042 return ERROR_INTERNAL_ERROR;
1045 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1046 usbd_status, OutputBufferSize);
1050 wStream* s, UINT32 RequestField, UINT32 MessageId,
1051 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1053 size_t out_size = 0;
1054 UINT32 InterfaceId = 0;
1055 UINT32 OutputBufferSize = 0;
1056 UINT32 usbd_status = 0;
1058 BYTE bmRequestType = 0;
1061 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1062 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1064 if (!callback || !s || !udevman || !pdev)
1065 return ERROR_INVALID_PARAMETER;
1070 return ERROR_INVALID_PARAMETER;
1072 if (transferDir == 0)
1074 WLog_Print(urbdrc->log, WLOG_DEBUG,
1075 "urb_control_get_status_request: transfer out not supported");
1076 return ERROR_INVALID_PARAMETER;
1079 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1080 return ERROR_INVALID_DATA;
1082 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1083 Stream_Read_UINT16(s, Index);
1085 Stream_Read_UINT32(s, OutputBufferSize);
1086 if (OutputBufferSize > UINT32_MAX - 36)
1087 return ERROR_INVALID_DATA;
1088 out_size = 36ULL + OutputBufferSize;
1089 out = Stream_New(NULL, out_size);
1092 return ERROR_OUTOFMEMORY;
1094 Stream_Seek(out, 36);
1095 bmRequestType = func_recipient | 0x80;
1097 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1098 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1101 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1102 Stream_Free(out, TRUE);
1103 return ERROR_INTERNAL_ERROR;
1106 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1107 usbd_status, OutputBufferSize);
1111 wStream* s, UINT32 RequestField, UINT32 MessageId,
1112 IUDEVMAN* udevman, BYTE func_type,
1113 BYTE func_recipient,
int transferDir)
1115 UINT32 out_size = 0;
1116 UINT32 InterfaceId = 0;
1117 UINT32 TransferFlags = 0;
1118 UINT32 usbd_status = 0;
1119 UINT32 OutputBufferSize = 0;
1120 BYTE ReqTypeReservedBits = 0;
1122 BYTE bmRequestType = 0;
1127 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1128 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1130 if (!callback || !s || !udevman || !pdev)
1131 return ERROR_INVALID_PARAMETER;
1136 return ERROR_INVALID_PARAMETER;
1138 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1139 return ERROR_INVALID_DATA;
1141 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1142 Stream_Read_UINT32(s, TransferFlags);
1143 Stream_Read_UINT8(s, ReqTypeReservedBits);
1144 Stream_Read_UINT8(s, Request);
1145 Stream_Read_UINT16(s, Value);
1146 Stream_Read_UINT16(s, Index);
1147 Stream_Seek_UINT16(s);
1148 Stream_Read_UINT32(s, OutputBufferSize);
1149 if (OutputBufferSize > UINT32_MAX - 36)
1150 return ERROR_INVALID_DATA;
1152 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1154 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1155 return ERROR_INVALID_DATA;
1158 out_size = 36ULL + OutputBufferSize;
1159 out = Stream_New(NULL, out_size);
1162 return ERROR_OUTOFMEMORY;
1164 Stream_Seek(out, 36);
1167 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1169 Stream_Copy(s, out, OutputBufferSize);
1170 Stream_Rewind(out, OutputBufferSize);
1174 bmRequestType = func_type | func_recipient;
1176 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1177 bmRequestType |= 0x80;
1179 WLog_Print(urbdrc->log, WLOG_DEBUG,
1180 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1182 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1183 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1184 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1185 OutputBufferSize, bmRequestType);
1187 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1188 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1190 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1191 Stream_Free(out, TRUE);
1192 return ERROR_INTERNAL_ERROR;
1195 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1196 usbd_status, OutputBufferSize);
1200 wStream* s, UINT32 RequestField, UINT32 MessageId,
1201 IUDEVMAN* udevman,
int transferDir)
1203 size_t out_size = 0;
1204 UINT32 InterfaceId = 0;
1205 UINT32 OutputBufferSize = 0;
1206 UINT32 usbd_status = 0;
1208 BYTE InterfaceNumber = 0;
1209 BYTE Ms_PageIndex = 0;
1210 UINT16 Ms_featureDescIndex = 0;
1214 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1215 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1217 if (!callback || !s || !udevman || !pdev)
1218 return ERROR_INVALID_PARAMETER;
1223 return ERROR_INVALID_PARAMETER;
1225 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1226 return ERROR_INVALID_DATA;
1229 Stream_Read_UINT8(s, Recipient);
1230 Recipient = (Recipient & 0x1f);
1231 Stream_Read_UINT8(s, InterfaceNumber);
1232 Stream_Read_UINT8(s, Ms_PageIndex);
1233 Stream_Read_UINT16(s, Ms_featureDescIndex);
1235 Stream_Read_UINT32(s, OutputBufferSize);
1236 if (OutputBufferSize > UINT32_MAX - 36)
1237 return ERROR_INVALID_DATA;
1239 switch (transferDir)
1241 case USBD_TRANSFER_DIRECTION_OUT:
1242 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1243 return ERROR_INVALID_DATA;
1251 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1252 out_size = 36ULL + OutputBufferSize;
1253 out = Stream_New(NULL, out_size);
1256 return ERROR_OUTOFMEMORY;
1258 Stream_Seek(out, 36);
1260 switch (transferDir)
1262 case USBD_TRANSFER_DIRECTION_OUT:
1263 Stream_Copy(s, out, OutputBufferSize);
1264 Stream_Rewind(out, OutputBufferSize);
1267 case USBD_TRANSFER_DIRECTION_IN:
1273 WLog_Print(urbdrc->log, WLOG_DEBUG,
1274 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1275 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1276 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1277 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1279 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1280 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1281 &OutputBufferSize, Stream_Pointer(out), 1000);
1284 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1286 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1287 usbd_status, OutputBufferSize);
1291 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1292 int transferDir,
int action)
1294 UINT32 out_size = 0;
1295 UINT32 InterfaceId = 0;
1296 UINT32 PipeHandle = 0;
1297 UINT32 EndpointAddress = 0;
1298 UINT32 OutputBufferSize = 0;
1299 UINT32 usbd_status = 0;
1301 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1304 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1305 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1307 if (!callback || !s || !udevman || !pdev)
1308 return ERROR_INVALID_PARAMETER;
1313 return ERROR_INVALID_PARAMETER;
1315 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1316 return ERROR_INVALID_DATA;
1318 if (transferDir == 0)
1320 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1321 return ERROR_INVALID_PARAMETER;
1324 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1325 Stream_Read_UINT32(s, PipeHandle);
1326 Stream_Read_UINT32(s, OutputBufferSize);
1327 EndpointAddress = (PipeHandle & 0x000000ff);
1332 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1336 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %u", ret);
1338 ret = USBD_STATUS_SUCCESS;
1343 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1345 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1349 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %u", ret);
1351 ret = USBD_STATUS_SUCCESS;
1356 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1358 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1364 if (out_size > OutputBufferSize)
1366 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32,
1367 out_size, OutputBufferSize);
1368 return ERROR_BAD_CONFIGURATION;
1370 out = Stream_New(NULL, out_size);
1373 return ERROR_OUTOFMEMORY;
1375 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1380 UINT32 RequestId, UINT32 MessageId,
1381 UINT32 CompletionId, UINT32 FrameNumber)
1383 WINPR_ASSERT(callback);
1385 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1387 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1390 return ERROR_OUTOFMEMORY;
1392 Stream_Write_UINT32(out, 12);
1393 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1395 Stream_Free(out, TRUE);
1396 return ERROR_OUTOFMEMORY;
1399 Stream_Write_UINT32(out, FrameNumber);
1400 return send_urb_completion_message(callback, out, 0, 0, NULL);
1404 wStream* s, UINT32 RequestField, UINT32 MessageId,
1405 IUDEVMAN* udevman,
int transferDir)
1407 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1408 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1410 if (!callback || !s || !udevman || !pdev)
1411 return ERROR_INVALID_PARAMETER;
1416 return ERROR_INVALID_PARAMETER;
1418 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1419 return ERROR_INVALID_DATA;
1421 if (transferDir == 0)
1423 WLog_Print(urbdrc->log, WLOG_DEBUG,
1424 "urb_get_current_frame_number: not support transfer out");
1425 return ERROR_INVALID_PARAMETER;
1428 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1429 if (OutputBufferSize != 0)
1431 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0",
1435 const UINT32 dummy_frames = GetTickCount();
1436 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1439 return CHANNEL_RC_OK;
1441 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1446static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1448 UINT32 RequestField, UINT32 MessageId,
1449 IUDEVMAN* udevman,
int transferDir)
1451 size_t out_size = 0;
1452 UINT32 InterfaceId = 0;
1453 UINT32 OutputBufferSize = 0;
1454 UINT32 usbd_status = 0;
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 (transferDir == 0)
1470 WLog_Print(urbdrc->log, WLOG_DEBUG,
1471 "urb_control_get_configuration_request:"
1472 " not support transfer out");
1473 return ERROR_INVALID_PARAMETER;
1476 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1477 return ERROR_INVALID_DATA;
1479 Stream_Read_UINT32(s, OutputBufferSize);
1480 if (OutputBufferSize > UINT32_MAX - 36)
1481 return ERROR_INVALID_DATA;
1482 out_size = 36ULL + OutputBufferSize;
1483 out = Stream_New(NULL, out_size);
1486 return ERROR_OUTOFMEMORY;
1488 Stream_Seek(out, 36);
1489 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1491 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1493 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1495 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1496 Stream_Free(out, TRUE);
1497 return ERROR_INTERNAL_ERROR;
1500 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1501 usbd_status, OutputBufferSize);
1506 wStream* s, UINT32 RequestField, UINT32 MessageId,
1507 IUDEVMAN* udevman,
int transferDir)
1509 size_t out_size = 0;
1510 UINT32 InterfaceId = 0;
1511 UINT32 OutputBufferSize = 0;
1512 UINT32 usbd_status = 0;
1513 UINT16 InterfaceNr = 0;
1516 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1517 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1519 if (!callback || !s || !udevman || !pdev)
1520 return ERROR_INVALID_PARAMETER;
1525 return ERROR_INVALID_PARAMETER;
1527 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1528 return ERROR_INVALID_DATA;
1530 if (transferDir == 0)
1532 WLog_Print(urbdrc->log, WLOG_DEBUG,
1533 "urb_control_get_interface_request: not support transfer out");
1534 return ERROR_INVALID_PARAMETER;
1537 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1538 Stream_Read_UINT16(s, InterfaceNr);
1540 Stream_Read_UINT32(s, OutputBufferSize);
1541 if (OutputBufferSize > UINT32_MAX - 36)
1542 return ERROR_INVALID_DATA;
1543 out_size = 36ULL + OutputBufferSize;
1544 out = Stream_New(NULL, out_size);
1547 return ERROR_OUTOFMEMORY;
1549 Stream_Seek(out, 36);
1551 if (!pdev->control_transfer(
1552 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1553 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1555 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1556 Stream_Free(out, TRUE);
1557 return ERROR_INTERNAL_ERROR;
1560 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1561 usbd_status, OutputBufferSize);
1565 wStream* s, UINT32 RequestField, UINT32 MessageId,
1566 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1569 UINT32 InterfaceId = 0;
1570 UINT32 OutputBufferSize = 0;
1571 UINT32 usbd_status = 0;
1572 UINT16 FeatureSelector = 0;
1574 BYTE bmRequestType = 0;
1578 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1579 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1581 if (!callback || !s || !udevman || !pdev)
1582 return ERROR_INVALID_PARAMETER;
1587 return ERROR_INVALID_PARAMETER;
1589 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1590 return ERROR_INVALID_DATA;
1592 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1593 Stream_Read_UINT16(s, FeatureSelector);
1594 Stream_Read_UINT16(s, Index);
1595 Stream_Read_UINT32(s, OutputBufferSize);
1596 if (OutputBufferSize > UINT32_MAX - 36)
1597 return ERROR_INVALID_DATA;
1598 switch (transferDir)
1600 case USBD_TRANSFER_DIRECTION_OUT:
1601 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1602 return ERROR_INVALID_DATA;
1610 out = Stream_New(NULL, 36ULL + OutputBufferSize);
1613 return ERROR_OUTOFMEMORY;
1615 Stream_Seek(out, 36);
1616 bmRequestType = func_recipient;
1618 switch (transferDir)
1620 case USBD_TRANSFER_DIRECTION_OUT:
1621 WLog_Print(urbdrc->log, WLOG_ERROR,
1622 "Function urb_control_feature_request: OUT Unchecked");
1623 Stream_Copy(s, out, OutputBufferSize);
1624 Stream_Rewind(out, OutputBufferSize);
1625 bmRequestType |= 0x00;
1628 case USBD_TRANSFER_DIRECTION_IN:
1629 bmRequestType |= 0x80;
1637 case URB_SET_FEATURE:
1641 case URB_CLEAR_FEATURE:
1646 WLog_Print(urbdrc->log, WLOG_ERROR,
1647 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1648 Stream_Free(out, TRUE);
1649 return ERROR_INTERNAL_ERROR;
1652 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1653 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1655 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1656 Stream_Free(out, TRUE);
1657 return ERROR_INTERNAL_ERROR;
1660 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1661 usbd_status, OutputBufferSize);
1665 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1670 UINT16 URB_Function = 0;
1671 UINT32 RequestId = 0;
1672 UINT error = ERROR_INTERNAL_ERROR;
1675 if (!callback || !s || !udevman || !pdev)
1676 return ERROR_INVALID_PARAMETER;
1681 return ERROR_INVALID_PARAMETER;
1683 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1684 return ERROR_INVALID_DATA;
1686 Stream_Read_UINT32(s, CbTsUrb);
1687 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1688 return ERROR_INVALID_DATA;
1689 Stream_Read_UINT16(s, Size);
1690 if (Size != CbTsUrb)
1692 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1693 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1694 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1696 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x%04" PRIx16
1697 " != %s::CbTsUrb 0x%08" PRIx32,
1698 Size, section, CbTsUrb);
1699 return ERROR_INVALID_DATA;
1701 Stream_Read_UINT16(s, URB_Function);
1702 Stream_Read_UINT32(s, RequestId);
1703 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1706 switch (URB_Function)
1708 case TS_URB_SELECT_CONFIGURATION:
1709 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1713 case TS_URB_SELECT_INTERFACE:
1715 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1718 case TS_URB_PIPE_REQUEST:
1719 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1723 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1729 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1735 case TS_URB_GET_FRAME_LENGTH:
1741 case TS_URB_SET_FRAME_LENGTH:
1747 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1748 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1752 case TS_URB_CONTROL_TRANSFER:
1753 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1754 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1757 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1758 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1762 case TS_URB_ISOCH_TRANSFER:
1764 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1767 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1768 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1772 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1773 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1777 case TS_URB_SET_FEATURE_TO_DEVICE:
1778 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1779 0x00, URB_SET_FEATURE, transferDir);
1782 case TS_URB_SET_FEATURE_TO_INTERFACE:
1783 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1784 0x01, URB_SET_FEATURE, transferDir);
1787 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1788 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1789 0x02, URB_SET_FEATURE, transferDir);
1792 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1793 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1794 0x00, URB_CLEAR_FEATURE, transferDir);
1797 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1798 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1799 0x01, URB_CLEAR_FEATURE, transferDir);
1802 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1803 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1804 0x02, URB_CLEAR_FEATURE, transferDir);
1807 case TS_URB_GET_STATUS_FROM_DEVICE:
1808 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1812 case TS_URB_GET_STATUS_FROM_INTERFACE:
1813 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1817 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1818 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1822 case TS_URB_RESERVED_0X0016:
1825 case TS_URB_VENDOR_DEVICE:
1826 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1827 udevman, (0x02 << 5),
1831 case TS_URB_VENDOR_INTERFACE:
1832 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1833 udevman, (0x02 << 5),
1837 case TS_URB_VENDOR_ENDPOINT:
1838 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1839 udevman, (0x02 << 5),
1843 case TS_URB_CLASS_DEVICE:
1844 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1845 udevman, (0x01 << 5),
1849 case TS_URB_CLASS_INTERFACE:
1850 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1851 udevman, (0x01 << 5),
1855 case TS_URB_CLASS_ENDPOINT:
1856 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1857 udevman, (0x01 << 5),
1861 case TS_URB_RESERVE_0X001D:
1864 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1865 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1869 case TS_URB_CLASS_OTHER:
1870 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1871 udevman, (0x01 << 5),
1875 case TS_URB_VENDOR_OTHER:
1876 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1877 udevman, (0x02 << 5),
1881 case TS_URB_GET_STATUS_FROM_OTHER:
1882 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1886 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1887 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1888 0x03, URB_CLEAR_FEATURE, transferDir);
1891 case TS_URB_SET_FEATURE_TO_OTHER:
1892 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1893 0x03, URB_SET_FEATURE, transferDir);
1896 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1897 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1901 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1902 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1906 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1907 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1908 udevman, transferDir);
1911 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1912 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1913 udevman, transferDir);
1916 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1917 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1921 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1922 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1926 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1927 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1928 udevman, transferDir);
1931 case TS_URB_RESERVE_0X002B:
1932 case TS_URB_RESERVE_0X002C:
1933 case TS_URB_RESERVE_0X002D:
1934 case TS_URB_RESERVE_0X002E:
1935 case TS_URB_RESERVE_0X002F:
1939 case TS_URB_SYNC_RESET_PIPE:
1940 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1944 case TS_URB_SYNC_CLEAR_STALL:
1945 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1949 case TS_URB_CONTROL_TRANSFER_EX:
1950 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1951 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1955 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
1962 WLog_Print(urbdrc->log, WLOG_WARN,
1963 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1964 urb_function_string(URB_Function), URB_Function, error);
1971 IUDEVMAN* udevman,
wStream* data)
1973 UINT32 InterfaceId = 0;
1974 UINT32 MessageId = 0;
1975 UINT32 FunctionId = 0;
1976 IUDEVICE* pdev = NULL;
1977 UINT error = ERROR_INTERNAL_ERROR;
1979 if (!urbdrc || !data || !callback || !udevman)
1982 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1985 Stream_Rewind_UINT32(data);
1987 Stream_Read_UINT32(data, InterfaceId);
1988 Stream_Read_UINT32(data, MessageId);
1989 Stream_Read_UINT32(data, FunctionId);
1991 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1996 error = ERROR_SUCCESS;
2001 if (pdev->isChannelClosed(pdev))
2003 error = ERROR_SUCCESS;
2008 if (!pdev->detach_kernel_driver(pdev))
2010 error = ERROR_SUCCESS;
2016 case CANCEL_REQUEST:
2017 error = urbdrc_process_cancel_request(pdev, data, udevman);
2020 case REGISTER_REQUEST_CALLBACK:
2021 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2025 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2028 case INTERNAL_IO_CONTROL:
2029 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2032 case QUERY_DEVICE_TEXT:
2033 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2036 case TRANSFER_IN_REQUEST:
2037 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2038 USBD_TRANSFER_DIRECTION_IN);
2041 case TRANSFER_OUT_REQUEST:
2042 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2043 USBD_TRANSFER_DIRECTION_OUT);
2046 case RETRACT_DEVICE:
2047 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2051 WLog_Print(urbdrc->log, WLOG_WARN,
2052 "urbdrc_process_udev_data_transfer:"
2053 " unknown FunctionId 0x%" PRIX32
"",
2061 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);