[国嵌攻略][165][usb下载线驱动设计]
查看USB设备的生产商ID和设备ID
示例:
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
生产商ID是1d6b,设备ID是0002
创建USB总线型字符设备
usb_register_dev //效果同cdev创建字符设备效果相同
创建的主设备号都是180,次设备号可以设置为100
头文件
<linux/usb.h>
usb.c
/******************************************************************** *头文件 *********************************************************************/ #include <linux/init.h> #include <linux/module.h> #include <linux/usb.h> #include <linux/uaccess.h> /******************************************************************** *宏定义 *********************************************************************/ #define BUFSIZE 512 /******************************************************************** *全局变量 *********************************************************************/ struct usb_device *dnwdev; //设备结构 unsigned char bulkEndAddr; //端点地址 char *bulkBuffer; //批量缓存 /******************************************************************** *设备方法 *********************************************************************/ //写入设备 ssize_t dnw_write(struct file *filp, const char __user *buf, size_t lenght, loff_t *ppos){ int sumLen; //数据总长 int tmpLen; //临时长度 int retLen; //返回长度 //发送数据内容 sumLen = 0; while(lenght > 0){ //设置发送长度 tmpLen = (lenght > BUFSIZE) ? BUFSIZE : lenght; //写入数据内容 retLen = copy_from_user(bulkBuffer, buf + sumLen, tmpLen); //提交数据内容 usb_bulk_msg( dnwdev, usb_sndbulkpipe(dnwdev, bulkEndAddr), bulkBuffer, tmpLen, &retLen, 3 * HZ ); //设置数据长度 lenght -= tmpLen; sumLen += tmpLen; } return sumLen; } //打开设备 int dnw_open(struct inode *node, struct file *filp){ //分配批量缓存 bulkBuffer = kmalloc(BUFSIZE * sizeof(char), GFP_KERNEL); return 0; } //关闭设备 int dnw_close(struct inode *node, struct file *filp){ //释放批量缓存 kfree(bulkBuffer); return 0; } //设备方法 struct file_operations dnwfops = { .owner = THIS_MODULE, .write = dnw_write, .open = dnw_open, .release = dnw_close }; /******************************************************************** *驱动方法 *********************************************************************/ //设备信息 struct usb_class_driver dnwClass = { .name = "dnw%d", //设备名称 .fops = &dnwfops, //设备方法 .minor_base = 100 //起始次设备号,主设备号为180 }; //捕获设备 int dnw_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usb_host_interface *interface; int i; struct usb_endpoint_descriptor *endpoint; int isBulk; //获取设备 dnwdev = usb_get_dev(interface_to_usbdev(intf)); //获取接口 interface = intf->cur_altsetting; //获取端点 for(i = 0; i < interface->desc.bNumEndpoints; i++){ //获取端点结构 endpoint = &interface->endpoint[i].desc; //判断批量端点 isBulk = usb_endpoint_is_bulk_out(endpoint); if(isBulk){ bulkEndAddr = endpoint->bEndpointAddress; break; } } //注册设备 usb_register_dev(intf, &dnwClass); return 0; } //移除设备 void dnw_disconnect(struct usb_interface *intf){ //注销设备 usb_deregister_dev(intf, &dnwClass); } /******************************************************************** *驱动安装 *********************************************************************/ //设备列表 struct usb_device_id dnw_id_table[] = { { USB_DEVICE(0x5345, 0x1234) }, //Vender ID,Device ID { } }; //驱动结构 struct usb_driver dnwdrv = { .name = "idnw", //驱动名称 .probe = dnw_probe, //捕获设备 .disconnect = dnw_disconnect, //移除设备 .id_table = dnw_id_table //设备列表 }; //安装驱动 static int idnw_init(void){ //注册驱动 usb_register(&dnwdrv); return 0; } //卸载驱动 static void idnw_exit(void){ //注销驱动 usb_deregister(&dnwdrv); } /******************************************************************** *驱动声明 *********************************************************************/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("D"); MODULE_DESCRIPTION(""); MODULE_VERSION("v1.0"); module_init(idnw_init); module_exit(idnw_exit);
Makefile
obj-m := usb.o KDIR := /lib/modules/2.6.32-279.el6.i686/build/ all: make -C $(KDIR) M=$(PWD) modules clean: @rm -f *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers
dnw.c
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> const char* dev = "/dev/dnw0"; int main(int argc, char* argv[]) { unsigned char* file_buffer = NULL; long int addr = 0; if( 3 != argc ) { printf("Usage: dwn <filename> address\n"); return 1; } int fd = open(argv[1], O_RDONLY); if(-1 == fd) { printf("Can not open file - %s\n", argv[1]); return 1; } addr = strtol((char *) argv[2] ,NULL, 16); printf("addr = %x \n", addr); // get file size struct stat file_stat; if( -1 == fstat(fd, &file_stat) ) { printf("Get file size filed!\n"); return 1; } file_buffer = (unsigned char*)malloc(file_stat.st_size+10); if(NULL == file_buffer) { printf("malloc failed!\n"); goto error; } //memset(file_buffer, '\0', sizeof(file_buffer)); // bad code ! corrected by Qulory memset(file_buffer, '\0', sizeof(char)*(file_stat.st_size+10)); // the first 8 bytes in the file_buffer is reserved, the last 2 bytes also; if( file_stat.st_size != read(fd, file_buffer+8, file_stat.st_size)) { printf("Read file failed!\n"); goto error; } printf("File name : %s\n", argv[1]); printf("File size : %ld bytes\n", file_stat.st_size);// off_t is long int int fd_dev = open(dev, O_WRONLY); if( -1 == fd_dev) { printf("Can not open %s\n", dev); goto error; } /* * Note: the first 4 bytes store the dest addr ; * the following 4 bytes store the file size ; * and the last 2 bytes store the sum of each bytes of the file ; */ *((unsigned long*)file_buffer) = addr; //load address *((unsigned long*)file_buffer+1) = file_stat.st_size+10; //file size unsigned short sum = 0; int i; for(i=8; i<file_stat.st_size+8; i++) { sum += file_buffer[i]; } *((unsigned short*)(file_buffer+8+file_stat.st_size)) = sum; printf("Start Sending data...\n"); size_t remain_size = file_stat.st_size+10; size_t block_size = 512; size_t written = 0; while(remain_size > 0) { size_t to_write = remain_size > block_size ? block_size:remain_size; size_t real_write = write(fd_dev, file_buffer+written, to_write); if( to_write != real_write) { printf(" write /dev/secbulk0 failed! to_write = %u real_write = %u \n" , to_write ,real_write ); return 1; } remain_size -= to_write; written += to_write; printf("\rSent %lu%% \t %u bytes !", written*100/(file_stat.st_size+10), written); fflush(stdout); } printf("OK\n"); return 0; error: if(-1 != fd_dev) { close(fd_dev); } if(fd != -1) { close(fd); } if( NULL != file_buffer ) { free(file_buffer); } return -1; }