USB鼠标驱动

一、实验平台:开发板fs2410,采用三星s3c2410的CPU,linux操作系统。

二、实现功能:用USB鼠标模拟按键输入,按键左键输入l,按下右键输入s,按下中键为回车,并在LCD屏幕上显示文件信息。

三、实验原理:

       在linux内核中有USB总线驱动程序,当有USB设备插入时,USB总线驱动程序会检测到该设备,并创建一个struct usb_device结构体,并寻找匹配的驱动程序。

       这里我们只写USB设备驱动程序,使用总线驱动程序的一些函数来获得数据。获取数据后再将这些数据赋予一定的意义(比如右键为s等),再上报给输入子系统。

 

四、实验现象:

      加载模块后,插入USB鼠标,可以看到有检测到设备的提示信息。再按下鼠标左键、右键,LCD屏幕上出现ls,再按鼠标中键,LCD屏幕上显示文件信息。

 

五、实验总结:

       USB鼠标也是输入设备,与案件不同的是数据来源。USB鼠标的数据来源是USB总线,而按键的数据来源就是s3c2410的GPIO管脚。得到数据后,写代码的思路和步骤与按键驱动的后部分一样。

       USB设备的数据的传送是通过中断的方式告诉CPU的,而实际上是采用查询的方式,因为所有USB设备都没有主动发送数据的功能,只有USB主机要接收数据时,USB设备才被动发送数据。USB控制器负责了查询了工作,它会对USB设备不断的查询,当获取了有效数据后,USB控制器产生中断告诉CPU有了数据。

六、示例代码:

/*驱动代码usbmouse.c*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

static struct usb_device_id uk_id_table [] = {
	{USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_MOUSE)},
	{ }	/* Terminating entry */
};

static struct input_dev *uk_dev;
static unsigned char *buf;
static unsigned long buf_phys;
static struct urb *uk_urb;

static void uk_irq(struct urb *urb)
{
	static int cnt  = 0;
	int i;
	static unsigned char pre_val;

	if ((pre_val & (1<<0)) != (buf[0] & (1<<0)))
	{
		input_event(uk_dev, EV_KEY, KEY_L, (buf[0] & (1<<0)) ? 1 : 0);		
	}

	if ((pre_val & (1<<1)) != (buf[0] & (1<<1)))
	{
		input_event(uk_dev, EV_KEY, KEY_S, (buf[0] & (1<<1)) ? 1 : 0);
	}

	if ((pre_val & (1<<2)) != (buf[0] & (1<<2)))
	{
		input_event(uk_dev, EV_KEY, KEY_ENTER, (buf[0] & (1<<2)) ? 1 : 0);
	}

	if (pre_val != buf[0])
		input_sync(uk_dev);

	pre_val = buf[0];

	usb_submit_urb (uk_urb, GFP_ATOMIC);
}

static int uk_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	int pipe;
	int len;

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

	uk_dev = input_allocate_device();

	__set_bit(EV_KEY, uk_dev->evbit);
	__set_bit(EV_REP, uk_dev->evbit);
	
	__set_bit(KEY_L, uk_dev->keybit);
	__set_bit(KEY_S, uk_dev->keybit);
	__set_bit(KEY_ENTER, uk_dev->keybit);

	input_register_device(uk_dev);

	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

	buf = usb_buffer_alloc(dev, 4, GFP_ATOMIC, &buf_phys);

	len = 4;

	uk_urb = usb_alloc_urb(0, GFP_KERNEL);
	usb_fill_int_urb(uk_urb, dev, pipe, buf,len,uk_irq, NULL, endpoint->bInterval);
	
	uk_urb->transfer_dma = buf_phys;
	uk_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	usb_submit_urb(uk_urb, GFP_KERNEL);
		
	return 0;
}

static void uk_disconnect (struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	
	input_unregister_device(uk_dev);
	input_free_device(uk_dev);

	usb_kill_urb(uk_urb);
	usb_buffer_free(dev, 4, buf, buf_phys);
	usb_free_urb(uk_urb);
}

static struct usb_driver usbmouse_key_drv = {
	.name		= "usbmouse_key",	
	.id_table   = uk_id_table,
	.probe      = uk_probe,
	.disconnect = uk_disconnect,
};

static int usbmouse_as_key_init(void)
{
	usb_register(&usbmouse_key_drv);
	return 0;
}

static void usbmouse_as_key_exit(void)
{
	usb_deregister(&usbmouse_key_drv);
}

module_init(usbmouse_as_key_init);
module_exit(usbmouse_as_key_exit);

MODULE_LICENSE("GPL");

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值