1. USB驱动基础知识
在深入探究Linux下USB驱动前,我们有必要先梳理一下USB驱动的基础知识。USB的英文全称是Universal Serial Bus,中文译作通用串行总线。它是一种计算机外部设备连接标准,被广泛地应用于鼠标、键盘、打印机、手机等设备中。
USB是一种序列化接口,它连接的设备可以是低带宽(1.5Mbps)的从设备,也可以是全速设备(12Mbps)、高速设备(480Mbps)、超高速设备(5Gbps)等。
Linux内核中,USB驱动被分为两类:
USB核心驱动(usbcore):负责USB设备的探测、枚举和配置。
USB设备驱动:负责具体的USB设备类型的驱动和操作。
对于Linux下的USB驱动,我们需要掌握下面的一些概念:
USB设备描述符:包含了关于USB设备的描述信息。
USB接口描述符:描述了USB设备的一个特定接口。
USB端点描述符:描述了一个USB接口的端点,并包含了描述端点方向、类型、传输大小等方面的信息。
USB传输:根据端点描述符中的信息,进行USB数据的传输。
USB控制传输:使用特殊的USB控制命令进行数据传输。
2. USB驱动框架
Linux内核中,USB驱动采用了一种面向对象的编程方式,即将USB设备和USB驱动都分成多个不同的层级:
2.1. USB设备层
USB设备层表示了具体的USB设备,它由三个部分组成:
USB设备驱动(usb_device_driver):负责探测和匹配设备。
USB设备(usb_device):表示一个具体的USB设备,包含了设备描述符、接口描述符等信息。
USB接口(usb_interface):表示一个具体的USB设备接口,包含了一个或多个USB端点。
2.2. USB核心层
USB核心层负责枚举和控制所有已接入设备,这个层次的主要结构体有:
USB总线(usb_bus):表示一个具体的USB总线。
USB控制器(usb_hcd):代表一个具体的USB控制器,负责物理层面的定义和控制。
USB主机(usb_host):表示一个具体的USB主机,其中包含了一个或多个USB总线。
2.3. USB驱动层
USB驱动层负责具体的处理逻辑,对外提供一系列函数和接口,包括设备的打开、关闭、读写操作等等,具体的结构体有:
USB驱动(usb_driver):表示一个具体的USB驱动,负责设备的操作和处理。
USB请求块(urb):表示一个USB传输请求,包括传输的方向、长度、缓冲区等信息。
USB文件操作结构体(file_operations):表示针对USB设备的文件操作,如打开、读写等。
3. USB驱动开发
在Linux下进行USB驱动开发,需要了解一些基本的驱动接口,包括:
usb_register_driver():注册一个USB设备驱动。
usb_deregister_driver():注销一个USB设备驱动。
usb_register_dev():注册一个USB设备,创建一个字符设备节点。
usb_deregister_dev():注销一个USB设备,销毁相应的字符设备节点。
usb_submit_urb():向USB设备发送一个传输请求。
usb_unlink_urb():停止一个传输请求的传输。
usb_alloc_urb():分配一个传输请求。
usb_free_urb():释放一个传输请求。
下面是一个简单的示例代码,演示了如何实现一个USB设备的读操作:
static int my_usb_open(struct inode *i, struct file *f)
{
struct usb_interface *iface;
struct my_usb_data *devdata;
iface = usb_find_interface(&my_usb_driver, iminor(i));
if (!iface)
return -ENODEV;
devdata = kmalloc(sizeof(struct my_usb_data), GFP_KERNEL);
if (!devdata)
return -ENOMEM;
f->private_data = devdata;
return 0;
}
static int my_usb_read(struct file *f, char __user *buf, size_t count, loff_t *offp)
{
struct my_usb_data *devdata = f->private_data;
int retval;
struct urb *urb;
u8 endpoint = usb_rcvbulkpipe(devdata->udev, devdata->incoming_ep);
urb = usb_alloc_urb(0, GFP_KERNEL);
if (urb == NULL)
return -ENOMEM;
usb_fill_bulk_urb(urb, devdata->udev, endpoint,
devdata->buffer, devdata->buffer_size,
my_usb_read_complete, devdata);
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval)
usb_free_urb(urb);
else
wait_for_completion(&devdata->done);
/* 将读取到的数据拷贝到用户空间 */
if (*offp >= devdata->buffer_size)
return 0;
if (count > devdata->buffer_size - *offp)
count = devdata->buffer_size - *offp;
if (copy_to_user(buf, devdata->buffer + *offp, count))
return -EFAULT;
*offp += count;
return count;
}
static int my_usb_release(struct inode *i, struct file *f)
{
struct my_usb_data *devdata = f->private_data;
kfree(devdata);
return 0;
}
static struct file_operations my_usb_fops = {
owner: THIS_MODULE,
open: my_usb_open,
read: my_usb_read,
release: my_usb_release,
};
static struct usb_class_driver my_usb_class = {
name: "my_usb",
fops: &my_usb_fops,
minor_base: 0,
};
static struct usb_device_id my_usb_table[] = {
{ USB_DEVICE(ID_VENDOR, ID_PRODUCT) },
{ }
};
MODULE_DEVICE_TABLE(usb, my_usb_table);
static int my_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev;
struct my_usb_data *devdata;
u8 incoming_ep, outgoing_ep;
int retval;
udev = interface_to_usbdev(interface);
incoming_ep = usb_endpoint_num(&intf->altsetting[0].endpoint[0].desc);
outgoing_ep = usb_endpoint_num(&intf->altsetting[0].endpoint[1].desc);
devdata = kmalloc(sizeof(struct my_usb_data), GFP_KERNEL);
devdata->udev = udev;
devdata->incoming_ep = incoming_ep;
devdata->outgoing_ep = outgoing_ep;
interface->dev.driver_data = devdata;
retval = usb_register_dev(interface, &my_usb_class);
if (retval)
return retval;
usb_set_intfdata(interface, devdata);
return 0;
}
static void my_usb_disconnect(struct usb_interface *interface)
{
struct my_usb_data *devdata;
devdata = usb_get_intfdata(interface);
usb_deregister_dev(interface, &my_usb_class);
kfree(devdata);
}
static struct usb_driver my_usb_driver = {
name: "my_usb",
probe: my_usb_probe,
disconnect: my_usb_disconnect,
id_table: my_usb_table,
};
module_usb_driver(my_usb_driver);
4. 总结
本文对Linux下USB驱动进行了详细的讲解,包括USB驱动的基础知识、USB驱动框架、USB驱动的开发等方面。希望读者能够通过本文的学习,对Linux下USB驱动的开发有更加深入的了解。