⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hid-quirks.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		}	}	if (bl_entry != NULL)		dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",				bl_entry->quirks, bl_entry->idVendor,				bl_entry->idProduct);	return bl_entry;}/** * usbhid_modify_dquirk: add/replace a HID quirk * @idVendor: the 16-bit USB vendor ID, in native byteorder * @idProduct: the 16-bit USB product ID, in native byteorder * @quirks: the u32 quirks value to add/replace * * Description: *         If an dynamic quirk exists in memory for this (idVendor, *         idProduct) pair, replace its quirks value with what was *         provided.  Otherwise, add the quirk to the dynamic quirks list. * * Returns: 0 OK, -error on failure. */int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,		const u32 quirks){	struct quirks_list_struct *q_new, *q;	int list_edited = 0;	if (!idVendor) {		dbg_hid("Cannot add a quirk with idVendor = 0\n");		return -EINVAL;	}	q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);	if (!q_new) {		dbg_hid("Could not allocate quirks_list_struct\n");		return -ENOMEM;	}	q_new->hid_bl_item.idVendor = idVendor;	q_new->hid_bl_item.idProduct = idProduct;	q_new->hid_bl_item.quirks = quirks;	down_write(&dquirks_rwsem);	list_for_each_entry(q, &dquirks_list, node) {		if (q->hid_bl_item.idVendor == idVendor &&				q->hid_bl_item.idProduct == idProduct) {			list_replace(&q->node, &q_new->node);			kfree(q);			list_edited = 1;			break;		}	}	if (!list_edited)		list_add_tail(&q_new->node, &dquirks_list);	up_write(&dquirks_rwsem);	return 0;}/** * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory * * Description: *         Free all memory associated with dynamic quirks - called before *         module unload. * */static void usbhid_remove_all_dquirks(void){	struct quirks_list_struct *q, *temp;	down_write(&dquirks_rwsem);	list_for_each_entry_safe(q, temp, &dquirks_list, node) {		list_del(&q->node);		kfree(q);	}	up_write(&dquirks_rwsem);}/**  * usbhid_quirks_init: apply USB HID quirks specified at module load time */int usbhid_quirks_init(char **quirks_param){	u16 idVendor, idProduct;	u32 quirks;	int n = 0, m;	for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {		m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",				&idVendor, &idProduct, &quirks);		if (m != 3 ||				usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) {			printk(KERN_WARNING					"Could not parse HID quirk module param %s\n",					quirks_param[n]);		}	}	return 0;}/** * usbhid_quirks_exit: release memory associated with dynamic_quirks * * Description: *     Release all memory associated with dynamic quirks.  Called upon *     module unload. * * Returns: nothing */void usbhid_quirks_exit(void){	usbhid_remove_all_dquirks();}/** * usbhid_exists_squirk: return any static quirks for a USB HID device * @idVendor: the 16-bit USB vendor ID, in native byteorder * @idProduct: the 16-bit USB product ID, in native byteorder * * Description: *     Given a USB vendor ID and product ID, return a pointer to *     the hid_blacklist entry associated with that device. * * Returns: pointer if quirk found, or NULL if no quirks found. */static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,		const u16 idProduct){	const struct hid_blacklist *bl_entry = NULL;	int n = 0;	for (; hid_blacklist[n].idVendor; n++)		if (hid_blacklist[n].idVendor == idVendor &&				hid_blacklist[n].idProduct == idProduct)			bl_entry = &hid_blacklist[n];	if (bl_entry != NULL)		dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",				bl_entry->quirks, bl_entry->idVendor, 				bl_entry->idProduct);	return bl_entry;}/** * usbhid_lookup_quirk: return any quirks associated with a USB HID device * @idVendor: the 16-bit USB vendor ID, in native byteorder * @idProduct: the 16-bit USB product ID, in native byteorder * * Description: *     Given a USB vendor ID and product ID, return any quirks associated *     with that device. * * Returns: a u32 quirks value. */u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct){	u32 quirks = 0;	const struct hid_blacklist *bl_entry = NULL;	/* Ignore all Wacom devices */	if (idVendor == USB_VENDOR_ID_WACOM)		return HID_QUIRK_IGNORE;	/* ignore all Code Mercenaries IOWarrior devices */	if (idVendor == USB_VENDOR_ID_CODEMERCS)		if (idProduct >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST &&				idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)			return HID_QUIRK_IGNORE;	/* NCR devices must not be queried for reports */	if (idVendor == USB_VENDOR_ID_NCR &&			idProduct >= USB_DEVICE_ID_NCR_FIRST &&			idProduct <= USB_DEVICE_ID_NCR_LAST)			return HID_QUIRK_NOGET;	down_read(&dquirks_rwsem);	bl_entry = usbhid_exists_dquirk(idVendor, idProduct);	if (!bl_entry)		bl_entry = usbhid_exists_squirk(idVendor, idProduct);	if (bl_entry)		quirks = bl_entry->quirks;	up_read(&dquirks_rwsem);	return quirks;}/* * Cherry Cymotion keyboard have an invalid HID report descriptor, * that needs fixing before we can parse it. */static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize){	if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {		printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");		rdesc[11] = rdesc[16] = 0xff;		rdesc[12] = rdesc[17] = 0x03;	}}/* * Certain Logitech keyboards send in report #3 keys which are far * above the logical maximum described in descriptor. This extends * the original value of 0x28c of logical maximum to 0x104d */static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize){	if (rsize >= 90 && rdesc[83] == 0x26			&& rdesc[84] == 0x8c			&& rdesc[85] == 0x02) {		printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");		rdesc[84] = rdesc[89] = 0x4d;		rdesc[85] = rdesc[90] = 0x10;	}}/* Petalynx Maxter Remote has maximum for consumer page set too low */static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize){	if (rsize >= 60 && rdesc[39] == 0x2a			&& rdesc[40] == 0xf5			&& rdesc[41] == 0x00			&& rdesc[59] == 0x26			&& rdesc[60] == 0xf9			&& rdesc[61] == 0x00) {		printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");		rdesc[60] = 0xfa;		rdesc[40] = 0xfa;	}}/* * Some USB barcode readers from cypress have usage min and usage max in * the wrong order */static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize){	short fixed = 0;	int i;	for (i = 0; i < rsize - 4; i++) {		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {			unsigned char tmp;			rdesc[i] = 0x19; rdesc[i+2] = 0x29;			tmp = rdesc[i+3];			rdesc[i+3] = rdesc[i+1];			rdesc[i+1] = tmp;		}	}	if (fixed)		printk(KERN_INFO "Fixing up Cypress report descriptor\n");}/* * MacBook JIS keyboard has wrong logical maximum */static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize){	if (rsize >= 60 && rdesc[53] == 0x65			&& rdesc[59] == 0x65) {		printk(KERN_INFO "Fixing up MacBook JIS keyboard report descriptor\n");		rdesc[53] = rdesc[59] = 0xe7;	}}static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize){	if ((quirks & HID_QUIRK_RDESC_CYMOTION))		usbhid_fixup_cymotion_descriptor(rdesc, rsize);	if (quirks & HID_QUIRK_RDESC_LOGITECH)		usbhid_fixup_logitech_descriptor(rdesc, rsize);	if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)		usbhid_fixup_cypress_descriptor(rdesc, rsize);	if (quirks & HID_QUIRK_RDESC_PETALYNX)		usbhid_fixup_petalynx_descriptor(rdesc, rsize);	if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)		usbhid_fixup_macbook_descriptor(rdesc, rsize);}/** * usbhid_fixup_report_descriptor: check if report descriptor needs fixup * * Description: *	Walks the hid_rdesc_blacklist[] array and checks whether the device *	is known to have broken report descriptor that needs to be fixed up *	prior to entering the HID parser * * Returns: nothing */void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,				    char *rdesc, unsigned rsize, char **quirks_param){	int n, m;	u16 paramVendor, paramProduct;	u32 quirks;	/* static rdesc quirk entries */	for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)		if (hid_rdesc_blacklist[n].idVendor == idVendor &&				hid_rdesc_blacklist[n].idProduct == idProduct)			__usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,					rdesc, rsize);	/* runtime rdesc quirk entries handling */	for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {		m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",				&paramVendor, &paramProduct, &quirks);		if (m != 3)			printk(KERN_WARNING				"Could not parse HID quirk module param %s\n",				quirks_param[n]);		else if (paramVendor == idVendor && paramProduct == idProduct)			__usbhid_fixup_report_descriptor(quirks, rdesc, rsize);	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -