Linux下USB驱动程序简单例程 联系客服

发布时间 : 星期一 文章Linux下USB驱动程序简单例程更新完毕开始阅读320d55ecf8c75fbfc77db216

// 自定义结构体类型

// 用于保存USB设备相关信息 struct usb_skel {

struct usb_device * udev; /* usb设备对象 */ struct usb_interface * interface; /* usb设备接口对象 */ struct semaphore limit_sem; /* 写信号量 */

unsigned char * bulk_in_buffer; /* 批量传输方式的接收缓存 */ size_t bulk_in_size; /* 接收缓存中的有效字节数 */ __u8 bulk_in_endpointAddr; /* 批量输入端口地址 */ __u8 bulk_out_endpointAddr; /* 批量输出端口地址 */ struct kref kref; }dev;

// 以production ID和vendor ID组合匹配驱动程序 static struct usb_device_id skel_table [] = {

{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } /* Terminating entry */ };

Static ssize_t skel_write(struct file * filep, const char * buff, size_t count, loff_t * offp) {

// 数据的发送方式可以选择urb方式和非urb方式

// urb方式将数据填充到一个urb中,然后发送urb给内核,内核再将数据送上USB总线 // 非urb方式直接将数据发送给内核,而不填充urb结构

// 创建通讯管道

unsigned int pipe = usb_sndbulkpipe(dev.udevice, dev.bulk_out_endpointAddr);

/************************** urb 方式 *********************************/

// 创建一个urb(usb request block)

struct urb * usb_alloc_urb(0, // 等时包的数量,如果不是乘载等时包,应该为0

mem_flags);

// 填充urb

void usb_fill_bulk_urb(urb,

dev.udevice, // 目的USB设备指针 pipe, // 与USB设备通讯时使用的管道

buff, // 发送数据缓存

count,// 发送数据的字节数

skel_write_bulk_callback, // 数据发送结束后回调函数指针 void *context); // 由用户定义

// 发送urb,如果成功retval值为0,数据发送结束后可以通过urb->status查询状态 retval = usb_submit_urb(urb, GFP_KERNEL);

/*************************** 非urb方式 ***************************/ Usinged int bytes_read;

retval = usb_bulk_msg(dev->udev,

pipe, buff, count, &bytes_read,

10000);

}

// 设备文件操作结构

static struct file_operations skel_fops = { .owner = THIS_MODULE, .read = skel_read, .write = skel_write, .open = skel_open, .release = skel_release, };

static struct usb_class_driver skel_class = { .name = \设备驱动程序类名 .fops = &skel_fops, // 设备文件操作结构 .minor_base = USB_SKEL_MINOR_BASE, // 次设备号的基准值 };

skel_probe(usb_interface * interface, struct usb_device_id * device_id) {

dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface;

// 本例程,probe函数查找端口中BULK_IN端点和BULK_OUT端点, // 并将相关信息保存道dev变量中

iface_desc = interface->cur_altsetting; // 获取接口的当前配置 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)

{

endpoint = &iface_desc->endpoint[i].desc;

// 如果这是一个BULK_IN端点

if ( !dev->bulk_in_endpointAddr &&

((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) = = USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) = = USB_ENDPOINT_XFER_BULK))

{

buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);

dev->bulk_in_size = buffer_size;

dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!dev->bulk_in_buffer) {

err(\ goto error; } }

// 如果这是一个BULK_OUT端点

if (!dev->bulk_out_endpointAddr &&

((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)= =USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)= = USB_ENDPOINT_XFER_BULK))

{

/* we found a bulk out endpoint */

dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; } }

if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { err(\ goto error; }

// 注册usb_class_driver结构,其中包含对USB设备的操作方法等 retval = usb_register_dev(interface, &skel_class); }

static struct usb_driver skel_driver = { .name = \驱动程序名

.probe = skel_probe, // 函数指针,设备与skel_table匹配成功后被调用,

// 完成一些初始化工作

.disconnect = skel_disconnect,

.id_table = skel_table, // usb内核通过设备的production ID和vendor ID的组合

// 或者设备的class、subclass跟protocol的组合来识别设备 // skel_table用于匹配USB内核识别是否将此驱动程序作为已// 识别设备的驱动程序。

};

static int __init usb_skel_init(void) {

int result;

/* register this driver with the USB subsystem */ result = usb_register(&skel_driver); if (result)

err(\ return result; }

static void __exit usb_skel_exit(void) {

/* deregister this driver with the USB subsystem */ usb_deregister(&skel_driver); }

module_init (usb_skel_init); module_exit (usb_skel_exit); MODULE_LICENSE(\