* ***********************my_usb.c*********************** */
/* 内核版本 linux-2.6.20
* 编辑器 vi
*参考文献 O`REILLY出版社的《LINUX设备驱动程序》
* 通过Makefile调用内核的模块编译部分进行模块编译
* 本示例为usb驱动的框架代码,没有容错及并发处理,
* 仅使用usb的控制端点进寻通信。
*/
* ***********************my_usb.c*********************** */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* 定义次设备号 */
#define MINOR_BASE 192
/* 定义设备的厂商号和产品序列号,此dmeo程序中是用这两个号来匹配设备 */
#define USBL_VENDOR_ID 0x6666
#define USB_PRODUCT_ID 0x1111
MODULE_LICENSE("GPL");
MODULE_author("dq_zhang");
static struct usb_device_id id_table[] = {
{USB_DEVICE( USBL_VENDOR_ID , USB_PRODUCT_ID)},
{},
};
char data[16];
struct usb_device *mydev;
MODULE_DEVICE_TABLE(usb, id_table);
/* 以下几个函数均为对此设备文件可执行的操作的实现,可用printk函数,打印信息来
* 体验具体的调用。
*/
* ***********************fops_fun*********************** */
ssize_t diy_write(struct file *file, const char __user *buf, size_t num, loff_t *count)
{
ssize_t retval = 0;
/* 跟具体的设备实现相关,具体设备具体操作 */
retval = usb_control_msg(mydev, usb_sndctrlpipe(mydev, 0),
0x12, 0x58, 0x0a, 0x7, (void *)data, 2, 10000 );
printk("diy_write is called\n");
return 0;
}
int diy_open(struct inode *inode, struct file *file)
{
printk("diy_open is called\n");
return 0;
}
int diy_release(struct inode *inode, struct file *file)
{
printk("diy_release is called\n");
return 0;
}
/* ***********************fops_fun*********************** */
static const struct file_operations diy_fops = {
.owner = THIS_MODULE,
.write = diy_write,
.open = diy_open,
.release= diy_release,
};
/* fops 为文件操作结构,用户程序所能对该设备的操作
* 实现都在此结构内实现。
*/
static struct usb_class_driver diy_class = {
.name = "led_usb",
.fops = &diy_fops,
.minor_base= MINOR_BASE,
};
/* 次函数需要两个参数,一个结构usb_interface, 为该设备的接口,
* 另一个结构为usb_device_id.
* 此函数为指向usb驱动程序中的探测函数指针,当usb核心认为有一个
* 可用的结构usb_interface 时被调用,即插入usb设备并被系统识别时。
*/
/*
* 在此函数中调用了usb_register_dev,该函数为向系统注册我们的usb设备
* 参数为设备信息,包括name,fops即用户程序可进行的操作指针结构,等
* 信息。
*/
int diy_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
int retval;
retval = usb_register_dev(interface, &diy_class);
if(retval)
printk("Not able to get a minor for this device\n");
mydev = usb_get_dev(interface_to_usbdev(interface));
return 0;
}
/* 此函数调用usb_deregister_dev, 即注销该usb设备 */
void diy_disconnect(struct usb_interface *interface)
{
printk("disconnect is called now\n");
usb_deregister_dev(interface, &diy_class);
return ;
}
/* 内核定义结构 */
static struct usb_driver diy_driver ={
.name = "usb_DQ",
.probe = diy_probe,
.disconnect= diy_disconnect,
.id_table= id_table,
};
int __init my_usb_init(void)
{
int result;
/* 该函数属于内核函数,其作用是向内核注册该驱动程序 */
/* 其传入的参数为结构static struct usb_driver, 该结构也为内核定义,
* 我们只要声明一个该结构的变量并初始化就可以了,此程序仅使用最基本
* 成员即 name,probe,disconnect, id_table,
* name 成员即为该驱动的名字可以任意给出,
* probe 为函数指针变量,我们要自己实现该函数,该函数在我们的usb设备
* 插入时由系统调用。
* disconnect 为函数指针变量,我们要自己实现该函数,该函数在我们的usb设备
* 拔出时由系统调用。
* id_table 也是一个系统定义的结构usb_device_id,结构成员包括三部分,产品信息,设备分类信息
* 和接口分类信息,此程序用到的是产品信息, 所以仅初始化产品信息即可,
*/
result = usb_register(&diy_driver);
if(result)
printk("usb_register failed. Error number %d\n", result);
printk("init is ok\n");
return result;
}
static void __exit my_usb_exit(void)
{
usb_deregister(&diy_driver);
return ;
}
/* 定义该模块的入口函数和卸载函数,分别在insmod 和 rmmod 时调用,当然是由内核自动调用 */
module_init(my_usb_init);
module_exit(my_usb_exit);