5.USB驱动--四:USB 鼠标驱动

目标:
USB 鼠标用作按键:(相当于输入子系统)
左键 – L
右键 – S
中键 – Enter

直接在基础框架的probe函数中完善代码,使用input系统:
1.分配一个input_dev结构体*/
myusb_mouse_dev = input_allocate_device();
/2.设置input_dev结构体/

/*2.1能产生哪类事件*/
set_bit(EV_KEY, myusb_mouse_dev->evbit);
set_bit(EV_REP,myusb_mouse_dev->evbit);

/*2.2能产生这类事件下哪些事件*/
set_bit(KEY_L, myusb_mouse_dev->keybit);
set_bit(KEY_S, myusb_mouse_dev->keybit);
set_bit(KEY_ENTER, myusb_mouse_dev->keybit);

/3.注册input_dev结构体/
input_register_device(myusb_mouse_dev);

/4.硬件操作
/A数据传输三要素:源,目的,长度/
/*a.源:usb设备的某个端点pipe (int型) */

pipe =usb_rcvintpipe(dev, endpoint)
//创建一个接收(rcv)中断(int)类型的端点管道(pipe),用来端点和数据缓冲区之间的连接,鼠标为接收中断型

dev: usb_device设备结构体
endpoint:为端点描述符的成员endpoint->bEndpointAddress   //端点地址
对于控制类型的端点管道使用: usb_sndctrlpipe()/usb_rcvctrlpipe()
对于实时类型的端点管道使用: usb_sndisocpipe()/usb_sndisocpipe()
对于批量类型的端点管道使用: usb_sndbulkpipe()/usb_rcvbulkpipe()

端点地址位于:
;接口结构体->当前激活的接口结构体->这个端点结构体[0]->端点描述符下 即 usb_interface.cur_altsetting.endpoint[0].desc的成员内
1
这个宏“usb_rcvintpipe(dev,endpoint)”就包含了 USB 设备的地址,和哪一号端点(端点地址)。
“PIPE_INTERRUPT”中断类型端点。
“USB_DIR_IN”端点的方向。
“源-pipe”是个整数,这个整数里含有端点的类型-PIPE_INTERRUPT,和端点的方向–USB_DIR_IN。
“__create_pipe(dev,endpoint)”这里既含有设备地址,也含有端点地址。
2
“devnum”:就是 USB 设备的地址(USB 设备编号)。
“endpoint”:就是端点的地址(bEndpointAddress)也是端点的一个编号(也是整数)。

b.长度:一个端点的最大包大小(int型)
位于端点描述符内
len = usb_endpoint_descriptor->wMaxPacketSize

c.目的:从usb读取数据,读到一个缓冲区(为char型缓冲区虚拟地址)
分配一个缓冲区,不能用 kalloc 等 ,是用“usb_buffer_alloc()函数

void *usb_buffer_alloc(
	struct usb_device *dev,             //usb_device设备结构体
	size_t size,                          //配的缓冲区大小,即长度len
	gfp_t mem_flags,              //分配内存的参数,这里填GFP_ATOMIC,表示从不睡眠
	dma_addr_t *dma              //缓冲区分配成功后,返回的DMA缓冲区物理地址
)
 函数功能:分配usb缓冲区,同时可以得到分配缓冲区的虚拟地址(char类型)和物理地址 (u32型)
      返回值:缓冲区的虚拟地址(char类型)

B使用三要素:构建urb–usb请求块USB传输数据时,就是打包成urb结构体来传输
/1.分配一个urb结构体/
mouse_urb = usb_alloc_urb(iso_packets, mem_flags);
/分配一个urb数据结构体, 分配成功返回一个urb结构体
urb全称为usb request block,USB传输数据时,就是打包成urb结构体来传输
iso_packets:表示iso类型的包个数,这里我们不是iso类型包,直接填0
mem_flags:分配内存的参数,这里填入GFP_KERNEL,正常分配
/
2,使用三要素前要设置 urb 。
a,Usb_fill_int_urb():fill(填充)中断类型的 urb。
inline void usb_fill_int_urb (struct urb *urb,
struct usb_device *dev,
unsigned int pipe, //三要素:源
void *transfer_buffer, //三要素:目的
int buffer_length, //三要素:长度
usb_complete_t complete_fn, //complete_fn 完成函数。
void *context, //给 complete_fn 使用
int interval) //中断方式是通过查询,查询有多频繁(interval)。
鼠标是中断传输,实际上 USB 设备(鼠标)并没有主动通知“USB 主机控制器”的能
力,即没有打断“USB 主机控制器”的能力。如何保证数据是“及时”的–用不断的查询。这个查询不是由 CPU 来查询,是由“USB 主机控制器”来不断查询,查询到数据后,USB 主机控制器发出中断(USB 主机控制器有中断 CPU 的能力)。USB 设备却没有中断“USB 主机控制器”的能力。USB 设备(USB 鼠标)所谓的“中断传输”指“USB 主机控制器”不断的查询“USB 设备”是否有数据过来。当“USB 主机控制器”得到数据后,“USB 总线驱动程序”就会调用“complete_fn–完成函数”
“查询频率”:中断方式是通过查询,查询有多频繁(interval)。端点描述符中有个“interval–间隔、间隙”。
b,USB 主机控制器得到“USB 设备”的数据后,要往某个内存去写。它需要的是物理
地址。所以要告诉“USB 主机控制器”某个内存的物理地址。
c,设置某些标记(不知道其意思)。
//使用三要素:
//6.4,分配一个 usb request block(USB 请求块)
uk_urb = usb_alloc_urb(0, GFP_KERNEL);
//6.5,使用三要素设置 urb
//6.5.1,填充中断类型的 urb。
usb_fill_int_urb(uk_urb, dev, pipe, usb_buf,len,usbmouse_as_key_irq, NULL,
endpoint->bInterval);
//6.5.2,USB 主机控制收到 USB 设备数据要写到一个内存的物理地址.
uk_urb->transfer_dma = usb_buf_phys;
//6.5.3,设置某些标记
uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

3,使用“urb”:提交 urb.usb_submit_urb()
usb_submit_urb(mouse_urb, GFP_KERNEL); /初始化urb和中断函数退出时,都要重新提交一次,告诉内核初始化内存缓存等/

disconnect 函数
static void usbmouse_as_key_disconnect(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev (intf); //从形参 intf 接口到
usb_device USB 设备结构体.
//printk(“disconnect usbmouse!\n”);
//1.4.1,提交过 urb ,这里杀掉 urb
usb_kill_urb(uk_urb);
//1.4.2,分配过 urb ,这里释放 urb
usb_free_urb(uk_urb);
//1.4.3,分配过主机控制器从 USB 设备读数据后存放的 buffer,这里释放
usb_buffer_free(dev, len, usb_buf, usb_buf_phys);
//1.4.4,注册过 uk_dev ,这里卸载掉.
input_unregister_device (uk_dev);
//1.4.5,为 uk_dev 结构分配过空间,这里释放
input_free_device (uk_dev);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值