www.pudn.com > 44b0usb.rar > ev44b0_usb.c


/*------------------------------------------------------------------------
 . ev44b0_usb.c
 .
 . This is a USB driver for Philips's PDIUSBD12 single-chip USB device.
 .
 . (C) Copyright 2003
 . MICETEK International Inc., Shanghai China
 . Qin Wei 
 .
 .
 . This program is free software; you can redistribute it and/or modify
 . it under the terms of the GNU General Public License as published by
 . the Free Software Foundation; either version 2 of the License, or
 . (at your option) any later version.
 .
 . This program is distributed in the hope that it will be useful,
 . but WITHOUT ANY WARRANTY; without even the implied warranty of
 . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 . GNU General Public License for more details.
 .
 . You should have received a copy of the GNU General Public License
 . along with this program; if not, write to the Free Software
 . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 .
 .
 . author:
 .  Qin Wei                     ( king@micetek.com.cn )

 . History:
 .  01/14/03  Qin Wei
 ----------------------------------------------------------------------------*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include "ev44b0_usb.h"

#define EV44B0II_USB_MODULE_NAME    "usb"

#define USB_BULK_MAJOR    0x55

static const char usb_driver_version[] =
	"EV44B0II USB driver v1.0 (2003-01-09) Qinwei, MICETEK Shanghai";

#define CONFIG_USBD12_BASE 0x4000000

#define verbose 0

#define Usb_Base_Address CONFIG_USBD12_BASE

static char *usb_bulk_id = "ev44b0ii usb"; 
static volatile char USB_CONNECT_FLAG = 0;

#define MAXUSBBUFFERLEN        1024
static unsigned char gbuffer[MAXUSBBUFFERLEN];
static unsigned char controlbuffer0[64];
struct ev44b0ii_usb_priv gusb;
//****************************************************************************
//
// 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
{
    unsigned char bmRequestType;
    unsigned char bRequest;
    unsigned short wValue;
    unsigned short wIndex;
    unsigned short wLength;
} ControlTransfer;

//****************************************************************************
//
// 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;
//****************************************************************************
//
// This is the configuration descriptor for the digital audio player.  See the
// USB specification for the definition of this descriptor.
//
//****************************************************************************
static const unsigned char ucDeviceDescriptor[] =
{
    0x12,                               // bLength
    0x01,                               // bDescriptorType
    0x00, 0x01,                         // bcdUSB
    0x00,                               // bDeviceClass
    0x00,                               // bDeviceSubClass
    0x00,                               // bDeviceProtocol
    0x10,                               // bMaxPacketSize0
    0x5e, 0x04,                         // idVendor
    0x0a, 0x93,                         // idProduct
    0x00, 0x01,                         // bcdDevice
    0x01,                               // iManufacturer
    0x02,                               // iProduct
    0x00,                               // iSerial Number
    0x01                                // bNumConfigurations
};

//****************************************************************************
//
// This is the configuration descriptor for the digital audio player.  See the
// USB specification for the definition of this descriptor.
//
//****************************************************************************
static const unsigned char ucConfigurationDescriptor[] =
{
    //
    // The configuration descriptor structure.
    //
    0x09,                               // bLength
    0x02,                               // bDescriptorType
    0x20,                               // wTotalLength
    0x00,                               // bCorrection
    0x01,                               // bNumInterfaces
    0x01,                               // bConfigurationValue
    0x00,                               // iConfiguration
    0x40,                               // bmAttributes
    0x00,                               // MaxPower

    //
    // The interface descriptor structure.
    //
    0x09,                               // bLength
    0x04,                               // bDescriptorType
    0x00,                               // bInterfaceNumber
    0x00,                               // bAlternateSetting
    0x02,                               // bNumEndpoints
    0x00,                               // bInterfaceClass
    0x00,                               // bInterfaceSubClass
    0x00,                               // 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 unsigned char 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 unsigned char ucString1[] =
{
    0x1e,                               // bLength
    0x03,                               // bDescriptorType
    'M', 0x00,                          // wString[]
    'i', 0x00,
    'c', 0x00,
    'e', 0x00,
    't', 0x00,
    'e', 0x00,
    'k', 0x00,
    ' ', 0x00,
    'I', 0x00,
    'N', 0x00,
    'C', 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 unsigned char ucString2[] =
{
    0x52,                               // bLength
    0x03,                               // bDescriptorType
    'M', 0x00,                          // wString[]
    'i', 0x00,
    'c', 0x00,
    'e', 0x00,
    't', 0x00,
    'e', 0x00,
    'k', 0x00,
    ' ', 0x00,
    'E', 0x00,
    'v', 0x00,
    '4', 0x00,
    '4', 0x00,
    'b', 0x00,
    '0', 0x00,
    '-', 0x00,
    'i', 0x00,
    'i', 0x00,
    ' ', 0x00,
    'e', 0x00,
    'v', 0x00,
    'a', 0x00,
    'l', 0x00,
    'u', 0x00,
    'a', 0x00,
    't', 0x00,
    'i', 0x00,
    'o', 0x00,
    'n', 0x00,
    ' ', 0x00,
    'b', 0x00,
    'o', 0x00,
    'a', 0x00,
    'r', 0x00,
    'd', 0x00,
    ' ', 0x00,
    ' ', 0x00,
    ' ', 0x00,
    ' ', 0x00,
    ' ', 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
};

#define USB_STRUCT_INITED 0x55AAA55A

static void usb_wait_ms(unsigned int ms)
{

	if (!in_interrupt())
		{
		current->state = TASK_UNINTERRUPTIBLE;
		schedule_timeout(1 + ms * HZ / 1000);
		}
	else
		{
		current->state = TASK_INTERRUPTIBLE;
		schedule_timeout(1 + ms * HZ / 1000);
		current->state = TASK_RUNNING;
		}
}


static unsigned char USBInitStruct(void)
{
    if (sUSB.ulConfiguration == USB_STRUCT_INITED)
        return 0;

    memset(&sUSB, 0 , sizeof(sUSB));
    sUSB.ulConfiguration = USB_STRUCT_INITED;
    
    sUSB.pucControlIn = controlbuffer0;
    sUSB.ulControlInCount = 0;

//    sUSB.pucBulkIn = usbbuffer2;  /* The buffer that we send to host.*/
    sUSB.ulBulkInCount = 0;

    sUSB.pucBulkOut = gbuffer; /* The buffer that host send to us.*/
    sUSB.ulBulkOutCount = MAXUSBBUFFERLEN;

    sUSB.pucACKIn = controlbuffer0;
    sUSB.ulACKInCount = 0;
    
    sUSB.pucCommandOut = controlbuffer0;
    sUSB.ulCommandOutCount = 0;
    return 0;
}

//****************************************************************************
//
// USBReadData will read a  value from the data register of the PDIUSBD12.
//
//****************************************************************************
static unsigned char USBReadData(void)
{
    volatile unsigned char * dataregister = (unsigned char *)(unsigned char *)(Usb_Base_Address + Usb_Data_Address);
    int delay;
    unsigned char datavalue;

    //
    // Read the value from the data register.
    //
    datavalue = * dataregister;

    //
    // Delay a bit to comply with the timing specification of the PDIUSBD12.
    //
    for(delay = 0; delay < 24; delay++)
    {
    }

    //
    // Return the value read.
    //
    return(datavalue);
}

//****************************************************************************
//
// USBReadEndpoint reads data from the specified endpoint.
//
//****************************************************************************
static unsigned long USBReadEndpoint(unsigned long ulEndpoint, unsigned char **ppucData,
                unsigned long *pulLength)
{
    unsigned long ulIdx, ulLength;
    unsigned char *buffer = *ppucData;
    
    //
    // 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;
        if (ulEndpoint == USB_ENDPOINT_BULK_OUT)
        {   
            gusb.head += ulIdx;
            gusb.total += ulIdx;
        }
        if (verbose)
        {
            printk("Get %ld data from USB chip.\n",ulLength);
            {
                u8 i;
                for (i = 0; i< ulLength; i++)
                {
                    printk("%02x ", buffer[i]);
                }   
            }
            printk("\n");
        }

    }
    else /* haven't space to store the data, so drop it.*/
    {
        if (ulEndpoint == USB_ENDPOINT_BULK_OUT)
        {
            //
            // 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();
            gusb.dropped += ulLength;
        }
    }

    //
    // 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);
}


//****************************************************************************
//
// USBWriteCommand will write the specified value to the command register of
// the PDIUSBD12.
//
//****************************************************************************
static void USBWriteCommand(unsigned char commandvalue)
{
    volatile unsigned char *commandregister = (unsigned char *)(Usb_Base_Address + Usb_Command_Address);
    volatile 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.
//
//****************************************************************************
static void USBWriteData(unsigned char datavalue)
{
    volatile unsigned char *dataregister = (unsigned char *)(Usb_Base_Address + Usb_Data_Address);
    volatile 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++)
    {
    }
}

//****************************************************************************
//
// USBWriteEndpoint writes data to the specified endpoint.
//
//****************************************************************************
static void USBWriteEndpoint(unsigned long ulEndpoint, const unsigned char **ppucData,
                 unsigned long *pulLength)
{
    unsigned long 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);
}


static int ev44b0ii_usb_fasync(int fd, struct file *filp, int mode)
{
	return 0;
}

static int ev44b0ii_usb_release(struct inode *inode, struct file *filp)
{
	filp->f_op->fasync( -1, filp, 0 );  /* Remove ourselves from the async list */

   	USBWriteCommand(USB_COMMAND_SEND_RESUME);
    usb_wait_ms (10); /* Delay 10ms*/
    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_4M);

	MOD_DEC_USE_COUNT;
    
    USB_CONNECT_FLAG = 0; // we using soft-link, so we remove the pull up res.
	return 0;
}

static int ev44b0ii_usb_open(struct inode *inode, struct file *filp)
{
	struct ev44b0ii_usb_priv *dev;

	filp->private_data = &gusb;
	if (verbose)
	    printk("open usb\n");
    //
    // 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_4M);

	MOD_INC_USE_COUNT;
	while(USB_CONNECT_FLAG == 0); // wait till usb opend.
	return 0;
}

static ssize_t
ev44b0ii_usb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
    
    while ( sUSB.ulBulkInCount != 0 )// must wait send all last data.
    {
        if ( file->f_flags & O_NONBLOCK )
		        return -EAGAIN;          
    }

    sUSB.ulBulkInCount = count;
    sUSB.pucBulkIn = buf;
    USBWriteEndpoint(USB_ENDPOINT_BULK_IN, &sUSB.pucBulkIn,
                     &sUSB.ulBulkInCount);
    return count;
}

static ssize_t 
ev44b0ii_usb_read(struct file *filp, char *buf, size_t count, loff_t *l)
{
   	struct ev44b0ii_usb_priv *dev = (struct ev44b0ii_usb_priv *)filp->private_data;
   	size_t size;

	if (verbose)
	    printk("read usb\n");

    while ( dev->head == dev->tail )
    {
        if ( filp->f_flags & O_NONBLOCK )
		        return -EAGAIN;          
    }
    size = dev->head - dev->tail ;
    if (size < count) // read all?
    {
        count = size;
    }

   	if ( copy_to_user(buf, &dev->buf[dev->tail], count) ) 
	{
		return -EFAULT;
    }
    dev->tail += count;
    if (dev->tail == dev->head)
    {
        dev->head = 0;
        dev->tail = 0;
        sUSB.pucBulkOut = gbuffer; // reset the buffer.
    }

    sUSB.ulBulkOutCount += count;
    
    return count;
}
//****************************************************************************
//
// USB_isr is the interrupt handler routine for the USB on polling mode.
//
//****************************************************************************

static void USB_isr(int irq, void *dev_id, struct pt_regs *regs)
{
    unsigned long ulIntStatus, ulTransactionStatus, ulLength;
    unsigned char *pucChar;

    //
    // 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)
            printk("Host Send BUS-Reset Command.\n");
//        return;
    }

    //
    // Handle an interrupt on the bulk out endpoint.
    //
    if(ulIntStatus & USB_INT1_ENDPOINT2_OUT)
    {
        if (verbose)
            printk("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)
            printk("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 = (unsigned char *)&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)
            printk("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)
            printk("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);
        }
    }
    CLEAR_PEND_INT(irq);
}

//****************************************************************************
//
// USBStallEndpoint stalls or un-stalls the specified endpoint.
//
//****************************************************************************
static 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);
}

//****************************************************************************
//
// USBReserved handles device requests which are not supported by this USB
// device implementation.
//
//****************************************************************************
static void USBReserved(void)
{
    //
    // Stall both control endpoints.
    //
    USBStallEndpoint(USB_ENDPOINT_CONTROL_OUT, 1);
    USBStallEndpoint(USB_ENDPOINT_CONTROL_IN, 1);
}
//****************************************************************************
//
// USBGetStatus implements the USB Get_Status device request.
//
//****************************************************************************
static void USBGetStatus(void)
{
    unsigned char ucStatus[2];
    unsigned long 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;
        }
    }
}

//****************************************************************************
//
// USBClearFeature implements the USB Clear_Feature device request.
//
//****************************************************************************
static void USBClearFeature(void)
{
    unsigned long 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);
    }
}
//****************************************************************************
//
// USBSendControl transmits a block of data back to the host via the control
// endpoint.
//
//****************************************************************************

static 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);

    //
    // Success.
    //
    return(1);
}
//****************************************************************************
//
// USBSetFeature implements the USB Set_Feature device request.
//
//****************************************************************************
static void USBSetFeature(void)
{
    unsigned long 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.
//
//****************************************************************************
static 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.
//
//****************************************************************************
static void USBGetDescriptor(void)
{
    const unsigned char *pucDescriptor;
    unsigned long ulLength = 0;

    //
    // 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.
//
//****************************************************************************
static void USBGetConfiguration(void)
{
    //
    // Send the current configuration value back to the host.
    //
    USBSendControl((unsigned char *)&sUSB.ulConfiguration, 1);
}
//****************************************************************************
//
// USBSetConfiguration implements the USB Set_Configuration device request.
//
//****************************************************************************
static 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);
        USB_CONNECT_FLAG = 1;
    }

    //
    // 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.
//
//****************************************************************************
static void USBGetInterface(void)
{
    unsigned char 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.
//
//****************************************************************************
static 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);
    }
}

static int ev44b0ii_usb_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
    int RetVal = 0;
    
	return RetVal;
}

static unsigned int ev44b0ii_usb_poll(struct file *filp, poll_table *wait)
{
	struct ev44b0ii_usb_priv *dev = (struct ev44b0ii_usb_priv *)filp->private_data;

	return (dev->head == dev->tail ? 0 : (POLLIN | POLLRDNORM));
}

static struct file_operations ev44b0ii_usb_fops = {
	owner:		THIS_MODULE,
	read:		ev44b0ii_usb_read,
	write:      ev44b0ii_usb_write,
	poll:		ev44b0ii_usb_poll,
	ioctl:		ev44b0ii_usb_ioctl,
	open:		ev44b0ii_usb_open,
	release:	ev44b0ii_usb_release,
	fasync:		ev44b0ii_usb_fasync,
};

static int usb_cpu_init(void)
{
    CSR_WRITE(rPCONG,(CSR_READ(rPCONG) | 0x30));  
    return 0;  
}


int __init ev44b0ii_usb_init_module(void)
{
  	struct ev44b0ii_usb_priv *dev;
	dev = (struct ev44b0ii_usb_priv *)&gusb;

    USBInitStruct();
    USBWriteCommand(USB_COMMAND_SEND_RESUME);
    usb_wait_ms (10); /* Delay 10ms*/
    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);

#if 0
    // Qinwei???
    // 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_4M);

    USB_isr(0,0,0);
    while(1)
    {
        USB_isr(0,0,0);
    }
#endif

    if ( 0 != devfs_register_chrdev(USB_BULK_MAJOR, EV44B0II_USB_MODULE_NAME, &ev44b0ii_usb_fops))
    {
        printk(__FUNCTION__ ": can't get major number\n");
        return -1;
	}

   	if ( 0 != request_irq(INT_EINT2, USB_isr ,SA_INTERRUPT,usb_bulk_id, NULL)) 
   	{
		printk(KERN_WARNING "ev44b0ii_usb: failed to get IRQ\n");
		return 1;
	}
    
    usb_cpu_init();
	dev->head = 0;
	dev->tail = 0;
	dev->usage_count = 0;
	dev->total = 0;
	dev->dropped = 0;
	dev->buf = gbuffer;
    printk("%s\n",usb_driver_version);
    
	return 0;
}


void __exit ev44b0ii_usb_cleanup_module(void)
{
	printk(__FUNCTION__ ": EV44B0II USB BULK Exit.\n");
    free_irq(INT_EINT2,usb_bulk_id);

	devfs_unregister_chrdev(USB_BULK_MAJOR, EV44B0II_USB_MODULE_NAME);
}

module_init(ev44b0ii_usb_init_module);
module_exit(ev44b0ii_usb_cleanup_module);

MODULE_DESCRIPTION("EV44B0-II USB driver");
MODULE_AUTHOR("Qin Wei ");
MODULE_LICENSE("GPL");