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

📄 osrfx2.c~

📁 一个对cy7c68013芯片实现控制传输和批量传输的linux下的驱动
💻 C~
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************//* osrfx2.c    A Driver for the OSR USB FX2 Learning Kit device              *//*                                                                           *//* Copyright (C) 2006 by Robin Callender                                     *//*                                                                           *//* 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, version 2.                     *//*                                                                           *//*****************************************************************************//*****************************************************************************//*				modified by Yunxiang Liu				*//*****************************************************************************/#include <linux/version.h>//#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/kref.h>#include <linux/poll.h>#include <asm/uaccess.h>#include <linux/usb.h>/*****************************************************************************//* Define the vendor id and product id.                                      *//*****************************************************************************/#define VENDOR_ID   0x0547       #define PRODUCT_ID  0x1002#define DEVICE_MINOR_BASE   192#define CYPRESS_MAX_REQSIZE	8             #undef TRUE#define TRUE  (1)#undef FALSE#define FALSE (0)/*****************************************************************************//* Define the vendor commands supported by OSR USB FX2 device.               *//*****************************************************************************/#define OSRFX2_SET_XFER_START       0xBE//0xD8             /*****************************************************************************//* Table of devices that work with this driver                               *//*****************************************************************************/static struct usb_device_id id_table [] = {    { USB_DEVICE( VENDOR_ID, PRODUCT_ID ) },    { },};MODULE_DEVICE_TABLE(usb, id_table);/*****************************************************************************//* This is the private device context structure.                             *//*****************************************************************************/struct osrfx2 {    struct usb_device    * udev;    struct usb_interface * interface;        /*     * This queue is used by the poll and irq methods     */    wait_queue_head_t FieldEventQueue;        /*     *  Transfer Buffers     */    //unsigned char * int_in_buffer;    unsigned char * bulk_in_buffer;    unsigned char * bulk_out_buffer;        /*     *  Buffer sizes     */    //size_t int_in_size;    size_t bulk_in_size;    size_t bulk_out_size;        /*     *  USB Endpoints     */    //__u8  int_in_endpointAddr;    __u8  bulk_in_endpointAddr;    __u8  bulk_out_endpointAddr;        /*     *  Endpoint intervals     */    //__u8  int_in_endpointInterval;    __u8  bulk_in_endpointInterval;    __u8  bulk_out_endpointInterval;        /*     *  URBs     */    struct urb * bulk_in_urb;    //struct urb * int_in_urb;    struct urb * bulk_out_urb;        /*     *  Refrence counter     */    struct kref      kref;    struct semaphore sem;    /*     *  Data from interrupt is retained here.     */    //struct switches_state  switches;    unsigned char notify;    /*     *  Track usage of the bulk pipes: serialize each pipe's use.     */    atomic_t bulk_write_available;    atomic_t bulk_read_available;    /*     *  Data tracking for Read/Write.      *  Writes will add to the pending_data count and      *  reads will deplete the pending_data count.     *     *  Note: The OSRFX2 device specs states that the firmware will buffer     *        up-to four write packet (two on EP6 and two on EP8).     *        The buffers can be drained by issuing reads to EP8.     *        The fifth outstanding write packet attempt will cause the write     *        to block, waiting for the arrival of a read request to     *        effectively free a buffer into which the write data can be      *        held.     */    size_t  pending_data;    /*     *  Power Managment related fields     */    int   suspended;        /* boolean */}; /*****************************************************************************//* Forward declaration for our usb_driver definition later.                  *//*****************************************************************************/static struct usb_driver osrfx2_driver;/* Send a vendor command to device */static int vendor_command(struct usb_device *dev, unsigned char request, 			  unsigned char value, unsigned char index,			  void *buf, int size){	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),			       request, 			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,			       value, 			       index, buf, size,			       USB_CTRL_GET_TIMEOUT);}/*****************************************************************************//* This routine will set the bargraph LEDs.                                  *//*                                                                           *//* Note the two different function defintions depending on kernel version.   *//*****************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)static ssize_t set_xfer_start(struct device * dev,                             const char * buf,                            size_t count)#elsestatic ssize_t set_xfer_start(struct device * dev,                             struct device_attribute * attr,                             const char * buf,                            size_t count)#endif{    struct usb_interface  * intf   = to_usb_interface(dev);    struct osrfx2         * fx2dev = usb_get_intfdata(intf);    //struct bargraph_state * packet;    unsigned int value;    int retval;    char * end;		unsigned char *iobuf;    value = (simple_strtoul(buf, &end, 10) & 0xFF);    if (buf == end) {        value = 0;    }		/* allocate some memory for the i/o buffer*/	iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL);/*    retval = usb_control_msg(fx2dev->udev,                              usb_sndctrlpipe(fx2dev->udev, 0),                              OSRFX2_SET_BARGRAPH_DISPLAY,                              USB_DIR_OUT | USB_TYPE_VENDOR,                             0,                             0,                             iobuf,//packet,                              CYPRESS_MAX_REQSIZE,//sizeof(*packet),                             USB_CTRL_GET_TIMEOUT);*/		retval = vendor_command(fx2dev->udev, 			  OSRFX2_SET_XFER_START, 0, 0,			  iobuf, CYPRESS_MAX_REQSIZE);    if (retval < 0) {        dev_err(&fx2dev->udev->dev, "%s - retval=%d\n",                 __FUNCTION__, retval);    }        //kfree(packet);		kfree(iobuf);    return count;}/*****************************************************************************//* This macro creates an attribute under the sysfs directory                 *//*   ---  /sys/bus/usb/devices/<root_hub>-<hub>:1.0/bargraph                 *//*                                                                           *//* The DEVICE_ATTR() will create "dev_attr_bargraph".                        *//* "dev_attr_bargraph" is referenced in both probe and disconnect routines.  *//*****************************************************************************/static DEVICE_ATTR( start, S_IWUGO, NULL, set_xfer_start );/*****************************************************************************//*                                                                           *//*****************************************************************************/static int init_bulks(struct osrfx2 * fx2dev){    fx2dev->bulk_in_buffer = kmalloc(fx2dev->bulk_in_size, GFP_KERNEL);    if (!fx2dev->bulk_in_buffer) {        return -ENOMEM;    }    fx2dev->bulk_out_buffer = kmalloc(fx2dev->bulk_out_size, GFP_KERNEL);    if (!fx2dev->bulk_out_buffer) {        return -ENOMEM;    }    init_MUTEX( &fx2dev->sem );    init_waitqueue_head( &fx2dev->FieldEventQueue );    return 0; }/*****************************************************************************//* This routine will attempt to locate the required endpoints and            *//* retain relevant information in the osrfx2 structure instance.             *//*****************************************************************************/static int find_endpoints(struct osrfx2 * fx2dev){    struct usb_interface * interface = fx2dev->interface;    struct usb_endpoint_descriptor * endpoint;    unsigned char dir;    unsigned char attr;    int i;    for (i=0; i < interface->cur_altsetting->desc.bNumEndpoints; i++) {        endpoint = &interface->cur_altsetting->endpoint[i].desc;        dir  = endpoint->bEndpointAddress & USB_DIR_IN;        attr = endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;        switch ((dir << 8) + attr) {            /*case ((USB_DIR_IN << 8) + USB_ENDPOINT_XFER_INT) :                fx2dev->int_in_endpointAddr = endpoint->bEndpointAddress;                fx2dev->int_in_endpointInterval = endpoint->bInterval;                fx2dev->int_in_size = endpoint->wMaxPacketSize;                break;*/            case ((USB_DIR_IN << 8) + USB_ENDPOINT_XFER_BULK) :                fx2dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;                fx2dev->bulk_in_endpointInterval = endpoint->bInterval;                fx2dev->bulk_in_size = endpoint->wMaxPacketSize;                break;            case ((USB_DIR_OUT << 8) + USB_ENDPOINT_XFER_BULK) :                fx2dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;                fx2dev->bulk_out_endpointInterval = endpoint->bInterval;                fx2dev->bulk_out_size = endpoint->wMaxPacketSize;                break;            default:                break;        }    }    if (//fx2dev->int_in_endpointAddr   == 0 ||         fx2dev->bulk_in_endpointAddr  == 0 ||        fx2dev->bulk_out_endpointAddr == 0) {        dev_err(&interface->dev, "%s - failed to find required endpoints\n",                 __FUNCTION__);        return -ENODEV;    }    return 0;}/*****************************************************************************//*                                                                           *//*****************************************************************************/static void osrfx2_delete(struct kref * kref){    struct osrfx2 * fx2dev = container_of(kref, struct osrfx2, kref);    usb_put_dev( fx2dev->udev );        /*if (fx2dev->int_in_urb) {        usb_free_urb(fx2dev->int_in_urb);    }    if (fx2dev->int_in_buffer) {        kfree(fx2dev->int_in_buffer);    }*/    if (fx2dev->bulk_in_buffer) {        kfree( fx2dev->bulk_in_buffer );    }    if (fx2dev->bulk_out_buffer) {        kfree( fx2dev->bulk_out_buffer );    }    kfree( fx2dev );}/*****************************************************************************//* osrfx2_open                                                               *//*                                                                           *//* Note:                                                                     *//*   The serialization method used below has a side-effect which I don't     *//*   particularly care for. In effect switch_events and bulk I/O are         *//*   mutually exclusive, e.g. an open for switch_events will exclude         *//*   opens for bulk I/O (osrbulk) and vis-a-verse.                           *//*                                                                           *//* Note:                                                                     *//*   The usb_clear_halt() is being used to effect a pipe reset.              *//*   This will clear any residual data at the endpoint and ready it for      *//*   the new endpoint user's data.                                           *//*****************************************************************************/static int osrfx2_open(struct inode * inode, struct file * file){    struct usb_interface * interface;    struct osrfx2 * fx2dev;    int retval;    int flags;        interface = usb_find_interface(&osrfx2_driver, iminor(inode));    if (interface == NULL)         return -ENODEV;    fx2dev = usb_get_intfdata(interface);    if (fx2dev == NULL)         return -ENODEV;    /*     *   Serialize access to each of the bulk pipes.     */     flags = (file->f_flags & O_ACCMODE);    if ((flags == O_WRONLY) || (flags == O_RDWR)) {        if (atomic_dec_and_test( &fx2dev->bulk_write_available ) == 0) {            atomic_inc( &fx2dev->bulk_write_available );            return -EBUSY;        }        /*         *   The write interface is serialized, so reset bulk-out pipe (ep-6).         */        retval = usb_clear_halt(fx2dev->udev, fx2dev->bulk_out_endpointAddr);        if ((retval != 0) && (retval != -EPIPE)) {            dev_err(&interface->dev, "%s - error(%d) usb_clear_halt(%02X)\n",                     __FUNCTION__, retval, fx2dev->bulk_out_endpointAddr);        }    }    if ((flags == O_RDONLY) || (flags == O_RDWR)) {        if (atomic_dec_and_test( &fx2dev->bulk_read_available ) == 0) {            atomic_inc( &fx2dev->bulk_read_available );            if (flags == O_RDWR)                 atomic_inc( &fx2dev->bulk_write_available );            return -EBUSY;        }        /*         *   The read interface is serialized, so reset bulk-in pipe (ep-8).         */        retval = usb_clear_halt(fx2dev->udev, fx2dev->bulk_in_endpointAddr);        if ((retval != 0) && (retval != -EPIPE)) {            dev_err(&interface->dev, "%s - error(%d) usb_clear_halt(%02X)\n",                     __FUNCTION__, retval, fx2dev->bulk_in_endpointAddr);        }    }    /*     *   Set this device as non-seekable.     */     retval = nonseekable_open(inode, file);    if (retval != 0) {        return retval;    }    /*     *   Increment our usage count for the device.     */    kref_get(&fx2dev->kref);    /*     *   Save pointer to device instance in the file's private structure.     */    file->private_data = fx2dev;    return 0;}/*****************************************************************************//*                                                                           *//*****************************************************************************/static int osrfx2_release(struct inode * inode, struct file * file){    struct osrfx2 * fx2dev;    int flags;    fx2dev = (struct osrfx2 *)file->private_data;    if (fx2dev == NULL)        return -ENODEV;    /*      *  Release any bulk_[write|read]_available serialization.     */

⌨️ 快捷键说明

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