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