Example #1
0
/**************************************************************************//*!
 *
 * @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)

}