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)

}
Esempio n. 2
0
/**************************************************************************//*!
 *
 * @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);
    }
}