[国嵌攻略][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
");
        return 1;
    }
    

    int fd = open(argv[1], O_RDONLY);
    if(-1 == fd) {
        printf("Can not open file - %s
", argv[1]);
        return 1;
    }
    addr = strtol((char *) argv[2] ,NULL, 16);
    
    printf("addr = %x 
", addr);
    

    // get file size 
    struct stat file_stat;
    if( -1 == fstat(fd, &file_stat) ) {
        printf("Get file size filed!
");
        return 1;
    }    

    file_buffer = (unsigned char*)malloc(file_stat.st_size+10);
    if(NULL == file_buffer) {
        printf("malloc failed!
");
        goto error;
    }
    //memset(file_buffer, '', sizeof(file_buffer)); // bad code ! corrected by Qulory
    memset(file_buffer, '', 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!
");
        goto error;
    }

    printf("File name : %s
", argv[1]);
    printf("File size : %ld bytes
", 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
", 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...
");
    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 
" , to_write ,real_write );
            return 1;
        }
        remain_size -= to_write;
        written += to_write;
        printf("
Sent %lu%% 	 %u bytes !", written*100/(file_stat.st_size+10),  written);
        fflush(stdout);

    }    

    printf("OK
");
    return 0;

error:
    if(-1 != fd_dev) {
        close(fd_dev);
    }
    if(fd != -1)  {
        close(fd);
    }
    if( NULL != file_buffer ) {
        free(file_buffer);
    }
    return -1;
}
原文地址:https://www.cnblogs.com/d442130165/p/5299458.html