/**************************************************************************//*! * * @name USB_Class_Send_Data * * @brief The function calls the device to send data upon receiving an IN token * * @param handle: handle to Identify the controller * @param ep_num: The endpoint number * @param buff_ptr: buffer to send * @param size: length of transfer * * @return status * USB_OK : When Successfully * Others : Errors * *****************************************************************************/ usb_status USB_Class_Send_Data ( class_handle_t handle, /*[IN]*/ uint8_t ep_num, /* [IN] the Endpoint number */ uint8_t * buff_ptr, /* [IN] buffer to send */ uint32_t size /* [IN] length of the transfer */ ) { usb_status error = USB_OK; //uint16_t state; usb_class_object_struct_t* class_object_ptr = (usb_class_object_struct_t*)handle; if (NULL == class_object_ptr) { return USBERR_ERROR; } error = usb_device_send_data(class_object_ptr->controller_handle, ep_num,buff_ptr,size); return error; }
void _reentrant MTPRequestHandler(BOOL bSetup, BYTE btDirection, WORD _X *pbtBuffer, WORD wLength,WORD wPrivateData) { SyncObject *pObject; USB_SetupData * pSetup = &g_SetupData[0]; USB_PTP_STATUSREQ_DATA StatusData = {0}; USB_PTP_CANCELREQ_DATA CancelData = {0}; USBMTP_DEVICE * pDev = &UsbMtpDevice; WORD i, j; if(bSetup) { usb_device_read_setup_data(0); } switch(pSetup->RequestType.I) { case HOST_TO_DEVICE | VENDOR | RECIPIENT_DEVICE: usb_device_finish_transaction(0); usb_device_recv_data(0, 0, 0, pSetup->wLength, 0, FALSE); break; case DEVICE_TO_HOST | VENDOR | RECIPIENT_DEVICE: SystemHalt(); break; case DEVICE_TO_HOST | VENDOR | RECIPIENT_INTERFACE: switch(pSetup->btRequest) { case MSOS_VENDORCODE_TO_GET_MS_DESCRIPTOR: if (pSetup->wIndex == MSOS_FEATURE_INDEX_EXTENDED_PROP_DESC) { // Not implemented usb_device_finish_transaction(0); } break; default: //don't know how to handle SystemHalt(); break; } break; case HOST_TO_DEVICE | CLASS | RECIPIENT_INTERFACE: switch(pSetup->btRequest) { ////////////////////////////////////////////////////////////////////////////////////// // Cancel Request // ////////////////////////////////////////////////////////////////////////////////////// case USB_PTPREQUEST_CANCELIO: // Setup Phase // Verify command format and start data phase 6-bytes if(bSetup) { usb_device_finish_transaction(0); // // Verify the contents in Setup data packet: wLength // if ((pSetup->wValue == 0x00) && (pSetup->wIndex == 0x00) && (pSetup->wLength == 0x06)) { // Do NOT remove this delay. It seems superfluous, but it // fixes an unexplainable NACK'ing of Status IN transaction by // ARC core. for(i=0;i<1000;i++) { bDataPhaseCancel = TRUE; } // Get the 6 byte data, the first 2 bytes must be USB_PTPCANCELIO_ID usb_device_recv_data(0, Descriptor, 0, pSetup->wLength, 0, TRUE); bDataPhaseCancel = TRUE; } else { // // Stall End Point 0 // SystemHalt(); usb_device_stall_endpoint(0, USB_IN); } break; } if(bDataPhaseCancel) { // Data and Status Phase bDataPhaseCancel = FALSE; //usb_device_finish_transaction(0); CancelData.wCancelIOCode = LocalMtpGetLittleEndianINT16InX(Descriptor, 0); CancelData.TransactionId = LocalMtpGetLittleEndianINT32InX(Descriptor, 2); if ( CancelData.wCancelIOCode != USB_PTPCANCELIO_ID) { // // Stall End Point 0 // usb_device_stall_endpoint(0, USB_IN); } else { // if we are coming out of a stalled phase and MTP is cancelling // the previous transaction then don't wait for this flag to be // turned off for an OK device status request. if (pDev->Phase != DEVICE_PHASE_STALLED) { g_bHostCancelling = TRUE; // Set the flag to enable polling in forground g_bUsbPoll = TRUE; } else { pDev->Status = DEVICE_STATUSOK; pDev->Phase = DEVICE_PHASE_IDLE; } g_dwTransactionIdToCancel = (CancelData.TransactionId ); // Prepare status phase usb_device_send_data(0, 0, 0, 0, FALSE,0); bStatusPhaseCancel = TRUE; // Compute CRC g_wCancelCRC = MTP_CRC8(Device1CommandOutBuffer,0,TRANSFER_BUFFER_SIZE*sizeof(Device1CommandOutBuffer[0])); } /* else USB_PTPCANCELIO_ID == CancelData.wCanelIOCode */ break; } if(bStatusPhaseCancel) { bStatusPhaseCancel = FALSE; } break; case USB_PTPREQUEST_RESET: usb_device_finish_transaction(0); // Set the flag to be cleared in call from MtpCmdProcessor // It will also close the session MtpHandler.bMTPReset = TRUE; usb_device_send_data(0, 0, 0, 0, FALSE,0); break; default: break; } break; case DEVICE_TO_HOST | CLASS | RECIPIENT_INTERFACE: switch (pSetup->btRequest) { case USB_PTPREQUEST_GETEVENT: usb_device_finish_transaction(0); break; ////////////////////////////////////////////////////////////////////////////////////// // Get Status Request // ////////////////////////////////////////////////////////////////////////////////////// case USB_PTPREQUEST_GETSTATUS: if(bSetup) { usb_device_finish_transaction(0); bDataPhaseStatus = TRUE; // // Verify the contents in Setup data packet // if (pSetup->wLength) { DWORD dwParams = 0; // // Prepare the Device Status Data Packet // // Check the bulk endpoints to see if they are stalled if (usb_device_get_endpoint_status(UsbMtpDevice.wBulkInEndpointNum) == USB_ENDPOINT_STATUS_STALLED) { StatusData.Params[dwParams] = UsbMtpDevice.wBulkInEndpointNum | 0x80; dwParams ++; } if (usb_device_get_endpoint_status(UsbMtpDevice.wBulkOutEndpointNum) == USB_ENDPOINT_STATUS_STALLED) { StatusData.Params[dwParams] = UsbMtpDevice.wBulkOutEndpointNum; dwParams ++; } if (dwParams) { StatusData.wLength = 4 + (dwParams * 4); StatusData.Code = PTP_RESPONSECODE_TRANSACTIONCANCELLED; } else { StatusData.wLength = 4; if (g_bHostCancelling || (g_wActivityState != MTP_IDLE)) StatusData.Code = PTP_RESPONSECODE_DEVICEBUSY; else { if ( UsbMtpDevice.Status != DEVICE_STATUSOK ) UsbMtpDevice.Status = DEVICE_STATUSOK; StatusData.Code = PTP_RESPONSECODE_OK; } } // Build the Data Response MtpPutLittleEndianINT16IntoByteBufferInX( (void _X *)Descriptor, 0, (long)StatusData.wLength ); MtpPutLittleEndianINT16IntoByteBufferInX( (void _X *)Descriptor, 2, (long)StatusData.Code ); MtpPutLittleEndianINT32IntoByteBufferInX( (void _X *)Descriptor, 4, (long)StatusData.Params[0] ); MtpPutLittleEndianINT32IntoByteBufferInX( (void _X *)Descriptor, 8, (long)StatusData.Params[1] ); // // Send the data packet // usb_device_send_data(0, Descriptor, 0, StatusData.wLength, 0, TRUE); } // end if verify length of request else { usb_device_stall_endpoint(0, USB_IN); } } // if(bSetup) else if(bDataPhaseStatus) { bDataPhaseStatus = FALSE; // Prepare dTD for the status phase usb_device_recv_data(0, 0, 0, 0, FALSE,0); } break; default: SystemHalt(); break; } break; default: ch9ServiceEp0(bSetup, btDirection, pbtBuffer, wLength,wPrivateData); } // end of switch(pSetup->RequestType.I) }