Android Qcom USB Driver学习(四)

该系列文章总目录链接与各部分简介: Android Qcom USB Driver学习(零)

VID/PID识别USB设备

CDC-ACM驱动介绍
  CDC-ACM(Communication Device Class——Abstract Control Model)驱动实现以USB设备驱动和tty设备驱动为基础,将USB设备驱动的实现看作tty驱动和硬件之间数据流转换的桥梁。tty数据发送,相当于将串口数据需要转换为USB数据,再经由USB设备驱动传递给CDC串口硬件。tty数据接收,相当于硬件接收的数据先经过USB传递给USB设备驱动,在USB数据接收处理中将串口数据传递给tty驱动程序。

kernel/msm/drivers/usb/class/cdc-acm.c
#define X1_ACM_INF0(x) \
		USB_DEVICE_AND_INTERFACE_INFO(0x0C2E, x, \
		USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \
		USB_CDC_ACM_PROTO_AT_V25TER)

#define X1_ACM_INF1(x) \
		USB_DEVICE_AND_INTERFACE_INFO(0x0C2E, x, \
		USB_CLASS_CDC_DATA, 0, \
		USB_CDC_PROTO_NONE)

static const struct usb_device_id acm_ids[] = {
	/* quirky and broken devices */
	{ X1_ACM_INF0(0x10ea),  
	.bInterfaceNumber = 0, 如果一个配置有多个接口的话,那么每个接口的编号都有一个独立的编号,编号从0开始递增
	},
	{ X1_ACM_INF1(0x10ea), 
	.bInterfaceNumber = 1,
	},
	...

MODULE_DEVICE_TABLE(usb, acm_ids); 将acm_ids输出到用户空间,在加载模块时就知道了什么模块对应什么硬件设备,常用于热插拔中。

USB NCM usbnet 枚举流程代码分析
初始化 usb_device_id 结构体时,可以通过kernel/msm-4.19/include/linux/usb.h的宏控来更快速的对每个成员赋值

interfacedescription
USB_DEVICE(vendor, product) 可用来只匹配特定供应商和产品 ID 值,常用于需要特定驱动的 USB 设备
USB_DEVICE_VER(vendor, product, lo, hi)可以用来在一个版本范围中只匹配特定供应商和产品 ID 值
USB_DEVICE_INFO(class, subclass, protocol)可以用来只匹配一个特定类的 USB 设备
USB_INTERFACE_INFO(class, subclass, protocol)可以用来只匹配一个特定类的 USB 接口
USB_DEVICE_AND_INTERFACE_INFO(vendor,product,class,subclass,protocol)可以用来匹配具有特定类 USB 接口的特定 USB 设备

USB描述符-HID描述符
USB Class Code

InterfaceClass
#define USB_CLASS_COMM       0x02   ==   02h    Both    Communications and CDC Control
#define USB_CLASS_HID        0x03   ==   03h  Interface HID (Human Interface Device)
#define USB_CLASS_CDC_DATA   0x0a   ==   0Ah  Interface CDC-Data USB_CDC_SUBCLASS_ACM
InterfaceSubClass
#define USB_CDC_SUBCLASS_ACM 0x02
InterfaceProtocol 
#define USB_CDC_PROTO_NONE   0      当InterfaceSubClass为0x00,此值无效
#define USB_CDC_ACM_PROTO_AT_V25TER 1

kernel/msm-4.19/drivers/usb/gadget/function/f_acm.c 
以上配置依赖于USB CDC serial (ACM) function driver

static struct usb_interface_descriptor acm_control_interface_desc = {
        .bLength =              USB_DT_INTERFACE_SIZE,
        .bDescriptorType =      USB_DT_INTERFACE,
        /* .bInterfaceNumber = DYNAMIC */
        .bNumEndpoints =        1,
        .bInterfaceClass =      USB_CLASS_COMM,
        .bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
        .bInterfaceProtocol =   USB_CDC_ACM_PROTO_AT_V25TER,
        /* .iInterface = DYNAMIC */
};

static struct usb_interface_descriptor acm_data_interface_desc = {
        .bLength =              USB_DT_INTERFACE_SIZE,
        .bDescriptorType =      USB_DT_INTERFACE,
        /* .bInterfaceNumber = DYNAMIC */
        .bNumEndpoints =        2,
        .bInterfaceClass =      USB_CLASS_CDC_DATA,
        .bInterfaceSubClass =   0,
        .bInterfaceProtocol =   0,
        /* .iInterface = DYNAMIC */
};

Linux下USB HID device driver研究(二)
Linux下USB HID device driver研究(三)
usb hid quirks(configure more HID quirks at module load time)中文的意思是怪癖的意思,即某种特性与通常的USB设备不同,在hid-quirks.c中有一些列表,hid_quirks、hid_ignore_list等,描述了某个设备有什么样的问题需要修正或者是否需要忽略等,HID_QUIRK_NO_INIT_REPORTS不初始化包含重要信息的功能reports

kernel/msm/drivers/hid/hid-ids.h
#define USB_VENDOR_ID_x 0x0c2e
#define USB_DEVICE_ID_x1 0x10ea

kernel/msm-4.19/drivers/hid/hid-quirks.c 
static const struct hid_device_id hid_quirks[] = {
     ...
    { HID_USB_DEVICE(USB_VENDOR_ID_x, USB_DEVICE_ID_x1), HID_QUIRK_NO_INIT_REPORTS },
	{ 0 }
}; 
/*
* If HID_QUIRK_NO_INIT_REPORTS is set, make sure we don't initialize
* the reports.
 */
 
kernel/msm-4.19/drivers/hid/hid-core.c
hid_init
	hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS);
	查找insmod 时给的pid,vid参数在quirks列表中是否有,如果有,就替换。没有就创建

	
hid_device_probe
    hid_match_device + hid_match_one_id (VID+PID检测)
    hdrv->match(hdev, hid_ignore_special_drivers )
	hdev->quirks = hid_lookup_quirk(hdev);
		hid_exists_dquirk(hdev) //Dynamic	↑↑↑ quirks_param - dquirks_list
		hid_gets_squirk(hdev)   //static    ↑↑↑ hid_quirks/hid_ignore_list
			bl_entry = hid_match_id(hdev, hid_quirks);
                quirks |= bl_entry->driver_data;//HID_QUIRK_NO_INIT_REPORTS
    hdrv->probe(hdev, id);  //drivers/hid/usbhid/usbmouse.c probe

在老一点的linux kernel版本中,静态的检测只有一个hid_blacklist数组,功能与hid_quirks一致

识别log

usb 1-1.2: New USB device found, idVendor=0c2e, idProduct=10ea, bcdDevice= 1.68
usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1.2: Product: product
usb 1-1.2: Manufacturer: company
usb 1-1.2: SerialNumber: 34567890
cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device

dev/ttyACM0 On a Linux host running the ACM driver
dev/ttyUSB0 On a Linux host running the USB generic serial driver
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值