/** * FreeRDP: A Remote Desktop Protocol Implementation * RemoteFX USB Redirection * * Copyright 2012 Atrust corp. * Copyright 2012 Alfred Liu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include "urbdrc_types.h" #include "data_transfer.h" static void usb_process_get_port_status(IUDEVICE* pdev, BYTE* OutputBuffer) { int bcdUSB = pdev->query_device_descriptor(pdev, BCD_USB); switch (bcdUSB) { case USB_v1_0: data_write_UINT32(OutputBuffer, 0x303); break; case USB_v1_1: data_write_UINT32(OutputBuffer, 0x103); break; case USB_v2_0: data_write_UINT32(OutputBuffer, 0x503); break; default: data_write_UINT32(OutputBuffer, 0x503); break; } } #if ISOCH_FIFO static int func_check_isochronous_fds(IUDEVICE* pdev) { int ret = 0; BYTE* data_temp; UINT32 size_temp, process_times = 2; ISOCH_CALLBACK_QUEUE* isoch_queue = NULL; ISOCH_CALLBACK_DATA* isoch = NULL; URBDRC_CHANNEL_CALLBACK* callback; isoch_queue = (ISOCH_CALLBACK_QUEUE*) pdev->get_isoch_queue(pdev); while (process_times) { process_times--; if (isoch_queue == NULL || !pdev) return -1; pthread_mutex_lock(&isoch_queue->isoch_loading); if (isoch_queue->head == NULL) { pthread_mutex_unlock(&isoch_queue->isoch_loading); continue; } else { isoch = isoch_queue->head; } if (!isoch || !isoch->out_data) { pthread_mutex_unlock(&isoch_queue->isoch_loading); continue; } else { callback = (URBDRC_CHANNEL_CALLBACK*) isoch->callback; size_temp = isoch->out_size; data_temp = isoch->out_data; ret = isoch_queue->unregister_data(isoch_queue, isoch); if (!ret) WLog_DBG(TAG, "isoch_queue_unregister_data: Not found isoch data!!"); pthread_mutex_unlock(&isoch_queue->isoch_loading); if (pdev && !pdev->isSigToEnd(pdev)) { callback->channel->Write(callback->channel, size_temp, data_temp, NULL); zfree(data_temp); } } } return 0; } #endif static int urbdrc_process_register_request_callback(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, IUDEVMAN* udevman, UINT32 UsbDevice) { IUDEVICE* pdev; UINT32 NumRequestCompletion = 0; UINT32 RequestCompletion = 0; WLog_DBG(TAG, "urbdrc_process_register_request_callback"); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; if (data_sizem >= 8) { data_read_UINT32(data + 0, NumRequestCompletion); /** must be 1 */ /** RequestCompletion: * unique Request Completion interface for the client to use */ data_read_UINT32(data + 4, RequestCompletion); pdev->set_ReqCompletion(pdev, RequestCompletion); } else /** Unregister the device */ { data_read_UINT32(data + 0, RequestCompletion); if (1)//(pdev->get_ReqCompletion(pdev) == RequestCompletion) { /** The wrong driver may also receive this message, So we * need some time(default 3s) to check the driver or delete * it */ sleep(3); callback->channel->Write(callback->channel, 0, NULL, NULL); pdev->SigToEnd(pdev); } } return 0; } static int urbdrc_process_cancel_request(BYTE* data, UINT32 data_sizem, IUDEVMAN* udevman, UINT32 UsbDevice) { IUDEVICE* pdev; UINT32 CancelId; int error = 0; data_read_UINT32(data + 0, CancelId); /** RequestId */ WLog_DBG(TAG, "urbdrc_process_cancel_request: id 0x%"PRIx32"", CancelId); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; error = pdev->cancel_transfer_request(pdev, CancelId); return error; } static int urbdrc_process_retract_device_request(BYTE* data, UINT32 data_sizem, IUDEVMAN* udevman, UINT32 UsbDevice) { UINT32 Reason; WLog_DBG(TAG, "urbdrc_process_retract_device_request"); data_read_UINT32(data + 0, Reason); /** Reason */ switch (Reason) { case UsbRetractReason_BlockedByPolicy: WLog_DBG(TAG, "UsbRetractReason_BlockedByPolicy: now it is not support"); return -1; break; default: WLog_DBG(TAG, "urbdrc_process_retract_device_request: Unknown Reason %"PRIu32"", Reason); return -1; break; } return 0; } static int urbdrc_process_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice) { IUDEVICE* pdev; UINT32 out_size; UINT32 InterfaceId; UINT32 IoControlCode; UINT32 InputBufferSize; UINT32 OutputBufferSize; UINT32 RequestId; UINT32 usbd_status = USBD_STATUS_SUCCESS; BYTE* OutputBuffer; BYTE* out_data; int i, offset, success = 0; WLog_DBG(TAG, "urbdrc_process__io_control"); data_read_UINT32(data + 0, IoControlCode); data_read_UINT32(data + 4, InputBufferSize); data_read_UINT32(data + 8 + InputBufferSize, OutputBufferSize); data_read_UINT32(data + 12 + InputBufferSize, RequestId); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); /** process */ OutputBuffer = (BYTE *)calloc(1, OutputBufferSize); if (!OutputBuffer) return ERROR_OUTOFMEMORY; switch (IoControlCode) { case IOCTL_INTERNAL_USB_SUBMIT_URB: /** 0x00220003 */ WLog_DBG(TAG, "ioctl: IOCTL_INTERNAL_USB_SUBMIT_URB"); WLog_ERR(TAG, " Function IOCTL_INTERNAL_USB_SUBMIT_URB: Unchecked"); break; case IOCTL_INTERNAL_USB_RESET_PORT: /** 0x00220007 */ WLog_DBG(TAG, "ioctl: IOCTL_INTERNAL_USB_RESET_PORT"); break; case IOCTL_INTERNAL_USB_GET_PORT_STATUS: /** 0x00220013 */ WLog_DBG(TAG, "ioctl: IOCTL_INTERNAL_USB_GET_PORT_STATUS"); success = pdev->query_device_port_status(pdev, &usbd_status, &OutputBufferSize, OutputBuffer); if (success) { if (pdev->isExist(pdev) == 0) { data_write_UINT32(OutputBuffer, 0); } else { usb_process_get_port_status(pdev, OutputBuffer); OutputBufferSize = 4; } WLog_DBG(TAG, "PORT STATUS(fake!):0x%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"", OutputBuffer[3], OutputBuffer[2], OutputBuffer[1], OutputBuffer[0]); } break; case IOCTL_INTERNAL_USB_CYCLE_PORT: /** 0x0022001F */ WLog_DBG(TAG, "ioctl: IOCTL_INTERNAL_USB_CYCLE_PORT"); WLog_ERR(TAG, " Function IOCTL_INTERNAL_USB_CYCLE_PORT: Unchecked"); break; case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: /** 0x00220027 */ WLog_DBG(TAG, "ioctl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION"); WLog_ERR(TAG, " Function IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: Unchecked"); break; default: WLog_DBG(TAG, "urbdrc_process_io_control: unknown IoControlCode 0x%"PRIX32"", IoControlCode); zfree(OutputBuffer); return ERROR_INVALID_OPERATION; break; } offset = 28; out_size = offset + OutputBufferSize; out_data = (BYTE *) calloc(1, out_size); if (!out_data) { zfree(OutputBuffer); return ERROR_OUTOFMEMORY; } data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, IOCONTROL_COMPLETION); /** function id */ data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, USBD_STATUS_SUCCESS); /** HResult */ data_write_UINT32(out_data + 20, OutputBufferSize); /** Information */ data_write_UINT32(out_data + 24, OutputBufferSize); /** OutputBufferSize */ for (i = 0; i < OutputBufferSize; i++) { data_write_BYTE(out_data + offset, OutputBuffer[i]); /** OutputBuffer */ offset += 1; } if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); zfree(OutputBuffer); return CHANNEL_RC_OK; } static int urbdrc_process_internal_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice) { IUDEVICE* pdev; BYTE* out_data; UINT32 out_size, IoControlCode, InterfaceId, InputBufferSize; UINT32 OutputBufferSize, RequestId, frames; data_read_UINT32(data + 0, IoControlCode); WLog_DBG(TAG, "urbdrc_process_internal_io_control:0x%"PRIx32"", IoControlCode); data_read_UINT32(data + 4, InputBufferSize); data_read_UINT32(data + 8, OutputBufferSize); data_read_UINT32(data + 12, RequestId); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); /** Fixme: Currently this is a FALSE bustime... */ urbdrc_get_mstime(frames); out_size = 32; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, IOCONTROL_COMPLETION); /** function id */ data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0); /** HResult */ data_write_UINT32(out_data + 20, 4); /** Information */ data_write_UINT32(out_data + 24, 4); /** OutputBufferSize */ data_write_UINT32(out_data + 28, frames); /** OutputBuffer */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urbdrc_process_query_device_text(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice) { IUDEVICE* pdev; UINT32 out_size; UINT32 InterfaceId; UINT32 TextType; UINT32 LocaleId; UINT32 bufferSize = 1024; BYTE* out_data; BYTE DeviceDescription[bufferSize]; int out_offset; WLog_DBG(TAG, "urbdrc_process_query_device_text"); data_read_UINT32(data + 0, TextType); data_read_UINT32(data + 4, LocaleId); pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; pdev->control_query_device_text(pdev, TextType, LocaleId, &bufferSize, DeviceDescription); InterfaceId = ((STREAM_ID_STUB << 30) | UsbDevice); out_offset = 16; out_size = out_offset + bufferSize; if (bufferSize != 0) out_size += 2; out_data = (BYTE*) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if (bufferSize != 0) { data_write_UINT32(out_data + 8, (bufferSize/2)+1); /** cchDeviceDescription */ out_offset = 12; memcpy(out_data + out_offset, DeviceDescription, bufferSize); out_offset += bufferSize; data_write_UINT16(out_data + out_offset, 0x0000); out_offset += 2; } else { data_write_UINT32(out_data + 8, 0); /** cchDeviceDescription */ out_offset = 12; } data_write_UINT32(out_data + out_offset, 0); /** HResult */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static void func_select_all_interface_for_msconfig(IUDEVICE* pdev, MSUSB_CONFIG_DESCRIPTOR* MsConfig) { int inum; MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = MsConfig->MsInterfaces; BYTE InterfaceNumber, AlternateSetting; UINT32 NumInterfaces = MsConfig->NumInterfaces; for (inum = 0; inum < NumInterfaces; inum++) { InterfaceNumber = MsInterfaces[inum]->InterfaceNumber; AlternateSetting = MsInterfaces[inum]->AlternateSetting; pdev->select_interface(pdev, InterfaceNumber, AlternateSetting); } } static int urb_select_configuration(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice, int transferDir) { MSUSB_CONFIG_DESCRIPTOR * MsConfig = NULL; IUDEVICE* pdev = NULL; UINT32 out_size, InterfaceId, RequestId, NumInterfaces, usbd_status = 0; BYTE ConfigurationDescriptorIsValid; BYTE* out_data; int MsOutSize = 0, offset = 0; if (transferDir == 0) { WLog_ERR(TAG, "urb_select_configuration: not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_BYTE(data + 4, ConfigurationDescriptorIsValid); data_read_UINT32(data + 8, NumInterfaces); offset = 12; /** if ConfigurationDescriptorIsValid is zero, then just do nothing.*/ if (ConfigurationDescriptorIsValid) { /* parser data for struct config */ MsConfig = msusb_msconfig_read(data + offset, data_sizem - offset, NumInterfaces); /* select config */ pdev->select_configuration(pdev, MsConfig->bConfigurationValue); /* select all interface */ func_select_all_interface_for_msconfig(pdev, MsConfig); /* complete configuration setup */ MsConfig = pdev->complete_msconfig_setup(pdev, MsConfig); } if (MsConfig) MsOutSize = MsConfig->MsOutSize; if (MsOutSize > 0) out_size = 36 + MsOutSize; else out_size = 44; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); /** function id */ data_write_UINT32(out_data + 12, RequestId); /** RequestId */ if (MsOutSize > 0) { /** CbTsUrbResult */ data_write_UINT32(out_data + 16, 8 + MsOutSize); /** TS_URB_RESULT_HEADER Size*/ data_write_UINT16(out_data + 20, 8 + MsOutSize); } else { data_write_UINT32(out_data + 16, 16); data_write_UINT16(out_data + 20, 16); } /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_SELECT_CONFIGURATION); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ offset = 28; /** TS_URB_SELECT_CONFIGURATION_RESULT */ if (MsOutSize > 0) { msusb_msconfig_write(MsConfig, out_data, &offset); } else { data_write_UINT32(out_data + offset, 0); /** ConfigurationHandle */ data_write_UINT32(out_data + offset + 4, NumInterfaces); /** NumInterfaces */ offset += 8; } data_write_UINT32(out_data + offset, 0); /** HResult */ data_write_UINT32(out_data + offset + 4, 0); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_select_interface(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice, int transferDir) { MSUSB_CONFIG_DESCRIPTOR* MsConfig; MSUSB_INTERFACE_DESCRIPTOR* MsInterface; IUDEVICE* pdev; UINT32 out_size, InterfaceId, RequestId, ConfigurationHandle; UINT32 OutputBufferSize; BYTE InterfaceNumber; BYTE* out_data; int out_offset, interface_size; if (transferDir == 0) { WLog_ERR(TAG, "urb_select_interface: not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, ConfigurationHandle); out_offset = 8; MsInterface = msusb_msinterface_read(data + out_offset, data_sizem - out_offset, &out_offset); data_read_UINT32(data + out_offset, OutputBufferSize); pdev->select_interface(pdev, MsInterface->InterfaceNumber, MsInterface->AlternateSetting); /* replace device's MsInterface */ MsConfig = pdev->get_MsConfig(pdev); InterfaceNumber = MsInterface->InterfaceNumber; msusb_msinterface_replace(MsConfig, InterfaceNumber, MsInterface); /* complete configuration setup */ MsConfig = pdev->complete_msconfig_setup(pdev, MsConfig); MsInterface = MsConfig->MsInterfaces[InterfaceNumber]; interface_size = 16 + (MsInterface->NumberOfPipes * 20); out_size = 36 + interface_size ; out_data = (BYTE*) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); /** function id */ data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 8 + interface_size); /** CbTsUrbResult */ /** TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 8 + interface_size); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_SELECT_INTERFACE); data_write_UINT32(out_data + 24, USBD_STATUS_SUCCESS); /** UsbdStatus */ out_offset = 28; /** TS_URB_SELECT_INTERFACE_RESULT */ msusb_msinterface_write(MsInterface, out_data + out_offset, &out_offset); data_write_UINT32(out_data + out_offset, 0); /** HResult */ data_write_UINT32(out_data + out_offset + 4, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_control_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice, int transferDir, int External) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, EndpointAddress, PipeHandle; UINT32 TransferFlags, OutputBufferSize, usbd_status, Timeout; BYTE bmRequestType, Request; UINT16 Value, Index, length; BYTE* buffer; BYTE* out_data; int offset, ret; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, PipeHandle); data_read_UINT32(data + 8, TransferFlags); /** TransferFlags */ EndpointAddress = (PipeHandle & 0x000000ff); offset = 12; Timeout = 2000; switch (External) { case URB_CONTROL_TRANSFER_EXTERNAL: data_read_UINT32(data + offset, Timeout); /** TransferFlags */ offset += 4; break; case URB_CONTROL_TRANSFER_NONEXTERNAL: break; } /** SetupPacket 8 bytes */ data_read_BYTE(data + offset, bmRequestType); data_read_BYTE(data + offset + 1, Request); data_read_UINT16(data + offset + 2, Value); data_read_UINT16(data + offset + 4, Index); data_read_UINT16(data + offset + 6, length); data_read_UINT32(data + offset + 8, OutputBufferSize); offset += 12; if (length != OutputBufferSize) { WLog_ERR(TAG, "urb_control_transfer ERROR: buf != length"); return -1; } out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; /** Get Buffer Data */ if (transferDir == USBD_TRANSFER_DIRECTION_OUT) memcpy(buffer, data + offset, OutputBufferSize); /** process URB_FUNCTION_CONTROL_TRANSFER */ ret = pdev->control_transfer( pdev, RequestId, EndpointAddress, TransferFlags, bmRequestType, Request, Value, Index, &usbd_status, &OutputBufferSize, buffer, Timeout); if (ret < 0){ WLog_DBG(TAG, "control_transfer: error num %d!!", ret); OutputBufferSize = 0; } /** send data */ offset = 36; if (transferDir == USBD_TRANSFER_DIRECTION_IN) out_size = offset + OutputBufferSize; else out_size = offset; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(transferDir == USBD_TRANSFER_DIRECTION_IN && OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_CONTROL_TRANSFER); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYTE* data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN* udevman, UINT32 UsbDevice, int transferDir) { int offset; BYTE* Buffer; IUDEVICE* pdev; BYTE* out_data; UINT32 out_size, RequestId, InterfaceId, EndpointAddress, PipeHandle; UINT32 TransferFlags, OutputBufferSize, usbd_status = 0; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY << 30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, PipeHandle); data_read_UINT32(data + 8, TransferFlags); /** TransferFlags */ data_read_UINT32(data + 12, OutputBufferSize); offset = 16; EndpointAddress = (PipeHandle & 0x000000ff); if (transferDir == USBD_TRANSFER_DIRECTION_OUT) out_size = 36; else out_size = 36 + OutputBufferSize; Buffer = NULL; out_data = (BYTE*) malloc(out_size); memset(out_data, 0, out_size); switch (transferDir) { case USBD_TRANSFER_DIRECTION_OUT: Buffer = data + offset; break; case USBD_TRANSFER_DIRECTION_IN: Buffer = out_data + 36; break; } /** process URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER */ pdev->bulk_or_interrupt_transfer( pdev, RequestId, EndpointAddress, TransferFlags, &usbd_status, &OutputBufferSize, Buffer, 10000); offset = 36; if (transferDir == USBD_TRANSFER_DIRECTION_IN) out_size = offset + OutputBufferSize; else out_size = offset; /** send data */ data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(transferDir == USBD_TRANSFER_DIRECTION_IN && OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (pdev && !pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE * pdev; UINT32 RequestId, InterfaceId, EndpointAddress; UINT32 PipeHandle, TransferFlags, StartFrame, NumberOfPackets; UINT32 ErrorCount, OutputBufferSize, usbd_status = 0; UINT32 RequestField, noAck = 0; UINT32 out_size = 0; BYTE * iso_buffer = NULL; BYTE * iso_packets = NULL; BYTE * out_data = NULL; int offset, nullBuffer = 0, iso_status; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; if (pdev->isSigToEnd(pdev)) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestField); RequestId = RequestField & 0x7fffffff; noAck = (RequestField & 0x80000000)>>31; data_read_UINT32(data + 4, PipeHandle); EndpointAddress = (PipeHandle & 0x000000ff); data_read_UINT32(data + 8, TransferFlags); /** TransferFlags */ data_read_UINT32(data + 12, StartFrame); /** StartFrame */ data_read_UINT32(data + 16, NumberOfPackets); /** NumberOfPackets */ data_read_UINT32(data + 20, ErrorCount); /** ErrorCount */ offset = 24 + (NumberOfPackets * 12); data_read_UINT32(data + offset, OutputBufferSize); offset += 4; /** send data memory alloc */ if (transferDir == USBD_TRANSFER_DIRECTION_OUT) { if (!noAck) { out_size = 48 + (NumberOfPackets * 12); out_data = (BYTE *) malloc(out_size); iso_packets = out_data + 40; } } else { out_size = 48 + OutputBufferSize + (NumberOfPackets * 12); out_data = (BYTE *) malloc(out_size); iso_packets = out_data + 40; } if (out_size) memset(out_data, 0, out_size); switch (transferDir) { case USBD_TRANSFER_DIRECTION_OUT: /** Get Buffer Data */ //memcpy(iso_buffer, data + offset, OutputBufferSize); iso_buffer = data + offset; break; case USBD_TRANSFER_DIRECTION_IN: iso_buffer = out_data + 48 + (NumberOfPackets * 12); break; } WLog_DBG(TAG, "urb_isoch_transfer: EndpointAddress: 0x%"PRIx32", " "TransferFlags: 0x%"PRIx32", " "StartFrame: 0x%"PRIx32", " "NumberOfPackets: 0x%"PRIx32", " "OutputBufferSize: 0x%"PRIx32" " "RequestId: 0x%"PRIx32"", EndpointAddress, TransferFlags, StartFrame, NumberOfPackets, OutputBufferSize, RequestId); #if ISOCH_FIFO ISOCH_CALLBACK_QUEUE * isoch_queue = NULL; ISOCH_CALLBACK_DATA * isoch = NULL; if(!noAck) { isoch_queue = (ISOCH_CALLBACK_QUEUE *)pdev->get_isoch_queue(pdev); isoch = isoch_queue->register_data(isoch_queue, callback, pdev); } #endif iso_status = pdev->isoch_transfer( pdev, RequestId, EndpointAddress, TransferFlags, noAck, &ErrorCount, &usbd_status, &StartFrame, NumberOfPackets, iso_packets, &OutputBufferSize, iso_buffer, 2000); if(noAck) { zfree(out_data); return 0; } if (iso_status < 0) nullBuffer = 1; out_size = 48; if (nullBuffer) OutputBufferSize = 0; else out_size += OutputBufferSize + (NumberOfPackets * 12); /* fill the send data */ data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(OutputBufferSize != 0 && !nullBuffer) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 20 + (NumberOfPackets * 12)); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 20 + (NumberOfPackets * 12)); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_ISOCH_TRANSFER); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, StartFrame); /** StartFrame */ if (!nullBuffer) { /** NumberOfPackets */ data_write_UINT32(out_data + 32, NumberOfPackets); data_write_UINT32(out_data + 36, ErrorCount); /** ErrorCount */ offset = 40 + (NumberOfPackets * 12); } else { data_write_UINT32(out_data + 32, 0); /** NumberOfPackets */ data_write_UINT32(out_data + 36, NumberOfPackets); /** ErrorCount */ offset = 40; } data_write_UINT32(out_data + offset, 0); /** HResult */ data_write_UINT32(out_data + offset + 4, OutputBufferSize); /** OutputBufferSize */ #if ISOCH_FIFO if(!noAck){ pthread_mutex_lock(&isoch_queue->isoch_loading); isoch->out_data = out_data; isoch->out_size = out_size; pthread_mutex_unlock(&isoch_queue->isoch_loading); } #else if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); #endif if (nullBuffer) return -1; return 0; } static int urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK* callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, BYTE func_recipient, int transferDir) { IUDEVICE* pdev; UINT32 out_size, InterfaceId, RequestId, OutputBufferSize, usbd_status; BYTE bmRequestType, desc_index, desc_type; UINT16 langId; BYTE* buffer; BYTE* out_data; int ret, offset; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_BYTE(data + 4, desc_index); data_read_BYTE(data + 5, desc_type); data_read_UINT16(data + 6, langId); data_read_UINT32(data + 8, OutputBufferSize); out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; bmRequestType = func_recipient; switch (transferDir) { case USBD_TRANSFER_DIRECTION_IN: bmRequestType |= 0x80; break; case USBD_TRANSFER_DIRECTION_OUT: bmRequestType |= 0x00; offset = 12; memcpy(buffer, data + offset, OutputBufferSize); break; default: WLog_DBG(TAG, "get error transferDir"); OutputBufferSize = 0; usbd_status = USBD_STATUS_STALL_PID; break; } /** process get usb device descriptor */ ret = pdev->control_transfer( pdev, RequestId, 0, 0, bmRequestType, 0x06, /* REQUEST_GET_DESCRIPTOR */ (desc_type << 8) | desc_index, langId, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0) { WLog_DBG(TAG, "get_descriptor: error num %d", ret); OutputBufferSize = 0; } offset = 36; out_size = offset + OutputBufferSize; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, BYTE func_recipient, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status; UINT16 Index; BYTE bmRequestType; BYTE* buffer; BYTE* out_data; int offset, ret; if (transferDir == 0){ WLog_DBG(TAG, "urb_control_get_status_request: not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT16(data + 4, Index); /** Index */ data_read_UINT32(data + 8, OutputBufferSize); out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; bmRequestType = func_recipient | 0x80; ret = pdev->control_transfer( pdev, RequestId, 0, 0, bmRequestType, 0x00, /* REQUEST_GET_STATUS */ 0, Index, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0){ WLog_DBG(TAG, "control_transfer: error num %d!!", ret); OutputBufferSize = 0; usbd_status = USBD_STATUS_STALL_PID; } else{ usbd_status = USBD_STATUS_SUCCESS; } /** send data */ offset = 36; if (transferDir == USBD_TRANSFER_DIRECTION_IN) out_size = offset + OutputBufferSize; else out_size = offset; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(transferDir == USBD_TRANSFER_DIRECTION_IN && OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId, include NoAck*/ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_VENDOR_DEVICE); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, BYTE func_type, BYTE func_recipient, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, TransferFlags, usbd_status; UINT32 OutputBufferSize; BYTE ReqTypeReservedBits, Request, bmRequestType; UINT16 Value, Index, Padding; BYTE* buffer; BYTE* out_data; int offset, ret; /** control by vendor command */ pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, TransferFlags); /** TransferFlags */ data_read_BYTE(data + 8, ReqTypeReservedBits); /** ReqTypeReservedBids */ data_read_BYTE(data + 9, Request); /** Request */ data_read_UINT16(data + 10, Value); /** value */ data_read_UINT16(data + 12, Index); /** index */ data_read_UINT16(data + 14, Padding); /** Padding */ data_read_UINT32(data + 16, OutputBufferSize); offset = 20; out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; /** Get Buffer */ if (transferDir == USBD_TRANSFER_DIRECTION_OUT) memcpy(buffer, data + offset, OutputBufferSize); /** vendor or class command */ bmRequestType = func_type | func_recipient; if (TransferFlags & USBD_TRANSFER_DIRECTION) bmRequestType |= 0x80; WLog_DBG(TAG, "urb_control_vendor_or_class_request: " "RequestId 0x%"PRIx32" TransferFlags: 0x%"PRIx32" ReqTypeReservedBits: 0x%"PRIx8" " "Request:0x%"PRIx8" Value: 0x%"PRIx16" Index: 0x%"PRIx16" OutputBufferSize: 0x%"PRIx32" bmRequestType: 0x%"PRIx8"!!", RequestId, TransferFlags, ReqTypeReservedBits, Request, Value, Index, OutputBufferSize, bmRequestType); ret = pdev->control_transfer( pdev, RequestId, 0, 0, bmRequestType, Request, Value, Index, &usbd_status, &OutputBufferSize, buffer, 2000); if (ret < 0){ WLog_DBG(TAG, "control_transfer: error num %d!!", ret); OutputBufferSize = 0; usbd_status = USBD_STATUS_STALL_PID; } else{ usbd_status = USBD_STATUS_SUCCESS; } offset = 36; if (transferDir == USBD_TRANSFER_DIRECTION_IN) out_size = offset + OutputBufferSize; else out_size = offset; /** send data */ data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(transferDir == USBD_TRANSFER_DIRECTION_IN && OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId, include NoAck*/ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ data_write_UINT16(out_data + 22, URB_FUNCTION_VENDOR_DEVICE); /** Padding, MUST be ignored upon receipt */ data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status; BYTE Recipient, InterfaceNumber, Ms_PageIndex; UINT16 Ms_featureDescIndex; BYTE* out_data; BYTE* buffer; int offset, ret; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_BYTE(data + 4, Recipient); /** Recipient */ Recipient = (Recipient & 0x1f); /* XXX: origin: Recipient && 0x1f !? */ data_read_BYTE(data + 5, InterfaceNumber); /** InterfaceNumber */ data_read_BYTE(data + 6, Ms_PageIndex); /** Ms_PageIndex */ data_read_UINT16(data + 7, Ms_featureDescIndex); /** Ms_featureDescIndex */ data_read_UINT32(data + 12, OutputBufferSize); offset = 16; out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; switch (transferDir) { case USBD_TRANSFER_DIRECTION_OUT: WLog_ERR(TAG, "Function urb_os_feature_descriptor_request: OUT Unchecked"); memcpy(buffer, data + offset, OutputBufferSize); break; case USBD_TRANSFER_DIRECTION_IN: break; } WLog_DBG(TAG, "Ms descriptor arg: Recipient:0x%"PRIx8", " "InterfaceNumber:0x%"PRIx8", Ms_PageIndex:0x%"PRIx8", " "Ms_featureDescIndex:0x%"PRIx16", OutputBufferSize:0x%"PRIx32"", Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, OutputBufferSize); /** get ms string */ ret = pdev->os_feature_descriptor_request( pdev, RequestId, Recipient, InterfaceNumber, Ms_PageIndex, Ms_featureDescIndex, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0) WLog_DBG(TAG, "os_feature_descriptor_request: error num %d", ret); offset = 36; out_size = offset + OutputBufferSize; /** send data */ data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if(OutputBufferSize!=0) data_write_UINT32(out_data + 8, URB_COMPLETION); /** function id */ else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir, int action) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, PipeHandle, EndpointAddress; UINT32 OutputBufferSize, usbd_status = 0; BYTE* out_data; int out_offset, ret; if (transferDir == 0){ WLog_DBG(TAG, "urb_pipe_request: not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, PipeHandle); /** PipeHandle */ data_read_UINT32(data + 8, OutputBufferSize); EndpointAddress = (PipeHandle & 0x000000ff); switch (action){ case PIPE_CANCEL: WLog_DBG(TAG, "urb_pipe_request: PIPE_CANCEL 0x%"PRIx32"", EndpointAddress); ret = pdev->control_pipe_request( pdev, RequestId, EndpointAddress, &usbd_status, PIPE_CANCEL); if (ret < 0) { WLog_DBG(TAG, "PIPE SET HALT: error num %d", ret); } break; case PIPE_RESET: WLog_DBG(TAG, "urb_pipe_request: PIPE_RESET ep 0x%"PRIx32"", EndpointAddress); ret = pdev->control_pipe_request( pdev, RequestId, EndpointAddress, &usbd_status, PIPE_RESET); if (ret < 0) WLog_DBG(TAG, "PIPE RESET: error num %d!!", ret); break; default: WLog_DBG(TAG, "urb_pipe_request action: %d is not support!", action); break; } /** send data */ out_offset = 36; out_size = out_offset + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 0x00000008); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 0x0008); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, 0); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK* callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize; UINT32 dummy_frames; BYTE* out_data; if (transferDir == 0){ WLog_DBG(TAG, "urb_get_current_frame_number: not support transfer out"); //exit(1); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, OutputBufferSize); /** Fixme: Need to fill actual frame number!!*/ urbdrc_get_mstime(dummy_frames); out_size = 40; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 12); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 12); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_CURRENT_FRAME_NUMBER); data_write_UINT32(out_data + 24, USBD_STATUS_SUCCESS); /** UsbdStatus */ data_write_UINT32(out_data + 28, dummy_frames); /** FrameNumber */ data_write_UINT32(out_data + 32, 0); /** HResult */ data_write_UINT32(out_data + 36, 0); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } /* Unused function for current server */ static int urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK* callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status; BYTE* buffer; BYTE* out_data; int ret, offset; if (transferDir == 0) { WLog_DBG(TAG, "urb_control_get_configuration_request:" " not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT32(data + 4, OutputBufferSize); out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; ret = pdev->control_transfer( pdev, RequestId, 0, 0, 0x80 | 0x00, 0x08, /* REQUEST_GET_CONFIGURATION */ 0, 0, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0){ WLog_DBG(TAG, "control_transfer: error num %d", ret); OutputBufferSize = 0; } offset = 36; out_size = offset + OutputBufferSize; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if (OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 8); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 8); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_CONFIGURATION); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } /* Unused function for current server */ static int urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK* callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status; UINT16 interface; BYTE* buffer; BYTE* out_data; int ret, offset; if (transferDir == 0){ WLog_DBG(TAG, "urb_control_get_interface_request: not support transfer out"); return -1; } pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT16(data + 4, interface); data_read_UINT32(data + 8, OutputBufferSize); out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; ret = pdev->control_transfer(pdev, RequestId, 0, 0, 0x80 | 0x01, 0x0A, /* REQUEST_GET_INTERFACE */ 0, interface, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0){ WLog_DBG(TAG, "control_transfer: error num %d", ret); OutputBufferSize = 0; } offset = 36; out_size = offset + OutputBufferSize; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if (OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 8); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 8); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_INTERFACE); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, BYTE func_recipient, BYTE command, int transferDir) { IUDEVICE* pdev; UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status; UINT16 FeatureSelector, Index; BYTE bmRequestType, bmRequest; BYTE* buffer; BYTE* out_data; int ret, offset; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev)); data_read_UINT32(data + 0, RequestId); data_read_UINT16(data + 4, FeatureSelector); data_read_UINT16(data + 6, Index); data_read_UINT32(data + 8, OutputBufferSize); offset = 12; out_size = 36 + OutputBufferSize; out_data = (BYTE *) malloc(out_size); memset(out_data, 0, out_size); buffer = out_data + 36; bmRequestType = func_recipient; switch (transferDir) { case USBD_TRANSFER_DIRECTION_OUT: WLog_ERR(TAG, "Function urb_control_feature_request: OUT Unchecked"); memcpy(buffer, data + offset, OutputBufferSize); bmRequestType |= 0x00; break; case USBD_TRANSFER_DIRECTION_IN: bmRequestType |= 0x80; break; } switch (command) { case URB_SET_FEATURE: bmRequest = 0x03; /* REQUEST_SET_FEATURE */ break; case URB_CLEAR_FEATURE: bmRequest = 0x01; /* REQUEST_CLEAR_FEATURE */ break; default: WLog_ERR(TAG, "urb_control_feature_request: Error Command 0x%02"PRIx8"", command); zfree(out_data); return -1; } ret = pdev->control_transfer( pdev, RequestId, 0, 0, bmRequestType, bmRequest, FeatureSelector, Index, &usbd_status, &OutputBufferSize, buffer, 1000); if (ret < 0){ WLog_DBG(TAG, "feature control transfer: error num %d", ret); OutputBufferSize = 0; } offset = 36; out_size = offset + OutputBufferSize; data_write_UINT32(out_data + 0, InterfaceId); /** interface */ data_write_UINT32(out_data + 4, MessageId); /** message id */ if (OutputBufferSize != 0) data_write_UINT32(out_data + 8, URB_COMPLETION); else data_write_UINT32(out_data + 8, URB_COMPLETION_NO_DATA); data_write_UINT32(out_data + 12, RequestId); /** RequestId */ data_write_UINT32(out_data + 16, 8); /** CbTsUrbResult */ /** TsUrbResult TS_URB_RESULT_HEADER */ data_write_UINT16(out_data + 20, 8); /** Size */ /** Padding, MUST be ignored upon receipt */ data_write_UINT16(out_data + 22, URB_FUNCTION_GET_INTERFACE); data_write_UINT32(out_data + 24, usbd_status); /** UsbdStatus */ data_write_UINT32(out_data + 28, 0); /** HResult */ data_write_UINT32(out_data + 32, OutputBufferSize); /** OutputBufferSize */ if (!pdev->isSigToEnd(pdev)) callback->channel->Write(callback->channel, out_size, out_data, NULL); zfree(out_data); return 0; } static int urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data, UINT32 data_sizem, UINT32 MessageId, IUDEVMAN * udevman, UINT32 UsbDevice, int transferDir) { IUDEVICE * pdev; UINT32 CbTsUrb; UINT16 Size; UINT16 URB_Function; UINT32 OutputBufferSize; int error = 0; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL) return 0; data_read_UINT32(data + 0, CbTsUrb); /** CbTsUrb */ data_read_UINT16(data + 4, Size); /** size */ data_read_UINT16(data + 6, URB_Function); data_read_UINT32(data + 4 + CbTsUrb, OutputBufferSize); switch (URB_Function) { case URB_FUNCTION_SELECT_CONFIGURATION: /** 0x0000 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SELECT_CONFIGURATION"); error = urb_select_configuration( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_SELECT_INTERFACE: /** 0x0001 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SELECT_INTERFACE"); error = urb_select_interface( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_ABORT_PIPE: /** 0x0002 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_ABORT_PIPE"); error = urb_pipe_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, PIPE_CANCEL); break; case URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL: /** 0x0003 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL"); error = -1; /** This URB function is obsolete in Windows 2000 * and later operating systems * and is not supported by Microsoft. */ break; case URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL: /** 0x0004 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL"); error = -1; /** This URB function is obsolete in Windows 2000 * and later operating systems * and is not supported by Microsoft. */ break; case URB_FUNCTION_GET_FRAME_LENGTH: /** 0x0005 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_FRAME_LENGTH"); error = -1; /** This URB function is obsolete in Windows 2000 * and later operating systems * and is not supported by Microsoft. */ break; case URB_FUNCTION_SET_FRAME_LENGTH: /** 0x0006 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_FRAME_LENGTH"); error = -1; /** This URB function is obsolete in Windows 2000 * and later operating systems * and is not supported by Microsoft. */ break; case URB_FUNCTION_GET_CURRENT_FRAME_NUMBER: /** 0x0007 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_CURRENT_FRAME_NUMBER"); error = urb_get_current_frame_number( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_CONTROL_TRANSFER: /** 0x0008 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CONTROL_TRANSFER"); error = urb_control_transfer( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, URB_CONTROL_TRANSFER_NONEXTERNAL); break; case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: /** 0x0009 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"); error = urb_bulk_or_interrupt_transfer( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_ISOCH_TRANSFER: /** 0x000A */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_ISOCH_TRANSFER"); error = urb_isoch_transfer( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: /** 0x000B */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x00, transferDir); break; case URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE: /** 0x000C */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x00, transferDir); break; case URB_FUNCTION_SET_FEATURE_TO_DEVICE: /** 0x000D */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_FEATURE_TO_DEVICE"); error = urb_control_feature_request(callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x00, URB_SET_FEATURE, transferDir); break; case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: /** 0x000E */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_FEATURE_TO_INTERFACE"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x01, URB_SET_FEATURE, transferDir); break; case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: /** 0x000F */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_FEATURE_TO_ENDPOINT"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x02, URB_SET_FEATURE, transferDir); break; case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: /** 0x0010 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x00, URB_CLEAR_FEATURE, transferDir); break; case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: /** 0x0011 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x01, URB_CLEAR_FEATURE, transferDir); break; case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: /** 0x0012 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x02, URB_CLEAR_FEATURE, transferDir); break; case URB_FUNCTION_GET_STATUS_FROM_DEVICE: /** 0x0013 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_STATUS_FROM_DEVICE"); error = urb_control_get_status_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x00, transferDir); break; case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: /** 0x0014 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_STATUS_FROM_INTERFACE"); error = urb_control_get_status_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x01, transferDir); break; case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: /** 0x0015 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_STATUS_FROM_ENDPOINT"); error = urb_control_get_status_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x02, transferDir); break; case URB_FUNCTION_RESERVED_0X0016: /** 0x0016 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVED_0X0016"); error = -1; break; case URB_FUNCTION_VENDOR_DEVICE: /** 0x0017 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_VENDOR_DEVICE"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x02 << 5), /* vendor type */ 0x00, transferDir); break; case URB_FUNCTION_VENDOR_INTERFACE: /** 0x0018 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_VENDOR_INTERFACE"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x02 << 5), /* vendor type */ 0x01, transferDir); break; case URB_FUNCTION_VENDOR_ENDPOINT: /** 0x0019 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_VENDOR_ENDPOINT"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x02 << 5), /* vendor type */ 0x02, transferDir); break; case URB_FUNCTION_CLASS_DEVICE: /** 0x001A */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLASS_DEVICE"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x01 << 5), /* class type */ 0x00, transferDir); break; case URB_FUNCTION_CLASS_INTERFACE: /** 0x001B */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLASS_INTERFACE"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x01 << 5), /* class type */ 0x01, transferDir); break; case URB_FUNCTION_CLASS_ENDPOINT: /** 0x001C */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLASS_ENDPOINT"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x01 << 5), /* class type */ 0x02, transferDir); break; case URB_FUNCTION_RESERVE_0X001D: /** 0x001D */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X001D"); error = -1; break; case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: /** 0x001E */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL"); error = urb_pipe_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, PIPE_RESET); break; case URB_FUNCTION_CLASS_OTHER: /** 0x001F */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLASS_OTHER"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x01 << 5), /* class type */ 0x03, transferDir); break; case URB_FUNCTION_VENDOR_OTHER: /** 0x0020 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_VENDOR_OTHER"); error = urb_control_vendor_or_class_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, (0x02 << 5), /* vendor type */ 0x03, transferDir); break; case URB_FUNCTION_GET_STATUS_FROM_OTHER: /** 0x0021 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_STATUS_FROM_OTHER"); error = urb_control_get_status_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x03, transferDir); break; case URB_FUNCTION_CLEAR_FEATURE_TO_OTHER: /** 0x0022 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CLEAR_FEATURE_TO_OTHER"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x03, URB_CLEAR_FEATURE, transferDir); break; case URB_FUNCTION_SET_FEATURE_TO_OTHER: /** 0x0023 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_FEATURE_TO_OTHER"); error = urb_control_feature_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x03, URB_SET_FEATURE, transferDir); break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT: /** 0x0024 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x02, transferDir); break; case URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT: /** 0x0025 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x02, transferDir); break; case URB_FUNCTION_GET_CONFIGURATION: /** 0x0026 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_CONFIGURATION"); error = urb_control_get_configuration_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_GET_INTERFACE: /** 0x0027 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_INTERFACE"); error = urb_control_get_interface_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: /** 0x0028 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x01, transferDir); break; case URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE: /** 0x0029 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE"); error = urb_control_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, 0x01, transferDir); break; case URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR: /** 0x002A */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR"); error = urb_os_feature_descriptor_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir); break; case URB_FUNCTION_RESERVE_0X002B: /** 0x002B */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X002B"); error = -1; break; case URB_FUNCTION_RESERVE_0X002C: /** 0x002C */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X002C"); error = -1; break; case URB_FUNCTION_RESERVE_0X002D: /** 0x002D */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X002D"); error = -1; break; case URB_FUNCTION_RESERVE_0X002E: /** 0x002E */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X002E"); error = -1; break; case URB_FUNCTION_RESERVE_0X002F: /** 0x002F */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_RESERVE_0X002F"); error = -1; break; /** USB 2.0 calls start at 0x0030 */ case URB_FUNCTION_SYNC_RESET_PIPE: /** 0x0030 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SYNC_RESET_PIPE"); error = urb_pipe_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, PIPE_RESET); error = -9; /** function not support */ break; case URB_FUNCTION_SYNC_CLEAR_STALL: /** 0x0031 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_SYNC_CLEAR_STALL"); error = urb_pipe_request( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, PIPE_RESET); error = -9; break; case URB_FUNCTION_CONTROL_TRANSFER_EX: /** 0x0032 */ WLog_DBG(TAG, "URB_Func: URB_FUNCTION_CONTROL_TRANSFER_EX"); error = urb_control_transfer( callback, data + 8, data_sizem - 8, MessageId, udevman, UsbDevice, transferDir, URB_CONTROL_TRANSFER_EXTERNAL); break; default: WLog_DBG(TAG, "URB_Func: %"PRIx16" is not found!", URB_Function); break; } return error; } void* urbdrc_process_udev_data_transfer(void* arg) { TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg; URBDRC_CHANNEL_CALLBACK * callback = transfer_data->callback; BYTE * pBuffer = transfer_data->pBuffer; UINT32 cbSize = transfer_data->cbSize; UINT32 UsbDevice = transfer_data->UsbDevice; IUDEVMAN * udevman = transfer_data->udevman; UINT32 MessageId; UINT32 FunctionId; IUDEVICE* pdev; int error = 0; pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice); if (pdev == NULL || pdev->isSigToEnd(pdev)) { if (transfer_data->pBuffer) zfree(transfer_data->pBuffer); zfree(transfer_data); return 0; } pdev->push_action(pdev); /* USB kernel driver detach!! */ pdev->detach_kernel_driver(pdev); data_read_UINT32(pBuffer + 0, MessageId); data_read_UINT32(pBuffer + 4, FunctionId); switch (FunctionId) { case CANCEL_REQUEST: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>CANCEL_REQUEST<<0x%"PRIX32"", FunctionId); error = urbdrc_process_cancel_request( pBuffer + 8, cbSize - 8, udevman, UsbDevice); break; case REGISTER_REQUEST_CALLBACK: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>REGISTER_REQUEST_CALLBACK<<0x%"PRIX32"", FunctionId); error = urbdrc_process_register_request_callback( callback, pBuffer + 8, cbSize - 8, udevman, UsbDevice); break; case IO_CONTROL: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>IO_CONTROL<<0x%"PRIX32"", FunctionId); error = urbdrc_process_io_control( callback, pBuffer + 8, cbSize - 8, MessageId, udevman, UsbDevice); break; case INTERNAL_IO_CONTROL: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>INTERNAL_IO_CONTROL<<0x%"PRIX32"", FunctionId); error = urbdrc_process_internal_io_control( callback, pBuffer + 8, cbSize - 8, MessageId, udevman, UsbDevice); break; case QUERY_DEVICE_TEXT: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>QUERY_DEVICE_TEXT<<0x%"PRIX32"", FunctionId); error = urbdrc_process_query_device_text( callback, pBuffer + 8, cbSize - 8, MessageId, udevman, UsbDevice); break; case TRANSFER_IN_REQUEST: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>TRANSFER_IN_REQUEST<<0x%"PRIX32"", FunctionId); error = urbdrc_process_transfer_request( callback, pBuffer + 8, cbSize - 8, MessageId, udevman, UsbDevice, USBD_TRANSFER_DIRECTION_IN); break; case TRANSFER_OUT_REQUEST: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>TRANSFER_OUT_REQUEST<<0x%"PRIX32"", FunctionId); error = urbdrc_process_transfer_request( callback, pBuffer + 8, cbSize - 8, MessageId, udevman, UsbDevice, USBD_TRANSFER_DIRECTION_OUT); break; case RETRACT_DEVICE: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " >>RETRACT_DEVICE<<0x%"PRIX32"", FunctionId); error = urbdrc_process_retract_device_request( pBuffer + 8, cbSize - 8, udevman, UsbDevice); break; default: WLog_DBG(TAG, "urbdrc_process_udev_data_transfer:" " unknown FunctionId 0x%"PRIX32"", FunctionId); error = -1; break; } if (transfer_data) { if (transfer_data->pBuffer) zfree(transfer_data->pBuffer); zfree(transfer_data); } if (pdev) { #if ISOCH_FIFO /* check isochronous fds */ func_check_isochronous_fds(pdev); #endif /* close this channel, if device is not found. */ pdev->complete_action(pdev); } else { udevman->push_urb(udevman); return 0; } udevman->push_urb(udevman); return 0; }