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, 4,
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 BYTE InterfaceNumber = 0;
458 BYTE AlternateSetting = 0;
459 UINT32 NumInterfaces = MsConfig->NumInterfaces;
461 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
463 InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
464 AlternateSetting = MsInterfaces[inum]->AlternateSetting;
465 pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
471 UINT32 InterfaceId, UINT32 MessageId,
472 UINT32 RequestId, UINT32 UrbStatus,
476 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
478 return ERROR_OUTOFMEMORY;
480 const int size = 8 + ((MsConfig) ? MsConfig->MsOutSize : 8);
481 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
483 if (!Stream_EnsureRemainingCapacity(out, 4))
485 Stream_Write_UINT32(out, usize);
487 if (!write_urb_result_header(out, usize, UrbStatus))
492 msusb_msconfig_write(MsConfig, out);
495 Stream_Write_UINT32(out, 0);
496 Stream_Write_UINT32(out, 0);
499 return send_urb_completion_message(callback, out, 0, 0, NULL);
502 Stream_Free(out, TRUE);
503 return ERROR_OUTOFMEMORY;
507 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
511 UINT32 NumInterfaces = 0;
512 UINT32 usbd_status = 0;
513 BYTE ConfigurationDescriptorIsValid = 0;
515 const BOOL noAck = (RequestField & 0x80000000U) != 0;
516 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
518 if (!callback || !s || !udevman || !pdev)
519 return ERROR_INVALID_PARAMETER;
524 return ERROR_INVALID_PARAMETER;
526 if (transferDir == 0)
528 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
529 return ERROR_INVALID_PARAMETER;
532 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
533 return ERROR_INVALID_DATA;
535 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
536 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
538 Stream_Read_UINT32(s, NumInterfaces);
541 if (ConfigurationDescriptorIsValid)
544 MsConfig = msusb_msconfig_read(s, NumInterfaces);
547 return ERROR_INVALID_DATA;
550 pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
552 func_select_all_interface_for_msconfig(pdev, MsConfig);
554 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
556 msusb_msconfig_free(MsConfig);
562 return CHANNEL_RC_OK;
563 return send_urb_select_configuration_result(callback, InterfaceId, MessageId, RequestId,
564 usbd_status, MsConfig);
569 UINT32 InterfaceId, UINT32 MessageId,
571 UINT32 ConfigurationHandle)
573 WINPR_ASSERT(callback);
574 WINPR_ASSERT(MsInterface);
576 const UINT32 NumInterfaces = 1;
577 const uint32_t interface_size = 16U + (MsInterface->NumberOfPipes * 20U);
579 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
582 return ERROR_OUTOFMEMORY;
584 const uint32_t size = 8U + interface_size;
585 const uint16_t usize = WINPR_ASSERTING_INT_CAST(uint16_t, size);
587 if (!Stream_EnsureRemainingCapacity(out, 4))
589 Stream_Write_UINT32(out, usize);
591 if (!write_urb_result_header(out, usize, USBD_STATUS_SUCCESS))
594 if (!msusb_msinterface_write(MsInterface, out))
597 if (!Stream_EnsureRemainingCapacity(out, 8))
599 Stream_Write_UINT32(out, ConfigurationHandle);
600 Stream_Write_UINT32(out, NumInterfaces);
602 for (
size_t x = 0; x < NumInterfaces; x++)
605 if (!msusb_msinterface_write(ifc, out))
609 return send_urb_completion_message(callback, out, 0, 0, NULL);
612 Stream_Free(out, TRUE);
614 return ERROR_INTERNAL_ERROR;
618 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
621 const BOOL noAck = (RequestField & 0x80000000U) != 0;
622 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
624 if (!callback || !s || !udevman || !pdev)
625 return ERROR_INVALID_PARAMETER;
630 return ERROR_INVALID_PARAMETER;
632 if (transferDir == 0)
634 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
635 return ERROR_INVALID_PARAMETER;
638 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
639 return ERROR_INVALID_DATA;
641 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
642 const UINT32 ConfigurationHandle = Stream_Get_UINT32(s);
645 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
647 msusb_msinterface_free(MsInterface);
648 return ERROR_INVALID_DATA;
651 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
652 if (OutputBufferSize != 0)
654 WLog_Print(urbdrc->log, WLOG_ERROR,
655 "[MS-RDPEUSB] 2.2.9.3 TS_URB_SELECT_INTERFACE::OutputBufferSize must be 0, got "
658 msusb_msinterface_free(MsInterface);
659 return ERROR_INVALID_DATA;
662 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
665 const uint8_t InterfaceNumber = MsInterface->InterfaceNumber;
666 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
668 msusb_msconfig_free(MsConfig);
669 return ERROR_BAD_CONFIGURATION;
672 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
673 return ERROR_BAD_CONFIGURATION;
676 return CHANNEL_RC_OK;
678 return urb_select_interface_result(callback, RequestId, InterfaceId, MessageId, MsInterface,
679 ConfigurationHandle);
683 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
684 int transferDir,
int External)
687 UINT32 InterfaceId = 0;
688 UINT32 EndpointAddress = 0;
689 UINT32 PipeHandle = 0;
690 UINT32 TransferFlags = 0;
691 UINT32 OutputBufferSize = 0;
692 UINT32 usbd_status = 0;
694 BYTE bmRequestType = 0;
702 const BOOL noAck = (RequestField & 0x80000000U) != 0;
703 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
705 if (!callback || !s || !udevman || !pdev)
706 return ERROR_INVALID_PARAMETER;
711 return ERROR_INVALID_PARAMETER;
713 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
714 return ERROR_INVALID_DATA;
716 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
717 Stream_Read_UINT32(s, PipeHandle);
718 Stream_Read_UINT32(s, TransferFlags);
719 EndpointAddress = (PipeHandle & 0x000000ff);
724 case URB_CONTROL_TRANSFER_EXTERNAL:
725 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
726 return ERROR_INVALID_DATA;
728 Stream_Read_UINT32(s, Timeout);
731 case URB_CONTROL_TRANSFER_NONEXTERNAL:
738 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
739 return ERROR_INVALID_DATA;
741 Stream_Read_UINT8(s, bmRequestType);
742 Stream_Read_UINT8(s, Request);
743 Stream_Read_UINT16(s, Value);
744 Stream_Read_UINT16(s, Index);
745 Stream_Read_UINT16(s, length);
746 Stream_Read_UINT32(s, OutputBufferSize);
748 if (length != OutputBufferSize)
750 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
751 return ERROR_INVALID_DATA;
754 out_size = 36 + OutputBufferSize;
755 out = Stream_New(NULL, out_size);
758 return ERROR_OUTOFMEMORY;
760 Stream_Seek(out, 36);
762 buffer = Stream_Pointer(out);
764 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
766 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
768 Stream_Free(out, TRUE);
769 return ERROR_INVALID_DATA;
771 Stream_Copy(s, out, OutputBufferSize);
775 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
776 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
779 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
780 Stream_Free(out, TRUE);
781 return ERROR_INTERNAL_ERROR;
784 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
785 usbd_status, OutputBufferSize);
789 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
790 WINPR_ATTR_UNUSED UINT32 NumberOfPackets, UINT32 status,
791 WINPR_ATTR_UNUSED UINT32 StartFrame,
792 WINPR_ATTR_UNUSED UINT32 ErrorCount, UINT32 OutputBufferSize)
794 if (!pdev->isChannelClosed(pdev))
795 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
798 Stream_Free(out, TRUE);
802 wStream* s, UINT32 RequestField, UINT32 MessageId,
803 IUDEVMAN* udevman,
int transferDir)
805 UINT32 EndpointAddress = 0;
806 UINT32 PipeHandle = 0;
807 UINT32 TransferFlags = 0;
808 UINT32 OutputBufferSize = 0;
809 const BOOL noAck = (RequestField & 0x80000000U) != 0;
810 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
812 if (!pdev || !callback || !s || !udevman)
813 return ERROR_INVALID_PARAMETER;
815 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
816 return ERROR_INVALID_DATA;
818 Stream_Read_UINT32(s, PipeHandle);
819 Stream_Read_UINT32(s, TransferFlags);
820 Stream_Read_UINT32(s, OutputBufferSize);
821 EndpointAddress = (PipeHandle & 0x000000ff);
823 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
825 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
827 return ERROR_INVALID_DATA;
832 const int rc = pdev->bulk_or_interrupt_transfer(
833 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
834 OutputBufferSize, (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
835 urb_bulk_transfer_cb, 10000);
840static void urb_isoch_transfer_cb(WINPR_ATTR_UNUSED IUDEVICE* pdev,
842 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
843 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
844 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
848 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
849 Stream_SetPosition(out, 0);
851 const UINT32 FunctionId = (OutputBufferSize == 0) ? URB_COMPLETION_NO_DATA : URB_COMPLETION;
852 if (!write_shared_message_header_with_functionid(out, InterfaceId, MessageId, FunctionId))
854 Stream_Free(out, TRUE);
858 Stream_Write_UINT32(out, RequestId);
859 Stream_Write_UINT32(out, 20 + packetSize);
860 if (!write_urb_result_header(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize),
863 Stream_Free(out, TRUE);
867 Stream_Write_UINT32(out, StartFrame);
872 Stream_Write_UINT32(out, NumberOfPackets);
873 Stream_Write_UINT32(out, ErrorCount);
874 Stream_Seek(out, packetSize);
878 Stream_Write_UINT32(out, 0);
879 Stream_Write_UINT32(out, ErrorCount);
882 Stream_Write_UINT32(out, 0);
883 Stream_Write_UINT32(out, OutputBufferSize);
884 Stream_Seek(out, OutputBufferSize);
886 stream_write_and_free(callback->plugin, callback->channel, out);
891 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
895 UINT32 EndpointAddress = 0;
896 UINT32 PipeHandle = 0;
897 UINT32 TransferFlags = 0;
898 UINT32 StartFrame = 0;
899 UINT32 NumberOfPackets = 0;
900 UINT32 ErrorCount = 0;
901 UINT32 OutputBufferSize = 0;
902 BYTE* packetDescriptorData = NULL;
903 const BOOL noAck = (RequestField & 0x80000000U) != 0;
904 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
906 if (!pdev || !callback || !udevman)
907 return ERROR_INVALID_PARAMETER;
909 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
910 return ERROR_INVALID_DATA;
912 Stream_Read_UINT32(s, PipeHandle);
913 EndpointAddress = (PipeHandle & 0x000000ff);
914 Stream_Read_UINT32(s, TransferFlags);
915 Stream_Read_UINT32(s, StartFrame);
916 Stream_Read_UINT32(s, NumberOfPackets);
917 Stream_Read_UINT32(s, ErrorCount);
919 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
920 return ERROR_INVALID_DATA;
922 packetDescriptorData = Stream_Pointer(s);
923 Stream_Seek(s, 12ULL * NumberOfPackets);
925 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
926 return ERROR_INVALID_DATA;
927 Stream_Read_UINT32(s, OutputBufferSize);
929 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
931 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
932 return ERROR_INVALID_DATA;
935 rc = pdev->isoch_transfer(
936 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
937 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
938 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
939 urb_isoch_transfer_cb, 2000);
942 return ERROR_INTERNAL_ERROR;
947 wStream* s, UINT32 RequestField, UINT32 MessageId,
948 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
951 UINT32 InterfaceId = 0;
952 UINT32 OutputBufferSize = 0;
953 UINT32 usbd_status = 0;
954 BYTE bmRequestType = 0;
960 const BOOL noAck = (RequestField & 0x80000000U) != 0;
961 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
963 if (!callback || !s || !udevman || !pdev)
964 return ERROR_INVALID_PARAMETER;
969 return ERROR_INVALID_PARAMETER;
971 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
972 return ERROR_INVALID_DATA;
974 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
975 Stream_Read_UINT8(s, desc_index);
976 Stream_Read_UINT8(s, desc_type);
977 Stream_Read_UINT16(s, langId);
978 Stream_Read_UINT32(s, OutputBufferSize);
979 if (OutputBufferSize > UINT32_MAX - 36)
980 return ERROR_INVALID_DATA;
981 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
983 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
984 return ERROR_INVALID_DATA;
987 out_size = 36ULL + OutputBufferSize;
988 out = Stream_New(NULL, out_size);
991 return ERROR_OUTOFMEMORY;
993 Stream_Seek(out, 36);
994 bmRequestType = func_recipient;
998 case USBD_TRANSFER_DIRECTION_IN:
999 bmRequestType |= 0x80;
1002 case USBD_TRANSFER_DIRECTION_OUT:
1003 bmRequestType |= 0x00;
1004 Stream_Copy(s, out, OutputBufferSize);
1005 Stream_Rewind(out, OutputBufferSize);
1009 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
1010 OutputBufferSize = 0;
1011 usbd_status = USBD_STATUS_STALL_PID;
1016 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
1018 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
1019 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1021 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
1022 Stream_Free(out, TRUE);
1023 return ERROR_INTERNAL_ERROR;
1026 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1027 usbd_status, OutputBufferSize);
1031 wStream* s, UINT32 RequestField, UINT32 MessageId,
1032 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
1034 size_t out_size = 0;
1035 UINT32 InterfaceId = 0;
1036 UINT32 OutputBufferSize = 0;
1037 UINT32 usbd_status = 0;
1039 BYTE bmRequestType = 0;
1042 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1043 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1045 if (!callback || !s || !udevman || !pdev)
1046 return ERROR_INVALID_PARAMETER;
1051 return ERROR_INVALID_PARAMETER;
1053 if (transferDir == 0)
1055 WLog_Print(urbdrc->log, WLOG_DEBUG,
1056 "urb_control_get_status_request: transfer out not supported");
1057 return ERROR_INVALID_PARAMETER;
1060 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1061 return ERROR_INVALID_DATA;
1063 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1064 Stream_Read_UINT16(s, Index);
1066 Stream_Read_UINT32(s, OutputBufferSize);
1067 if (OutputBufferSize > UINT32_MAX - 36)
1068 return ERROR_INVALID_DATA;
1069 out_size = 36ULL + OutputBufferSize;
1070 out = Stream_New(NULL, out_size);
1073 return ERROR_OUTOFMEMORY;
1075 Stream_Seek(out, 36);
1076 bmRequestType = func_recipient | 0x80;
1078 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1079 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1082 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1083 Stream_Free(out, TRUE);
1084 return ERROR_INTERNAL_ERROR;
1087 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1088 usbd_status, OutputBufferSize);
1092 wStream* s, UINT32 RequestField, UINT32 MessageId,
1093 IUDEVMAN* udevman, BYTE func_type,
1094 BYTE func_recipient,
int transferDir)
1096 UINT32 out_size = 0;
1097 UINT32 InterfaceId = 0;
1098 UINT32 TransferFlags = 0;
1099 UINT32 usbd_status = 0;
1100 UINT32 OutputBufferSize = 0;
1101 BYTE ReqTypeReservedBits = 0;
1103 BYTE bmRequestType = 0;
1108 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1109 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1111 if (!callback || !s || !udevman || !pdev)
1112 return ERROR_INVALID_PARAMETER;
1117 return ERROR_INVALID_PARAMETER;
1119 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1120 return ERROR_INVALID_DATA;
1122 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1123 Stream_Read_UINT32(s, TransferFlags);
1124 Stream_Read_UINT8(s, ReqTypeReservedBits);
1125 Stream_Read_UINT8(s, Request);
1126 Stream_Read_UINT16(s, Value);
1127 Stream_Read_UINT16(s, Index);
1128 Stream_Seek_UINT16(s);
1129 Stream_Read_UINT32(s, OutputBufferSize);
1130 if (OutputBufferSize > UINT32_MAX - 36)
1131 return ERROR_INVALID_DATA;
1133 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1135 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1136 return ERROR_INVALID_DATA;
1139 out_size = 36ULL + OutputBufferSize;
1140 out = Stream_New(NULL, out_size);
1143 return ERROR_OUTOFMEMORY;
1145 Stream_Seek(out, 36);
1148 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1150 Stream_Copy(s, out, OutputBufferSize);
1151 Stream_Rewind(out, OutputBufferSize);
1155 bmRequestType = func_type | func_recipient;
1157 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1158 bmRequestType |= 0x80;
1160 WLog_Print(urbdrc->log, WLOG_DEBUG,
1161 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1163 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1164 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1165 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1166 OutputBufferSize, bmRequestType);
1168 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1169 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1171 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1172 Stream_Free(out, TRUE);
1173 return ERROR_INTERNAL_ERROR;
1176 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1177 usbd_status, OutputBufferSize);
1181 wStream* s, UINT32 RequestField, UINT32 MessageId,
1182 IUDEVMAN* udevman,
int transferDir)
1184 size_t out_size = 0;
1185 UINT32 InterfaceId = 0;
1186 UINT32 OutputBufferSize = 0;
1187 UINT32 usbd_status = 0;
1189 BYTE InterfaceNumber = 0;
1190 BYTE Ms_PageIndex = 0;
1191 UINT16 Ms_featureDescIndex = 0;
1195 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1196 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1198 if (!callback || !s || !udevman || !pdev)
1199 return ERROR_INVALID_PARAMETER;
1204 return ERROR_INVALID_PARAMETER;
1206 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1207 return ERROR_INVALID_DATA;
1210 Stream_Read_UINT8(s, Recipient);
1211 Recipient = (Recipient & 0x1f);
1212 Stream_Read_UINT8(s, InterfaceNumber);
1213 Stream_Read_UINT8(s, Ms_PageIndex);
1214 Stream_Read_UINT16(s, Ms_featureDescIndex);
1216 Stream_Read_UINT32(s, OutputBufferSize);
1217 if (OutputBufferSize > UINT32_MAX - 36)
1218 return ERROR_INVALID_DATA;
1220 switch (transferDir)
1222 case USBD_TRANSFER_DIRECTION_OUT:
1223 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1224 return ERROR_INVALID_DATA;
1232 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1233 out_size = 36ULL + OutputBufferSize;
1234 out = Stream_New(NULL, out_size);
1237 return ERROR_OUTOFMEMORY;
1239 Stream_Seek(out, 36);
1241 switch (transferDir)
1243 case USBD_TRANSFER_DIRECTION_OUT:
1244 Stream_Copy(s, out, OutputBufferSize);
1245 Stream_Rewind(out, OutputBufferSize);
1248 case USBD_TRANSFER_DIRECTION_IN:
1254 WLog_Print(urbdrc->log, WLOG_DEBUG,
1255 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1256 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1257 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1258 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1260 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1261 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1262 &OutputBufferSize, Stream_Pointer(out), 1000);
1265 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1267 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1268 usbd_status, OutputBufferSize);
1272 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1273 int transferDir,
int action)
1275 UINT32 out_size = 0;
1276 UINT32 InterfaceId = 0;
1277 UINT32 PipeHandle = 0;
1278 UINT32 EndpointAddress = 0;
1279 UINT32 OutputBufferSize = 0;
1280 UINT32 usbd_status = 0;
1282 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1285 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1286 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1288 if (!callback || !s || !udevman || !pdev)
1289 return ERROR_INVALID_PARAMETER;
1294 return ERROR_INVALID_PARAMETER;
1296 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1297 return ERROR_INVALID_DATA;
1299 if (transferDir == 0)
1301 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1302 return ERROR_INVALID_PARAMETER;
1305 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1306 Stream_Read_UINT32(s, PipeHandle);
1307 Stream_Read_UINT32(s, OutputBufferSize);
1308 EndpointAddress = (PipeHandle & 0x000000ff);
1313 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1317 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %d", ret);
1319 ret = USBD_STATUS_SUCCESS;
1324 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1326 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1330 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %d", ret);
1332 ret = USBD_STATUS_SUCCESS;
1337 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1339 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1345 if (out_size > OutputBufferSize)
1347 WLog_Print(urbdrc->log, WLOG_DEBUG,
"out_size %" PRIu32
" > OutputBufferSize %" PRIu32,
1348 out_size, OutputBufferSize);
1349 return ERROR_BAD_CONFIGURATION;
1351 out = Stream_New(NULL, out_size);
1354 return ERROR_OUTOFMEMORY;
1356 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1361 UINT32 RequestId, UINT32 MessageId,
1362 UINT32 CompletionId, UINT32 FrameNumber)
1364 WINPR_ASSERT(callback);
1366 const UINT32 InterfaceId = ((STREAM_ID_PROXY << 30) | CompletionId);
1368 create_urb_completion_message(InterfaceId, MessageId, RequestId, URB_COMPLETION_NO_DATA);
1371 return ERROR_OUTOFMEMORY;
1373 Stream_Write_UINT32(out, 12);
1374 if (!write_urb_result_header(out, 12, USBD_STATUS_SUCCESS))
1376 Stream_Free(out, TRUE);
1377 return ERROR_OUTOFMEMORY;
1380 Stream_Write_UINT32(out, FrameNumber);
1381 return send_urb_completion_message(callback, out, 0, 0, NULL);
1385 wStream* s, UINT32 RequestField, UINT32 MessageId,
1386 IUDEVMAN* udevman,
int transferDir)
1388 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1389 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1391 if (!callback || !s || !udevman || !pdev)
1392 return ERROR_INVALID_PARAMETER;
1397 return ERROR_INVALID_PARAMETER;
1399 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1400 return ERROR_INVALID_DATA;
1402 if (transferDir == 0)
1404 WLog_Print(urbdrc->log, WLOG_DEBUG,
1405 "urb_get_current_frame_number: not support transfer out");
1406 return ERROR_INVALID_PARAMETER;
1409 const UINT32 OutputBufferSize = Stream_Get_UINT32(s);
1410 if (OutputBufferSize != 0)
1412 WLog_Print(urbdrc->log, WLOG_WARN,
"OutputBufferSize=%" PRIu32
", expected 0");
1415 const UINT32 dummy_frames = GetTickCount();
1416 const UINT32 CompletionId = pdev->get_ReqCompletion(pdev);
1419 return CHANNEL_RC_OK;
1421 return urb_send_current_frame_number_result(callback, RequestId, MessageId, CompletionId,
1426static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1428 UINT32 RequestField, UINT32 MessageId,
1429 IUDEVMAN* udevman,
int transferDir)
1431 size_t out_size = 0;
1432 UINT32 InterfaceId = 0;
1433 UINT32 OutputBufferSize = 0;
1434 UINT32 usbd_status = 0;
1437 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1438 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1440 if (!callback || !s || !udevman || !pdev)
1441 return ERROR_INVALID_PARAMETER;
1446 return ERROR_INVALID_PARAMETER;
1448 if (transferDir == 0)
1450 WLog_Print(urbdrc->log, WLOG_DEBUG,
1451 "urb_control_get_configuration_request:"
1452 " not support transfer out");
1453 return ERROR_INVALID_PARAMETER;
1456 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1457 return ERROR_INVALID_DATA;
1459 Stream_Read_UINT32(s, OutputBufferSize);
1460 if (OutputBufferSize > UINT32_MAX - 36)
1461 return ERROR_INVALID_DATA;
1462 out_size = 36ULL + OutputBufferSize;
1463 out = Stream_New(NULL, out_size);
1466 return ERROR_OUTOFMEMORY;
1468 Stream_Seek(out, 36);
1469 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1471 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1473 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1475 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1476 Stream_Free(out, TRUE);
1477 return ERROR_INTERNAL_ERROR;
1480 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1481 usbd_status, OutputBufferSize);
1486 wStream* s, UINT32 RequestField, UINT32 MessageId,
1487 IUDEVMAN* udevman,
int transferDir)
1489 size_t out_size = 0;
1490 UINT32 InterfaceId = 0;
1491 UINT32 OutputBufferSize = 0;
1492 UINT32 usbd_status = 0;
1493 UINT16 InterfaceNr = 0;
1496 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1497 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1499 if (!callback || !s || !udevman || !pdev)
1500 return ERROR_INVALID_PARAMETER;
1505 return ERROR_INVALID_PARAMETER;
1507 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1508 return ERROR_INVALID_DATA;
1510 if (transferDir == 0)
1512 WLog_Print(urbdrc->log, WLOG_DEBUG,
1513 "urb_control_get_interface_request: not support transfer out");
1514 return ERROR_INVALID_PARAMETER;
1517 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1518 Stream_Read_UINT16(s, InterfaceNr);
1520 Stream_Read_UINT32(s, OutputBufferSize);
1521 if (OutputBufferSize > UINT32_MAX - 36)
1522 return ERROR_INVALID_DATA;
1523 out_size = 36ULL + OutputBufferSize;
1524 out = Stream_New(NULL, out_size);
1527 return ERROR_OUTOFMEMORY;
1529 Stream_Seek(out, 36);
1531 if (!pdev->control_transfer(
1532 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1533 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1535 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1536 Stream_Free(out, TRUE);
1537 return ERROR_INTERNAL_ERROR;
1540 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1541 usbd_status, OutputBufferSize);
1545 wStream* s, UINT32 RequestField, UINT32 MessageId,
1546 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1549 UINT32 InterfaceId = 0;
1550 UINT32 OutputBufferSize = 0;
1551 UINT32 usbd_status = 0;
1552 UINT16 FeatureSelector = 0;
1554 BYTE bmRequestType = 0;
1558 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1559 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1561 if (!callback || !s || !udevman || !pdev)
1562 return ERROR_INVALID_PARAMETER;
1567 return ERROR_INVALID_PARAMETER;
1569 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1570 return ERROR_INVALID_DATA;
1572 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1573 Stream_Read_UINT16(s, FeatureSelector);
1574 Stream_Read_UINT16(s, Index);
1575 Stream_Read_UINT32(s, OutputBufferSize);
1576 if (OutputBufferSize > UINT32_MAX - 36)
1577 return ERROR_INVALID_DATA;
1578 switch (transferDir)
1580 case USBD_TRANSFER_DIRECTION_OUT:
1581 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1582 return ERROR_INVALID_DATA;
1590 out = Stream_New(NULL, 36ULL + OutputBufferSize);
1593 return ERROR_OUTOFMEMORY;
1595 Stream_Seek(out, 36);
1596 bmRequestType = func_recipient;
1598 switch (transferDir)
1600 case USBD_TRANSFER_DIRECTION_OUT:
1601 WLog_Print(urbdrc->log, WLOG_ERROR,
1602 "Function urb_control_feature_request: OUT Unchecked");
1603 Stream_Copy(s, out, OutputBufferSize);
1604 Stream_Rewind(out, OutputBufferSize);
1605 bmRequestType |= 0x00;
1608 case USBD_TRANSFER_DIRECTION_IN:
1609 bmRequestType |= 0x80;
1617 case URB_SET_FEATURE:
1621 case URB_CLEAR_FEATURE:
1626 WLog_Print(urbdrc->log, WLOG_ERROR,
1627 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1628 Stream_Free(out, TRUE);
1629 return ERROR_INTERNAL_ERROR;
1632 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1633 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1635 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1636 Stream_Free(out, TRUE);
1637 return ERROR_INTERNAL_ERROR;
1640 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1641 usbd_status, OutputBufferSize);
1645 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1650 UINT16 URB_Function = 0;
1651 UINT32 RequestId = 0;
1652 UINT error = ERROR_INTERNAL_ERROR;
1655 if (!callback || !s || !udevman || !pdev)
1656 return ERROR_INVALID_PARAMETER;
1661 return ERROR_INVALID_PARAMETER;
1663 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1664 return ERROR_INVALID_DATA;
1666 Stream_Read_UINT32(s, CbTsUrb);
1667 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4ULL + CbTsUrb))
1668 return ERROR_INVALID_DATA;
1669 Stream_Read_UINT16(s, Size);
1670 if (Size != CbTsUrb)
1672 const char* section = (transferDir == USBD_TRANSFER_DIRECTION_IN)
1673 ?
"2.2.6.7 Transfer In Request (TRANSFER_IN_REQUEST)"
1674 :
"2.2.6.8 Transfer Out Request (TRANSFER_OUT_REQUEST)";
1676 "[MS-RDPEUSB] 2.2.9.1.1 TS_URB_HEADER::Size 0x04" PRIx16
1677 " != %s::CbTsUrb 0x%08" PRIx32,
1678 Size, section, CbTsUrb);
1679 return ERROR_INVALID_DATA;
1681 Stream_Read_UINT16(s, URB_Function);
1682 Stream_Read_UINT32(s, RequestId);
1683 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1686 switch (URB_Function)
1688 case TS_URB_SELECT_CONFIGURATION:
1689 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1693 case TS_URB_SELECT_INTERFACE:
1695 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1698 case TS_URB_PIPE_REQUEST:
1699 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1703 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1709 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1715 case TS_URB_GET_FRAME_LENGTH:
1721 case TS_URB_SET_FRAME_LENGTH:
1727 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1728 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1732 case TS_URB_CONTROL_TRANSFER:
1733 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1734 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1737 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1738 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1742 case TS_URB_ISOCH_TRANSFER:
1744 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1747 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1748 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1752 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1753 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1757 case TS_URB_SET_FEATURE_TO_DEVICE:
1758 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1759 0x00, URB_SET_FEATURE, transferDir);
1762 case TS_URB_SET_FEATURE_TO_INTERFACE:
1763 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1764 0x01, URB_SET_FEATURE, transferDir);
1767 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1768 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1769 0x02, URB_SET_FEATURE, transferDir);
1772 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1773 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1774 0x00, URB_CLEAR_FEATURE, transferDir);
1777 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1778 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1779 0x01, URB_CLEAR_FEATURE, transferDir);
1782 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1783 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1784 0x02, URB_CLEAR_FEATURE, transferDir);
1787 case TS_URB_GET_STATUS_FROM_DEVICE:
1788 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1792 case TS_URB_GET_STATUS_FROM_INTERFACE:
1793 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1797 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1798 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1802 case TS_URB_RESERVED_0X0016:
1805 case TS_URB_VENDOR_DEVICE:
1806 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1807 udevman, (0x02 << 5),
1811 case TS_URB_VENDOR_INTERFACE:
1812 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1813 udevman, (0x02 << 5),
1817 case TS_URB_VENDOR_ENDPOINT:
1818 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1819 udevman, (0x02 << 5),
1823 case TS_URB_CLASS_DEVICE:
1824 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1825 udevman, (0x01 << 5),
1829 case TS_URB_CLASS_INTERFACE:
1830 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1831 udevman, (0x01 << 5),
1835 case TS_URB_CLASS_ENDPOINT:
1836 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1837 udevman, (0x01 << 5),
1841 case TS_URB_RESERVE_0X001D:
1844 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1845 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1849 case TS_URB_CLASS_OTHER:
1850 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1851 udevman, (0x01 << 5),
1855 case TS_URB_VENDOR_OTHER:
1856 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1857 udevman, (0x02 << 5),
1861 case TS_URB_GET_STATUS_FROM_OTHER:
1862 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1866 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1867 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1868 0x03, URB_CLEAR_FEATURE, transferDir);
1871 case TS_URB_SET_FEATURE_TO_OTHER:
1872 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1873 0x03, URB_SET_FEATURE, transferDir);
1876 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1877 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1881 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1882 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1886 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1887 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1888 udevman, transferDir);
1891 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1892 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1893 udevman, transferDir);
1896 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1897 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1901 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1902 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1906 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1907 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1908 udevman, transferDir);
1911 case TS_URB_RESERVE_0X002B:
1912 case TS_URB_RESERVE_0X002C:
1913 case TS_URB_RESERVE_0X002D:
1914 case TS_URB_RESERVE_0X002E:
1915 case TS_URB_RESERVE_0X002F:
1919 case TS_URB_SYNC_RESET_PIPE:
1920 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1924 case TS_URB_SYNC_CLEAR_STALL:
1925 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1929 case TS_URB_CONTROL_TRANSFER_EX:
1930 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1931 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1935 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
1942 WLog_Print(urbdrc->log, WLOG_WARN,
1943 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1944 urb_function_string(URB_Function), URB_Function, error);
1951 IUDEVMAN* udevman,
wStream* data)
1953 UINT32 InterfaceId = 0;
1954 UINT32 MessageId = 0;
1955 UINT32 FunctionId = 0;
1956 IUDEVICE* pdev = NULL;
1957 UINT error = ERROR_INTERNAL_ERROR;
1959 if (!urbdrc || !data || !callback || !udevman)
1962 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1965 Stream_Rewind_UINT32(data);
1967 Stream_Read_UINT32(data, InterfaceId);
1968 Stream_Read_UINT32(data, MessageId);
1969 Stream_Read_UINT32(data, FunctionId);
1971 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1976 error = ERROR_SUCCESS;
1981 if (pdev->isChannelClosed(pdev))
1983 error = ERROR_SUCCESS;
1988 pdev->detach_kernel_driver(pdev);
1992 case CANCEL_REQUEST:
1993 error = urbdrc_process_cancel_request(pdev, data, udevman);
1996 case REGISTER_REQUEST_CALLBACK:
1997 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
2001 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
2004 case INTERNAL_IO_CONTROL:
2005 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
2008 case QUERY_DEVICE_TEXT:
2009 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
2012 case TRANSFER_IN_REQUEST:
2013 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2014 USBD_TRANSFER_DIRECTION_IN);
2017 case TRANSFER_OUT_REQUEST:
2018 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
2019 USBD_TRANSFER_DIRECTION_OUT);
2022 case RETRACT_DEVICE:
2023 error = urbdrc_process_retract_device_request(pdev, data, udevman);
2027 WLog_Print(urbdrc->log, WLOG_WARN,
2028 "urbdrc_process_udev_data_transfer:"
2029 " unknown FunctionId 0x%" PRIX32
"",
2037 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);