de3_dev.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 901 行 · 第 1/2 页

C
901
字号
/******************************************************************* * *    DESCRIPTION: Peripheral Funciton Driver for Lyberty Design  *                 Example Four of the development kit. * *    AUTHOR: GXJ@CYPRESS.COM * *    HISTORY:     * *******************************************************************//** include files **///#define  MODULE#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/compatmac.h>#include <linux/slab.h>#include <asm/semaphore.h>#include <asm/ioctls.h>#include "../usbd.h"#include "../usbd-func.h"#include "../usbd-bus.h"#include "../usbd-debug.h"#include "../usbd-inline.h"#include "../usbd-arch.h"#include "../usbd-export.h"#include "../usbd-build.h"#include "../../cy7c67200_300_common.h"#include "../../cy7c67200_300_debug.h"#include "de3_dev.h"static int dev_dbg_on = 0;#define dev_dbg(format, arg...) \    if( dev_dbg_on != 0 ) \        printk(KERN_DEBUG __FILE__ ":"  "%d: " format "\n" ,__LINE__, ## arg)/** local definitions **/struct de3_priv {    int                             major_number;    struct usb_device_instance *    device;        struct urb_link                 int_in_tx;        int                             open_count;    struct semaphore                sem;};static struct de3_priv * de3_priv = NULL;extern int dbgflg_usbdfd_usbe;#define dbg_usbe(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_usbe,lvl,fmt,##args)/* function prototypes */static void de3_event(struct usb_device_instance *, usb_device_event_t, int);static int  de3_urb_sent(struct usbd_urb *, int);static int  de3_recv_urb(struct usbd_urb *);static void de3_function_init(struct usb_bus_instance *,                               struct usb_device_instance *,                               struct usb_function_driver *);static void de3_function_exit(struct usb_device_instance *);static ssize_t de3_read(struct file *, char *, size_t, loff_t *);//static ssize_t ep_read(struct de3_priv *, char *, size_t, int);static ssize_t de3_write(struct file *, const char *, size_t, loff_t *);static ssize_t ep_write(struct de3_priv *, const char *, size_t, int);static int de3_open(struct inode *, struct file *);static int de3_release(struct inode *, struct file *);static int de3_ioctl(struct inode *, struct file *, unsigned int,                      unsigned long);static void de3_recycle_urb(struct usbd_urb *urb, struct urb_link *link);/*******************************************************************************   FUNCTION CONFIGURATION DESCRIPTORS *//* Design Example 3 Endpoints *  +---------------------+---------------+--------------+ *  |    Control in       |               |              | *  +---------------------+  Endpoint 0   |  Control     | *  |    Control out      |               |              | *  +---------------------+---------------+--------------+ *  |    Interrupt in     |  Endpoint 1   |  report      | *  +---------------------+ --------------+--------------| */      struct usb_endpoint_description de3_endpoint_description[] = {    {        bEndpointAddress :  INT_IN_EP,        bmAttributes :      INTERRUPT,        wMaxPacketSize :    8,        bInterval :         10,        direction :         IN,        transferSize :      8,    },};struct usb_class_description de3_class_description[] = {    {        bDescriptorSubtype: USB_ST_HID,        elements:           0,        description: {                     hid: {                          bcdHID:             0x100,                          bCountryCode:       0x21,                          bDescriptorType1:   USB_ST_REP,                          // size needs to be consistant with de3_bios.asm                          // HID report descriptor size                          wDescriptorLength1: 0x3f,                          },                     },    },};                struct usb_alternate_description de3_alternate_description = {    iInterface :            0,    bAlternateSetting :     0,    classes :               sizeof(de3_class_description) /                            sizeof(struct usb_class_description),    class_list :            de3_class_description,    endpoints :             sizeof(de3_endpoint_description) /                            sizeof(struct usb_endpoint_description),    endpoint_list :         de3_endpoint_description,    otg_description :       0,};struct usb_interface_description de3_interface_description[] = {    {        bInterfaceClass :       HID_INTERFACE_CLASS,        bInterfaceSubClass :    HID_INTERFACE_SUBCLASS_BOOT,        bInterfaceProtocol :    HID_INTERFACE_PROTOCOL_KEYBOARD,        iInterface :            0,        alternates :            sizeof(de3_alternate_description) /                                sizeof(struct usb_alternate_description),        alternate_list :        &de3_alternate_description    },};struct usb_configuration_description de3_configuration_description = {    iConfiguration :        0,    bmAttributes :          BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED,    bMaxPower :             0,    interfaces :            sizeof(de3_interface_description) /                            sizeof(struct usb_interface_description),    interface_list :        &de3_interface_description};struct usb_device_description de3_device_description = {    bDeviceClass :      DE3_DEVICE_CLASS,    bDeviceSubClass :   DE3_DEVICE_SUBCLASS,    bDeviceProtocol :   DE3_DEVICE_PROTOCOL,    idVendor :          DE3_VENDOR_ID,    idProduct :         DE3_PRODUCT_ID,    iManufacturer :     DE3_MANUFACTURER_STR,    iProduct :          DE3_PRODUCT_STR,    iSerialNumber :     DE3_SERIAL_NUMBER_STR,};/*****************************************************************************/struct usb_function_operations de3_function_ops = {    event : de3_event,    urb_sent : de3_urb_sent,    recv_urb : de3_recv_urb,    recv_setup : 0,    function_init : de3_function_init,    function_exit : de3_function_exit,};struct usb_function_driver de3_function_driver = {    name : "DE3_function_driver",    ops : &de3_function_ops,    device_description : &de3_device_description,    configurations : sizeof(de3_configuration_description) /                     sizeof(struct usb_configuration_description),    configuration_description : &de3_configuration_description,    this_module : THIS_MODULE,};struct file_operations de3_file_ops = {    owner : THIS_MODULE,    read : de3_read,    write : de3_write,    open : de3_open,    release : de3_release,    ioctl : de3_ioctl,};/****************************************************************************** *  PARAMETERS:  bus -> pointer to usb_bus_instance *               device -> pointer to usb_device_instance *               func_driver -> pointer to usb_function_driver *  DESCRIPTION: This routine will initialize the function driver's private  *               data.  It is called from the peripheral controller  * *  RETURNS: * */void de3_function_init(struct usb_bus_instance * bus,                        struct usb_device_instance * device,                        struct usb_function_driver * func_driver){    dev_dbg("de3_function_init enter");         de3_priv = kmalloc( sizeof(struct de3_priv), GFP_KERNEL);    if(de3_priv == NULL) {        cy_err("de3_priv memory allocation failed.");        return;    }    /* Register device driver */    de3_priv->major_number =         register_chrdev( 0, DE3_DEVICE_NAME, &de3_file_ops );    if( de3_priv->major_number == 0 )    {        cy_err("register_chrdev() failed.");        kfree(de3_priv);         de3_priv = NULL;        return;    }                                      /* save off the usb_device_instance pointer */    de3_priv->device = device;        de3_priv->open_count = 0;    /* initialize the semaphore, (kernel) */    sema_init(&de3_priv->sem, 1);        /* save our private data into the usb_function_instance private pointer */    device->function_instance_array->privdata = de3_priv;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */void de3_function_exit(struct usb_device_instance * device){    int i;    dev_dbg("de3_function_exit enter");    /* deallocate URB's for each endpoint */    for(i = 0; i < TOTAL_ENDPOINTS; i++) {        /* free up URB buffers */        // FIXME next line needs to be fixed        //kfree(dev->endpoint_data[i].buffer);    }          unregister_chrdev( de3_priv->major_number, DE3_DEVICE_NAME );    /* deallocate the function private structure */    kfree(de3_priv);    de3_priv = NULL;        /* set the usb_function_instance privdata pointer to null */    device->function_instance_array->privdata = NULL;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */void de3_event(struct usb_device_instance * device, usb_device_event_t event, int data){    extern char *usbd_device_events[];    dev_dbg("de3_event enter: event: %s, data = %d",            usbd_device_events[event], data);    switch(event)    {        case DEVICE_UNKNOWN:            break;            case DEVICE_INIT:            {                struct usbd_urb * urb;                size_t i;                                /* initialize URB linked lists */                urb_link_init(&de3_priv->int_in_tx);                /* allocate int send urbs */                for(i=0; i<5; i++)                {                    urb = usbd_alloc_urb(device,                                          device->function_instance_array,                                          INT_IN_EP,                                          64);                    de3_recycle_urb(urb, &de3_priv->int_in_tx);                }            }            break;                case DEVICE_CREATE:            break;                case DEVICE_HUB_CONFIGURED:            break;                case DEVICE_RESET:            break;                case DEVICE_ADDRESS_ASSIGNED:            break;                case DEVICE_CONFIGURED:            break;                case DEVICE_SET_INTERFACE:            break;                case DEVICE_SET_FEATURE:            break;                case DEVICE_CLEAR_FEATURE:            break;                case DEVICE_DE_CONFIGURED:            break;                                    case DEVICE_BUS_INACTIVE:            break;                    case DEVICE_BUS_ACTIVITY:            break;        case DEVICE_POWER_INTERRUPTION:            break;                case DEVICE_HUB_RESET:            break;        case DEVICE_DESTROY:            break;                case DEVICE_FUNCTION_PRIVATE:            break;    }}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: Callback to notify function that a URB has been transmitted *  on the bus successfully. * *  RETURNS: Zero for SUCCESS, negative for ERROR. * */int de3_urb_sent(struct usbd_urb * sent_urb, int data){    int return_value = ERROR;    dev_dbg("de3_urb_sent enter");    /* check the status of the completed URB */    switch(sent_urb->status)    {    case SEND_FINISHED_OK:    case SEND_FINISHED_ERROR:        switch( sent_urb->endpoint->endpoint_address & 0xf)        {        case INT_IN_EP:            de3_recycle_urb(sent_urb, &de3_priv->int_in_tx);            return_value = SUCCESS;            break;        default:            cy_warn("ERROR didn't recycle urb");            break;        }        break;        default:        cy_err("ERROR de3_urb_sent: unhandled sent status.");        break;    }    return(return_value);}/****************************************************************************** *  PARAMETERS: recv_urb -> a pointer to a URB passed from the peripheral core  *  layer. * *  DESCRIPTION:  Called to receive a URB, called in the interrupt context.   *  This function determines to which endpoint the received URB belongs, and  *  saves off the pointer to this URB in the function's private data.  This  *  will then be processed in the read() function when called by the  *  application.  The read() function will then recycle the URB.   * *  In the future, this may just store the data in a buffer and return.  Then  *  the read function would read directly from the buffer.  This implementation *  would return the URB's immediately to the peripheral controller driver.   *  Currently, instead of allocating a separate buffer, this function saves  *  off a pointer to the URB and the read() function handles it directly,  *  essentially using the URB buffer to store the data, instead of allocating  *  separate buffer space. * *  RETURNS:  A negative value for an error condition, and zero for success.   *  If an error is returned, then the calling function will check this return  *  value, and recycle the URB, essentially discarding the data. * */int de3_recv_urb(struct usbd_urb * recv_urb){    int ret_value = -EINVAL;           dev_dbg("de3_recv_urb enter");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?