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

📄 hid-core.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	return 0;}static int hid_submit_ctrl(struct hid_device *hid){	struct hid_report *report;	unsigned char dir;	report = hid->ctrl[hid->ctrltail].report;	dir = hid->ctrl[hid->ctrltail].dir;	if (dir == USB_DIR_OUT)		hid_output_report(report, hid->ctrlbuf);	hid->urbctrl->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + ((report->id > 0) && (dir != USB_DIR_OUT));	hid->urbctrl->pipe = (dir == USB_DIR_OUT) ?  usb_sndctrlpipe(hid->dev, 0) : usb_rcvctrlpipe(hid->dev, 0);	hid->urbctrl->dev = hid->dev;	hid->cr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;	hid->cr.bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;	hid->cr.wValue = ((report->type + 1) << 8) | report->id;	hid->cr.wIndex = cpu_to_le16(hid->ifnum);	hid->cr.wLength = cpu_to_le16(hid->urbctrl->transfer_buffer_length);	dbg("submitting ctrl urb");	if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {		err("usb_submit_urb(ctrl) failed");		return -1;	}	return 0;}/* * Output interrupt completion handler. */static void hid_irq_out(struct urb *urb){	struct hid_device *hid = urb->context;	unsigned long flags;	if (urb->status)		warn("output irq status %d received", urb->status);	spin_lock_irqsave(&hid->outlock, flags);	hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);	if (hid->outhead != hid->outtail) {		hid_submit_out(hid);		spin_unlock_irqrestore(&hid->outlock, flags);		return;	}	clear_bit(HID_OUT_RUNNING, &hid->iofl);	spin_unlock_irqrestore(&hid->outlock, flags);	wake_up(&hid->wait);}/* * Control pipe completion handler. */static void hid_ctrl(struct urb *urb){	struct hid_device *hid = urb->context;	unsigned long flags;	if (urb->status)		warn("ctrl urb status %d received", urb->status);	spin_lock_irqsave(&hid->ctrllock, flags);	if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 		hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb);	hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);	if (hid->ctrlhead != hid->ctrltail) {		hid_submit_ctrl(hid);		spin_unlock_irqrestore(&hid->ctrllock, flags);		return;	}	clear_bit(HID_CTRL_RUNNING, &hid->iofl);	spin_unlock_irqrestore(&hid->ctrllock, flags);	wake_up(&hid->wait);}void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir){	int head;	unsigned long flags;	if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)		return;	if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {		spin_lock_irqsave(&hid->outlock, flags);		if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {			spin_unlock_irqrestore(&hid->outlock, flags);			warn("output queue full");			return;		}		hid->out[hid->outhead] = report;		hid->outhead = head;		if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))			hid_submit_out(hid);		spin_unlock_irqrestore(&hid->outlock, flags);		return;	}	spin_lock_irqsave(&hid->ctrllock, flags);	if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {		spin_unlock_irqrestore(&hid->ctrllock, flags);		warn("control queue full");		return;	}	hid->ctrl[hid->ctrlhead].report = report;	hid->ctrl[hid->ctrlhead].dir = dir;	hid->ctrlhead = head;	if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))		hid_submit_ctrl(hid);	spin_unlock_irqrestore(&hid->ctrllock, flags);}int hid_wait_io(struct hid_device *hid){	DECLARE_WAITQUEUE(wait, current);	int timeout = 10*HZ;	set_current_state(TASK_UNINTERRUPTIBLE);	add_wait_queue(&hid->wait, &wait);	while (timeout && test_bit(HID_CTRL_RUNNING, &hid->iofl) &&			  test_bit(HID_OUT_RUNNING, &hid->iofl))		timeout = schedule_timeout(timeout);	set_current_state(TASK_RUNNING);	remove_wait_queue(&hid->wait, &wait);	if (!timeout) {		dbg("timeout waiting for ctrl or out queue to clear");		return -1;	}	return 0;}static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,		unsigned char type, void *buf, int size){	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,		(type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);}int hid_open(struct hid_device *hid){	if (hid->open++)		return 0;	hid->urbin->dev = hid->dev;	if (usb_submit_urb(hid->urbin, GFP_KERNEL))		return -EIO;	return 0;}void hid_close(struct hid_device *hid){	if (!--hid->open)		usb_unlink_urb(hid->urbin);}/* * Initialize all reports */void hid_init_reports(struct hid_device *hid){	struct hid_report_enum *report_enum;	struct hid_report *report;	struct list_head *list;	int len;	report_enum = hid->report_enum + HID_INPUT_REPORT;	list = report_enum->report_list.next;	while (list != &report_enum->report_list) {		report = (struct hid_report *) list;		hid_submit_report(hid, report, USB_DIR_IN);		list = list->next;	}	report_enum = hid->report_enum + HID_FEATURE_REPORT;	list = report_enum->report_list.next;	while (list != &report_enum->report_list) {		report = (struct hid_report *) list;		hid_submit_report(hid, report, USB_DIR_IN);		list = list->next;	}	if (hid_wait_io(hid)) {		warn("timeout initializing reports\n");		return;	}	report_enum = hid->report_enum + HID_INPUT_REPORT;	list = report_enum->report_list.next;	while (list != &report_enum->report_list) {		report = (struct hid_report *) list;		len = ((report->size - 1) >> 3) + 1 + report_enum->numbered;		if (len > hid->urbin->transfer_buffer_length)			hid->urbin->transfer_buffer_length = len < HID_BUFFER_SIZE ? len : HID_BUFFER_SIZE;		usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),			0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);		list = list->next;	}}#define USB_VENDOR_ID_WACOM		0x056a#define USB_DEVICE_ID_WACOM_GRAPHIRE	0x0010#define USB_DEVICE_ID_WACOM_INTUOS	0x0020#define USB_VENDOR_ID_GRIFFIN		0x077d#define USB_DEVICE_ID_POWERMATE		0x0410#define USB_DEVICE_ID_SOUNDKNOB		0x04AA#define USB_VENDOR_ID_ATEN             0x0557  #define USB_DEVICE_ID_ATEN_UC100KM     0x2004#define USB_DEVICE_ID_ATEN_CS124U      0x2202#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204struct hid_blacklist {	__u16 idVendor;	__u16 idProduct;	unsigned quirks;} hid_blacklist[] = {	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE  },	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE  },	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },	{ 0, 0 }};static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum){	struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;	struct hid_descriptor *hdesc;	struct hid_device *hid;	unsigned quirks = 0, rsize = 0;	char *buf;	int n;	for (n = 0; hid_blacklist[n].idVendor; n++)		if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&			(hid_blacklist[n].idProduct == dev->descriptor.idProduct))				quirks = hid_blacklist[n].quirks;	if (quirks & HID_QUIRK_IGNORE)		return NULL;	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||		usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {			dbg("class descriptor not present\n");			return NULL;	}	for (n = 0; n < hdesc->bNumDescriptors; n++)		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {		dbg("weird size of report descriptor (%u)", rsize);		return NULL;	}	{		__u8 rdesc[rsize];		if ((n = hid_get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {			dbg("reading report descriptor failed");			return NULL;		}#ifdef DEBUG_DATA		printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);		for (n = 0; n < rsize; n++)			printk(" %02x", (unsigned) rdesc[n]);		printk("\n");#endif		if (!(hid = hid_parse_report(rdesc, rsize))) {			dbg("parsing report descriptor failed");			return NULL;		}	}	hid->quirks = quirks;	for (n = 0; n < interface->bNumEndpoints; n++) {		struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];		int pipe;		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */			continue;		if (endpoint->bEndpointAddress & USB_DIR_IN) {			if (hid->urbin)				continue;			if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))				goto fail;			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);			FILL_INT_URB(hid->urbin, dev, pipe, hid->inbuf, 0, hid_irq_in, hid, endpoint->bInterval);		} else {			if (hid->urbout)				continue;			if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))				goto fail;			pipe = usb_sndbulkpipe(dev, endpoint->bEndpointAddress);			FILL_BULK_URB(hid->urbout, dev, pipe, hid->outbuf, 0, hid_irq_out, hid);		}	}	if (!hid->urbin) {		err("couldn't find an input interrupt endpoint");		goto fail;	}	init_waitqueue_head(&hid->wait);		hid->outlock = SPIN_LOCK_UNLOCKED;	hid->ctrllock = SPIN_LOCK_UNLOCKED;	hid->version = hdesc->bcdHID;	hid->country = hdesc->bCountryCode;	hid->dev = dev;	hid->ifnum = interface->bInterfaceNumber;	hid->name[0] = 0;	if (!(buf = kmalloc(64, GFP_KERNEL)))		goto fail;	if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {		strcat(hid->name, buf);		if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)			sprintf(hid->name, "%s %s", hid->name, buf);	} else		sprintf(hid->name, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);	usb_make_path(dev, buf, 63);	sprintf(hid->phys, "%s/input%d", buf, ifnum);	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)		hid->uniq[0] = 0;	kfree(buf);	hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);	FILL_CONTROL_URB(hid->urbctrl, dev, 0, (void*) &hid->cr, hid->ctrlbuf, 1, hid_ctrl, hid);	return hid;fail:	hid_free_device(hid);	if (hid->urbin) usb_free_urb(hid->urbin);	if (hid->urbout) usb_free_urb(hid->urbout);	if (hid->urbctrl) usb_free_urb(hid->urbctrl);	return NULL;}static void* hid_probe(struct usb_device *dev, unsigned int ifnum,		       const struct usb_device_id *id){	struct hid_device *hid;	char path[64];	int i;	char *c;	dbg("HID probe called for ifnum %d", ifnum);	if (!(hid = usb_hid_configure(dev, ifnum)))		return NULL;	hid_init_reports(hid);	hid_dump_device(hid);	if (!hidinput_connect(hid))		hid->claimed |= HID_CLAIMED_INPUT;	if (!hiddev_connect(hid))		hid->claimed |= HID_CLAIMED_HIDDEV;	if (!hid->claimed) {		hid_free_device(hid);		return NULL;	}	printk(KERN_INFO);	if (hid->claimed & HID_CLAIMED_INPUT)		printk("input");	if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV))		printk(",");	if (hid->claimed & HID_CLAIMED_HIDDEV)		printk("hiddev%d", hid->minor);	c = "Device";	for (i = 0; i < hid->maxapplication; i++)		if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {			c = hid_types[hid->application[i] & 0xffff];			break;		}	usb_make_path(dev, path, 63);	printk(": USB HID v%x.%02x %s [%s] on %s\n",		hid->version >> 8, hid->version & 0xff, c, hid->name, path);	return hid;}static void hid_disconnect(struct usb_device *dev, void *ptr){	struct hid_device *hid = ptr;	usb_unlink_urb(hid->urbin);	usb_unlink_urb(hid->urbout);	usb_unlink_urb(hid->urbctrl);	if (hid->claimed & HID_CLAIMED_INPUT)		hidinput_disconnect(hid);	if (hid->claimed & HID_CLAIMED_HIDDEV)		hiddev_disconnect(hid);	usb_free_urb(hid->urbin);	usb_free_urb(hid->urbctrl);	if (hid->urbout)		usb_free_urb(hid->urbout);	hid_free_device(hid);}static struct usb_device_id hid_usb_ids [] = {	{ match_flags: USB_DEVICE_ID_MATCH_INT_CLASS,	    bInterfaceClass: USB_INTERFACE_CLASS_HID },	{ }						/* Terminating entry */};MODULE_DEVICE_TABLE (usb, hid_usb_ids);static struct usb_driver hid_driver = {	name:		"hid",	probe:		hid_probe,	disconnect:	hid_disconnect,	id_table:	hid_usb_ids,};static int __init hid_init(void){	hiddev_init();	usb_register(&hid_driver);	info(DRIVER_VERSION ":" DRIVER_DESC);	return 0;}static void __exit hid_exit(void){	hiddev_exit();	usb_deregister(&hid_driver);}module_init(hid_init);module_exit(hid_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE(DRIVER_LICENSE);

⌨️ 快捷键说明

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