USB设备驱动程序(一)

2024-07-18  

USB驱动编程原理:

当我们把USB设备插入USB口时会提示需要安装相对应的驱动,如USB鼠标、USB键盘等,这些电脑自己自身已经自带有相对于的驱动程序,

当电脑检查到该USB设备类型相同就去帮你安装相对于驱动,但有些由于系统没有自带有相对于的USB驱动程序,需要联网或者厂家资料自带有

就需要手动安装驱动,如USB转串口驱动,搞开发搭建前期时需要安装一大推驱动程序开可以进行开发。

 

USB驱动开发依据主从关系的:也就是把USB口这一端作为主设备,也即开发板,USB设备作为从设备,主设备上具备有一个USB控制器来进行设置,

 

USB驱动开发遵循USB_Bus_Type模式,但有点特别的是,总线(总线驱动程序,虚拟的总线)一端注册一个设备不需要你编写程序,内核已经帮你写好了,只关注驱动一端程序的编写

 

 

我们做一个USB鼠标实验,实现输入左键为L字母,右键为S字母,中建为Enter按键,符合输入子系统,该按键驱动在probe函数里编写

既然符合输入子设备类型,则编写驱动程序思路大概如下:

1、分配一个input_dev结构体

2、配置这个结构体

3、注册它

4、硬件相关的操作

 

USB驱动程序编写框架:

APP

----------------------------------------------------------------------------------------------------------

内核:                       USB设备驱动(了解数据含义)

                     --------------------------------------------------------

                              USB总线驱动程序

-----------------------------------------------------------------------------------------------------------

硬件:                       USB主机控制器

                    ---------------------------------------------------------

                                USB设备

USB总线驱动程序需要做的事情:

1、识别设备

2、找到相对于的设备驱动程序

3、提供USB读写函数(不了解数据含义)


USB总线驱动程序的作用

1. 识别USB设备

1.1 分配地址

1.2 并告诉USB设备(set address)

1.3 发出命令获取描述符

描述符的信息可以在includelinuxusbCh9.h看到



2. 查找并安装对应的设备驱动程序


3. 提供USB读写函数


把USB设备接到开发板上,看输出信息:

usb 1-1: new full speed USB device using s3c2410-ohci and address 2

usb 1-1: configuration #1 chosen from 1 choice

scsi0 : SCSI emulation for USB Mass Storage devices

scsi 0:0:0:0: Direct-Access     HTC      Android Phone    0100 PQ: 0 ANSI: 2

sd 0:0:0:0: [sda] Attached SCSI removable disk

拔掉

usb 1-1: USB disconnect, address 2


再接上:

usb 1-1: new full speed USB device using s3c2410-ohci and address 3

usb 1-1: configuration #1 chosen from 1 choice

scsi1 : SCSI emulation for USB Mass Storage devices

scsi 1:0:0:0: Direct-Access     HTC      Android Phone    0100 PQ: 0 ANSI: 2

sd 1:0:0:0: [sda] Attached SCSI removable disk


在内核目录下搜:

grep "USB device using" * -nR

drivers/usb/core/hub.c:2186:              "%s %s speed %sUSB device using %s and address %dn",


hub_irq

    kick_khubd

        hub_thread

            hub_events

                hub_port_connect_change

                

                    udev = usb_alloc_dev(hdev, hdev->bus, port1);

                                dev->dev.bus = &usb_bus_type;

                

                    choose_address(udev); // 给新设备分配编号(地址)

                    

                    

                    hub_port_init   // usb 1-1: new full speed USB device using s3c2410-ohci and address 3

                        

                        hub_set_address  // 把编号(地址)告诉USB设备

                        

                        usb_get_device_descriptor(udev, 8); // 获取设备描述符

                        retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);

                        

                        usb_new_device(udev)   

                            err = usb_get_configuration(udev); // 把所有的描述符都读出来,并解析

                            usb_parse_configuration

                            

                            device_add  // 把device放入usb_bus_type的dev链表, 

                                        // 从usb_bus_type的driver链表里取出usb_driver,

                                        // 把usb_interface和usb_driver的id_table比较

                                        // 如果能匹配,调用usb_driver的probe

                            


怎么写USB设备驱动程序?

1. 分配/设置usb_driver结构体

        .id_table

        .probe

        .disconnect

2. 注册


测试1th/2th:

1. make menuconfig去掉原来的USB鼠标驱动

-> Device Drivers 

  -> HID Devices

  <> USB Human Interface Device (full HID) support 


2. make uImage 并使用新的内核启动


3. insmod usbmouse_as_key.ko

4. 在开发板上接入、拔出USB鼠标


具体参考代码如下:该函数主要实现了识别USB设备,probe只是打印了一些信息


/*

 * drivershidusbhidusbmouse.c

 */


#include

#include

#include

#include

#include

#include


static struct usb_device_id usbmouse_as_key_id_table [] = {

    { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

        USB_INTERFACE_PROTOCOL_MOUSE) },

    //{USB_DEVICE(0x1234,0x5678)},

    { }    /* Terminating entry */

};



static int usbmouse_as_key_probe(struct usb_interface *intf, const struct usb_device_id *id)

{

    printk("found usbmouse!n");

    return 0;

}


static void usbmouse_as_key_disconnect(struct usb_interface *intf)

{

    printk("disconnect usbmouse!n");

}


/* 1. 分配/设置usb_driver */

static struct usb_driver usbmouse_as_key_driver = {

    .name        = "usbmouse_as_key_",

    .probe        = usbmouse_as_key_probe,

    .disconnect    = usbmouse_as_key_disconnect,

    .id_table    = usbmouse_as_key_id_table,

};



static int usbmouse_as_key_init(void)

{

    /* 2. 注册 */

    usb_register(&usbmouse_as_key_driver);

    return 0;

}


static void usbmouse_as_key_exit(void)

{

    usb_deregister(&usbmouse_as_key_driver);    

}


module_init(usbmouse_as_key_init);

module_exit(usbmouse_as_key_exit);


MODULE_LICENSE("GPL");


Makefile:


KERN_DIR = /work/system/linux-2.6.22.6


all:

    make -C $(KERN_DIR) M=`pwd` modules 


clean:

    make -C $(KERN_DIR) M=`pwd` modules clean

    rm -rf modules.order


obj-m    += usbmouse_as_key.o


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。