⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 de4_dev.c

📁 cypress usb芯片驱动程序,该程序实现了cypress63700的3个驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************* * * Copyright (c) 2003 Cypress Semiconductor * * * 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. * *//******************************************************************* * *    DESCRIPTION: Peripheral Funciton Driver for EZ-HOST Design  *                 Example Four of the development kit. * *******************************************************************//** 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 "de4_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 de4_priv {    int                             major_number;    struct usb_device_instance *    device;        struct urb_link                 bulk_out_rcv;    struct urb_link                 bulk_in_tx;        hid_keyboard_report_t           hidrpt;    int                             open_count;    struct semaphore                sem;};static struct de4_priv * de4_priv = NULL;extern int dbgflg_usbdfd_usbe;#define dbg_usbe(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_usbe,lvl,fmt,##args)/* function prototypes */static void de4_event(struct usb_device_instance *, usb_device_event_t, int);static int  de4_urb_sent(struct usbd_urb *, int);static int  de4_recv_urb(struct usbd_urb *);static void de4_function_init(struct usb_bus_instance *,                               struct usb_device_instance *,                               struct usb_function_driver *);static void de4_function_exit(struct usb_device_instance *);static ssize_t de4_read(struct file *, char *, size_t, loff_t *);static ssize_t ep_read(struct de4_priv *, char *, size_t, int);static ssize_t de4_write(struct file *, const char *, size_t, loff_t *);static ssize_t ep_write(struct de4_priv *, const char *, size_t, int);static int de4_open(struct inode *, struct file *);static int de4_release(struct inode *, struct file *);static int de4_ioctl(struct inode *, struct file *, unsigned int,                      unsigned long);static void de4_recycle_urb(struct usbd_urb *urb, struct urb_link *link);/*******************************************************************************   FUNCTION CONFIGURATION DESCRIPTORS *//* Design Example 4 Endpoints *  +---------------------+---------------+--------------+ *  |      Bulk in        |  Endpoint 1   |  loopback    | *  +---------------------+ --------------+--------------| *  |      Bulk out       |  Endpoint 2   |  loopback    | *  +---------------------+---------------+--------------+ *  |      Bulk out       |  Endpoint 3   |  report      | *  +---------------------+---------------+--------------+ */      struct usb_endpoint_description de4_endpoint_description[] = {    {        bEndpointAddress :  BULK_IN_EP,        bmAttributes :      BULK,        wMaxPacketSize :    64,        bInterval :         0,        direction :         IN,        transferSize :      1024,    },         {        bEndpointAddress :  BULK_OUT_EP,        bmAttributes :      BULK,        wMaxPacketSize :    64,        bInterval :         0,        direction :         OUT,        transferSize :      1024,    },    {        bEndpointAddress :  BULK_OUT2_EP,        bmAttributes :      BULK,        wMaxPacketSize :    64,        bInterval :         0,        direction :         OUT,        transferSize :      64,    },};struct usb_alternate_description de4_alternate_description = {    iInterface :            0,    bAlternateSetting :     0,    classes :               0,    class_list :           NULL,    endpoints :             sizeof(de4_endpoint_description) /                            sizeof(struct usb_endpoint_description),    endpoint_list :        de4_endpoint_description,    otg_description :      0};struct usb_interface_description de4_interface_description = {    bInterfaceClass :       0,    bInterfaceSubClass :    0,    bInterfaceProtocol :    0,    iInterface :            0,    alternates :            sizeof(de4_alternate_description) /                            sizeof(struct usb_alternate_description),    alternate_list :        &de4_alternate_description};struct usb_configuration_description de4_configuration_description = {    iConfiguration :        0,    bmAttributes :          BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED,    bMaxPower :             0,    interfaces :            sizeof(de4_interface_description) /                            sizeof(struct usb_interface_description),    interface_list :        &de4_interface_description};struct usb_device_description de4_device_description = {    bDeviceClass :      DE4_DEVICE_CLASS,    bDeviceSubClass :   DE4_DEVICE_SUBCLASS,    bDeviceProtocol :   DE4_DEVICE_PROTOCOL,    idVendor :          DE4_VENDOR_ID,    idProduct :         DE4_PRODUCT_ID,    iManufacturer :     DE4_MANUFACTURER_STR,    iProduct :          DE4_PRODUCT_STR,    iSerialNumber :     DE4_SERIAL_NUMBER_STR};/*****************************************************************************/struct usb_function_operations de4_function_ops = {    event : de4_event,    urb_sent : de4_urb_sent,    recv_urb : de4_recv_urb,    recv_setup : 0,    function_init : de4_function_init,    function_exit : de4_function_exit,};struct usb_function_driver de4_function_driver = {    name : "DE4_function_driver",    ops : &de4_function_ops,    device_description : &de4_device_description,    configurations : sizeof(de4_configuration_description) /                     sizeof(struct usb_configuration_description),    configuration_description : &de4_configuration_description,    this_module : THIS_MODULE,};struct file_operations de4_file_ops = {    owner : THIS_MODULE,    read : de4_read,    write : de4_write,    open : de4_open,    release : de4_release,    ioctl : de4_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 de4_function_init(struct usb_bus_instance * bus,                        struct usb_device_instance * device,                        struct usb_function_driver * func_driver){    dev_dbg("de4_function_init enter");        de4_priv = kmalloc( sizeof(struct de4_priv), GFP_KERNEL);    if(de4_priv == NULL)     {        cy_err("de4_priv memory allocation failed.");        return;    }    de4_priv->hidrpt.valid = 0;    /* Register device driver */    de4_priv->major_number =         register_chrdev( 0, DE4_DEVICE_NAME, &de4_file_ops );    if( de4_priv->major_number == 0 )    {        cy_err("register_chrdev() failed.");        kfree(de4_priv);         de4_priv = NULL;        return;    }                                      /* save off the usb_device_instance pointer */    de4_priv->device = device;        de4_priv->open_count = 0;    /* initialize the semaphore, (kernel) */    sema_init(&de4_priv->sem, 1);        /* save our private data into the usb_function_instance private pointer */    device->function_instance_array->privdata = de4_priv;}/****************************************************************************** * *  DESCRIPTION: not used in DE4 * *  RETURNS: * */void de4_function_exit(struct usb_device_instance * device){    int i;    dev_dbg("de4_function_exit enter");    /* deallocate URB's for each endpoint */    for(i = 0; i < TOTAL_ENDPOINTS; i++)     {        /* free up URB buffers */    }          unregister_chrdev( de4_priv->major_number, DE4_DEVICE_NAME );    /* deallocate the function private structure */    kfree(de4_priv);    de4_priv = NULL;        /* set the usb_function_instance privdata pointer to null */    device->function_instance_array->privdata = NULL;}/****************************************************************************** * *  DESCRIPTION: Event handler that processes events from the usbd core. * *  RETURNS: * */void de4_event(struct usb_device_instance * device, usb_device_event_t event,                int data){    extern char *usbd_device_events[];    dev_dbg("de4_event enter: event: %s, data = %d",            usbd_device_events[event], data);    switch(event)    {        case DEVICE_INIT:            {                struct usbd_urb * urb;                size_t i;                                /* initialize URB linked lists */                urb_link_init(&de4_priv->bulk_out_rcv);                urb_link_init(&de4_priv->bulk_in_tx);                /* allocate bulk send urbs */                for(i=0; i<5; i++)                {                    urb = usbd_alloc_urb(device,                                          device->function_instance_array,                                          BULK_IN_EP,                                          BULK_IN_BUFF_SZ);                    de4_recycle_urb(urb, &de4_priv->bulk_in_tx);                }            }            break;                case DEVICE_UNKNOWN:        case DEVICE_CREATE:        case DEVICE_HUB_CONFIGURED:        case DEVICE_RESET:        case DEVICE_ADDRESS_ASSIGNED:        case DEVICE_CONFIGURED:        case DEVICE_SET_INTERFACE:        case DEVICE_SET_FEATURE:        case DEVICE_CLEAR_FEATURE:        case DEVICE_DE_CONFIGURED:        case DEVICE_BUS_INACTIVE:        case DEVICE_BUS_ACTIVITY:        case DEVICE_POWER_INTERRUPTION:        case DEVICE_HUB_RESET:        case DEVICE_DESTROY:        case DEVICE_FUNCTION_PRIVATE:            break;    }}/****************************************************************************** * *  DESCRIPTION: Callback to notify function that a URB has been transmitted *  on the bus successfully. * *  RETURNS: Zero for SUCCESS, negative for ERROR. * */int de4_urb_sent(struct usbd_urb * sent_urb, int data){    int return_value = ERROR;    dev_dbg("de4_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 BULK_IN_EP:            de4_recycle_urb(sent_urb, &de4_priv->bulk_in_tx);            return_value = SUCCESS;            break;        default:            cy_warn("ERROR didn't recycle urb");            break;        }        break;        default:        cy_err("ERROR de4_urb_sent: unhandled sent status.");        break;    }    return(return_value);}/****************************************************************************** * *  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 de4_recv_urb(struct usbd_urb * recv_urb){    int port = 0;    struct usb_device_instance *device = recv_urb->device;    struct de4_priv * priv = (device->function_instance_array+port)->privdata;    int ret_value = -EINVAL;           dev_dbg("de4_recv_urb enter");    if((recv_urb != NULL) && (recv_urb->status != RECV_ERROR))     {             // determine which endpoint received the URB.            switch(recv_urb->endpoint->endpoint_address & 0xf)         {                /* save off the URB pointer for a subsequent read by the                  * application, this will add the URB to a linked list, it                  * allows us to receive data faster than the application                  * may request it */            case BULK_OUT_EP:                               dev_dbg("de4_recv_urb BULK_OUT");                urb_append_irq(&priv->bulk_out_rcv, recv_urb);                            /* the read() function will recycle the URB after the                  * application retrieves the data, so we are done */                ret_value = SUCCESS;                break;                        case BULK_OUT2_EP:                dev_dbg("de4_recv_urb BULK_OUT2");                if (de4_priv->hidrpt.valid == 0)                 {                    if (recv_urb->actual_length == HID_REPORT_SIZE )                    {                        if( memcpy(de4_priv->hidrpt.report, recv_urb->buffer,                                    HID_REPORT_SIZE) != NULL)                         {                            dev_dbg("Valid HID report");                            de4_priv->hidrpt.valid = 1;                        }                    }                }                                usbd_recycle_urb(recv_urb);                ret_value = SUCCESS;                            break;

⌨️ 快捷键说明

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