学习Linux下s3c2440的USB鼠标驱动笔记

2024-07-23  

1、ARM-Linux下USB驱动程序开发

1.1.1、linux下USB配置:

*********(MassStorage:存储设备)************************************

-> Device Drivers

-> SCSI device support(通用设备)

-> SCSI disk support (磁盘支持)

-> SCSI device support(设备支持)


-> Device Drivers

-> USB support (USB设备)

-> USB device filesystem (USB设备文件系统)

-> OHCI HCD support (主要是非PC上的USB芯片)

-> USB Mass Storage support(USB大容量设备)

-> USB Monitor (USB 主设备)


-> File systems

-> DOS/FAT/NT Filesystems

-> MSDOS fs support

-> VFAT (Windows-95) fs support


-> Partition Types (分区类型)

-> PC BIOS (MSDOS partition tables) support


-> Native Language Suppor (本地语言设置)

-> Simplified Chinese charset (CP936, GB2312)

-> NLS UTF-8


make uImage (生成uImage)

测试 mount /dev/sda1 /mnt/


*********(HID:人机接口(鼠标、键盘))********************************

-> Device Drivers

HID Devices --->

-> USB Human Interface Device (full HID) support

USB support --->

-> Support for Host-side USB

make uImage (生成uImage)

测试 cat /dev/mouse1


*********(RNDIS:网卡)********************************


-> Device Drivers x

-> USB support x

-> USB Gadget Support

Support for USB Gadgets

Ethernet Gadget (with CDC Et hernet support) x x

[*] RNDIS support (EXPERIMENTAL) (NEW)

编译内核模块


cp drivers/usb/gadget/_ether.ko /work/nfs_root/first_fs/

cp /arch/arm/boot/uImage /work/nfs_root/new_uImage


*********(CDC-ACM:USB虚拟串口)********************************

(未能识别USB driver)可能是没有配置USB设备


 



1.2.1、驱动程序编写

struct usb_driver {

const char *name; /*USB驱动名字*/

int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);/*USB core发现该驱动程序能够处理USB接口时,调用*/

void (*disconnect) (struct usb_interface *intf);/*USB移除的时候调用*/

const struct usb_device_id *id_table; /*该驱动程序支持哪些设备 idVendor(制造商ID) idProduct(产品id)*/

};

1.2.2、linux提供宏来定义 一种 设备 :

USB_DEVICE(vend,prod)

vend:USB Vendor ID 制造商ID

prod:USB Product ID 设备ID


1.2.3、linux提供宏来定义 一类 设备 :

USB_INTERFACE_INFO(cl,sc,pr)

cl:类 blnterfaceClass Value

sc:子类 blnterfaceSubClass value

pr:协议 blnterfaceProtocil Value


1.2.4、USB注册:传入一个参数usb_driver

static inline int usb_register(struct usb_driver *driver)


1.2.5、usb_device结构

int devnum; /* Address on USB bus */

char devpath [16]; /* Use in messages: /port/port/... */

enum usb_device_state state; /* configured, not attached, etc */

enum usb_device_speed speed; /* high/full/low (or error) */

struct usb_device_descriptor descriptor; /* Descriptor 设备描述符号*/

struct usb_host_config *config; /* All of the configs */

struct usb_config_descriptor desc; /*usb配置描述符*/

struct usb_interface *interface[USB_MAXINTERFACES];

ruct usb_host_interface *cur_altsetting; /* the currently

/*USB 接口描述符 一个[配置]包含一个或者多个接口,一个接口包含一个或者多个[设置] */

struct usb_interface_descriptor desc;

struct usb_host_endpoint *endpoint; /*USB端点*/

struct usb_endpoint_descriptor desc;/*USB 端点描述符 */


1.3.1、URB(usb request block)请求块 ,承载USB之间的数据传输


①URB处理流程:

1、USB设备驱动程序创建并初始化一个访问特点USB设备指定的端点的URB,并提交给USB Core

2、USB core提交该URB到USB主控制驱动程序

3、USB主控制器驱动程序根据该URB的描述信息,来访问USB设备

4、当访问设备结束后,USB主控制器驱动程序通知USB设备驱动(device)程序


②创建urb的函数为:

struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)

参数1:iso_packets:urb所含的等时数据包个数

参数2:mem_flags:内存分配标示


③初始化urb函数为:interrupt

static inline void usb_fill_int_urb (

struct urb *urb, //要初始化urb指针

struct usb_device *dev, //usb_device设备

unsigned int pipe, //要访问的端点所对应的管道,使用usb_sndintpipe()/usb_rcvintpipe()

void *transfer_buffer, //要传输数据的缓冲区

int buffer_length, //要传输数据的长度

usb_complete_t complete_fn, //当完成urb所请求的操作时候调用的回调函数

void *context, //通常取值为DEV

int interval //URB被调度的时间间隔

);

问:何为管道?

答:管道:驱动程序的数据缓冲区与一个端点的连接,代表一个在两者之间要移动数据的能力。


批量urb:使用usb_fill_bulk_urb()

控制urb: 使用usb_control_urb()

等时urb没有像中断、控制、批量传输那样有URB初始化函数,我们只有手动初始化urb.


④提交URB

在完成urb的创建和初始化后,URB就可以通过usb_smbmit_urb函数来提交给usb core

int usb_submit_urb(struct urb *urb, gfp_t mem_flags)

urb:指向URB的指针

mem_flags:内存分配标示,用于告知USB core如何分配内存换成区。



⑤URB处理 以下三种情况被认为URB处理完成,调用complete_fn函数

1、URB成功发送给设备,并且设备返回正确,URB->status = 0

2、如果接收和发送发生错误时候 urb->status = error

3、urb被取消,就发生在驱动程序通过,usb_unlink_urb() / usb_kill_urb()



鼠标驱动程序:


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 #include

 12 

 13 

 14 /*创建输入设备*/

 15 static struct input_dev *uk_dev;

 16 static int len;

 17 static char *usb_buf;

 18 static dma_addr_t usb_data_dma;

 19 static struct urb *uk_urb;

 20 

 21 

 22 

 23 

 24 //usb支持的设备列表

 25 static struct usb_device_id usbmouse_key_table [] = {

 26     { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,

 27         USB_INTERFACE_PROTOCOL_MOUSE) },

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

 29     { }    /* Terminating entry */

 30 };

 31 

 32 static void usb_mouse_irq(struct urb *urb)

 33 {

 34     static unsigned char pre_val;

 35 #if 0    

 36     int i;

 37     char b[100];

 38     static int cnt = 0;

 39     printk("data cnt %d: ", ++cnt);

 40     for (i = 0; i < len; i++)

 41     {

 42         printk("%02x   ", usb_buf[i]);

 43     }

 44     printk("n");

 45 

 46 

 47 

 48     /* USB鼠标数据含义

 49      * data[1]: bit0-左键, 1-按下, 0-松开

 50      *          bit1-右键, 1-按下, 0-松开

 51      *          bit2-中键, 1-按下, 0-松开 

 52      *

 53      */

 54     // if ((pre_val & (1<<0)) != (usb_buf[1] & (1<<0)))

 55     // {

 56     //     /* 左键发生了变化 */

 57     //     input_event(uk_dev, EV_KEY, KEY_L, (usb_buf[1] & (1<<0)) ? 1 : 0);

 58     //     input_sync(uk_dev);

 59     // }

 60 

 61     // if ((pre_val & (1<<1)) != (usb_buf[1] & (1<<1)))

 62     // {

 63     //     /* 右键发生了变化 */

 64     //     input_event(uk_dev, EV_KEY, KEY_S, (usb_buf[1] & (1<<1)) ? 1 : 0);

 65     //     input_sync(uk_dev);

 66     // }

 67 

 68     // if ((pre_val & (1<<2)) != (usb_buf[1] & (1<<2)))

 69     // {

 70     //     /* 中键发生了变化 */

 71     //     input_event(uk_dev, EV_KEY, KEY_ENTER, (usb_buf[1] & (1<<2)) ? 1 : 0);

 72     //     input_sync(uk_dev);

 73     // }    

 74     

 75     // pre_val = usb_buf[1];

 76     /* 重新提交urb */

 77     usb_submit_urb(uk_urb, GFP_KERNEL);

 78 

 79 #else

 80 

 81     switch (urb->status) {

 82     case 0:            /* success */

 83         break;

 84     case -ECONNRESET:    /* unlink */

 85     case -ENOENT:

 86     case -ESHUTDOWN:

 87         return;

 88     /* -EPIPE:  should clear the halt */

 89     default:        /* error */

 90         goto resubmit;

 91     }

 92 

 93     input_report_key(uk_dev, BTN_LEFT,   usb_buf[1] & 0x01);

 94     input_report_key(uk_dev, BTN_RIGHT,  usb_buf[1] & 0x02);

 95     input_report_key(uk_dev, BTN_MIDDLE, usb_buf[1] & 0x04);

 96     input_report_key(uk_dev, BTN_SIDE,   usb_buf[1] & 0x08);

 97     input_report_key(uk_dev, BTN_EXTRA,  usb_buf[1] & 0x10);

 98 

 99     input_report_rel(uk_dev, REL_X,     usb_buf[3]);

100     input_report_rel(uk_dev, REL_Y,     usb_buf[4]);

101     input_report_rel(uk_dev, REL_WHEEL, usb_buf[5]);

102 

103     input_sync(uk_dev);

104 resubmit:

105      usb_submit_urb (urb, GFP_ATOMIC);

106 #endif

107 

108 

109 

110 

111 }

112 

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

114 {

115     struct usb_device *dev = interface_to_usbdev(intf);

116     struct usb_host_interface *interface;

117     struct usb_endpoint_descriptor *endpoint;

118     int pipe;

119     /*获取当前usb接口的设置*/

120     interface = intf->cur_altsetting;

121     endpoint  = &interface->endpoint[0].desc;

122 

123     /* a. 分配一个input_dev */

124     uk_dev = input_allocate_device();

125     /* b. 设置 */

126     /* b.1 能产生哪类事件 */

127      set_bit(EV_KEY, uk_dev->evbit);

128      set_bit(EV_REL, uk_dev->evbit);

129     

130     // /* b.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */

131     // set_bit(BTN_LEFT, uk_dev->keybit);

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