在开发板上实现usb mouse做画笔的功能

今天尝试自动动手写usb设备驱动程序。本想自己写一个U盘的驱动程序,实现简单的挂载。但块设备读写还不是弄得很透彻,只能照着教程实现简单的usb鼠标驱动程序。
usb hid设备驱动程序,在系统里是自带的。需要去掉 CONFIG_USB_HIDX选项,但是CONFIG_HID_GENERIC需要选中,否则,注册usb驱动之后,不能识别HID设备,就跳转不到probe成员中。
首先,需要申明usb_device_id,系统就是根据这个ID号来匹配设备,进而调用驱动的。

static struct usb_device_id usb_mouse_pen_id_table [] = {
    {USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID,USB_INTERFACE_SUBCLASS_BOOT,                                       USB_INTERFACE_PROTOCOL_MOUSE)},
    //{USB_DEVICE(0x046d,0xc534)},
    {}

};

这里可以用鼠标的接口描述符来声明,实际测试,如果你知道设备的PID,VID,用PID,VID的方式声明也是可以的,这样驱动就只适合特定的设备了。用lsusb查看,得到设备的PID,VID号为0x046d,0xc534。但我的usb receiver是连接鼠标和键盘的。这会导致两次进入.probe函数,需要分别处理键盘和鼠标设备。这里,简单起见,我就只识别了鼠标。
usb driver的声明

static struct usb_driver usb_pen_driver = {
.name = "usb_pen_driver",
.probe = usbpen_probe,
.disconnect = usbpen_disconnect,
.id_table = usb_mouse_pen_id_table, 
};

init函数中,只需要usb_register(&usb_pen_driver);就可以了。
在probe中,申请,注册一个input_device

/*申请设置一个inputdevice*/
up_dev = input_allocate_device();
/*setting*/
set_bit(EV_SYN, up_dev->evbit);
set_bit(EV_ABS, up_dev->evbit);
set_bit(EV_KEY, up_dev->evbit);

set_bit(BTN_TOUCH, up_dev->keybit);

set_bit(ABS_X, up_dev->absbit);
set_bit(ABS_Y, up_dev->absbit);
set_bit(ABS_PRESSURE, up_dev->absbit);
set_bit(BTN_TOUCH, up_dev->keybit);

input_set_abs_params(up_dev, ABS_X, 0, 800, 0, 0);
input_set_abs_params(up_dev, ABS_Y, 0, 480, 0, 0);
input_set_abs_params(up_dev, ABS_PRESSURE, 0, 1, 0 , 0);

input_register_device(up_dev);

分配,设置,最后提交urb

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

len = endpoint->wMaxPacketSize;

usb_buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &usb_buf_phys);

up_urb = usb_alloc_urb(0,GFP_KERNEL);
usb_fill_int_urb(up_urb,dev,pipe,usb_buf,len,usb_pen_irq,NULL,endpoint->bInterval);
up_urb->transfer_dma = usb_buf_phys;
up_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
//up_urb->hcpriv = "just_as_a_flag";

usb_submit_urb(up_urb,GFP_KERNEL);

中断函数中,需要解析usb鼠标传过来的数据。第二个byte表示各个按键的标志位。第三个byte和第四个byte是x轴和y轴的相对位移。这里,鼠标的反应是很灵敏的,可以在这里除以一个参数。这里,我的设计是,监测到位移后,x,y的坐标值做相应改变。鼠标左键按下后,提交绝对位置。

static void usb_pen_irq(struct urb *urb)
{
//USB_PRINT("%s, urb[%x], up_urb[%x]\n",__FUNCTION__,(unsigned long)urb,(unsigned long)up_urb);
signed char *ms_data = usb_buf;
if(ms_data[1]&0x01)
{
    // 左键按下

            USB_PRINT("pressed x[%d], y[%d]\n",ms_data[1] ,ms_data[2]);

            input_report_abs(up_dev, ABS_X, up_location.x);
            input_report_abs(up_dev, ABS_Y, up_location.y);
            input_report_abs(up_dev, ABS_PRESSURE, 1);
            input_report_key(up_dev, BTN_TOUCH, 1);

            input_sync(up_dev);

}else
    {
        // 左键松开
        USB_PRINT("rel\n");
        input_report_abs(up_dev, ABS_PRESSURE, 0);
        input_report_key(up_dev, BTN_TOUCH, 0);
        input_sync(up_dev);
    }

    if ((ms_data[3]!=0)||(ms_data[4]!=0))
    {
            if (ms_data[3]>0)
            {
                if (ms_data[3]+up_location.x<800)
                {
                    up_location.x += ms_data[3];
                }
                else
                {
                    up_location.x = 800;
                }   
            }else
            {
                if (ms_data[3]+up_location.x < 0)
                {
                        up_location.x = 0;
                }   else
                {
                    up_location.x += ms_data[3];
                }
            }

            if (ms_data[4]>0)
            {
                if (ms_data[4]+up_location.y<480)
                {
                    up_location.y += ms_data[4]/4;
                }
                else
                {
                    up_location.y = 480;
                }   
            }else
            {
                if (ms_data[4]+up_location.y < 0)
                {
                        up_location.y = 0;
                }   else
                {
                    up_location.y += ms_data[4]/4;
                }
            }

            //USB_PRINT("move x[%d], y[%d]\n",up_location.x ,up_location.y);
            //USB_PRINT("move d0[%d], d1[%d],d2[%d],d3[%d],d4[%d],d5[%d]\n",ms_data[0],ms_data[1],ms_data[2],ms_data[3],ms_data[4],ms_data[5]);
    }

usb_submit_urb(urb, GFP_KERNEL);
return;
}

编译,insmod之后,插上鼠标,就能在/dev/input下看到新增加的event*设备。
按照tslib的配置流程,设置TSLIB_TSDEVICE为新增加的event,运行ts_test就可以用鼠标当画笔。不过ts_calibrate校准的过程,需要根据触摸屏大小,计算几个校准点的位置,然后根据打印出来的数据来校准。以后碰到usb设备的驱动程序,也有章可循

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值