zoukankan      html  css  js  c++  java
  • [国嵌攻略][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;
    }
  • 相关阅读:
    apache wicket 7.X让html回归webapp文件夹下
    HDU 4050 wolf5x (概率DP 求期望)
    struts2和数据库模糊查询
    codeforces 453A Little Pony and Expected Maximum 最大值期望
    挖坑
    BZOJ1430: 小猴打架
    BZOJ1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚
    1645: [Usaco2007 Open]City Horizon 城市地平线
    POJ1741 Tree
    CH Round #53-数据备份
  • 原文地址:https://www.cnblogs.com/d442130165/p/5299458.html
Copyright © 2011-2022 走看看