[国嵌攻略][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 = ; while(lenght > ){
//设置发送长度
tmpLen = (lenght > BUFSIZE) ? BUFSIZE : lenght; //写入数据内容
retLen = copy_from_user(bulkBuffer, buf + sumLen, tmpLen); //提交数据内容
usb_bulk_msg(
dnwdev,
usb_sndbulkpipe(dnwdev, bulkEndAddr),
bulkBuffer,
tmpLen,
&retLen,
* HZ
); //设置数据长度
lenght -= tmpLen;
sumLen += tmpLen;
} return sumLen;
} //打开设备
int dnw_open(struct inode *node, struct file *filp){
//分配批量缓存
bulkBuffer = kmalloc(BUFSIZE * sizeof(char), GFP_KERNEL); return ;
} //关闭设备
int dnw_close(struct inode *node, struct file *filp){
//释放批量缓存
kfree(bulkBuffer); return ;
} //设备方法
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 = //起始次设备号,主设备号为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 = ; 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 ;
} //移除设备
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 ;
} //卸载驱动
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.-.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 = ; if( != argc ) {
printf("Usage: dwn <filename> address\n");
return ;
} int fd = open(argv[], O_RDONLY);
if(- == fd) {
printf("Can not open file - %s\n", argv[]);
return ;
}
addr = strtol((char *) argv[] ,NULL, ); printf("addr = %x \n", addr); // get file size
struct stat file_stat;
if( - == fstat(fd, &file_stat) ) {
printf("Get file size filed!\n");
return ;
} file_buffer = (unsigned char*)malloc(file_stat.st_size+);
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+)); // the first 8 bytes in the file_buffer is reserved, the last 2 bytes also;
if( file_stat.st_size != read(fd, file_buffer+, file_stat.st_size)) {
printf("Read file failed!\n");
goto error;
} printf("File name : %s\n", argv[]);
printf("File size : %ld bytes\n", file_stat.st_size);// off_t is long int int fd_dev = open(dev, O_WRONLY);
if( - == 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+) = file_stat.st_size+; //file size
unsigned short sum = ;
int i;
for(i=; i<file_stat.st_size+; i++) {
sum += file_buffer[i];
} *((unsigned short*)(file_buffer++file_stat.st_size)) = sum; printf("Start Sending data...\n");
size_t remain_size = file_stat.st_size+;
size_t block_size = ;
size_t written = ;
while(remain_size > ) {
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 ;
}
remain_size -= to_write;
written += to_write;
printf("\rSent %lu%% \t %u bytes !", written*/(file_stat.st_size+), written);
fflush(stdout); } printf("OK\n");
return ; error:
if(- != fd_dev) {
close(fd_dev);
}
if(fd != -) {
close(fd);
}
if( NULL != file_buffer ) {
free(file_buffer);
}
return -;
}
[国嵌攻略][165][usb下载线驱动设计]的更多相关文章
- [国嵌攻略][155][I2C用户态驱动设计]
用户态驱动模型 用户态驱动模型首先是一个应用程序,其次是在这个用户程序中通过内核调用来驱动设备. IIC通用驱动代码 IIC通用驱动程序的代码在/drivers/i2c/i2c-dev.c中.一次读操 ...
- [国嵌攻略][164][USB驱动程序设计]
USB驱动模型 1.USB host controller driver(主控器驱动):为USB主控制器提供驱动程序 2.USB core(USB核心):连接USB主控制器驱动和USB设备驱动 3.U ...
- [国嵌攻略][161][USB总线介绍]
USB发展史 USB(universal serial bus),通用串行总线,是一种外部总线标准.用于规范电脑与外部设备的连接和通讯.USB是在1994年底由英特尔.康柏.IBM.Microsoft ...
- [国嵌攻略][162][USB协议分析]
USB设备逻辑结构 在USB设备的逻辑组织中,包含设备.配置.接口和端点4个层次.设备通常有一个或多个配置,配置通常有一个或多个接口,接口通常有零个或多个端点. USB设备描述符 当我们把USB设备( ...
- [国嵌攻略][149][Yaffs2文件系统应用]
嵌入式系统自启动 MTD技术通过把Nand FLash划分成bootloader分区,Linux kernel分区和file system分区来达到自启动的效果. 配置和编译内核 1.配置Linux内 ...
- [国嵌攻略][163][linux-usb软件系统架构]
软件系统架构 1.主机端软件架构 USB设备驱动->USB核心->USB主控制器驱动->USB主控制器 2.设备端软件架构 Gadget驱动->Gadget API->U ...
- [国嵌攻略][171][V4L2图像编程接口深度学习]
V4L2摄像编程模型 1.打开摄像头设备文件 2.获取驱动信息-VIDIOC_QUERYCAP 3.设置图像格式-VIDIOC_S_FMT 4.申请帧缓冲-VIDIOC_REQBUFS 5.获取帧缓冲 ...
- [国嵌攻略][157][SPI总线介绍]
SPI总线架构 SPI(serial peripheral interface)串行外设接口,是一种高速,全双工,同步的通信总线.采用主从模式(master slave)架构,支持多个slave,一般 ...
- [国嵌攻略][156][I2C自编设备驱动设计]
AT24C08的驱动在Linux内核中已经提供,在/drivers/misc/eeprom/at24.c文件中.在对应的probe函数中有一个创建/sys/.../eeprom文件的函数,应用程序通过 ...
随机推荐
- php多语言切换---转载
文件内容: /include/language.php <?php $languages = array (); $languages ['zh-cn'] ["name"] ...
- Java NIO (一) 初识NIO
Java NIO(New IO / Non-Blocking IO)是从JDK 1.4版本开始引入的IO API , 可以替代标准的Java IO API .NIO与原来标准IO有同样的作用和目的,但 ...
- [编织消息框架][网络IO模型]NIO(select and poll)
上面测试论证系统内核在read data时会阻塞,如果我们在把第一个阶段解决掉那么性能就会提高 NIO 编程 JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度.实 ...
- Webpack 2 视频教程 019 - Webpack 2 中配置多页面编译
原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...
- 怎么制作html5网站页面让它适应电脑和手机的尺寸
https://zhidao.baidu.com/question/918130826792192539.html 用以下代码开头:<!DOCTYPE HTML><html>& ...
- 二维码utils希望对大家有帮助
package cn.itcast.utils; import java.io.File; import java.nio.file.Path; import java.util.HashMap; ...
- 漂亮的提示框SweetAlert使用教程
一.简介 所使用过的弹出框插件,SweetAlert是最好用的.发展至今,已经有两个版本,一个是原版 t4t5/sweetalert , 一个是分支版 limonte/sweetalert2 ,更新相 ...
- SourceTree管理工具的一些使用总结
一.冲突解决 在团队合作中,如果两个人同时修改一个文件 ,这个时候如果合并他人提交的代码是会产生冲突的,怎么解决? 1.先将代码提交至本地服务器 2.合并他人代码,这个时候在工作副本中会显示我们冲突的 ...
- 纯css提示效果 提示层
<!DOCTYPE HTML PUBLIC "-//W3C//DTD xHTML 1.0 Transitional//EN"><HTML> <HEAD ...
- bootstrap媒体查询
Bootstrap 中的媒体查询允许您基于视口大小移动.显示并隐藏内容.下面的媒体查询在 LESS 文件中使用,用来创建 Bootstrap 网格系统中的关键的分界点阈值. /* 超小设备(手机,小于 ...