Linux 内核注册一个 USB 驱动

所有 USB 驱动必须创建的主要结构是 struct usb_driver. 这个结构必须被 USB 驱动填 充并且包含多个函数回调和变量, 来向 USB 核心代码描述 USB 驱动:

 

struct module *owner

 

指向这个驱动的模块拥有者的指针. USB 核心使用它正确地引用计数这个 USB 驱 动, 以便它不被在不合适的时刻卸载. 这个变量应当设置到 THIS_MODULE 宏.

 

const char *name

 

指向驱动名子的指针. 它必须在内核 USB 驱动中是唯一的并且通常被设置为和驱 动的模块名相同. 它出现在 sysfs 中在 /sys/bus/usb/drivers/ 之下, 当驱动在 内核中时.

 

const struct usb_device_id *id_table

 

指向 struct usb_device_id 表的指针, 包含这个驱动可接受的所有不同类型 USB 设备的列表. 如果这个变量没被设置, USB 驱动中的探测回调函数不会被调用. 如 果你需要你的驱动给系统中每个 USB 设备一直被调用, 创建一个只设置这个 driver_info 成员的入口项:

 

static struct usb_device_id usb_ids[] = {

{.driver_info = 42},

{}

};

 

int (*probe) (struct usb_interface *intf, const struct usb_device_id *id)

 

指向 USB 驱动中探测函数的指针. 这个函数(在"探测和去连接的细节"一节中描述) 被 USB 核心调用当它认为它有一个这个驱动可处理的 struct usb_interface. 一 个指向 USB 核心用来做决定的 struct usb_device_id 的指针也被传递到这个函 数. 如果这个 USB 驱动主张传递给它的 struct usb_interface, 它应当正确地初 始化设备并且返回 0. 如果驱动不想主张这个设备, 或者发生一个错误, 它应当返 回一个负错误值.

 

void (*disconnect) (struct usb_interface *intf)

 

指向 USB 驱动的去连接函数的指针. 这个函数(在"探测和去连接的细节"一节中描 述)被 USB 核心调用, 当 struct usb_interface 已被从系统中清除或者当驱动被 从 USB 核心卸载.

 

为创建一个值 struct usb_driver 结构, 只有 5 个成员需要被初始化:

 

static struct usb_driver skel_driver = {

.owner = THIS_MODULE,

.name = "skeleton",

.id_table = skel_table,

.probe = skel_probe,

.disconnect = skel_disconnect,

};

 

struct usb_driver 确实包含更多几个回调, 它们通常不经常用到, 并且不被要求使 USB 驱动正确工作:

 

int (*ioctl) (struct usb_interface *intf, unsigned int code, void *buf)

 

指向 USB 驱动的 ioctl 函数的指针. 如果它出现, 在用户空间程序对一个关联到 USB 设备的 usbfs 文件系统设备入口, 做一个 ioctl 调用时被调用. 实际上, 只 有 USB 集线器驱动使用这个 ioctl, 因为没有其他的真实需要对于任何其他 USB 驱动要使用.

 

int (*suspend) (struct usb_interface *intf, u32 state)

 

指向 USB 驱动中的悬挂函数的指针. 当设备要被 USB 核心悬挂时被调用. int (*resume) (struct usb_interface *intf)

指向 USB 驱动中的恢复函数的指针. 当设备正被 USB 核心恢复时被调用.

 

为注册 struct usb_driver 到 USB 核心, 一个调用 usb_register_driver 带一个指向 struct usb_driver 的指针. 传统上在 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("usb_register failed. Error number %d", result); return result;

}

 

当 USB 驱动被卸载, struct usb_driver 需要从内核注销. 使用对 usb_deregister_driver 的调用做这个. 当这个调用发生, 任何当前绑定到这个驱动的 USB 接口被去连接, 并且去连接函数为它们而被调用.

 

static void   exit usb_skel_exit(void)

{

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

}

转载于:https://www.cnblogs.com/fanweisheng/p/11147373.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写一个Linux内核驱动需要掌握C语言、Linux内核编程和设备驱动编程的知识。 下面以编写一个简单的字符设备驱动为例: 1. 首先创建一个新的目录,用于存放驱动程序的源代码和Makefile文件。 ``` mkdir mychardev ``` 2. 在该目录下创建一个C源文件并定义一个字符设备驱动模块。 ```c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #define DEVICE_NAME "mychardev" // 设备名称 static int major_num; // 设备号 // 打开设备 static int mychardev_open(struct inode *inode, struct file *filp) { printk(KERN_ALERT "mychardev: Device has been opened.\n"); return 0; } // 释放设备 static int mychardev_release(struct inode *inode, struct file *filp) { printk(KERN_ALERT "mychardev: Device has been released.\n"); return 0; } // 读取设备 static ssize_t mychardev_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { printk(KERN_ALERT "mychardev: Device has been read.\n"); return 0; } // 写入设备 static ssize_t mychardev_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { printk(KERN_ALERT "mychardev: Device has been written.\n"); return count; } // 设备操作集合 static struct file_operations mychardev_fops = { .owner = THIS_MODULE, .open = mychardev_open, .release = mychardev_release, .read = mychardev_read, .write = mychardev_write, }; // 初始化驱动 static int __init mychardev_init(void) { printk(KERN_ALERT "mychardev: Initializing device driver.\n"); // 注册字符设备驱动 major_num = register_chrdev(0, DEVICE_NAME, &mychardev_fops); if (major_num < 0) { printk(KERN_ALERT "mychardev: Failed to register device driver.\n"); return major_num; } printk(KERN_ALERT "mychardev: Device driver registered successfully with major number %d.\n", major_num); return 0; } // 卸载驱动 static void __exit mychardev_exit(void) { printk(KERN_ALERT "mychardev: Unregistering device driver.\n"); // 注销字符设备驱动 unregister_chrdev(major_num, DEVICE_NAME); printk(KERN_ALERT "mychardev: Device driver unregistered successfully.\n"); } module_init(mychardev_init); module_exit(mychardev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple character device driver."); ``` 3. 在该目录下创建一个Makefile文件。 ``` obj-m += mychardev.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean ``` 4. 编译驱动程序。 ``` make ``` 5. 加载驱动程序。 ``` sudo insmod mychardev.ko ``` 6. 检查设备是否被正确注册。 ``` cat /proc/devices ``` 输出应类似于: ``` Character devices: 1 mem 4 /dev/vc/0 4 tty 4 ttyS 5 /dev/tty 5 /dev/console 5 /dev/ptmx 10 misc 13 input 29 fb 89 i2c 116 alsa 128 ptm 136 pts 180 usb 188 ttyUSB 189 usb_device 226 drm 251 mychardev ``` 7. 测试设备。 ``` sudo chmod 666 /dev/mychardev echo "Hello, world!" > /dev/mychardev cat /dev/mychardev ``` 输出应类似于: ``` mychardev: Device has been written. mychardev: Device has been read. Hello, world! ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值