www.pudn.com > hf44b0_TEST.rar > usb.c


#include "..\inc\44b.h" 
#include "..\inc\44blib.h" 
#include "..\inc\def.h" 
#include "..\inc\option.h" 
#include "..\inc\usb.h" 
#include  
#include  
#include  
 
//static NU_HISR  usb_comm_hisr; 
//static NU_TASK  task_usbcomm; 
//NU_EVENT_GROUP 	eg_usbcomm; 
 
int usboperation=0; 
 
static U32 verbose = 0; 
 
static U8 usbbuffer0[256]; 
static U8 usbbuffer1[256]; 
static U8 usbbuffer2[256]; 
 
void USBISRPOLLING(int number); 
 
//**************************************************************************** 
// 
// This structure defines the setup packet received from the host via the 
// control out endpoint.  This sturcture is padded at the end to the maximum 
// control endpoint transfer size. 
// 
//**************************************************************************** 
typedef struct 
{ 
    U8 bmRequestType; 
    U8 bRequest; 
    U16 wValue; 
    U16 wIndex; 
    U16 wLength; 
} ControlTransfer; 
 
//**************************************************************************** 
// 
// This is the configuration descriptor for the digital audio player.  See the 
// USB specification for the definition of this descriptor. 
// 
//**************************************************************************** 
static const U8 ucDeviceDescriptor[] = 
{ 
    0x12,                               // bLength 
    0x01,                               // bDescriptorType 
    0x00, 0x01,                         // bcdUSB 
    0x00,                               // bDeviceClass 
    0x00,                               // bDeviceSubClass 
    0x00,                               // bDeviceProtocol 
    0x10,                               // bMaxPacketSize0 
    0x71, 0x04,                         // idVendor 0x5e, 0x04, 
    0x22, 0x02,                         // idProduct 0x0a, 0x93, 
    0x00, 0x01,                         // bcdDevice 
    0x01,                               // iManufacturer 
    0x02,                               // iProduct 
    0x00,                               // iSerial Number 
    0x01                                // bNumConfigurations 
}; 
 
static const U8 ucConfigurationDescriptor[] = 
{ 
    // 
    // The configuration descriptor structure. 
    // 
    0x09,                               // bLength 
    0x02,                               // bDescriptorType 
    0x20,                               // wTotalLength 
    0x00,                               // bCorrection 
    0x01,                               // bNumInterfaces 
    0x01,                               // bConfigurationValue 
    0x00,                               // iConfiguration 
    0x80,                               // bmAttributes 0x40 
    0x32,                               // MaxPower 0x00 
 
    // 
    // The interface descriptor structure. 
    // 
    0x09,                               // bLength 
    0x04,                               // bDescriptorType 
    0x00,                               // bInterfaceNumber 
    0x00,                               // bAlternateSetting 
    0x02,                               // bNumEndpoints 
    0x00, //00                              // bInterfaceClass 
    0x00,                               // bInterfaceSubClass 
    0x00, //00                              // bInterfaceProtocol 
    0x00,                               // iInterface 
 
    // 
    // The endpoint descriptor structure. 
    // 
    0x07,                               // bLength 
    0x05,                               // bDescriptorType 
    0x82,                               // bEndpointAddress 
    0x02,                               // bmAttributes 
    0x40, 0x00,                         // wMaxPacketSize 
    0x00,                               // bInterval 
 
    // 
    // The endpoint descriptor structure. 
    // 
    0x07,                               // bLength 
    0x05,                               // bDescriptorType 
    0x02,                               // bEndpointAddress 
    0x02,                               // bmAttributes 
    0x40, 0x00,                         // wMaxPacketSize 
    0x00                                // bInterval 
}; 
//**************************************************************************** 
// 
// String descriptor 0 for the digital audio player.  This defines the 
// languages supported by the string descriptors.  See the USB specification 
// for the definition of this descriptor. 
// 
//**************************************************************************** 
static const U8 ucString0[] = 
{ 
    0x04,                               // bLength 
    0x03,                               // bDescriptorType 
    0x09, 0x04                          // wLANGID[0] -> US English 
}; 
 
//**************************************************************************** 
// 
// String descriptor 1 for the digital audio player.  This defines the 
// manufacturer of the player.  See the USB specification for the definition 
// of this descriptor. 
// 
//**************************************************************************** 
static const U8 ucString1[] = 
{ 
    0x26,                               // bLength 
    0x03,                               // bDescriptorType 
    'S', 0x00,                          // wString[] 
    'W', 0x00, 
    '4', 0x00, 
    '4', 0x00, 
    'B', 0x00, 
    '0', 0x00, 
    ' ', 0x00, 
    'B', 0x00, 
    'O', 0x00, 
    'A', 0x00, 
    'R', 0x00, 
    'D', 0x00, 
    ' ', 0x00, 
    ' ', 0x00, 
    ' ', 0x00, 
    ' ', 0x00, 
    ' ', 0x00, 
    ' ', 0x00 
}; 
 
//**************************************************************************** 
// 
// String descriptor 1 for the digital audio player.  This defines the product 
// description of the player.  See the USB specification for the definition of 
// this descriptor. 
// 
//**************************************************************************** 
static const U8 ucString2[] = 
{ 
    0x52,                               // bLength 
    0x03,                               // bDescriptorType 
    'S', 0x00,                          // wString[] 
    'W', 0x00, 
    '4', 0x00, 
    '4', 0x00, 
    'B', 0x00, 
    '0', 0x00, 
    '-', 0x00, 
    'P', 0x00, 
    'D', 0x00, 
    'I', 0x00, 
    'U', 0x00, 
    'S', 0x00, 
    'B', 0x00, 
    'D', 0x00, 
    '1', 0x00, 
    '2', 0x00, 
    ' ', 0x00, 
    'D', 0x00, 
    'E', 0x00, 
    'V', 0x00, 
    'I', 0x00, 
    'C', 0x00, 
    'E', 0x00, 
    'S', 0x00, 
    ' ', 0x00 
}; 
//**************************************************************************** 
// 
// An array of pointers to the USB standard device request handler Functions. 
// 
//**************************************************************************** 
void (* const USBStandardDeviceRequest[])(void) = 
{ 
    USBGetStatus, 
    USBClearFeature, 
    USBReserved, 
    USBSetFeature, 
    USBReserved, 
    USBSetAddress, 
    USBGetDescriptor, 
    USBReserved, 
    USBGetConfiguration, 
    USBSetConfiguration, 
    USBGetInterface, 
    USBSetInterface, 
    USBReserved 
}; 
 
//**************************************************************************** 
// 
// The following structure contains the persistent state of the USB interface. 
// 
//**************************************************************************** 
static struct 
{ 
    // The currently selected USB configuration. 
    unsigned long ulConfiguration; 
 
    // The buffer of data that is being sent to the control endpoint. 
    const unsigned char *pucControlIn; 
 
    // The number of bytes to be sent to the control endpoint. 
     unsigned long ulControlInCount; 
 
    // The buffer of data that is being received from the control endpoint. 
    ControlTransfer sControlOut; 
 
    // The buffer of data that is being sent to the bulk endpoint. 
     const unsigned char *pucBulkIn; 
 
    // The number of bytes to be sent to the bulk endpoint. 
    unsigned long ulBulkInCount; 
 
    // The buffer of data that is being received from the bulk endpoint. 
    unsigned char *pucBulkOut; 
 
    // The number of bytes still to be read from the bulk endpoint. 
    unsigned long ulBulkOutCount; 
 
    const unsigned char *pucACKIn; 
 
    unsigned long ulACKInCount; 
     
    unsigned char  *pucCommandOut; 
     
    unsigned long ulCommandOutCount; 
 
} sUSB; 
 
 
#define USB_STRUCT_INITED 0x55AAA55A 
 
U8 USBInitStruct(void) 
{ 
    if (sUSB.ulConfiguration == USB_STRUCT_INITED) 
        return 0; 
         
    memset(&sUSB, 0 , sizeof(sUSB));     
    sUSB.ulConfiguration = USB_STRUCT_INITED; 
     
    sUSB.pucControlIn = usbbuffer0; 
    sUSB.ulControlInCount = 0; 
 
    sUSB.pucBulkIn = usbbuffer2; 
    sUSB.ulBulkInCount = 0; 
 
    sUSB.pucBulkOut = usbbuffer2; 
    sUSB.ulBulkOutCount = 0; 
 
    sUSB.pucACKIn = usbbuffer1; 
    sUSB.ulACKInCount = 0; 
     
    sUSB.pucCommandOut = usbbuffer1; 
    sUSB.ulCommandOutCount = 0; 
    return 0; 
} 
 
 
void USBEnable(void) 
{ 
	pISR_EINT0=(int)USBISR; 
 	rINTMSK =~(BIT_GLOBAL|BIT_EINT0); 
} 
 
void USBDisable(void) 
{ 
	 rINTMSK =BIT_EINT0; 
} 
 
//**************************************************************************** 
// 
// USBWriteCommand will write the specified value to the command register of 
// the PDIUSBD12. 
// 
//**************************************************************************** 
void USBWriteCommand(U8 commandvalue) 
{ 
    U8 * volatile commandregister = (U8 *)(Usb_Base_Address + Usb_Command_Address); 
    int delay; 
 
    // Write the value to the command register. 
     *commandregister = commandvalue; 
 
    // Delay a bit to comply with the timing specification of the PDIUSBD12. 
     for(delay = 0; delay < 24; delay++) 
    { 
    } 
} 
 
//**************************************************************************** 
// 
// USBWriteData will write the specified value to the data register of the 
// PDIUSBD12. 
// 
//**************************************************************************** 
void USBWriteData(U8 datavalue) 
{ 
    U8 * volatile dataregister = (U8 *)(Usb_Base_Address + Usb_Data_Address); 
    int delay; 
 
    // Write the value to the data register. 
 
    *dataregister = datavalue; 
 
    // Delay a bit to comply with the timing specification of the PDIUSBD12. 
    for(delay = 0; delay < 24; delay++) 
    { 
    } 
} 
//**************************************************************************** 
// 
// USBInit configures the PDIUSBD12 device. 
// 
//**************************************************************************** 
void USBON(void) 
{ 
    int saveSyscfg; 
     
    saveSyscfg=rSYSCFG; 
     
//    rNCACHBE1=( (0x6000000>>12)<<16 )|(0x4000000>>12); 
//    rSYSCFG=SYSCFG_8KBn; 
     
    USBInitStruct(); 
    USBWriteCommand(USB_COMMAND_SEND_RESUME); 
    Delay(10000); 
    USBWriteCommand(USB_COMMAND_SET_ADDRESS_ENABLE); 
    USBWriteData(0); 
     
    USBWriteCommand(USB_COMMAND_SET_ENDPOINT_ENABLE); 
    USBWriteData(0); 
    // 
    // Enable the interrupts for the bulk endpoints. 
    // 
    USBWriteCommand(USB_COMMAND_SET_DMA); 
    USBWriteData(USB_DMA_ENDP4_INT_ENABLE | USB_DMA_ENDP5_INT_ENABLE); 
 
    // 
    // Configure the PDIUSBD12 and enable the SoftConnect pull-up. 
    // 
    USBWriteCommand(USB_COMMAND_SET_MODE); 
    USBWriteData(USB_CONFIG1_NO_LAZY_CLOCK | USB_CONFIG1_CLOCK_RUNNING | 
                 USB_CONFIG1_SOFT_CONNECT); 
    USBWriteData(USB_CONFIG2_SET_TO_ONE | USB_CONFIG2_CLOCK_12M); 
    Uart_Printf("USB ON\n"); 
    Uart_Printf("Your PC will add the new USB\n"); 
    Uart_Printf("Press any key ,close USB and exit\n"); 
    USBEnable(); 
    do{ 
    	USBISRPOLLING(0); 
    } 
    while(!Uart_GetKey()); 
    USBOFF(); 
    rSYSCFG=saveSyscfg; 
} 
 
void USBOFF(void) 
{ 
    USBWriteCommand(USB_COMMAND_SEND_RESUME); 
    Delay(10000); 
    USBWriteCommand(USB_COMMAND_SET_ADDRESS_ENABLE); 
    USBWriteData(0); 
     
    USBWriteCommand(USB_COMMAND_SET_ENDPOINT_ENABLE); 
    USBWriteData(0); 
    // 
    // Enable the interrupts for the bulk endpoints. 
    // 
    USBWriteCommand(USB_COMMAND_SET_DMA); 
    USBWriteData(USB_DMA_ENDP4_INT_ENABLE | USB_DMA_ENDP5_INT_ENABLE); 
      
    USBWriteCommand(USB_COMMAND_SET_MODE); 
    USBWriteData(0); 
    USBWriteData(USB_CONFIG2_SET_TO_ONE | USB_CONFIG2_CLOCK_12M); 
 } 
 
//**************************************************************************** 
// 
// USBISR is the interrupt handler routine for the USB. 
// 
//**************************************************************************** 
void __irq USBISR(void) 
{ 
    unsigned long ulIntStatus, ulTransactionStatus, ulLength,uSize; 
    U8 *pucChar, ucChar; 
    static int choosebool=0; 
     
    // Read the PDIUSBD12 interrupt register. 
    rI_ISPC=BIT_EINT0;	//clear pending_bit 
    USBWriteCommand(USB_COMMAND_READ_INTERRUPT); 
    ulIntStatus = USBReadData(); 
    ulIntStatus |= USBReadData() << 8; 
 
    // Do nothing if there was a bus reset. 
      if(ulIntStatus & USB_INT1_BUS_RESET) 
    { 
    	return; 
    } 
    // Handle an interrupt on the bulk out endpoint. 
     if(ulIntStatus & USB_INT1_ENDPOINT2_OUT) 
    { 
       //Uart_Printf("Occur USB_INT1_ENDPOINT2_OUT interrupt\n"); 
        // Read the status of the last transaction on the bulk out endpoint. 
         USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + 
                        USB_ENDPOINT_BULK_OUT); 
        ulTransactionStatus = USBReadData(); 
        //Uart_Printf("Status: %u\n",ulTransactionStatus); 
 
        // Was a packet of data received successfully? 
        if(ulTransactionStatus & USB_XACTION_STATUS_DATA_RX_TX_SUCCESS) 
        { 
       // If there is a buffer to read this data into, then read the data into that buffer. 
       // Read the packet. 
        	uSize=USBReadEndpoint(USB_ENDPOINT_BULK_OUT, &sUSB.pucBulkOut, &sUSB.ulBulkOutCount); 
        	//Uart_Printf("Size: %u\n",uSize); 
        	Uart_Printf("usbbuffer0: %s\n",usbbuffer0); 
        	Uart_Printf("usbbuffer1: %s\n",usbbuffer1); 
        	Uart_Printf("usbbuffer2: %s\n",usbbuffer2); 
         } 
    } 
    // Handle an interrupt on the control out endpoint. 
    if(ulIntStatus & USB_INT1_CONTROL_OUT) 
    { 
        //Uart_Printf("Occur USB_INT1_CONTROL_OUT interrupt\n"); 
        // Read the status of the last transaction on the control out endpoint. 
       USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS +  USB_ENDPOINT_CONTROL_OUT); 
        ulTransactionStatus = USBReadData(); 
        // Was a setup packet received? 
        if(ulTransactionStatus & USB_XACTION_STATUS_SETUP_PACKET) 
        { 
        // Read the packet. 
            pucChar = (U8 *)&sUSB.sControlOut; 
            ulLength = sizeof(ControlTransfer); 
            if(USBReadEndpoint(USB_ENDPOINT_CONTROL_OUT, &pucChar, 
                               &ulLength) != sizeof(ControlTransfer)) 
            { 
          // The size of the setup packet is incorrect, so stall both of the control endpoints. 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
            } 
            else 
            { 
             // Acknowledge both the control in and control out endpoints, 
             // and send a clear buffer command to the control out endpoint. 
                USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + USB_ENDPOINT_CONTROL_OUT); 
                USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
                USBWriteCommand(USB_COMMAND_CLEAR_BUFFER); 
                USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + USB_ENDPOINT_CONTROL_IN); 
                USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
 
            // Process the command in the setup packet. 
            if(((sUSB.sControlOut.bmRequestType & USB_RT_TYPE_MASK) == 
                    USB_RT_TYPE_STANDARD) && (sUSB.sControlOut.bRequest < 16)) 
                { 
            // This is a standard request, so call the appropriate routine. 
              (*USBStandardDeviceRequest[sUSB.sControlOut.bRequest])(); 
                } 
                else 
                { 
            // All other requests are treated as reserved requests. 
                    USBReserved(); 
                } 
            } 
        } 
        else 
        {  // The packet was not a setup packet, so ignore it.  Send a clear 
            // buffer command to the control out endpoint so it will receive new packets. 
            // 
            USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + 
                            USB_ENDPOINT_CONTROL_OUT); 
            USBWriteCommand(USB_COMMAND_CLEAR_BUFFER); 
            // Acknowledge both the control in and control out endpoints. 
            USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
            USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + USB_ENDPOINT_CONTROL_IN); 
            USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
        } 
    } 
    // Handle an interrupt on the control in endpoint. 
    if(ulIntStatus & USB_INT1_CONTROL_IN) 
    { 
        //Uart_Printf("Occur USB_INT1_CONTROL_IN interrupt\n"); 
        // Read the status of the last transaction on the control in endpoint. 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + USB_ENDPOINT_CONTROL_IN); 
        USBReadData(); 
 
        // Was this the last block of data to be sent back to the host? 
         if(sUSB.ulControlInCount != 0) 
        { 
            // Send the next packet of data to the host. 
        USBWriteEndpoint(USB_ENDPOINT_CONTROL_IN, &sUSB.pucControlIn,&sUSB.ulControlInCount); 
        } 
        else 
        {  // There is no more data to send, so send an empty packet. 
            ulLength = 0; 
            USBWriteEndpoint(USB_ENDPOINT_CONTROL_IN, 0, &ulLength); 
        } 
    } 
    // Handle an interrupt on the bulk in endpoint. 
    if(ulIntStatus & USB_INT1_ENDPOINT2_IN) 
    { 
        //Uart_Printf("Occur USB_INT1_ENDPOINT2_IN interrupt\n"); 
        // Read the status of the last transaction on the bulk in endpoint. 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + USB_ENDPOINT_BULK_IN); 
        USBReadData(); 
 
        // Was this the last block of data to be sent back to the host? 
        if(sUSB.ulBulkInCount != 0) 
        {// Send the next packet of data to the host. 
         USBWriteEndpoint(USB_ENDPOINT_BULK_IN, &sUSB.pucBulkIn, &sUSB.ulBulkInCount); 
        } 
    } 
} 
 
//**************************************************************************** 
// 
// USBReadData will read a  value from the data register of the PDIUSBD12. 
// 
//**************************************************************************** 
unsigned char USBReadData(void) 
{ 
    unsigned char * volatile dataregister = (unsigned char*)(unsigned char *)(Usb_Base_Address + Usb_Data_Address); 
    int delay; 
    U8 datavalue; 
 
    // Write the value to the data register. 
    datavalue = * dataregister; 
    for(delay = 0; delay < 24; delay++) 
    { 
    } 
    return(datavalue); 
} 
 
//**************************************************************************** 
// 
// USBWriteEndpoint writes data to the specified endpoint. 
// 
//**************************************************************************** 
void USBWriteEndpoint(unsigned long ulEndpoint, const unsigned char **ppucData,unsigned long *pulLength) 
{ 
    U32 ulIdx, ulLength; 
 
    // Determine the size of the packet to be sent based on the endpoint. 
    if(ulEndpoint == USB_ENDPOINT_CONTROL_IN) 
    { 
        // The maximum packet size for the control endpoint is 16. 
        ulLength = (*pulLength > 16) ? 16 : *pulLength; 
    } 
    else 
    { 
        // The maxmium packet size for the bulk endpoint is 64. 
         ulLength = (*pulLength > 64) ? 64 : *pulLength; 
    } 
    // Select the appropriate endpoint. 
    USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + ulEndpoint); 
 
    // Send the write buffer command. 
    USBWriteCommand(USB_COMMAND_WRITE_BUFFER); 
 
    // Write the reserved byte to the buffer. 
    USBWriteData(0); 
 
    // Write the length of the data packet. 
    USBWriteData(ulLength); 
 
    // Write the data into the transmit buffer. 
    for(ulIdx = 0; ulIdx < ulLength; ulIdx++) 
    { 
        USBWriteData(*(*ppucData)++); 
    } 
 
    // 
    // Decrement the count of bytes to write. 
    *pulLength -= ulLength; 
 
 
    // Send the validate buffer command so that the endpoint will transmit the packet. 
    USBWriteCommand(USB_COMMAND_VALIDATE_BUFFER); 
} 
 
//**************************************************************************** 
// 
// USBReadEndpoint reads data from the specified endpoint. 
// 
//**************************************************************************** 
unsigned long 
USBReadEndpoint(unsigned long ulEndpoint,unsigned char **ppucData,unsigned long *pulLength) 
{ 
    U32 ulIdx, ulLength; 
      
    // Select the appropriate endpoint. 
    USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + ulEndpoint); 
 
    // Is there buffer space to fill with this data or should we throw the data away? 
    if(*pulLength) 
    {    // Send the read buffer command. 
       USBWriteCommand(USB_COMMAND_READ_BUFFER); 
        // Throw away the reserved byte from the beginning of the buffer. 
 
        USBReadData(); 
        // Read the length of the data buffer. 
        ulLength = USBReadData(); 
        // Read the data into the receive buffer. 
        for(ulIdx = 0; (ulIdx < ulLength) && (ulIdx < *pulLength); ulIdx++) 
        { 
            *(*ppucData)++ = USBReadData(); 
        } 
 
        // Decrement the count of bytes to read. 
        *pulLength -= ulIdx; 
    }   
    // Send the clear buffer command so that the endpoint can receive another packet. 
    USBWriteCommand(USB_COMMAND_CLEAR_BUFFER); 
 
    // Return the size of the packet received. 
    return(ulLength); 
} 
 
//**************************************************************************** 
// 
// USBSendACK transmits a block of data back to the host via the bulk 
// endpoint 1. 
// 
//**************************************************************************** 
unsigned long 
USBSendACK(const unsigned char *pucData, unsigned long ulLength) 
{ 
    // If a block is already being transmitted, then return a failure. 
     if(sUSB.ulACKInCount) 
    { 
        return(0); 
    } 
    // Prepare to transmit this block back to the host. 
    sUSB.pucACKIn = pucData; 
    sUSB.ulACKInCount = ulLength; 
 
    // Send the first packet of this block back to the host. 
    USBWriteEndpoint(USB_ENDPOINT_ACK_IN, &sUSB.pucACKIn,&sUSB.ulACKInCount); 
    return(1); 
} 
 
//**************************************************************************** 
// 
// USBReserved handles device requests which are not supported by this USB 
// device implementation. 
// 
//**************************************************************************** 
void USBReserved(void) 
{ 
    // Stall both control endpoints. 
    USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
    USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
} 
 
//**************************************************************************** 
// 
// USBStallEndpoint stalls or un-stalls the specified endpoint. 
// 
//**************************************************************************** 
void USBStallEndpoint(unsigned long ulEndpoint, unsigned long bStall) 
{ 
    // 
    // Send the appropriate set endpoint status command to the PDIUSBD12. 
    // 
    USBWriteCommand(USB_COMMAND_SET_ENDPOINT_STATUS + ulEndpoint); 
    USBWriteData(bStall ? 1 : 0); 
} 
 
//**************************************************************************** 
// 
// USBGetStatus implements the USB Get_Status device request. 
// 
//**************************************************************************** 
void USBGetStatus(void) 
{ 
    U8 ucStatus[2]; 
    U32 ulEndpoint; 
    // Determine how to handle this request based on the recipient. 
 
    switch(sUSB.sControlOut.bmRequestType & USB_RT_RECIPIENT_MASK) 
    { 
        // If the recipient is a device, return the state of the device's 
        // remote wakeup and self powered states. 
         case USB_RT_RECIPIENT_DEVICE: 
        { 
            // The player is self powered and does not support remote wakeup. 
            ucStatus[0] = USB_DEVICE_STATUS_SELF_POWERED; 
            ucStatus[1] = 0; 
 
            // Send our response back to the host. 
            USBSendControl(ucStatus, 2); 
 
            // We're done handling this request. 
             break; 
        } 
        // If the recipient is a device interface, return a value of 
        // 0x00 as required by the USB spec. 
        case USB_RT_RECIPIENT_INTERFACE: 
        { 
       // The USB spec. requires a GetStatus request for an interface return a pair of zero bytes. 
            ucStatus[0] = 0; 
            ucStatus[1] = 0; 
            // Send our response back to the host. 
            USBSendControl(ucStatus, 2); 
 
            // We're done handling this request. 
            break; 
        } 
 
        // 
        // If the recipient is an endpoint, determine whether it is stalled or 
        // not and return that information to the host. 
        // 
        case USB_RT_RECIPIENT_ENDPOINT: 
        { 
            // Find out which endpoint is the recipient of the request. 
            ulEndpoint = sUSB.sControlOut.wIndex & USB_ENDPOINT_ADDRESS_MASK; 
            // Determine whether the IN or the OUT endpoint is being addressed 
            // in the device request. 
            ulEndpoint *= 2; 
            if(sUSB.sControlOut.wIndex & USB_ENDPOINT_DIRECTION_MASK) 
            { 
                ulEndpoint++; 
            } 
 
            // Read the endpoint status. 
            USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT); 
            ulEndpoint = USBReadData(); 
 
            // Send the endpoint's status to the host. 
            if(ulEndpoint & USB_ENDPOINT_STALL) 
            { 
                ucStatus[0] = USB_ENDPOINT_STATUS_STALLED; 
            } 
            else 
            { 
                ucStatus[0] = 0; 
            } 
            ucStatus[1] = 0; 
 
            // Send our response back to the host. 
            USBSendControl(ucStatus, 2); 
 
            // We're done handling this request. 
            break; 
        } 
        // If an invalid request is received, stall the control endpoint. 
 
        default: 
        { 
            // Stall the both control endpoints. 
            USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
            USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
 
            // We're done handling this request. 
            break; 
        } 
    } 
} 
 
//**************************************************************************** 
// 
// USBSendControl transmits a block of data back to the host via the control 
// endpoint. 
// 
//**************************************************************************** 
unsigned long 
USBSendControl(const unsigned char *pucData, unsigned long ulLength) 
{ 
    // If a block is already being transmitted, then return a failure. 
    if(sUSB.ulControlInCount) 
    { 
        return(0); 
    } 
    // Prepare to transmit this block back to the host. 
    sUSB.pucControlIn = pucData; 
    sUSB.ulControlInCount = ulLength; 
 
    // Send the first packet of this block back to the host. 
     USBWriteEndpoint(USB_ENDPOINT_CONTROL_IN, &sUSB.pucControlIn,&sUSB.ulControlInCount); 
    return(1); 
} 
 
//**************************************************************************** 
// 
// USBClearFeature implements the USB Clear_Feature device request. 
// 
//**************************************************************************** 
void USBClearFeature(void) 
{ 
    U32 ulEndpoint; 
 
    // The only feature we support is stall on an endpoint. 
   if(((sUSB.sControlOut.bmRequestType & USB_RT_RECIPIENT_MASK) == USB_RT_RECIPIENT_ENDPOINT) && 
       (sUSB.sControlOut.wValue == USB_FEATURE_ENDPOINT_STALL)) 
    { 
        // Compute the endpoint number. 
        ulEndpoint = (sUSB.sControlOut.wIndex & USB_ENDPOINT_ADDRESS_MASK) * 2; 
        if(sUSB.sControlOut.wIndex & USB_ENDPOINT_DIRECTION_MASK) 
        { 
            ulEndpoint++; 
        } 
 
        // Clear the stall condition on the specified endpoint. 
        USBStallEndpoint(ulEndpoint, 0); 
    } 
    else 
    { 
        // An unknown feature was specified, so stall both control endpoints. 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBSetFeature implements the USB Set_Feature device request. 
// 
//**************************************************************************** 
void USBSetFeature(void) 
{ 
    U32 ulEndpoint; 
 
    // The only feature we support is stall on an endpoint. 
    if(((sUSB.sControlOut.bmRequestType & USB_RT_RECIPIENT_MASK) == 
        USB_RT_RECIPIENT_ENDPOINT) && 
       (sUSB.sControlOut.wValue == USB_FEATURE_ENDPOINT_STALL)) 
    { 
        // Compute the endpoint number. 
        ulEndpoint = (sUSB.sControlOut.wIndex & USB_ENDPOINT_ADDRESS_MASK) * 2; 
        if(sUSB.sControlOut.wIndex & USB_ENDPOINT_DIRECTION_MASK) 
        { 
            ulEndpoint++; 
        } 
 
        // Set the stall condition on the specified endpoint. 
        USBStallEndpoint(ulEndpoint, 1); 
    } 
    else 
    { 
        // An unknown feature was specified, so stall both control endpoints. 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBSetAddress implements the USB Set_Address device request. 
// 
//**************************************************************************** 
void USBSetAddress(void) 
{ 
    // Configure our UBS controller for the USB address assigned by the host. 
    USBWriteCommand(USB_COMMAND_SET_ADDRESS_ENABLE); 
    USBWriteData(sUSB.sControlOut.wValue | 0x80); 
 
    // Respond to the host with an empty packet. 
    USBSendControl(0, 0); 
} 
 
//**************************************************************************** 
// 
// USBGetDescriptor implements the USB Get_Descriptor device request. 
// 
//**************************************************************************** 
void USBGetDescriptor(void) 
{ 
    const U8 *pucDescriptor; 
    U32 ulLength; 
 
    // Determine how to handle this request based on the requested descriptor. 
 
    switch(sUSB.sControlOut.wValue & USB_DESCRIPTOR_TYPE_MASK) 
    { 
        // The device descriptor was requested. 
        case USB_DESCRIPTOR_DEVICE: 
        { 
            // Prepare to return the device descriptor. 
            pucDescriptor = ucDeviceDescriptor; 
            ulLength = sizeof(ucDeviceDescriptor); 
 
            // We're done handling this request. 
            break; 
        } 
 
        // The configuration descriptor was requested. 
        case USB_DESCRIPTOR_CONFIGURATION: 
        { 
            // Prepare to return the configuration descriptor. 
            pucDescriptor = ucConfigurationDescriptor; 
            ulLength = sizeof(ucConfigurationDescriptor); 
 
            // We're done handling this request. 
            break; 
        } 
 
        // A string descriptor was requested. 
        case USB_DESCRIPTOR_STRING: 
        { 
        // Make sure that the language and string index requested are valid. 
          if(((sUSB.sControlOut.wValue & USB_DESCRIPTOR_INDEX_MASK) != 0) && 
               ((sUSB.sControlOut.wIndex != 0x0409) || 
                ((sUSB.sControlOut.wValue & USB_DESCRIPTOR_INDEX_MASK) > 2))) 
            { 
             // Stall both of the control endpoints. 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
 
                // We're done handling this request. 
                return; 
            } 
 
            // Prepare to return the requested string. 
            switch(sUSB.sControlOut.wValue & USB_DESCRIPTOR_INDEX_MASK) 
            { 
                // String index 0 is the language ID string. 
                 case 0x00: 
                { 
                    pucDescriptor = ucString0; 
                    ulLength = sizeof(ucString0); 
                    break; 
                } 
                // String index 1 is the manufacturer name. 
                case 0x01: 
                { 
                    pucDescriptor = ucString1; 
                    ulLength = sizeof(ucString1); 
                    break; 
                } 
 
                // String index 2 is the product name. 
                case 0x02: 
                { 
                    pucDescriptor = ucString2; 
                    ulLength = sizeof(ucString2); 
                    break; 
                } 
            } 
 
            // We're done handling this request. 
            break; 
        } 
 
        // An invalid request is received, so stall both control endpoints. 
        default: 
        { 
         // Stall both of the control endpoints. 
            USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
            USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
         // We're done handling this request. 
            return; 
        } 
    } 
 
    // If the requested length is less than the length of the descriptor to be 
    // returned, then simply return the requested portion of the descriptor. 
 
    if(sUSB.sControlOut.wLength < ulLength) 
    { 
        ulLength = sUSB.sControlOut.wLength; 
    } 
 
    // Send the descriptor back to the host. 
    USBSendControl(pucDescriptor, ulLength); 
} 
 
//**************************************************************************** 
// 
// USBGetConfiguration implements the USB Get_Configuration device request. 
// 
//**************************************************************************** 
void USBGetConfiguration(void) 
{ 
    // Send the current configuration value back to the host. 
    USBSendControl((U8 *)&sUSB.ulConfiguration, 1); 
} 
 
//**************************************************************************** 
// 
// USBSetConfiguration implements the USB Set_Configuration device request. 
// 
//**************************************************************************** 
void USBSetConfiguration(void) 
{ 
    // If the requested configuration is zero, then go into the unconfigured state. 
     if(sUSB.sControlOut.wValue == 0) 
    { 
        // Clear the global configuration flag. 
        sUSB.ulConfiguration = 0; 
 
        // Disable the generic endpoints. 
        USBWriteCommand(USB_COMMAND_SET_ENDPOINT_ENABLE); 
        USBWriteData(0); 
 
        // Respond to the host with an empty packet. 
        USBSendControl(0, 0); 
    } 
 
    // If the requested configuration is one, then go into the configured state. 
     else if(sUSB.sControlOut.wValue == 1) 
    { 
      // Set the global configuration flag. 
      sUSB.ulConfiguration = 1; 
 
        // Disable the generic endpoints. 
        USBWriteCommand(USB_COMMAND_SET_ENDPOINT_ENABLE); 
        USBWriteData(0); 
 
        // Enable the generic endpoints. 
        USBWriteCommand(USB_COMMAND_SET_ENDPOINT_ENABLE); 
        USBWriteData(1); 
 
        // Respond to the host with an empty packet. 
        USBSendControl(0, 0); 
    } 
 
    // If the requested configuration is anything else, then stall both of the control endpoints. 
     else 
    { 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
    } 
} 
 
 
//**************************************************************************** 
// 
// USBGetInterface implements the USB Get_Interface device request. 
// 
//**************************************************************************** 
void USBGetInterface(void) 
{ 
    U8 ucInterface = 0; 
 
    // We only support a single interface, so the current interface is always 
    // the first one.  Send our response back to the host. 
    USBSendControl(&ucInterface, 1); 
} 
 
//**************************************************************************** 
// 
// USBSetInterface implements the USB Set_Interface device request. 
// 
//**************************************************************************** 
void USBSetInterface(void) 
{ 
    // We only support a single interface. 
    if((sUSB.sControlOut.wValue == 0) && (sUSB.sControlOut.wIndex == 0)) 
    { 
        // The first interface was requested, so do nothing. 
        return; 
    } 
    else 
    { 
        // A non-existent interface was requested, so stall both control endpoints. 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
        USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBReceiveBulk reads a block of data from the host via the bulk endpoint. 
// 
//**************************************************************************** 
unsigned long 
USBReceiveBulk(unsigned char *pucData, unsigned long ulLength) 
{ 
    // If a block is already being read, then return a failure. 
    if(sUSB.ulBulkOutCount) 
    { 
        return(0); 
    } 
 
    // Prepare to read data from the host into this buffer. 
    sUSB.pucBulkOut = pucData; 
    sUSB.ulBulkOutCount = ulLength; 
    return(1); 
} 
 
//**************************************************************************** 
// 
// USBReceiveBulkDone determines if the data receive from the bulk endpoint 
// has completed. 
// 
//**************************************************************************** 
unsigned long 
USBReceiveBulkDone(void) 
{ 
    // Is there more data to receive from the bulk endpoint? 
    if(sUSB.ulBulkOutCount) 
    { 
        // There's more data to receive, so indicate that we're not done. 
        return(0); 
    } 
    else 
    { 
        // We've received all the data, so indicate that we're done. 
        return(1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBReceiveCommand reads a block of data from the host via the bulk endpoint 1. 
// 
//**************************************************************************** 
unsigned long 
USBReceiveCommand(unsigned char *pucData, unsigned long ulLength) 
{ 
    // If a block is already being read, then return a failure. 
    if(sUSB.ulCommandOutCount) 
    { 
        return(0); 
    } 
 
    // Prepare to read data from the host into this buffer. 
    sUSB.pucCommandOut = pucData; 
    sUSB.ulCommandOutCount = ulLength; 
    return(1); 
} 
 
//**************************************************************************** 
// 
// USBReceiveCommandDone determines if the data receive from the bulk endpoint 
// has completed. 
// 
//**************************************************************************** 
unsigned long 
USBReceiveCommandDone(void) 
{ 
    // Is there more data to receive from the bulk endpoint? 
    if(sUSB.ulCommandOutCount) 
    {     // There's more data to receive, so indicate that we're not done. 
         return(0); 
    } 
    else 
    { 
        // We've received all the data, so indicate that we're done. 
     return(1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBSendACKDone determines if the data transmit to the bulk endpoint 2 has 
// completed. 
// 
//**************************************************************************** 
unsigned long 
USBSendACKDone(void) 
{ 
     // Is there more data to be sent to the bulk endpoint? 
    if(sUSB.ulACKInCount != 0) 
    { 
        // There's more data to transmit, so indicate that we're not done. 
         return(0); 
    } 
    else 
    {   // We've sent all the data, so indicate that we're done. 
         return(1); 
    } 
} 
 
//**************************************************************************** 
// 
// USBSendBulk transmits a block of data back to the host via the bulk 
// endpoint. 
// 
//**************************************************************************** 
unsigned long 
USBSendBulk(const unsigned char *pucData, unsigned long ulLength) 
{ 
    // If a block is already being transmitted, then return a failure. 
    if(sUSB.ulBulkInCount) 
    { 
        return(0); 
    } 
    // Prepare to transmit this block back to the host. 
    sUSB.pucBulkIn = pucData; 
    sUSB.ulBulkInCount = ulLength; 
 
     USBWriteEndpoint(USB_ENDPOINT_BULK_IN, &sUSB.pucBulkIn, &sUSB.ulBulkInCount); 
 
    return(1); 
} 
 
//**************************************************************************** 
// 
// USBSendBulkDone determines if the data transmit to the bulk endpoint has 
// completed. 
// 
//**************************************************************************** 
unsigned long 
USBSendBulkDone(void) 
{ 
    // Is there more data to be sent to the bulk endpoint? 
    if(sUSB.ulBulkInCount) 
    { 
        // There's more data to transmit, so indicate that we're not done. 
        return(0); 
    } 
    else 
    { 
        // We've sent all the data, so indicate that we're done. 
         return(1); 
    } 
} 
 
 
//**************************************************************************** 
// 
// USBSendControlDone determines if the data transmit to the control endpoint 
// has completed. 
// 
//**************************************************************************** 
unsigned long 
USBSendControlDone(void) 
{ 
    // Is there more data to be sent to the control endpoint? 
    if(sUSB.ulControlInCount) 
    { 
        // There's more data to transmit, so indicate that we're not done. 
        return(0); 
    } 
    else 
    { 
        // We've sent all the data, so indicate that we're done. 
        return(1); 
    } 
} 
 
void USBISRPOLLING(int number) 
{ 
    unsigned long ulIntStatus, ulTransactionStatus, ulLength; 
    unsigned char *pucChar, ucChar; 
    static int choosebool=0; 
 
    // 
    // Read the PDIUSBD12 interrupt register. 
    // 
    USBWriteCommand(USB_COMMAND_READ_INTERRUPT); 
    ulIntStatus = USBReadData(); 
    ulIntStatus |= USBReadData() << 8; 
 
    // 
    // Do nothing if there was a bus reset. 
    // 
    if(ulIntStatus & USB_INT1_BUS_RESET) 
    { 
        if (verbose) 
            printf("Host Send BUS-Reset Command.\n"); 
       
        return; 
    } 
 
    // 
    // Handle an interrupt on the bulk out endpoint. 
    // 
    if(ulIntStatus & USB_INT1_ENDPOINT2_OUT) 
    { 
        if (verbose) 
            printf("Occur Main-Out-Endpoint Interrupt.\n"); 
 
        // 
        // Read the status of the last transaction on the bulk out endpoint. 
        // 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + 
                        USB_ENDPOINT_BULK_OUT); 
        ulTransactionStatus = USBReadData(); 
 
        // 
        // Was a packet of data received successfully? 
        // 
        if(ulTransactionStatus & USB_XACTION_STATUS_DATA_RX_TX_SUCCESS) 
        { 
            // 
            // If there is a buffer to read this data into, then read the data 
            // into that buffer. 
            // 
            // 
            // Read the packet. 
            // 
            USBReadEndpoint(USB_ENDPOINT_BULK_OUT, &sUSB.pucBulkOut,&sUSB.ulBulkOutCount); 
        } 
    } 
 
    // 
    // Handle an interrupt on the control out endpoint. 
    // 
    if(ulIntStatus & USB_INT1_CONTROL_OUT) 
    { 
        if (verbose) 
            printf("Occur Control-Out-Endpoint Interrupt.\n"); 
 
        // 
        // Read the status of the last transaction on the control out endpoint. 
        // 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + 
                        USB_ENDPOINT_CONTROL_OUT); 
        ulTransactionStatus = USBReadData(); 
 
        // 
        // Was a setup packet received? 
        // 
        if(ulTransactionStatus & USB_XACTION_STATUS_SETUP_PACKET) 
        { 
            // 
            // Read the packet. 
            // 
            pucChar = (U8 *)&sUSB.sControlOut; 
            ulLength = sizeof(ControlTransfer); 
            if(USBReadEndpoint(USB_ENDPOINT_CONTROL_OUT, &pucChar,&ulLength) != sizeof(ControlTransfer)) 
            { 
                // 
                // The size of the setup packet is incorrect, so stall both of 
                // the control endpoints. 
                // 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1); 
                USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1); 
            } 
            else 
            { 
                // 
                // Acknowledge both the control in and control out endpoints, 
                // and send a clear buffer command to the control out endpoint. 
                // 
                USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + 
                                USB_ENDPOINT_CONTROL_OUT); 
                USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
                USBWriteCommand(USB_COMMAND_CLEAR_BUFFER); 
                USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + 
                                USB_ENDPOINT_CONTROL_IN); 
                USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
 
                // 
                // 
                // Process the command in the setup packet. 
                // 
                if(((sUSB.sControlOut.bmRequestType & USB_RT_TYPE_MASK) == 
                    USB_RT_TYPE_STANDARD) && (sUSB.sControlOut.bRequest < 16)) 
                { 
                    // 
                    // This is a standard request, so call the appropriate 
                    // routine. 
                    // 
                    (*USBStandardDeviceRequest[sUSB.sControlOut.bRequest])(); 
                } 
                else 
                { 
                    // 
                    // All other requests are treated as reserved requests. 
                    // 
                    USBReserved(); 
                } 
            } 
        } 
        else 
        { 
            // 
            // The packet was not a setup packet, so ignore it.  Send a clear 
            // buffer command to the control out endpoint so it will receive 
            // new packets. 
            // 
            USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + 
                            USB_ENDPOINT_CONTROL_OUT); 
            USBWriteCommand(USB_COMMAND_CLEAR_BUFFER); 
 
            // 
            // Acknowledge both the control in and control out endpoints. 
            // 
            USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
            USBWriteCommand(USB_COMMAND_SELECT_ENDPOINT + 
                            USB_ENDPOINT_CONTROL_IN); 
            USBWriteCommand(USB_COMMAND_ACKNOWLEDGE_ENDPOINT); 
        } 
    } 
 
    // 
    // Handle an interrupt on the control in endpoint. 
    // 
    if(ulIntStatus & USB_INT1_CONTROL_IN) 
    { 
        if (verbose) 
            printf("Occur Control-In--Endpoint Interrupt.\n"); 
 
        // 
        // Read the status of the last transaction on the control in endpoint. 
        // 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + 
                        USB_ENDPOINT_CONTROL_IN); 
        USBReadData(); 
 
        // 
        // Was this the last block of data to be sent back to the host? 
        // 
        if(sUSB.ulControlInCount != 0) 
        { 
            // 
            // Send the next packet of data to the host. 
            // 
            USBWriteEndpoint(USB_ENDPOINT_CONTROL_IN, &sUSB.pucControlIn, 
                             &sUSB.ulControlInCount); 
        } 
        else 
        { 
            // 
            // There is no more data to send, so send an empty packet. 
            // 
            ulLength = 0; 
            USBWriteEndpoint(USB_ENDPOINT_CONTROL_IN, 0, &ulLength); 
        } 
    } 
 
    // 
    // Handle an interrupt on the bulk in endpoint. 
    // 
    if(ulIntStatus & USB_INT1_ENDPOINT2_IN) 
    { 
        if (verbose) 
            printf("Occur Main-In--Endpoint Interrupt.\n"); 
 
        // 
        // Read the status of the last transaction on the bulk in endpoint. 
        // 
        USBWriteCommand(USB_COMMAND_READ_LAST_XACTION_STATUS + 
                        USB_ENDPOINT_BULK_IN); 
        USBReadData(); 
 
        // 
        // Was this the last block of data to be sent back to the host? 
        // 
        if(sUSB.ulBulkInCount != 0) 
        { 
            // 
            // Send the next packet of data to the host. 
            // 
            USBWriteEndpoint(USB_ENDPOINT_BULK_IN, &sUSB.pucBulkIn, 
                             &sUSB.ulBulkInCount); 
        } 
    } 
}