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"
33 static void usb_process_get_port_status(IUDEVICE* pdev,
wStream* out)
35 int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB);
40 Stream_Write_UINT32(out, 0x303);
44 Stream_Write_UINT32(out, 0x103);
49 Stream_Write_UINT32(out, 0x503);
55 wStream* out, UINT32 InterfaceId, UINT32 MessageId,
56 UINT32 RequestId, UINT32 usbd_status, UINT32 OutputBufferSize)
59 return ERROR_INVALID_PARAMETER;
61 if (Stream_Capacity(out) < OutputBufferSize + 36)
63 Stream_Free(out, TRUE);
64 return ERROR_INVALID_PARAMETER;
67 Stream_SetPosition(out, 0);
68 Stream_Write_UINT32(out, InterfaceId);
69 Stream_Write_UINT32(out, MessageId);
71 if (OutputBufferSize != 0)
72 Stream_Write_UINT32(out, URB_COMPLETION);
74 Stream_Write_UINT32(out, URB_COMPLETION_NO_DATA);
76 Stream_Write_UINT32(out, RequestId);
77 Stream_Write_UINT32(out, 8);
79 Stream_Write_UINT16(out, 8);
80 Stream_Write_UINT16(out, 0);
81 Stream_Write_UINT32(out, usbd_status);
82 Stream_Write_UINT32(out, 0);
83 Stream_Write_UINT32(out, OutputBufferSize);
84 Stream_Seek(out, OutputBufferSize);
87 return stream_write_and_free(callback->plugin, callback->channel, out);
89 Stream_Free(out, TRUE);
94 static wStream* urb_create_iocompletion(UINT32 InterfaceField, UINT32 MessageId, UINT32 RequestId,
95 UINT32 OutputBufferSize)
97 const UINT32 InterfaceId = (STREAM_ID_PROXY << 30) | (InterfaceField & 0x3FFFFFFF);
99 #if UINT32_MAX >= SIZE_MAX
100 if (OutputBufferSize > UINT32_MAX - 28ull)
104 wStream* out = Stream_New(NULL, OutputBufferSize + 28ull);
109 Stream_Write_UINT32(out, InterfaceId);
110 Stream_Write_UINT32(out, MessageId);
111 Stream_Write_UINT32(out, IOCONTROL_COMPLETION);
112 Stream_Write_UINT32(out, RequestId);
113 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
114 Stream_Write_UINT32(out, OutputBufferSize);
115 Stream_Write_UINT32(out, OutputBufferSize);
119 static UINT urbdrc_process_register_request_callback(IUDEVICE* pdev,
123 UINT32 NumRequestCompletion = 0;
124 UINT32 RequestCompletion = 0;
126 if (!callback || !s || !udevman || !pdev)
127 return ERROR_INVALID_PARAMETER;
132 return ERROR_INVALID_PARAMETER;
134 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urbdrc_process_register_request_callback");
136 if (Stream_GetRemainingLength(s) >= 8)
138 Stream_Read_UINT32(s, NumRequestCompletion);
141 Stream_Read_UINT32(s, RequestCompletion);
142 pdev->set_ReqCompletion(pdev, RequestCompletion);
144 else if (Stream_GetRemainingLength(s) >= 4)
146 Stream_Read_UINT32(s, RequestCompletion);
148 if (pdev->get_ReqCompletion(pdev) == RequestCompletion)
149 pdev->setChannelClosed(pdev);
152 return ERROR_INVALID_DATA;
154 return ERROR_SUCCESS;
157 static UINT urbdrc_process_cancel_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
162 if (!s || !udevman || !pdev)
163 return ERROR_INVALID_PARAMETER;
167 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
168 return ERROR_INVALID_DATA;
170 Stream_Read_UINT32(s, CancelId);
171 WLog_Print(urbdrc->log, WLOG_DEBUG,
"CANCEL_REQUEST: CancelId=%08" PRIx32
"", CancelId);
173 if (pdev->cancel_transfer_request(pdev, CancelId) < 0)
174 return ERROR_INTERNAL_ERROR;
176 return ERROR_SUCCESS;
179 static UINT urbdrc_process_retract_device_request(IUDEVICE* pdev,
wStream* s, IUDEVMAN* udevman)
185 return ERROR_INVALID_PARAMETER;
190 return ERROR_INVALID_PARAMETER;
192 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
193 return ERROR_INVALID_DATA;
195 Stream_Read_UINT32(s, Reason);
199 case UsbRetractReason_BlockedByPolicy:
200 WLog_Print(urbdrc->log, WLOG_DEBUG,
201 "UsbRetractReason_BlockedByPolicy: now it is not support");
202 return ERROR_ACCESS_DENIED;
205 WLog_Print(urbdrc->log, WLOG_DEBUG,
206 "urbdrc_process_retract_device_request: Unknown Reason %" PRIu32
"", Reason);
207 return ERROR_ACCESS_DENIED;
210 return ERROR_SUCCESS;
214 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
216 UINT32 InterfaceId = 0;
217 UINT32 IoControlCode = 0;
218 UINT32 InputBufferSize = 0;
219 UINT32 OutputBufferSize = 0;
220 UINT32 RequestId = 0;
221 UINT32 usbd_status = USBD_STATUS_SUCCESS;
226 if (!callback || !s || !udevman || !pdev)
227 return ERROR_INVALID_PARAMETER;
232 return ERROR_INVALID_PARAMETER;
234 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
235 return ERROR_INVALID_DATA;
237 Stream_Read_UINT32(s, IoControlCode);
238 Stream_Read_UINT32(s, InputBufferSize);
240 if (!Stream_SafeSeek(s, InputBufferSize))
241 return ERROR_INVALID_DATA;
242 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
243 return ERROR_INVALID_DATA;
245 Stream_Read_UINT32(s, OutputBufferSize);
246 Stream_Read_UINT32(s, RequestId);
248 if (OutputBufferSize > UINT32_MAX - 4)
249 return ERROR_INVALID_DATA;
251 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
252 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, OutputBufferSize + 4);
255 return ERROR_OUTOFMEMORY;
257 switch (IoControlCode)
259 case IOCTL_INTERNAL_USB_SUBMIT_URB:
260 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB");
261 WLog_Print(urbdrc->log, WLOG_ERROR,
262 " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked");
265 case IOCTL_INTERNAL_USB_RESET_PORT:
266 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_RESET_PORT");
269 case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
270 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS");
271 success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize,
272 Stream_Pointer(out));
276 if (!Stream_SafeSeek(out, OutputBufferSize))
278 Stream_Free(out, TRUE);
279 return ERROR_INVALID_DATA;
282 if (pdev->isExist(pdev) == 0)
283 Stream_Write_UINT32(out, 0);
285 usb_process_get_port_status(pdev, out);
290 case IOCTL_INTERNAL_USB_CYCLE_PORT:
291 WLog_Print(urbdrc->log, WLOG_DEBUG,
"ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT");
292 WLog_Print(urbdrc->log, WLOG_ERROR,
293 " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked");
296 case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
297 WLog_Print(urbdrc->log, WLOG_DEBUG,
298 "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION");
299 WLog_Print(urbdrc->log, WLOG_ERROR,
300 " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked");
304 WLog_Print(urbdrc->log, WLOG_DEBUG,
305 "urbdrc_process_io_control: unknown IoControlCode 0x%" PRIX32
"",
307 Stream_Free(out, TRUE);
308 return ERROR_INVALID_OPERATION;
311 return stream_write_and_free(callback->plugin, callback->channel, out);
315 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
318 UINT32 IoControlCode = 0;
319 UINT32 InterfaceId = 0;
320 UINT32 InputBufferSize = 0;
321 UINT32 OutputBufferSize = 0;
322 UINT32 RequestId = 0;
325 if (!pdev || !callback || !s || !udevman)
326 return ERROR_INVALID_PARAMETER;
328 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
329 return ERROR_INVALID_DATA;
331 Stream_Read_UINT32(s, IoControlCode);
332 Stream_Read_UINT32(s, InputBufferSize);
334 if (!Stream_SafeSeek(s, InputBufferSize))
335 return ERROR_INVALID_DATA;
336 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8ULL))
337 return ERROR_INVALID_DATA;
338 Stream_Read_UINT32(s, OutputBufferSize);
339 Stream_Read_UINT32(s, RequestId);
340 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
343 frames = GetTickCount();
344 out = urb_create_iocompletion(InterfaceId, MessageId, RequestId, 4);
347 return ERROR_OUTOFMEMORY;
349 Stream_Write_UINT32(out, frames);
350 return stream_write_and_free(callback->plugin, callback->channel, out);
354 wStream* s, UINT32 MessageId, IUDEVMAN* udevman)
359 UINT32 InterfaceId = 0;
360 UINT8 bufferSize = 0xFF;
363 BYTE DeviceDescription[0x100] = { 0 };
365 if (!pdev || !callback || !s || !udevman)
366 return ERROR_INVALID_PARAMETER;
367 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
368 return ERROR_INVALID_DATA;
370 Stream_Read_UINT32(s, TextType);
371 Stream_Read_UINT32(s, LocaleId);
372 if (LocaleId > UINT16_MAX)
373 return ERROR_INVALID_DATA;
375 hr = pdev->control_query_device_text(pdev, TextType, (UINT16)LocaleId, &bufferSize,
377 InterfaceId = ((STREAM_ID_STUB << 30) | pdev->get_UsbDevice(pdev));
378 out_size = 16 + bufferSize;
383 out = Stream_New(NULL, out_size);
386 return ERROR_OUTOFMEMORY;
388 Stream_Write_UINT32(out, InterfaceId);
389 Stream_Write_UINT32(out, MessageId);
390 Stream_Write_UINT32(out, bufferSize / 2);
391 Stream_Write(out, DeviceDescription, bufferSize);
392 Stream_Write_UINT32(out, hr);
393 return stream_write_and_free(callback->plugin, callback->channel, out);
396 static void func_select_all_interface_for_msconfig(IUDEVICE* pdev,
400 BYTE InterfaceNumber = 0;
401 BYTE AlternateSetting = 0;
402 UINT32 NumInterfaces = MsConfig->NumInterfaces;
404 for (UINT32 inum = 0; inum < NumInterfaces; inum++)
406 InterfaceNumber = MsInterfaces[inum]->InterfaceNumber;
407 AlternateSetting = MsInterfaces[inum]->AlternateSetting;
408 pdev->select_interface(pdev, InterfaceNumber, AlternateSetting);
413 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
418 UINT32 InterfaceId = 0;
419 UINT32 NumInterfaces = 0;
420 UINT32 usbd_status = 0;
421 BYTE ConfigurationDescriptorIsValid = 0;
423 size_t MsOutSize = 0;
425 const BOOL noAck = (RequestField & 0x80000000U) != 0;
426 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
428 if (!callback || !s || !udevman || !pdev)
429 return ERROR_INVALID_PARAMETER;
434 return ERROR_INVALID_PARAMETER;
436 if (transferDir == 0)
438 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_configuration: unsupported transfer out");
439 return ERROR_INVALID_PARAMETER;
442 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
443 return ERROR_INVALID_DATA;
445 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
446 Stream_Read_UINT8(s, ConfigurationDescriptorIsValid);
448 Stream_Read_UINT32(s, NumInterfaces);
451 if (ConfigurationDescriptorIsValid)
454 MsConfig = msusb_msconfig_read(s, NumInterfaces);
457 return ERROR_INVALID_DATA;
460 pdev->select_configuration(pdev, MsConfig->bConfigurationValue);
462 func_select_all_interface_for_msconfig(pdev, MsConfig);
464 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
466 msusb_msconfig_free(MsConfig);
472 MsOutSize = WINPR_ASSERTING_INT_CAST(
size_t, MsConfig->MsOutSize);
476 if (MsOutSize > SIZE_MAX - 36)
477 return ERROR_INVALID_DATA;
479 out_size = 36 + MsOutSize;
484 out = Stream_New(NULL, out_size);
487 return ERROR_OUTOFMEMORY;
489 Stream_Write_UINT32(out, InterfaceId);
490 Stream_Write_UINT32(out, MessageId);
491 Stream_Write_UINT32(out, URB_COMPLETION_NO_DATA);
492 Stream_Write_UINT32(out, RequestId);
497 Stream_Write_UINT32(out, 8U + (UINT32)MsOutSize);
499 Stream_Write_UINT16(out, WINPR_ASSERTING_INT_CAST(uint16_t, 8U + (UINT32)MsOutSize));
503 Stream_Write_UINT32(out, 16);
504 Stream_Write_UINT16(out, 16);
508 Stream_Write_UINT16(out, TS_URB_SELECT_CONFIGURATION);
509 Stream_Write_UINT32(out, usbd_status);
513 msusb_msconfig_write(MsConfig, out);
516 Stream_Write_UINT32(out, 0);
517 Stream_Write_UINT32(out, NumInterfaces);
520 Stream_Write_UINT32(out, 0);
521 Stream_Write_UINT32(out, 0);
524 return stream_write_and_free(callback->plugin, callback->channel, out);
526 Stream_Free(out, TRUE);
528 return ERROR_SUCCESS;
532 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
538 UINT32 InterfaceId = 0;
539 UINT32 ConfigurationHandle = 0;
540 UINT32 OutputBufferSize = 0;
541 BYTE InterfaceNumber = 0;
543 UINT32 interface_size = 0;
545 const BOOL noAck = (RequestField & 0x80000000U) != 0;
546 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
548 if (!callback || !s || !udevman || !pdev)
549 return ERROR_INVALID_PARAMETER;
554 return ERROR_INVALID_PARAMETER;
556 if (transferDir == 0)
558 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_select_interface: not support transfer out");
559 return ERROR_INVALID_PARAMETER;
562 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
563 return ERROR_INVALID_DATA;
565 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
566 Stream_Read_UINT32(s, ConfigurationHandle);
567 MsInterface = msusb_msinterface_read(s);
569 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4) || !MsInterface)
571 msusb_msinterface_free(MsInterface);
572 return ERROR_INVALID_DATA;
575 Stream_Read_UINT32(s, OutputBufferSize);
576 pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting);
578 MsConfig = pdev->get_MsConfig(pdev);
579 InterfaceNumber = MsInterface->InterfaceNumber;
580 if (!msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface))
582 msusb_msconfig_free(MsConfig);
583 return ERROR_BAD_CONFIGURATION;
586 if (!pdev->complete_msconfig_setup(pdev, MsConfig))
588 msusb_msconfig_free(MsConfig);
589 return ERROR_BAD_CONFIGURATION;
591 MsInterface = MsConfig->MsInterfaces[InterfaceNumber];
592 interface_size = 16 + (MsInterface->NumberOfPipes * 20);
593 out_size = 36 + interface_size;
594 out = Stream_New(NULL, out_size);
597 return ERROR_OUTOFMEMORY;
599 Stream_Write_UINT32(out, InterfaceId);
600 Stream_Write_UINT32(out, MessageId);
601 Stream_Write_UINT32(out, URB_COMPLETION_NO_DATA);
602 Stream_Write_UINT32(out, RequestId);
603 Stream_Write_UINT32(out, 8 + interface_size);
605 Stream_Write_UINT16(out, WINPR_ASSERTING_INT_CAST(uint16_t, 8 + interface_size));
607 Stream_Write_UINT16(out, TS_URB_SELECT_INTERFACE);
608 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
610 msusb_msinterface_write(MsInterface, out);
611 Stream_Write_UINT32(out, 0);
612 Stream_Write_UINT32(out, 0);
615 return stream_write_and_free(callback->plugin, callback->channel, out);
617 Stream_Free(out, TRUE);
619 return ERROR_SUCCESS;
623 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
624 int transferDir,
int External)
627 UINT32 InterfaceId = 0;
628 UINT32 EndpointAddress = 0;
629 UINT32 PipeHandle = 0;
630 UINT32 TransferFlags = 0;
631 UINT32 OutputBufferSize = 0;
632 UINT32 usbd_status = 0;
634 BYTE bmRequestType = 0;
642 const BOOL noAck = (RequestField & 0x80000000U) != 0;
643 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
645 if (!callback || !s || !udevman || !pdev)
646 return ERROR_INVALID_PARAMETER;
651 return ERROR_INVALID_PARAMETER;
653 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
654 return ERROR_INVALID_DATA;
656 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
657 Stream_Read_UINT32(s, PipeHandle);
658 Stream_Read_UINT32(s, TransferFlags);
659 EndpointAddress = (PipeHandle & 0x000000ff);
664 case URB_CONTROL_TRANSFER_EXTERNAL:
665 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
666 return ERROR_INVALID_DATA;
668 Stream_Read_UINT32(s, Timeout);
671 case URB_CONTROL_TRANSFER_NONEXTERNAL:
678 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
679 return ERROR_INVALID_DATA;
681 Stream_Read_UINT8(s, bmRequestType);
682 Stream_Read_UINT8(s, Request);
683 Stream_Read_UINT16(s, Value);
684 Stream_Read_UINT16(s, Index);
685 Stream_Read_UINT16(s, length);
686 Stream_Read_UINT32(s, OutputBufferSize);
688 if (length != OutputBufferSize)
690 WLog_Print(urbdrc->log, WLOG_ERROR,
"urb_control_transfer ERROR: buf != length");
691 return ERROR_INVALID_DATA;
694 out_size = 36 + OutputBufferSize;
695 out = Stream_New(NULL, out_size);
698 return ERROR_OUTOFMEMORY;
700 Stream_Seek(out, 36);
702 buffer = Stream_Pointer(out);
704 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
706 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
708 Stream_Free(out, TRUE);
709 return ERROR_INVALID_DATA;
711 Stream_Copy(s, out, OutputBufferSize);
715 if (!pdev->control_transfer(pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType,
716 Request, Value, Index, &usbd_status, &OutputBufferSize, buffer,
719 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
720 Stream_Free(out, TRUE);
721 return ERROR_INTERNAL_ERROR;
724 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
725 usbd_status, OutputBufferSize);
729 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId, UINT32 RequestId,
730 UINT32 NumberOfPackets, UINT32 status, UINT32 StartFrame,
731 UINT32 ErrorCount, UINT32 OutputBufferSize)
733 if (!pdev->isChannelClosed(pdev))
734 urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, status,
737 Stream_Free(out, TRUE);
741 wStream* s, UINT32 RequestField, UINT32 MessageId,
742 IUDEVMAN* udevman,
int transferDir)
744 UINT32 EndpointAddress = 0;
745 UINT32 PipeHandle = 0;
746 UINT32 TransferFlags = 0;
747 UINT32 OutputBufferSize = 0;
748 const BOOL noAck = (RequestField & 0x80000000U) != 0;
749 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
751 if (!pdev || !callback || !s || !udevman)
752 return ERROR_INVALID_PARAMETER;
754 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
755 return ERROR_INVALID_DATA;
757 Stream_Read_UINT32(s, PipeHandle);
758 Stream_Read_UINT32(s, TransferFlags);
759 Stream_Read_UINT32(s, OutputBufferSize);
760 EndpointAddress = (PipeHandle & 0x000000ff);
762 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
764 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
766 return ERROR_INVALID_DATA;
771 const int rc = pdev->bulk_or_interrupt_transfer(
772 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, noAck,
773 OutputBufferSize, (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
774 urb_bulk_transfer_cb, 10000);
780 UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
781 UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
782 UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize)
786 UINT32 packetSize = (status == 0) ? NumberOfPackets * 12 : 0;
787 Stream_SetPosition(out, 0);
789 Stream_Write_UINT32(out, InterfaceId);
790 Stream_Write_UINT32(out, MessageId);
792 if (OutputBufferSize == 0)
793 Stream_Write_UINT32(out, URB_COMPLETION_NO_DATA);
795 Stream_Write_UINT32(out, URB_COMPLETION);
797 Stream_Write_UINT32(out, RequestId);
798 Stream_Write_UINT32(out, 20 + packetSize);
800 Stream_Write_UINT16(out, WINPR_ASSERTING_INT_CAST(uint16_t, 20 + packetSize));
801 Stream_Write_UINT16(out, 0);
802 Stream_Write_UINT32(out, status);
803 Stream_Write_UINT32(out, StartFrame);
808 Stream_Write_UINT32(out, NumberOfPackets);
809 Stream_Write_UINT32(out, ErrorCount);
810 Stream_Seek(out, packetSize);
814 Stream_Write_UINT32(out, 0);
815 Stream_Write_UINT32(out, ErrorCount);
818 Stream_Write_UINT32(out, 0);
819 Stream_Write_UINT32(out, OutputBufferSize);
820 Stream_Seek(out, OutputBufferSize);
822 stream_write_and_free(callback->plugin, callback->channel, out);
827 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
831 UINT32 EndpointAddress = 0;
832 UINT32 PipeHandle = 0;
833 UINT32 TransferFlags = 0;
834 UINT32 StartFrame = 0;
835 UINT32 NumberOfPackets = 0;
836 UINT32 ErrorCount = 0;
837 UINT32 OutputBufferSize = 0;
838 BYTE* packetDescriptorData = NULL;
839 const BOOL noAck = (RequestField & 0x80000000U) != 0;
840 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
842 if (!pdev || !callback || !udevman)
843 return ERROR_INVALID_PARAMETER;
845 if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
846 return ERROR_INVALID_DATA;
848 Stream_Read_UINT32(s, PipeHandle);
849 EndpointAddress = (PipeHandle & 0x000000ff);
850 Stream_Read_UINT32(s, TransferFlags);
851 Stream_Read_UINT32(s, StartFrame);
852 Stream_Read_UINT32(s, NumberOfPackets);
853 Stream_Read_UINT32(s, ErrorCount);
855 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, NumberOfPackets, 12ull))
856 return ERROR_INVALID_DATA;
858 packetDescriptorData = Stream_Pointer(s);
859 Stream_Seek(s, 12ULL * NumberOfPackets);
861 if (!Stream_CheckAndLogRequiredLength(TAG, s,
sizeof(UINT32)))
862 return ERROR_INVALID_DATA;
863 Stream_Read_UINT32(s, OutputBufferSize);
865 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
867 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
868 return ERROR_INVALID_DATA;
871 rc = pdev->isoch_transfer(
872 pdev, callback, MessageId, RequestId, EndpointAddress, TransferFlags, StartFrame,
873 ErrorCount, noAck, packetDescriptorData, NumberOfPackets, OutputBufferSize,
874 (transferDir == USBD_TRANSFER_DIRECTION_OUT) ? Stream_Pointer(s) : NULL,
875 urb_isoch_transfer_cb, 2000);
878 return ERROR_INTERNAL_ERROR;
883 wStream* s, UINT32 RequestField, UINT32 MessageId,
884 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
887 UINT32 InterfaceId = 0;
888 UINT32 OutputBufferSize = 0;
889 UINT32 usbd_status = 0;
890 BYTE bmRequestType = 0;
896 const BOOL noAck = (RequestField & 0x80000000U) != 0;
897 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
899 if (!callback || !s || !udevman || !pdev)
900 return ERROR_INVALID_PARAMETER;
905 return ERROR_INVALID_PARAMETER;
907 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
908 return ERROR_INVALID_DATA;
910 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
911 Stream_Read_UINT8(s, desc_index);
912 Stream_Read_UINT8(s, desc_type);
913 Stream_Read_UINT16(s, langId);
914 Stream_Read_UINT32(s, OutputBufferSize);
915 if (OutputBufferSize > UINT32_MAX - 36)
916 return ERROR_INVALID_DATA;
917 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
919 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
920 return ERROR_INVALID_DATA;
923 out_size = 36ULL + OutputBufferSize;
924 out = Stream_New(NULL, out_size);
927 return ERROR_OUTOFMEMORY;
929 Stream_Seek(out, 36);
930 bmRequestType = func_recipient;
934 case USBD_TRANSFER_DIRECTION_IN:
935 bmRequestType |= 0x80;
938 case USBD_TRANSFER_DIRECTION_OUT:
939 bmRequestType |= 0x00;
940 Stream_Copy(s, out, OutputBufferSize);
941 Stream_Rewind(out, OutputBufferSize);
945 WLog_Print(urbdrc->log, WLOG_DEBUG,
"get error transferDir");
946 OutputBufferSize = 0;
947 usbd_status = USBD_STATUS_STALL_PID;
952 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType,
954 WINPR_ASSERTING_INT_CAST(UINT16, ((desc_type << 8) | desc_index)),
955 langId, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
957 WLog_Print(urbdrc->log, WLOG_ERROR,
"get_descriptor failed");
958 Stream_Free(out, TRUE);
959 return ERROR_INTERNAL_ERROR;
962 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
963 usbd_status, OutputBufferSize);
967 wStream* s, UINT32 RequestField, UINT32 MessageId,
968 IUDEVMAN* udevman, BYTE func_recipient,
int transferDir)
971 UINT32 InterfaceId = 0;
972 UINT32 OutputBufferSize = 0;
973 UINT32 usbd_status = 0;
975 BYTE bmRequestType = 0;
978 const BOOL noAck = (RequestField & 0x80000000U) != 0;
979 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
981 if (!callback || !s || !udevman || !pdev)
982 return ERROR_INVALID_PARAMETER;
987 return ERROR_INVALID_PARAMETER;
989 if (transferDir == 0)
991 WLog_Print(urbdrc->log, WLOG_DEBUG,
992 "urb_control_get_status_request: transfer out not supported");
993 return ERROR_INVALID_PARAMETER;
996 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
997 return ERROR_INVALID_DATA;
999 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1000 Stream_Read_UINT16(s, Index);
1002 Stream_Read_UINT32(s, OutputBufferSize);
1003 if (OutputBufferSize > UINT32_MAX - 36)
1004 return ERROR_INVALID_DATA;
1005 out_size = 36ULL + OutputBufferSize;
1006 out = Stream_New(NULL, out_size);
1009 return ERROR_OUTOFMEMORY;
1011 Stream_Seek(out, 36);
1012 bmRequestType = func_recipient | 0x80;
1014 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, 0x00,
1015 0, Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out),
1018 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1019 Stream_Free(out, TRUE);
1020 return ERROR_INTERNAL_ERROR;
1023 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1024 usbd_status, OutputBufferSize);
1028 wStream* s, UINT32 RequestField, UINT32 MessageId,
1029 IUDEVMAN* udevman, BYTE func_type,
1030 BYTE func_recipient,
int transferDir)
1032 UINT32 out_size = 0;
1033 UINT32 InterfaceId = 0;
1034 UINT32 TransferFlags = 0;
1035 UINT32 usbd_status = 0;
1036 UINT32 OutputBufferSize = 0;
1037 BYTE ReqTypeReservedBits = 0;
1039 BYTE bmRequestType = 0;
1044 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1045 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1047 if (!callback || !s || !udevman || !pdev)
1048 return ERROR_INVALID_PARAMETER;
1053 return ERROR_INVALID_PARAMETER;
1055 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
1056 return ERROR_INVALID_DATA;
1058 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1059 Stream_Read_UINT32(s, TransferFlags);
1060 Stream_Read_UINT8(s, ReqTypeReservedBits);
1061 Stream_Read_UINT8(s, Request);
1062 Stream_Read_UINT16(s, Value);
1063 Stream_Read_UINT16(s, Index);
1064 Stream_Seek_UINT16(s);
1065 Stream_Read_UINT32(s, OutputBufferSize);
1066 if (OutputBufferSize > UINT32_MAX - 36)
1067 return ERROR_INVALID_DATA;
1069 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1071 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1072 return ERROR_INVALID_DATA;
1075 out_size = 36ULL + OutputBufferSize;
1076 out = Stream_New(NULL, out_size);
1079 return ERROR_OUTOFMEMORY;
1081 Stream_Seek(out, 36);
1084 if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
1086 Stream_Copy(s, out, OutputBufferSize);
1087 Stream_Rewind(out, OutputBufferSize);
1091 bmRequestType = func_type | func_recipient;
1093 if (TransferFlags & USBD_TRANSFER_DIRECTION)
1094 bmRequestType |= 0x80;
1096 WLog_Print(urbdrc->log, WLOG_DEBUG,
1097 "RequestId 0x%" PRIx32
" TransferFlags: 0x%" PRIx32
" ReqTypeReservedBits: 0x%" PRIx8
1099 "Request:0x%" PRIx8
" Value: 0x%" PRIx16
" Index: 0x%" PRIx16
1100 " OutputBufferSize: 0x%" PRIx32
" bmRequestType: 0x%" PRIx8,
1101 RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index,
1102 OutputBufferSize, bmRequestType);
1104 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index,
1105 &usbd_status, &OutputBufferSize, Stream_Pointer(out), 2000))
1107 WLog_Print(urbdrc->log, WLOG_ERROR,
"control_transfer failed");
1108 Stream_Free(out, TRUE);
1109 return ERROR_INTERNAL_ERROR;
1112 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1113 usbd_status, OutputBufferSize);
1117 wStream* s, UINT32 RequestField, UINT32 MessageId,
1118 IUDEVMAN* udevman,
int transferDir)
1120 size_t out_size = 0;
1121 UINT32 InterfaceId = 0;
1122 UINT32 OutputBufferSize = 0;
1123 UINT32 usbd_status = 0;
1125 BYTE InterfaceNumber = 0;
1126 BYTE Ms_PageIndex = 0;
1127 UINT16 Ms_featureDescIndex = 0;
1131 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1132 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1134 if (!callback || !s || !udevman || !pdev)
1135 return ERROR_INVALID_PARAMETER;
1140 return ERROR_INVALID_PARAMETER;
1142 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1143 return ERROR_INVALID_DATA;
1146 Stream_Read_UINT8(s, Recipient);
1147 Recipient = (Recipient & 0x1f);
1148 Stream_Read_UINT8(s, InterfaceNumber);
1149 Stream_Read_UINT8(s, Ms_PageIndex);
1150 Stream_Read_UINT16(s, Ms_featureDescIndex);
1152 Stream_Read_UINT32(s, OutputBufferSize);
1153 if (OutputBufferSize > UINT32_MAX - 36)
1154 return ERROR_INVALID_DATA;
1156 switch (transferDir)
1158 case USBD_TRANSFER_DIRECTION_OUT:
1159 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1160 return ERROR_INVALID_DATA;
1168 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1169 out_size = 36ULL + OutputBufferSize;
1170 out = Stream_New(NULL, out_size);
1173 return ERROR_OUTOFMEMORY;
1175 Stream_Seek(out, 36);
1177 switch (transferDir)
1179 case USBD_TRANSFER_DIRECTION_OUT:
1180 Stream_Copy(s, out, OutputBufferSize);
1181 Stream_Rewind(out, OutputBufferSize);
1184 case USBD_TRANSFER_DIRECTION_IN:
1190 WLog_Print(urbdrc->log, WLOG_DEBUG,
1191 "Ms descriptor arg: Recipient:0x%" PRIx8
", "
1192 "InterfaceNumber:0x%" PRIx8
", Ms_PageIndex:0x%" PRIx8
", "
1193 "Ms_featureDescIndex:0x%" PRIx16
", OutputBufferSize:0x%" PRIx32
"",
1194 Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize);
1196 ret = pdev->os_feature_descriptor_request(pdev, RequestId, Recipient, InterfaceNumber,
1197 Ms_PageIndex, Ms_featureDescIndex, &usbd_status,
1198 &OutputBufferSize, Stream_Pointer(out), 1000);
1201 WLog_Print(urbdrc->log, WLOG_DEBUG,
"os_feature_descriptor_request: error num %d", ret);
1203 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1204 usbd_status, OutputBufferSize);
1208 UINT32 RequestField, UINT32 MessageId, IUDEVMAN* udevman,
1209 int transferDir,
int action)
1211 UINT32 out_size = 0;
1212 UINT32 InterfaceId = 0;
1213 UINT32 PipeHandle = 0;
1214 UINT32 EndpointAddress = 0;
1215 UINT32 OutputBufferSize = 0;
1216 UINT32 usbd_status = 0;
1218 UINT32 ret = USBD_STATUS_REQUEST_FAILED;
1221 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1222 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1224 if (!callback || !s || !udevman || !pdev)
1225 return ERROR_INVALID_PARAMETER;
1230 return ERROR_INVALID_PARAMETER;
1232 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1233 return ERROR_INVALID_DATA;
1235 if (transferDir == 0)
1237 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: not support transfer out");
1238 return ERROR_INVALID_PARAMETER;
1241 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1242 Stream_Read_UINT32(s, PipeHandle);
1243 Stream_Read_UINT32(s, OutputBufferSize);
1244 EndpointAddress = (PipeHandle & 0x000000ff);
1249 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1253 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE SET HALT: error %d", ret);
1255 ret = USBD_STATUS_SUCCESS;
1260 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request: PIPE_RESET ep 0x%" PRIx32
"",
1262 rc = pdev->control_pipe_request(pdev, RequestId, EndpointAddress, &usbd_status,
1266 WLog_Print(urbdrc->log, WLOG_DEBUG,
"PIPE RESET: error %d", ret);
1268 ret = USBD_STATUS_SUCCESS;
1273 WLog_Print(urbdrc->log, WLOG_DEBUG,
"urb_pipe_request action: %d not supported",
1275 ret = USBD_STATUS_INVALID_URB_FUNCTION;
1281 out = Stream_New(NULL, out_size);
1284 return ERROR_OUTOFMEMORY;
1286 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId, ret,
1291 wStream* s, UINT32 RequestField, UINT32 MessageId,
1292 IUDEVMAN* udevman,
int transferDir)
1294 UINT32 out_size = 0;
1295 UINT32 InterfaceId = 0;
1296 UINT32 OutputBufferSize = 0;
1297 UINT32 dummy_frames = 0;
1300 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1301 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1303 if (!callback || !s || !udevman || !pdev)
1304 return ERROR_INVALID_PARAMETER;
1309 return ERROR_INVALID_PARAMETER;
1311 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1312 return ERROR_INVALID_DATA;
1314 if (transferDir == 0)
1316 WLog_Print(urbdrc->log, WLOG_DEBUG,
1317 "urb_get_current_frame_number: not support transfer out");
1318 return ERROR_INVALID_PARAMETER;
1321 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1322 Stream_Read_UINT32(s, OutputBufferSize);
1324 dummy_frames = GetTickCount();
1326 out = Stream_New(NULL, out_size);
1329 return ERROR_OUTOFMEMORY;
1331 Stream_Write_UINT32(out, InterfaceId);
1332 Stream_Write_UINT32(out, MessageId);
1333 Stream_Write_UINT32(out, URB_COMPLETION_NO_DATA);
1334 Stream_Write_UINT32(out, RequestId);
1335 Stream_Write_UINT32(out, 12);
1337 Stream_Write_UINT16(out, 12);
1339 Stream_Write_UINT16(out, TS_URB_GET_CURRENT_FRAME_NUMBER);
1340 Stream_Write_UINT32(out, USBD_STATUS_SUCCESS);
1341 Stream_Write_UINT32(out, dummy_frames);
1342 Stream_Write_UINT32(out, 0);
1343 Stream_Write_UINT32(out, 0);
1346 return stream_write_and_free(callback->plugin, callback->channel, out);
1348 Stream_Free(out, TRUE);
1350 return ERROR_SUCCESS;
1354 static UINT urb_control_get_configuration_request(IUDEVICE* pdev,
1356 UINT32 RequestField, UINT32 MessageId,
1357 IUDEVMAN* udevman,
int transferDir)
1359 size_t out_size = 0;
1360 UINT32 InterfaceId = 0;
1361 UINT32 OutputBufferSize = 0;
1362 UINT32 usbd_status = 0;
1365 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1366 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1368 if (!callback || !s || !udevman || !pdev)
1369 return ERROR_INVALID_PARAMETER;
1374 return ERROR_INVALID_PARAMETER;
1376 if (transferDir == 0)
1378 WLog_Print(urbdrc->log, WLOG_DEBUG,
1379 "urb_control_get_configuration_request:"
1380 " not support transfer out");
1381 return ERROR_INVALID_PARAMETER;
1384 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1385 return ERROR_INVALID_DATA;
1387 Stream_Read_UINT32(s, OutputBufferSize);
1388 if (OutputBufferSize > UINT32_MAX - 36)
1389 return ERROR_INVALID_DATA;
1390 out_size = 36ULL + OutputBufferSize;
1391 out = Stream_New(NULL, out_size);
1394 return ERROR_OUTOFMEMORY;
1396 Stream_Seek(out, 36);
1397 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1399 if (!pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x00,
1401 0, 0, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1403 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1404 Stream_Free(out, TRUE);
1405 return ERROR_INTERNAL_ERROR;
1408 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1409 usbd_status, OutputBufferSize);
1414 wStream* s, UINT32 RequestField, UINT32 MessageId,
1415 IUDEVMAN* udevman,
int transferDir)
1417 size_t out_size = 0;
1418 UINT32 InterfaceId = 0;
1419 UINT32 OutputBufferSize = 0;
1420 UINT32 usbd_status = 0;
1421 UINT16 InterfaceNr = 0;
1424 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1425 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1427 if (!callback || !s || !udevman || !pdev)
1428 return ERROR_INVALID_PARAMETER;
1433 return ERROR_INVALID_PARAMETER;
1435 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1436 return ERROR_INVALID_DATA;
1438 if (transferDir == 0)
1440 WLog_Print(urbdrc->log, WLOG_DEBUG,
1441 "urb_control_get_interface_request: not support transfer out");
1442 return ERROR_INVALID_PARAMETER;
1445 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1446 Stream_Read_UINT16(s, InterfaceNr);
1448 Stream_Read_UINT32(s, OutputBufferSize);
1449 if (OutputBufferSize > UINT32_MAX - 36)
1450 return ERROR_INVALID_DATA;
1451 out_size = 36ULL + OutputBufferSize;
1452 out = Stream_New(NULL, out_size);
1455 return ERROR_OUTOFMEMORY;
1457 Stream_Seek(out, 36);
1459 if (!pdev->control_transfer(
1460 pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A,
1461 0, InterfaceNr, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1463 WLog_Print(urbdrc->log, WLOG_DEBUG,
"control_transfer failed");
1464 Stream_Free(out, TRUE);
1465 return ERROR_INTERNAL_ERROR;
1468 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1469 usbd_status, OutputBufferSize);
1473 wStream* s, UINT32 RequestField, UINT32 MessageId,
1474 IUDEVMAN* udevman, BYTE func_recipient, BYTE command,
1477 UINT32 InterfaceId = 0;
1478 UINT32 OutputBufferSize = 0;
1479 UINT32 usbd_status = 0;
1480 UINT16 FeatureSelector = 0;
1482 BYTE bmRequestType = 0;
1486 const BOOL noAck = (RequestField & 0x80000000U) != 0;
1487 const UINT32 RequestId = RequestField & 0x7FFFFFFF;
1489 if (!callback || !s || !udevman || !pdev)
1490 return ERROR_INVALID_PARAMETER;
1495 return ERROR_INVALID_PARAMETER;
1497 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1498 return ERROR_INVALID_DATA;
1500 InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev));
1501 Stream_Read_UINT16(s, FeatureSelector);
1502 Stream_Read_UINT16(s, Index);
1503 Stream_Read_UINT32(s, OutputBufferSize);
1504 if (OutputBufferSize > UINT32_MAX - 36)
1505 return ERROR_INVALID_DATA;
1506 switch (transferDir)
1508 case USBD_TRANSFER_DIRECTION_OUT:
1509 if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
1510 return ERROR_INVALID_DATA;
1518 out = Stream_New(NULL, 36ULL + OutputBufferSize);
1521 return ERROR_OUTOFMEMORY;
1523 Stream_Seek(out, 36);
1524 bmRequestType = func_recipient;
1526 switch (transferDir)
1528 case USBD_TRANSFER_DIRECTION_OUT:
1529 WLog_Print(urbdrc->log, WLOG_ERROR,
1530 "Function urb_control_feature_request: OUT Unchecked");
1531 Stream_Copy(s, out, OutputBufferSize);
1532 Stream_Rewind(out, OutputBufferSize);
1533 bmRequestType |= 0x00;
1536 case USBD_TRANSFER_DIRECTION_IN:
1537 bmRequestType |= 0x80;
1545 case URB_SET_FEATURE:
1549 case URB_CLEAR_FEATURE:
1554 WLog_Print(urbdrc->log, WLOG_ERROR,
1555 "urb_control_feature_request: Error Command 0x%02" PRIx8
"", command);
1556 Stream_Free(out, TRUE);
1557 return ERROR_INTERNAL_ERROR;
1560 if (!pdev->control_transfer(pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector,
1561 Index, &usbd_status, &OutputBufferSize, Stream_Pointer(out), 1000))
1563 WLog_Print(urbdrc->log, WLOG_DEBUG,
"feature control transfer failed");
1564 Stream_Free(out, TRUE);
1565 return ERROR_INTERNAL_ERROR;
1568 return urb_write_completion(pdev, callback, noAck, out, InterfaceId, MessageId, RequestId,
1569 usbd_status, OutputBufferSize);
1573 wStream* s, UINT32 MessageId, IUDEVMAN* udevman,
1578 UINT16 URB_Function = 0;
1579 UINT32 RequestId = 0;
1580 UINT error = ERROR_INTERNAL_ERROR;
1583 if (!callback || !s || !udevman || !pdev)
1584 return ERROR_INVALID_PARAMETER;
1589 return ERROR_INVALID_PARAMETER;
1591 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
1592 return ERROR_INVALID_DATA;
1594 Stream_Read_UINT32(s, CbTsUrb);
1595 Stream_Read_UINT16(s, Size);
1596 Stream_Read_UINT16(s, URB_Function);
1597 Stream_Read_UINT32(s, RequestId);
1598 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB %s[%" PRIu16
"]", urb_function_string(URB_Function),
1601 switch (URB_Function)
1603 case TS_URB_SELECT_CONFIGURATION:
1604 error = urb_select_configuration(pdev, callback, s, RequestId, MessageId, udevman,
1608 case TS_URB_SELECT_INTERFACE:
1610 urb_select_interface(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1613 case TS_URB_PIPE_REQUEST:
1614 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1618 case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
1624 case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
1630 case TS_URB_GET_FRAME_LENGTH:
1636 case TS_URB_SET_FRAME_LENGTH:
1642 case TS_URB_GET_CURRENT_FRAME_NUMBER:
1643 error = urb_get_current_frame_number(pdev, callback, s, RequestId, MessageId, udevman,
1647 case TS_URB_CONTROL_TRANSFER:
1648 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1649 transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL);
1652 case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
1653 error = urb_bulk_or_interrupt_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1657 case TS_URB_ISOCH_TRANSFER:
1659 urb_isoch_transfer(pdev, callback, s, RequestId, MessageId, udevman, transferDir);
1662 case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
1663 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1667 case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
1668 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1672 case TS_URB_SET_FEATURE_TO_DEVICE:
1673 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1674 0x00, URB_SET_FEATURE, transferDir);
1677 case TS_URB_SET_FEATURE_TO_INTERFACE:
1678 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1679 0x01, URB_SET_FEATURE, transferDir);
1682 case TS_URB_SET_FEATURE_TO_ENDPOINT:
1683 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1684 0x02, URB_SET_FEATURE, transferDir);
1687 case TS_URB_CLEAR_FEATURE_TO_DEVICE:
1688 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1689 0x00, URB_CLEAR_FEATURE, transferDir);
1692 case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
1693 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1694 0x01, URB_CLEAR_FEATURE, transferDir);
1697 case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
1698 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1699 0x02, URB_CLEAR_FEATURE, transferDir);
1702 case TS_URB_GET_STATUS_FROM_DEVICE:
1703 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1707 case TS_URB_GET_STATUS_FROM_INTERFACE:
1708 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1712 case TS_URB_GET_STATUS_FROM_ENDPOINT:
1713 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1717 case TS_URB_RESERVED_0X0016:
1720 case TS_URB_VENDOR_DEVICE:
1721 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1722 udevman, (0x02 << 5),
1726 case TS_URB_VENDOR_INTERFACE:
1727 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1728 udevman, (0x02 << 5),
1732 case TS_URB_VENDOR_ENDPOINT:
1733 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1734 udevman, (0x02 << 5),
1738 case TS_URB_CLASS_DEVICE:
1739 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1740 udevman, (0x01 << 5),
1744 case TS_URB_CLASS_INTERFACE:
1745 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1746 udevman, (0x01 << 5),
1750 case TS_URB_CLASS_ENDPOINT:
1751 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1752 udevman, (0x01 << 5),
1756 case TS_URB_RESERVE_0X001D:
1759 case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
1760 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1764 case TS_URB_CLASS_OTHER:
1765 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1766 udevman, (0x01 << 5),
1770 case TS_URB_VENDOR_OTHER:
1771 error = urb_control_vendor_or_class_request(pdev, callback, s, RequestId, MessageId,
1772 udevman, (0x02 << 5),
1776 case TS_URB_GET_STATUS_FROM_OTHER:
1777 error = urb_control_get_status_request(pdev, callback, s, RequestId, MessageId, udevman,
1781 case TS_URB_CLEAR_FEATURE_TO_OTHER:
1782 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1783 0x03, URB_CLEAR_FEATURE, transferDir);
1786 case TS_URB_SET_FEATURE_TO_OTHER:
1787 error = urb_control_feature_request(pdev, callback, s, RequestId, MessageId, udevman,
1788 0x03, URB_SET_FEATURE, transferDir);
1791 case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
1792 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1796 case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
1797 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1801 case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
1802 error = urb_control_get_configuration_request(pdev, callback, s, RequestId, MessageId,
1803 udevman, transferDir);
1806 case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
1807 error = urb_control_get_interface_request(pdev, callback, s, RequestId, MessageId,
1808 udevman, transferDir);
1811 case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
1812 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1816 case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
1817 error = urb_control_descriptor_request(pdev, callback, s, RequestId, MessageId, udevman,
1821 case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
1822 error = urb_os_feature_descriptor_request(pdev, callback, s, RequestId, MessageId,
1823 udevman, transferDir);
1826 case TS_URB_RESERVE_0X002B:
1827 case TS_URB_RESERVE_0X002C:
1828 case TS_URB_RESERVE_0X002D:
1829 case TS_URB_RESERVE_0X002E:
1830 case TS_URB_RESERVE_0X002F:
1834 case TS_URB_SYNC_RESET_PIPE:
1835 error = urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1839 case TS_URB_SYNC_CLEAR_STALL:
1840 urb_pipe_request(pdev, callback, s, RequestId, MessageId, udevman, transferDir,
1844 case TS_URB_CONTROL_TRANSFER_EX:
1845 error = urb_control_transfer(pdev, callback, s, RequestId, MessageId, udevman,
1846 transferDir, URB_CONTROL_TRANSFER_EXTERNAL);
1850 WLog_Print(urbdrc->log, WLOG_DEBUG,
"URB_Func: %" PRIx16
" is not found!",
1857 WLog_Print(urbdrc->log, WLOG_WARN,
1858 "USB transfer request URB Function '%s' [0x%08x] failed with %08" PRIx32,
1859 urb_function_string(URB_Function), URB_Function, error);
1866 IUDEVMAN* udevman,
wStream* data)
1868 UINT32 InterfaceId = 0;
1869 UINT32 MessageId = 0;
1870 UINT32 FunctionId = 0;
1871 IUDEVICE* pdev = NULL;
1872 UINT error = ERROR_INTERNAL_ERROR;
1874 if (!urbdrc || !data || !callback || !udevman)
1877 if (!Stream_CheckAndLogRequiredLength(TAG, data, 8))
1880 Stream_Rewind_UINT32(data);
1882 Stream_Read_UINT32(data, InterfaceId);
1883 Stream_Read_UINT32(data, MessageId);
1884 Stream_Read_UINT32(data, FunctionId);
1886 pdev = udevman->get_udevice_by_UsbDevice(udevman, InterfaceId);
1891 error = ERROR_SUCCESS;
1896 if (pdev->isChannelClosed(pdev))
1898 error = ERROR_SUCCESS;
1903 pdev->detach_kernel_driver(pdev);
1907 case CANCEL_REQUEST:
1908 error = urbdrc_process_cancel_request(pdev, data, udevman);
1911 case REGISTER_REQUEST_CALLBACK:
1912 error = urbdrc_process_register_request_callback(pdev, callback, data, udevman);
1916 error = urbdrc_process_io_control(pdev, callback, data, MessageId, udevman);
1919 case INTERNAL_IO_CONTROL:
1920 error = urbdrc_process_internal_io_control(pdev, callback, data, MessageId, udevman);
1923 case QUERY_DEVICE_TEXT:
1924 error = urbdrc_process_query_device_text(pdev, callback, data, MessageId, udevman);
1927 case TRANSFER_IN_REQUEST:
1928 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
1929 USBD_TRANSFER_DIRECTION_IN);
1932 case TRANSFER_OUT_REQUEST:
1933 error = urbdrc_process_transfer_request(pdev, callback, data, MessageId, udevman,
1934 USBD_TRANSFER_DIRECTION_OUT);
1937 case RETRACT_DEVICE:
1938 error = urbdrc_process_retract_device_request(pdev, data, udevman);
1942 WLog_Print(urbdrc->log, WLOG_WARN,
1943 "urbdrc_process_udev_data_transfer:"
1944 " unknown FunctionId 0x%" PRIX32
"",
1952 WLog_WARN(TAG,
"USB request failed with %08" PRIx32, error);