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) }
/**************************************************************************//*! * * @name USB_Service_Dic_Bulk_Out * * @brief The function ic callback function of DIC Bulk Out Endpoint * * @param event * * @return None * *****************************************************************************/ void USB_Service_Dic_Bulk_Out(usb_event_struct_t* event, void* arg) { uint8_t event_type; cdc_device_struct_t * cdc_obj_ptr = (cdc_device_struct_t *)arg; //if(USB_UNINITIALIZED_VAL_32 == event->len) return; #if CDC_IMPLEMENT_QUEUING uint8_t index; uint8_t producer, consumer; cdc_queue_struct_t queue; usb_status status = USB_OK; /* map the endpoint num to the index of the endpoint structure */ index = USB_Map_Ep_To_Struct_Index(cdc_obj_ptr, event->ep_num); USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; consumer = cdc_obj_ptr->ep[index].bin_consumer; /* No pending transfer */ if(producer == consumer) { return; } /* if there are no errors de-queue the queue and decrement the no. of transfers left, else send the same data again */ cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; while(consumer != producer) { queue = cdc_obj_ptr->ep[index].queue[consumer%CDC_MAX_QUEUE_ELEMS]; status = usb_device_recv_data(cdc_obj_ptr->controller_handle, queue.channel, queue.app_data.data_ptr, queue.app_data.data_size); if(USB_OK == status) { break; } else { USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); if(cdc_obj_ptr->class_specific_callback.callback != NULL) { event_type = USB_DEV_EVENT_DATA_RECEIVED; event->len = 0xFFFFFFFF; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, &(event->buffer_ptr), &(event->len), cdc_obj_ptr->class_specific_callback.arg); } USB_Cdc_Ep_Mutex_Lock(cdc_obj_ptr, event->ep_num); producer = cdc_obj_ptr->ep[index].bin_producer; cdc_obj_ptr->ep[index].bin_consumer++; consumer = cdc_obj_ptr->ep[index].bin_consumer; } } USB_Cdc_Ep_Mutex_Unlock(cdc_obj_ptr, event->ep_num); #endif if (cdc_obj_ptr->class_specific_callback.callback != NULL) { event_type = USB_DEV_EVENT_DATA_RECEIVED; cdc_obj_ptr->class_specific_callback.callback(event_type, USB_REQ_VAL_INVALID, &(event->buffer_ptr), &(event->len), cdc_obj_ptr->class_specific_callback.arg); } }