Arch Linux下USB鼠标键盘不能工作之迷[1]

Arch Linux下USB鼠标键盘不能工作之迷[1],第1张

由于长期使用i3wm和vim工作,再搭配上thinkpad小红点,完全没用用过外接键鼠,非常香。这两天在家工作学习,就把家里工作环境搭起来,配置了外接显示器发现小红点的的移动速度实在有点慢,不够跟手,而且在大屏上 *** 作对精度要求也很高,所以就想尝试下外接键鼠。

刚好家里有个无线双模的蓝牙鼠标,不过貌似蓝牙模块是损坏的,只能用usb toggle。发现插上usb toggle后,本子是能识别到的(lsusb能查看到),但是鼠标却不能工作,非常奇怪,还以为是没有驱动的原因。但是网上看了一圈也没看到专门的驱动也就作罢,就在网上定了一个通用的usb有线鼠标,期待能工作。

趁鼠标还没到,我又折腾起键盘来,刚好家里有个常年不用的usb键盘,但是连接上我发现连数字灯都没亮,很奇怪,就以为键盘已经坏了,就丢了,️又上网淘了个二手的(垃圾佬万岁)。

待续

鼠标驱动可分为几个部分:驱动加载部分、probe部分、open部分、urb回调函数处理部分。

下文阴影部分为注解。

一、驱动加载部分

static int __init usb_mouse_init(void)

{

int retval = usb_register(&usb_mouse_driver)//注册鼠标驱动

if (retval == 0)

info(DRIVER_VERSION ":" DRIVER_DESC)

return retval

}

其中usb_mouse_driver的定义为:

static struct usb_driver usb_mouse_driver = {

.owner = THIS_MODULE,

.name = "usbmouse",

.probe = usb_mouse_probe,

.disconnect = usb_mouse_disconnect,

.id_table = usb_mouse_id_table,

}

如果注册成功的话,将会调用usb_mouse_probe。那么什么时候才算注册成功呢?

和其它驱动注册过程一样,只有在其对应的“总线”上发现匹配的“设备”才会调用probe。总线匹配的方法和具体总线相关,如:platform_bus_type中是判断驱动名称和平台设备名称是否相同;那如何确认usb总线的匹配方法呢?

Usb设备是注册在usb_bus_type总线下的。查看usb_bus_type的匹配方法。

struct bus_type usb_bus_type = {

.name ="usb",

.match = usb_device_match,

.hotplug =usb_hotplug,

.suspend = usb_generic_suspend,

.resume = usb_generic_resume,

}

其中usb_device_match定义了匹配方法

static int usb_device_match (struct device *dev, struct device_driver *drv)

{

struct usb_interface *intf

struct usb_driver *usb_drv

const struct usb_device_id *id

/* check for generic driver, which we don't match any device with */

if (drv == &usb_generic_driver)

return 0

intf = to_usb_interface(dev)

usb_drv = to_usb_driver(drv)

id = usb_match_id (intf, usb_drv->id_table)

if (id)

return 1

return 0

}

可以看出usb的匹配方法是usb_match_id (intf, usb_drv->id_table),也就是说通过比对“dev中intf信息”和“usb_drv->id_table信息”,如果匹配则说明驱动所对应的设备已经添加到总线上了,所以接下了就会调用drv中的probe方法注册usb设备驱动。

usb_mouse_id_table的定义为:

static struct usb_device_id usb_mouse_id_table[] = {

{ USB_INTERFACE_INFO(3, 1, 2) },

{ } /* Terminating entry */

}

#define USB_INTERFACE_INFO(cl,sc,pr) /

.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, /

.bInterfaceClass = (cl), /

.bInterfaceSubClass = (sc), /

.bInterfaceProtocol = (pr)

鼠标设备遵循USB人机接口设备(HID),在HID规范中规定鼠标接口类码为:

接口类:0x03

接口子类:0x01

接口协议:0x02

这样分类的好处是设备厂商可以直接利用标准的驱动程序。除了HID类以外还有Mass storage、printer、audio等

#define USB_DEVICE_ID_MATCH_INT_INFO /

(USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)

匹配的过程为:

usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)

{

struct usb_host_interface *intf

struct usb_device *dev

/* proc_connectinfo in devio.c may call us with id == NULL. */

if (id == NULL)

return NULL

intf = interface->cur_altsetting

dev = interface_to_usbdev(interface)

/* It is important to check that id->driver_info is nonzero,

since an entry that is all zeroes except for a nonzero

id->driver_info is the way to create an entry that

indicates that the driver want to examine every

device and interface. */

for (id->idVendor || id->bDeviceClass || id->bInterfaceClass ||

id->driver_infoid++) {

if ((id->match_flags &USB_DEVICE_ID_MATCH_VENDOR) &&

id->idVendor != le16_to_cpu(dev->descriptor.idVendor))

continue

if ((id->match_flags &USB_DEVICE_ID_MATCH_PRODUCT) &&

id->idProduct != le16_to_cpu(dev->descriptor.idProduct))

continue

/* No need to test id->bcdDevice_lo != 0, since 0 is never greater than any unsigned number. */

if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_LO) &&

(id->bcdDevice_lo >le16_to_cpu(dev->descriptor.bcdDevice)))

continue

if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_HI) &&

(id->bcdDevice_hi <le16_to_cpu(dev->descriptor.bcdDevice)))

continue

if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_CLASS) &&

(id->bDeviceClass != dev->descriptor.bDeviceClass))

continue

if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&

(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))

continue

if ((id->match_flags &USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&

(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))

continue

//接口类

if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_CLASS) &&

(id->bInterfaceClass != intf->desc.bInterfaceClass))

continue

//接口子类

if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&

(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))

continue

//遵循的协议

if ((id->match_flags &USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&

(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))

continue

return id

}

return NULL

}

从中可以看出,只有当设备的接口类、接口子类、接口协议匹配鼠标驱动时鼠标驱动才会调用probe方法。

 故障现象:

USB键盘无法使用,插入键盘后电脑检测不到,也不出现叹号设备,替换电脑测试USB盘正常。

原因分析:

仔细观察人体学输入设备中有两个设备,通过硬件id确认其中USB 输入设备是鼠标,上面的英文设备实际上是键盘。也就是windows系统错误的把键盘识别为了别的设备。

解决方案:

右键选择更新驱动程序--浏览计算机以查找驱动程序软件--从计算机的设备驱动程序列表中选择--选择USB输入设备--下一步问题解决。

1. 右键选择HID-compliant device---更新驱动程序

2. 浏览计算机以查找驱动程序软件

3. 从计算机的设备驱动程序列表中选择

4. 选择USB输入设备

5. 下一步

 最终设备管理器重新检测到键盘。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/5924725.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-08
下一篇 2023-03-08

发表评论

登录后才能评论

评论列表(0条)

保存