您的位置:首页 > 运维架构 > Linux

linux 2.4内核下自定义USB设备驱动编写

2017-11-09 13:26 465 查看
 usb-skeleton.c里的代码写得很详细了。第一眼看上去,感觉太简单,像使用串口一样!其实也就这样了!关键就是那几个数据结构!

    对于其代码分析,网上太多文章了。我这记录下我在修改过程中遇到的问题及解决办法!

 1.首先出现的问题是无法自动在/DEV下创建设备文件节点,源代码如下

 

sprintf(name, "skel%d", dev->minor);

    

    dev->devfs = devfs_register (usb_devfs_handle, name,

                     DEVFS_FL_DEFAULT, USB_MAJOR,

                     USB_SKEL_MINOR_BASE + dev->minor,

                     S_IFCHR | S_IRUSR | S_IWUSR | 

                     S_IRGRP | S_IWGRP | S_IROTH, 

                     &skel_fops, NULL);

devfs_register 文件的定义如下:

devfs_handle_t devfs_register(devfs_handle_t dir, const char *name,  unsigned int flags,   unsigned int major, unsigned int minor, umode_t mode, void *ops, void fo);

 

其中devfs_handle_t表示Devfs的句柄(一个结构类型),每个参数的含义如下:

   

dir : 我们要创建的文件所在的Devfs的句柄。NULL意味着这是Devfs的根,即 /dev。

flags :设备文件系统的标志,缺省值为DEVFS_FL_DEFAULT。

major : 主设备号,普通文件不需要这一参数。

minor : 次设备号, 普通文件也不需要这一参数

mode : 缺省的文件模式(包括属性和许可权)。

ops : 指向  file_operations 或 block_device_operations结构的指针

info : 任意一个指针,这个指针将被写到file结构的private_data域

 

他的作用是登记设备的入口点,我跟踪后发现返回的是0,没有起到它的作用。我直接用  register_chrdev();来注册字符设备!

register_chrdev(181, "myusb", &skel_fops);

devfs_register的源代码在2.4.28里我找不到,有人知道为什么吗?

USB_MAJOR 是180.我的设备直接用181,这样不冲突

次设备号怎么办?如果写0,是注册不成功的。

代码里有:

#define USB_SKEL_MINOR_BASE 192 

USB_SKEL_MINOR_BASE + dev->minor

我手动:mknod myusb c  181 192

搞定!

4000
在应用程序里可以OPEN,READ,WRITE了!

2.USB真的跟操作串口一样,直接填充你的命令到代码里就可以!在skel_probe里面把你要操作的端点提出来,记下他们的地址。在read,write里写与发命令就可以!

3 批量传进大于包的最大字节怎么办?

    明天接着解决这个问题!

下班了!

接着写。。

昨天说到大于512字个节的包这个问题。其实很简单,把申请的空间直接变大就行。用URB接收数据。代码如下:

 

/**

 *    skel_probe

 *

 *    Called by the usb core when a new device is connected that it thinks

 *    this driver might be interested in.

 */
static void * skel_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)

{

    struct usb_skel *dev = NULL;

    struct usb_interface *interface;

    struct usb_interface_descriptor *iface_desc;

    struct usb_endpoint_descriptor *endpoint;

    int minor;

    int buffer_size;

    int i;

    char name[10];

     printk(KERN_ALERT "Ocean USB insert OK\n"); 

    /* See if the device offered us matches what we can accept */

    if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||

        (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) {

        return NULL;

    }

    /* select a "subminor" number (part of a minor number) */

    down (&minor_table_mutex);

    for (minor = 0; minor < MAX_DEVICES; ++minor) {

        if (minor_table[minor] == NULL)

            break;

    }

    if (minor >= MAX_DEVICES) {

        info ("Too many devices plugged in, can not handle this device.");

        goto exit;

    }

    /* allocate memory for our device state and intialize it */

    dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);

    if (dev == NULL) {

        err ("Out of memory");

        goto exit;

    }

    memset (dev, 0x00, sizeof (*dev));

    minor_table[minor] = dev;

    interface = &udev->actconfig->interface[ifnum];

    init_MUTEX (&dev->sem);

    dev->udev = udev;

    dev->interface = interface;

    dev->minor = minor;

    /* set up the endpoint information */

    /* check out the endpoints */

    iface_desc = &interface->altsetting[0];

    for (i = 0; i < iface_desc->bNumEndpoints; ++i) {

        endpoint = &iface_desc->endpoint[i];

        if ((endpoint->bEndpointAddress & 0x80) &&

            ((endpoint->bmAttributes & 3) == 0x02)&&

            (endpoint->bEndpointAddress==0x82)) {

            /* we found a bulk in endpoint */

            dev->read_urb = usb_alloc_urb(0);

            if (!dev->read_urb) {

                err("No free urbs available");

                goto error;

            }

            buffer_size = endpoint->wMaxPacketSize;

            dev->bulk_in_size = buffer_size*10;//这里申请的时候直接申请最大的

            dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;

        //    dev->bulk_in_buffer = usb_buffer_alloc(dev, buffer_size, GFP_ATOMIC, &dev->data_dma);//test->data   
               dev->bulk_in_buffer = kmalloc (dev->bulk_in_size, GFP_KERNEL);

            if (!dev->bulk_in_buffer){    

                printk(KERN_ALERT "usb read OK\n"); 

                    goto error;

                }

            FILL_BULK_URB(dev->read_urb, udev, 

                      usb_rcvbulkpipe(udev, 

                              endpoint->bEndpointAddress),

                      dev->bulk_in_buffer, buffer_size,

                      skel_write_bulk_callback, dev);

        }

        

        if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&

            ((endpoint->bmAttributes & 3) == 0x02)) {

            /* we found a bulk out endpoint */

            dev->write_urb = usb_alloc_urb(0);

            if (!dev->write_urb) {

                err("No free urbs available");

                goto error;

            }

            buffer_size = endpoint->wMaxPacketSize;

            dev->bulk_out_size = buffer_size;

            dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;

            dev->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);

            if (!dev->bulk_out_buffer) {

                err("Couldn't allocate bulk_out_buffer");

                goto error;

            }

            FILL_BULK_URB(dev->write_urb, udev, 

                      usb_sndbulkpipe(udev, 

                              endpoint->bEndpointAddress),

                      dev->bulk_out_buffer, buffer_size,

                      skel_write_bulk_callback, dev);

        }

    }

    /* initialize the devfs node for this device and register it */

    //sprintf(name, "skel%d", dev->minor);

   // info ("name %s ", name);

    //register_chrdev(181, "myusb", &skel_fops);

    //dev->devfs = devfs_register( NULL, name, DEVFS_FL_DEFAULT,181,&skel_fops, NULL);

/*    dev->devfs =devfs_register(NULL, "myusb",

                     DEVFS_FL_DEFAULT, 181,

                     USB_SKEL_MINOR_BASE + dev->minor,

                     S_IFCHR | S_IRUSR | S_IWUSR | 

                     S_IRGRP | S_IWGRP | S_IROTH, 

                     &skel_fops, NULL);*/

    /* let the user know what node this device is now attached to */

    info ("USB device %d ", dev->devfs);

    info ("USB Skeleton device now attached to USBSkel%d", dev->minor);

    goto exit;    

error:

    skel_delete (dev);

    dev = NULL;

exit:

    up (&minor_table_mutex);

    return dev;

}

 

 read :

 

/**

 *    skel_read

 */
static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos)

{

    struct usb_skel *dev;

    int retval = 0;

    dev = (struct usb_skel *)file->private_data;

    printk(KERN_ALERT "usb read OK\n"); 

    /* lock this object */

    down (&dev->sem);

    /* verify that the device wasn't unplugged */

    if (dev->udev == NULL) {

        up (&dev->sem);

        return -ENODEV;

    }    

    /* do an immediate bulk read to get data from the device */
//    printk(KERN_ALERT "read inPD 0x%x\n", dev->bulk_in_endpointAddr); 
    /*retval = usb_bulk_msg (dev->udev,

                   usb_rcvbulkpipe (dev->udev, 0x82),

                   dev->bulk_in_buffer, dev->bulk_in_size,

                   &count, HZ*10);*/

       FILL_BULK_URB(dev->read_urb, dev->udev, 

                      usb_rcvbulkpipe(dev->udev, 

                              0x82),

                      dev->bulk_in_buffer, dev->bulk_in_size,

                      skel_write_bulk_callback, dev);

    

    /* if the read was successful, copy the data to userspace */

    retval = usb_submit_urb(dev->read_urb);

    if (!retval) {

        if (copy_to_user (buffer, dev->bulk_in_buffer, count))

            retval = -EFAULT;

        else

            retval = count;

    }

    /* unlock the device */

    up (&dev->sem);    

    return retval;

}

 

到这里,USB驱动全部搞定。希望多初学的有点帮助
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  usb 内核
相关文章推荐