赞
踩
从二月底到现在已经快两个月了,当初媳妇的一句“辞职吧,我养你”,让我现在在家浪荡了快两个月了,现在疫情有所缓和,但是能不出门还是少出门,现在翻翻书,看看内核代码,再敲敲代码,偶尔玩玩游戏也还可以,但还是要趁这段时间充实一下自己,提高自己的能力水平,才能更好的去面对30岁以后的危机,才能迎接美好的未来。
通用串行总线(USB)是主机和外围设备之间的一种连接。
从拓扑上来看,是一颗由几个点对点的连接构建而成的树。这些连接是连接设备和集线器(hub)的四线电缆(底线、电源线和两根信号线)。USB主控制器(host controller)负责询问每一个USB设备是否有数据需要发送。
Linux内核支持两种主要类型的USB驱动程序:宿主(host)系统上的驱动程序和设备(device)上的驱动程序。宿主系统上的USB驱动程序控制插入其中的USB设备,USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。
USB驱动程序存在于不同的内核子系统和USB硬件控制器之中,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口。
USB设备的构成,包括配置、接口和端点,以及USB驱动程序如何绑定到USB接口上,而不是整个USB设备
Linux内核中的USB代码通过一个称为urb(USB请求块)的东西与所有的USB设备通信,使用struct urb结构体来描述这个请求块。
urb被用来以一种异步的方式往/从特定的USB设备上的特定USB端点发送/接收数据。
一个urb的典型生命周期:
由USB设备驱动程序创建。
分配给一个特定的USB设备的特定端点。
由USB设备驱动程序递交到USB核心。
由USB核心递交到特定设备的特定USB中控制器驱动程序。
由USB主控制器驱动程序处理,从设备进行USB传送。
当urb结束之后,USB主控制器驱动程序通知USB设备驱动程序。
驱动程序把驱动程序对象注册到USB子系统中,稍后再使用制造商和设备标识来判断是否已经安装了硬件。
USB核心使用struct usb_device_id结构体来判断对于一个设备该使用哪一个驱动程序,热插拔脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪一个驱动程序
struct usb_device_id { __u16 match_flags; /*确定设备和结构体中下列字段中的哪一个相匹配*/ __u16 idVendor; /*设备的USB制造商ID*/ __u16 idProduct; /*设备的USB产品ID*/ /*定义了制造商指派的产品的版本号范围的最低和最高值。bcdDevice_hi值包括在内,该值是最高编号的设备的编号*/ __u16 bcdDevice_lo; __u16 bcdDevice_hi; /*分别定义设备的类型、子类型和协议。这些值详细说明了整个设备的行为,包括该设备上的所有接口*/ __u8 bDeviceClass; __u8 bDeviceSubClass; __u8 bDeviceProtocol; /*分别定义了类型、子类型和单个接口的协议*/ __u8 bInterfaceClass; __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; __u8 bInterfaceNumber; /*不是用来比较是否匹配的,包含了驱动程序在USB驱动程序的探测回调函数中可以用来区分不同设备的信息*/ kernel_ulong_t driver_info __attribute__((aligned(sizeof(kernel_ulong_t)))); };
有许多用来初始化该结构体的宏:
USB_DEVICE(vend, prod),仅和指定的制造商和产品ID值相匹配。用于需要一个特定驱动程序的USB设备。
USB_DEVICE_VER(vend, prod, lo, hi),仅和某版本范围内的指定制造商和产品ID值相匹配。
USB_DEVICE_INFO(cl, sc, pr),仅和USB设备的指定类型相匹配。
USB_INTERFACE_INFO(cl, sc, pr),仅和USB接口的指定类型相匹配。
struct usb_driver { const char *name; /*指向驱动程序名字的指针。在内核的所有USB驱动程序中必须是唯一的,通常被设置为和驱动程序模块名相同的名字。*/ int (*probe) (struct usb_interface *intf, const struct usb_device_id *id); /*指向USB驱动程序中的探测函数的指针。*/ void (*disconnect) (struct usb_interface *intf); /*指向USB驱动程序中的断开函数的指针。当struct usb_interface被从系统中移除或者驱动程序正在从USB核心中卸载时,USB核心将调用该函数。*/ int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code, void *buf); int (*suspend) (struct usb_interface *intf, pm_message_t message); int (*resume) (struct usb_interface *intf); int (*reset_resume)(struct usb_interface *intf); int (*pre_reset)(struct usb_interface *intf); int (*post_reset)(struct usb_interface *intf); const struct usb_device_id *id_table; /*指向struct usb_device_id表的指针,包含了一系列驱动程序可以支持的所有不同类型的USB设备。*/ struct usb_dynids dynids; struct usbdrv_wrap drvwrap; unsigned int no_dynamic_id:1; unsigned int supports_autosuspend:1; unsigned int disable_hub_initiated_lpm:1; unsigned int soft_unbind:1; };
int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver);
struct usb_class_driver {
char *name; /*sysfs用来描述设备的名字*/
char *(*devnode)(struct device *dev, umode_t *mode); /*回调函数,创建设备节点*/
const struct file_operations *fops; /*指向struct file_operations的指针,驱动程序定义该结构体,用它来注册为字符设备*/
int minor_base; /*为驱动程序指派的次设备号范围的开始值*/
};
/* 创建一个urb */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error; } /* 创建DMA缓冲区,并把数据拷贝到缓冲区 */ buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } if (copy_from_user(buf, user_buffer, writesize)) { retval = -EFAULT; goto error; } /* this lock makes sure we don't submit URBs to gone devices */ mutex_lock(&dev->io_mutex); if (!dev->interface) { /* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto error; } /* 初始化urb */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, writesize, skel_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->submitted); /* 把数据从批量端口发出 */ retval = usb_submit_urb(urb, GFP_KERNEL); mutex_unlock(&dev->io_mutex); if (retval) { dev_err(&dev->interface->dev, "%s - failed submitting write urb, error %d\n", __func__, retval); goto error_unanchor; }
static void skel_write_bulk_callback(struct urb *urb) { struct usb_skel *dev; dev = urb->context; /* sync/async 解链接故障不是错误 */ if (urb->status) { if (!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) dev_err(&dev->interface->dev, "%s - nonzero write bulk status received: %d\n", __func__, urb->status); spin_lock(&dev->err_lock); dev->errors = urb->status; spin_unlock(&dev->err_lock); } /* 释放已分配的缓冲区 */ usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); up(&dev->limit_sem); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。