Chinaunix首页 | 论坛 | 博客
  • 博客访问: 366474
  • 博文数量: 48
  • 博客积分: 1084
  • 博客等级: 少尉
  • 技术积分: 496
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-17 14:09
文章分类

全部博文(48)

文章存档

2014年(2)

2013年(3)

2012年(13)

2011年(24)

2010年(6)

分类: LINUX

2010-12-19 19:34:14



* ***********************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
#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);

阅读(1527) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~