162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * USB HID support for Linux 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 1999 Andreas Gal 662306a36Sopenharmony_ci * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> 762306a36Sopenharmony_ci * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc 862306a36Sopenharmony_ci * Copyright (c) 2007-2008 Oliver Neukum 962306a36Sopenharmony_ci * Copyright (c) 2006-2010 Jiri Kosina 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/init.h> 1862306a36Sopenharmony_ci#include <linux/kernel.h> 1962306a36Sopenharmony_ci#include <linux/list.h> 2062306a36Sopenharmony_ci#include <linux/mm.h> 2162306a36Sopenharmony_ci#include <linux/mutex.h> 2262306a36Sopenharmony_ci#include <linux/spinlock.h> 2362306a36Sopenharmony_ci#include <asm/unaligned.h> 2462306a36Sopenharmony_ci#include <asm/byteorder.h> 2562306a36Sopenharmony_ci#include <linux/input.h> 2662306a36Sopenharmony_ci#include <linux/wait.h> 2762306a36Sopenharmony_ci#include <linux/workqueue.h> 2862306a36Sopenharmony_ci#include <linux/string.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#include <linux/usb.h> 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include <linux/hid.h> 3362306a36Sopenharmony_ci#include <linux/hiddev.h> 3462306a36Sopenharmony_ci#include <linux/hid-debug.h> 3562306a36Sopenharmony_ci#include <linux/hidraw.h> 3662306a36Sopenharmony_ci#include "usbhid.h" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * Version Information 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define DRIVER_DESC "USB HID core driver" 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* 4562306a36Sopenharmony_ci * Module parameters. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic unsigned int hid_mousepoll_interval; 4962306a36Sopenharmony_cimodule_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); 5062306a36Sopenharmony_ciMODULE_PARM_DESC(mousepoll, "Polling interval of mice"); 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic unsigned int hid_jspoll_interval; 5362306a36Sopenharmony_cimodule_param_named(jspoll, hid_jspoll_interval, uint, 0644); 5462306a36Sopenharmony_ciMODULE_PARM_DESC(jspoll, "Polling interval of joysticks"); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic unsigned int hid_kbpoll_interval; 5762306a36Sopenharmony_cimodule_param_named(kbpoll, hid_kbpoll_interval, uint, 0644); 5862306a36Sopenharmony_ciMODULE_PARM_DESC(kbpoll, "Polling interval of keyboards"); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic unsigned int ignoreled; 6162306a36Sopenharmony_cimodule_param_named(ignoreled, ignoreled, uint, 0644); 6262306a36Sopenharmony_ciMODULE_PARM_DESC(ignoreled, "Autosuspend with active leds"); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* Quirks specified at module load time */ 6562306a36Sopenharmony_cistatic char *quirks_param[MAX_USBHID_BOOT_QUIRKS]; 6662306a36Sopenharmony_cimodule_param_array_named(quirks, quirks_param, charp, NULL, 0444); 6762306a36Sopenharmony_ciMODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " 6862306a36Sopenharmony_ci " quirks=vendorID:productID:quirks" 6962306a36Sopenharmony_ci " where vendorID, productID, and quirks are all in" 7062306a36Sopenharmony_ci " 0x-prefixed hex"); 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * Input submission and I/O error handler. 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistatic void hid_io_error(struct hid_device *hid); 7562306a36Sopenharmony_cistatic int hid_submit_out(struct hid_device *hid); 7662306a36Sopenharmony_cistatic int hid_submit_ctrl(struct hid_device *hid); 7762306a36Sopenharmony_cistatic void hid_cancel_delayed_stuff(struct usbhid_device *usbhid); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* Start up the input URB */ 8062306a36Sopenharmony_cistatic int hid_start_in(struct hid_device *hid) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci unsigned long flags; 8362306a36Sopenharmony_ci int rc = 0; 8462306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci spin_lock_irqsave(&usbhid->lock, flags); 8762306a36Sopenharmony_ci if (test_bit(HID_IN_POLLING, &usbhid->iofl) && 8862306a36Sopenharmony_ci !test_bit(HID_DISCONNECTED, &usbhid->iofl) && 8962306a36Sopenharmony_ci !test_bit(HID_SUSPENDED, &usbhid->iofl) && 9062306a36Sopenharmony_ci !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { 9162306a36Sopenharmony_ci rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); 9262306a36Sopenharmony_ci if (rc != 0) { 9362306a36Sopenharmony_ci clear_bit(HID_IN_RUNNING, &usbhid->iofl); 9462306a36Sopenharmony_ci if (rc == -ENOSPC) 9562306a36Sopenharmony_ci set_bit(HID_NO_BANDWIDTH, &usbhid->iofl); 9662306a36Sopenharmony_ci } else { 9762306a36Sopenharmony_ci clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl); 9862306a36Sopenharmony_ci } 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 10162306a36Sopenharmony_ci return rc; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci/* I/O retry timer routine */ 10562306a36Sopenharmony_cistatic void hid_retry_timeout(struct timer_list *t) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci struct usbhid_device *usbhid = from_timer(usbhid, t, io_retry); 10862306a36Sopenharmony_ci struct hid_device *hid = usbhid->hid; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); 11162306a36Sopenharmony_ci if (hid_start_in(hid)) 11262306a36Sopenharmony_ci hid_io_error(hid); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* Workqueue routine to reset the device or clear a halt */ 11662306a36Sopenharmony_cistatic void hid_reset(struct work_struct *work) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci struct usbhid_device *usbhid = 11962306a36Sopenharmony_ci container_of(work, struct usbhid_device, reset_work); 12062306a36Sopenharmony_ci struct hid_device *hid = usbhid->hid; 12162306a36Sopenharmony_ci int rc; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { 12462306a36Sopenharmony_ci dev_dbg(&usbhid->intf->dev, "clear halt\n"); 12562306a36Sopenharmony_ci rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); 12662306a36Sopenharmony_ci clear_bit(HID_CLEAR_HALT, &usbhid->iofl); 12762306a36Sopenharmony_ci if (rc == 0) { 12862306a36Sopenharmony_ci hid_start_in(hid); 12962306a36Sopenharmony_ci } else { 13062306a36Sopenharmony_ci dev_dbg(&usbhid->intf->dev, 13162306a36Sopenharmony_ci "clear-halt failed: %d\n", rc); 13262306a36Sopenharmony_ci set_bit(HID_RESET_PENDING, &usbhid->iofl); 13362306a36Sopenharmony_ci } 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { 13762306a36Sopenharmony_ci dev_dbg(&usbhid->intf->dev, "resetting device\n"); 13862306a36Sopenharmony_ci usb_queue_reset_device(usbhid->intf); 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/* Main I/O error handler */ 14362306a36Sopenharmony_cistatic void hid_io_error(struct hid_device *hid) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci unsigned long flags; 14662306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci spin_lock_irqsave(&usbhid->lock, flags); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* Stop when disconnected */ 15162306a36Sopenharmony_ci if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) 15262306a36Sopenharmony_ci goto done; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* If it has been a while since the last error, we'll assume 15562306a36Sopenharmony_ci * this a brand new error and reset the retry timeout. */ 15662306a36Sopenharmony_ci if (time_after(jiffies, usbhid->stop_retry + HZ/2)) 15762306a36Sopenharmony_ci usbhid->retry_delay = 0; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci /* When an error occurs, retry at increasing intervals */ 16062306a36Sopenharmony_ci if (usbhid->retry_delay == 0) { 16162306a36Sopenharmony_ci usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ 16262306a36Sopenharmony_ci usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); 16362306a36Sopenharmony_ci } else if (usbhid->retry_delay < 100) 16462306a36Sopenharmony_ci usbhid->retry_delay *= 2; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (time_after(jiffies, usbhid->stop_retry)) { 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* Retries failed, so do a port reset unless we lack bandwidth*/ 16962306a36Sopenharmony_ci if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) 17062306a36Sopenharmony_ci && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci schedule_work(&usbhid->reset_work); 17362306a36Sopenharmony_ci goto done; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci mod_timer(&usbhid->io_retry, 17862306a36Sopenharmony_ci jiffies + msecs_to_jiffies(usbhid->retry_delay)); 17962306a36Sopenharmony_cidone: 18062306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic void usbhid_mark_busy(struct usbhid_device *usbhid) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct usb_interface *intf = usbhid->intf; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci usb_mark_last_busy(interface_to_usbdev(intf)); 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int usbhid_restart_out_queue(struct usbhid_device *usbhid) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(usbhid->intf); 19362306a36Sopenharmony_ci int kicked; 19462306a36Sopenharmony_ci int r; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) || 19762306a36Sopenharmony_ci test_bit(HID_SUSPENDED, &usbhid->iofl)) 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci if ((kicked = (usbhid->outhead != usbhid->outtail))) { 20162306a36Sopenharmony_ci hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Try to wake up from autosuspend... */ 20462306a36Sopenharmony_ci r = usb_autopm_get_interface_async(usbhid->intf); 20562306a36Sopenharmony_ci if (r < 0) 20662306a36Sopenharmony_ci return r; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* 20962306a36Sopenharmony_ci * If still suspended, don't submit. Submission will 21062306a36Sopenharmony_ci * occur if/when resume drains the queue. 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci if (test_bit(HID_SUSPENDED, &usbhid->iofl)) { 21362306a36Sopenharmony_ci usb_autopm_put_interface_no_suspend(usbhid->intf); 21462306a36Sopenharmony_ci return r; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Asynchronously flush queue. */ 21862306a36Sopenharmony_ci set_bit(HID_OUT_RUNNING, &usbhid->iofl); 21962306a36Sopenharmony_ci if (hid_submit_out(hid)) { 22062306a36Sopenharmony_ci clear_bit(HID_OUT_RUNNING, &usbhid->iofl); 22162306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci wake_up(&usbhid->wait); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci return kicked; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(usbhid->intf); 23162306a36Sopenharmony_ci int kicked; 23262306a36Sopenharmony_ci int r; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci WARN_ON(hid == NULL); 23562306a36Sopenharmony_ci if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) || 23662306a36Sopenharmony_ci test_bit(HID_SUSPENDED, &usbhid->iofl)) 23762306a36Sopenharmony_ci return 0; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { 24062306a36Sopenharmony_ci hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* Try to wake up from autosuspend... */ 24362306a36Sopenharmony_ci r = usb_autopm_get_interface_async(usbhid->intf); 24462306a36Sopenharmony_ci if (r < 0) 24562306a36Sopenharmony_ci return r; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 24862306a36Sopenharmony_ci * If still suspended, don't submit. Submission will 24962306a36Sopenharmony_ci * occur if/when resume drains the queue. 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_ci if (test_bit(HID_SUSPENDED, &usbhid->iofl)) { 25262306a36Sopenharmony_ci usb_autopm_put_interface_no_suspend(usbhid->intf); 25362306a36Sopenharmony_ci return r; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Asynchronously flush queue. */ 25762306a36Sopenharmony_ci set_bit(HID_CTRL_RUNNING, &usbhid->iofl); 25862306a36Sopenharmony_ci if (hid_submit_ctrl(hid)) { 25962306a36Sopenharmony_ci clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); 26062306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci wake_up(&usbhid->wait); 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci return kicked; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* 26862306a36Sopenharmony_ci * Input interrupt completion handler. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic void hid_irq_in(struct urb *urb) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci struct hid_device *hid = urb->context; 27462306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 27562306a36Sopenharmony_ci int status; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci switch (urb->status) { 27862306a36Sopenharmony_ci case 0: /* success */ 27962306a36Sopenharmony_ci usbhid->retry_delay = 0; 28062306a36Sopenharmony_ci if (!test_bit(HID_OPENED, &usbhid->iofl)) 28162306a36Sopenharmony_ci break; 28262306a36Sopenharmony_ci usbhid_mark_busy(usbhid); 28362306a36Sopenharmony_ci if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { 28462306a36Sopenharmony_ci hid_input_report(urb->context, HID_INPUT_REPORT, 28562306a36Sopenharmony_ci urb->transfer_buffer, 28662306a36Sopenharmony_ci urb->actual_length, 1); 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * autosuspend refused while keys are pressed 28962306a36Sopenharmony_ci * because most keyboards don't wake up when 29062306a36Sopenharmony_ci * a key is released 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci if (hid_check_keys_pressed(hid)) 29362306a36Sopenharmony_ci set_bit(HID_KEYS_PRESSED, &usbhid->iofl); 29462306a36Sopenharmony_ci else 29562306a36Sopenharmony_ci clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci break; 29862306a36Sopenharmony_ci case -EPIPE: /* stall */ 29962306a36Sopenharmony_ci usbhid_mark_busy(usbhid); 30062306a36Sopenharmony_ci clear_bit(HID_IN_RUNNING, &usbhid->iofl); 30162306a36Sopenharmony_ci set_bit(HID_CLEAR_HALT, &usbhid->iofl); 30262306a36Sopenharmony_ci schedule_work(&usbhid->reset_work); 30362306a36Sopenharmony_ci return; 30462306a36Sopenharmony_ci case -ECONNRESET: /* unlink */ 30562306a36Sopenharmony_ci case -ENOENT: 30662306a36Sopenharmony_ci case -ESHUTDOWN: /* unplug */ 30762306a36Sopenharmony_ci clear_bit(HID_IN_RUNNING, &usbhid->iofl); 30862306a36Sopenharmony_ci return; 30962306a36Sopenharmony_ci case -EILSEQ: /* protocol error or unplug */ 31062306a36Sopenharmony_ci case -EPROTO: /* protocol error or unplug */ 31162306a36Sopenharmony_ci case -ETIME: /* protocol error or unplug */ 31262306a36Sopenharmony_ci case -ETIMEDOUT: /* Should never happen, but... */ 31362306a36Sopenharmony_ci usbhid_mark_busy(usbhid); 31462306a36Sopenharmony_ci clear_bit(HID_IN_RUNNING, &usbhid->iofl); 31562306a36Sopenharmony_ci hid_io_error(hid); 31662306a36Sopenharmony_ci return; 31762306a36Sopenharmony_ci default: /* error */ 31862306a36Sopenharmony_ci hid_warn(urb->dev, "input irq status %d received\n", 31962306a36Sopenharmony_ci urb->status); 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci status = usb_submit_urb(urb, GFP_ATOMIC); 32362306a36Sopenharmony_ci if (status) { 32462306a36Sopenharmony_ci clear_bit(HID_IN_RUNNING, &usbhid->iofl); 32562306a36Sopenharmony_ci if (status != -EPERM) { 32662306a36Sopenharmony_ci hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n", 32762306a36Sopenharmony_ci hid_to_usb_dev(hid)->bus->bus_name, 32862306a36Sopenharmony_ci hid_to_usb_dev(hid)->devpath, 32962306a36Sopenharmony_ci usbhid->ifnum, status); 33062306a36Sopenharmony_ci hid_io_error(hid); 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic int hid_submit_out(struct hid_device *hid) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci struct hid_report *report; 33862306a36Sopenharmony_ci char *raw_report; 33962306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 34062306a36Sopenharmony_ci int r; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci report = usbhid->out[usbhid->outtail].report; 34362306a36Sopenharmony_ci raw_report = usbhid->out[usbhid->outtail].raw_report; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci usbhid->urbout->transfer_buffer_length = hid_report_len(report); 34662306a36Sopenharmony_ci usbhid->urbout->dev = hid_to_usb_dev(hid); 34762306a36Sopenharmony_ci if (raw_report) { 34862306a36Sopenharmony_ci memcpy(usbhid->outbuf, raw_report, 34962306a36Sopenharmony_ci usbhid->urbout->transfer_buffer_length); 35062306a36Sopenharmony_ci kfree(raw_report); 35162306a36Sopenharmony_ci usbhid->out[usbhid->outtail].raw_report = NULL; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci dbg_hid("submitting out urb\n"); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci r = usb_submit_urb(usbhid->urbout, GFP_ATOMIC); 35762306a36Sopenharmony_ci if (r < 0) { 35862306a36Sopenharmony_ci hid_err(hid, "usb_submit_urb(out) failed: %d\n", r); 35962306a36Sopenharmony_ci return r; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci usbhid->last_out = jiffies; 36262306a36Sopenharmony_ci return 0; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic int hid_submit_ctrl(struct hid_device *hid) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct hid_report *report; 36862306a36Sopenharmony_ci unsigned char dir; 36962306a36Sopenharmony_ci char *raw_report; 37062306a36Sopenharmony_ci int len, r; 37162306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci report = usbhid->ctrl[usbhid->ctrltail].report; 37462306a36Sopenharmony_ci raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; 37562306a36Sopenharmony_ci dir = usbhid->ctrl[usbhid->ctrltail].dir; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci len = hid_report_len(report); 37862306a36Sopenharmony_ci if (dir == USB_DIR_OUT) { 37962306a36Sopenharmony_ci usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); 38062306a36Sopenharmony_ci if (raw_report) { 38162306a36Sopenharmony_ci memcpy(usbhid->ctrlbuf, raw_report, len); 38262306a36Sopenharmony_ci kfree(raw_report); 38362306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrltail].raw_report = NULL; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci } else { 38662306a36Sopenharmony_ci int maxpacket; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); 38962306a36Sopenharmony_ci maxpacket = usb_maxpacket(hid_to_usb_dev(hid), 39062306a36Sopenharmony_ci usbhid->urbctrl->pipe); 39162306a36Sopenharmony_ci len += (len == 0); /* Don't allow 0-length reports */ 39262306a36Sopenharmony_ci len = round_up(len, maxpacket); 39362306a36Sopenharmony_ci if (len > usbhid->bufsize) 39462306a36Sopenharmony_ci len = usbhid->bufsize; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci usbhid->urbctrl->transfer_buffer_length = len; 39762306a36Sopenharmony_ci usbhid->urbctrl->dev = hid_to_usb_dev(hid); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; 40062306a36Sopenharmony_ci usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : 40162306a36Sopenharmony_ci HID_REQ_GET_REPORT; 40262306a36Sopenharmony_ci usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | 40362306a36Sopenharmony_ci report->id); 40462306a36Sopenharmony_ci usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); 40562306a36Sopenharmony_ci usbhid->cr->wLength = cpu_to_le16(len); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", 40862306a36Sopenharmony_ci usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : 40962306a36Sopenharmony_ci "Get_Report", 41062306a36Sopenharmony_ci usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci r = usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC); 41362306a36Sopenharmony_ci if (r < 0) { 41462306a36Sopenharmony_ci hid_err(hid, "usb_submit_urb(ctrl) failed: %d\n", r); 41562306a36Sopenharmony_ci return r; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci usbhid->last_ctrl = jiffies; 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/* 42262306a36Sopenharmony_ci * Output interrupt completion handler. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic void hid_irq_out(struct urb *urb) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci struct hid_device *hid = urb->context; 42862306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 42962306a36Sopenharmony_ci unsigned long flags; 43062306a36Sopenharmony_ci int unplug = 0; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci switch (urb->status) { 43362306a36Sopenharmony_ci case 0: /* success */ 43462306a36Sopenharmony_ci break; 43562306a36Sopenharmony_ci case -ESHUTDOWN: /* unplug */ 43662306a36Sopenharmony_ci unplug = 1; 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci case -EILSEQ: /* protocol error or unplug */ 43962306a36Sopenharmony_ci case -EPROTO: /* protocol error or unplug */ 44062306a36Sopenharmony_ci case -ECONNRESET: /* unlink */ 44162306a36Sopenharmony_ci case -ENOENT: 44262306a36Sopenharmony_ci break; 44362306a36Sopenharmony_ci default: /* error */ 44462306a36Sopenharmony_ci hid_warn(urb->dev, "output irq status %d received\n", 44562306a36Sopenharmony_ci urb->status); 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci spin_lock_irqsave(&usbhid->lock, flags); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci if (unplug) { 45162306a36Sopenharmony_ci usbhid->outtail = usbhid->outhead; 45262306a36Sopenharmony_ci } else { 45362306a36Sopenharmony_ci usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (usbhid->outhead != usbhid->outtail && 45662306a36Sopenharmony_ci hid_submit_out(hid) == 0) { 45762306a36Sopenharmony_ci /* Successfully submitted next urb in queue */ 45862306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 45962306a36Sopenharmony_ci return; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci clear_bit(HID_OUT_RUNNING, &usbhid->iofl); 46462306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 46562306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 46662306a36Sopenharmony_ci wake_up(&usbhid->wait); 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/* 47062306a36Sopenharmony_ci * Control pipe completion handler. 47162306a36Sopenharmony_ci */ 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistatic void hid_ctrl(struct urb *urb) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci struct hid_device *hid = urb->context; 47662306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 47762306a36Sopenharmony_ci unsigned long flags; 47862306a36Sopenharmony_ci int unplug = 0, status = urb->status; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci switch (status) { 48162306a36Sopenharmony_ci case 0: /* success */ 48262306a36Sopenharmony_ci if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) 48362306a36Sopenharmony_ci hid_input_report(urb->context, 48462306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrltail].report->type, 48562306a36Sopenharmony_ci urb->transfer_buffer, urb->actual_length, 0); 48662306a36Sopenharmony_ci break; 48762306a36Sopenharmony_ci case -ESHUTDOWN: /* unplug */ 48862306a36Sopenharmony_ci unplug = 1; 48962306a36Sopenharmony_ci break; 49062306a36Sopenharmony_ci case -EILSEQ: /* protocol error or unplug */ 49162306a36Sopenharmony_ci case -EPROTO: /* protocol error or unplug */ 49262306a36Sopenharmony_ci case -ECONNRESET: /* unlink */ 49362306a36Sopenharmony_ci case -ENOENT: 49462306a36Sopenharmony_ci case -EPIPE: /* report not available */ 49562306a36Sopenharmony_ci break; 49662306a36Sopenharmony_ci default: /* error */ 49762306a36Sopenharmony_ci hid_warn(urb->dev, "ctrl urb status %d received\n", status); 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci spin_lock_irqsave(&usbhid->lock, flags); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci if (unplug) { 50362306a36Sopenharmony_ci usbhid->ctrltail = usbhid->ctrlhead; 50462306a36Sopenharmony_ci } else if (usbhid->ctrlhead != usbhid->ctrltail) { 50562306a36Sopenharmony_ci usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (usbhid->ctrlhead != usbhid->ctrltail && 50862306a36Sopenharmony_ci hid_submit_ctrl(hid) == 0) { 50962306a36Sopenharmony_ci /* Successfully submitted next urb in queue */ 51062306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 51162306a36Sopenharmony_ci return; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); 51662306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 51762306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 51862306a36Sopenharmony_ci wake_up(&usbhid->wait); 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_cistatic void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, 52262306a36Sopenharmony_ci unsigned char dir) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci int head; 52562306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) || 52862306a36Sopenharmony_ci test_bit(HID_DISCONNECTED, &usbhid->iofl)) 52962306a36Sopenharmony_ci return; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { 53262306a36Sopenharmony_ci if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { 53362306a36Sopenharmony_ci hid_warn(hid, "output queue full\n"); 53462306a36Sopenharmony_ci return; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC); 53862306a36Sopenharmony_ci if (!usbhid->out[usbhid->outhead].raw_report) { 53962306a36Sopenharmony_ci hid_warn(hid, "output queueing failed\n"); 54062306a36Sopenharmony_ci return; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); 54362306a36Sopenharmony_ci usbhid->out[usbhid->outhead].report = report; 54462306a36Sopenharmony_ci usbhid->outhead = head; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci /* If the queue isn't running, restart it */ 54762306a36Sopenharmony_ci if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) { 54862306a36Sopenharmony_ci usbhid_restart_out_queue(usbhid); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci /* Otherwise see if an earlier request has timed out */ 55162306a36Sopenharmony_ci } else if (time_after(jiffies, usbhid->last_out + HZ * 5)) { 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* Prevent autosuspend following the unlink */ 55462306a36Sopenharmony_ci usb_autopm_get_interface_no_resume(usbhid->intf); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* 55762306a36Sopenharmony_ci * Prevent resubmission in case the URB completes 55862306a36Sopenharmony_ci * before we can unlink it. We don't want to cancel 55962306a36Sopenharmony_ci * the wrong transfer! 56062306a36Sopenharmony_ci */ 56162306a36Sopenharmony_ci usb_block_urb(usbhid->urbout); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci /* Drop lock to avoid deadlock if the callback runs */ 56462306a36Sopenharmony_ci spin_unlock(&usbhid->lock); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci usb_unlink_urb(usbhid->urbout); 56762306a36Sopenharmony_ci spin_lock(&usbhid->lock); 56862306a36Sopenharmony_ci usb_unblock_urb(usbhid->urbout); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci /* Unlink might have stopped the queue */ 57162306a36Sopenharmony_ci if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) 57262306a36Sopenharmony_ci usbhid_restart_out_queue(usbhid); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* Now we can allow autosuspend again */ 57562306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci return; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { 58162306a36Sopenharmony_ci hid_warn(hid, "control queue full\n"); 58262306a36Sopenharmony_ci return; 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (dir == USB_DIR_OUT) { 58662306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC); 58762306a36Sopenharmony_ci if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { 58862306a36Sopenharmony_ci hid_warn(hid, "control queueing failed\n"); 58962306a36Sopenharmony_ci return; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrlhead].report = report; 59462306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrlhead].dir = dir; 59562306a36Sopenharmony_ci usbhid->ctrlhead = head; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* If the queue isn't running, restart it */ 59862306a36Sopenharmony_ci if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { 59962306a36Sopenharmony_ci usbhid_restart_ctrl_queue(usbhid); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* Otherwise see if an earlier request has timed out */ 60262306a36Sopenharmony_ci } else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci /* Prevent autosuspend following the unlink */ 60562306a36Sopenharmony_ci usb_autopm_get_interface_no_resume(usbhid->intf); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci /* 60862306a36Sopenharmony_ci * Prevent resubmission in case the URB completes 60962306a36Sopenharmony_ci * before we can unlink it. We don't want to cancel 61062306a36Sopenharmony_ci * the wrong transfer! 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci usb_block_urb(usbhid->urbctrl); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* Drop lock to avoid deadlock if the callback runs */ 61562306a36Sopenharmony_ci spin_unlock(&usbhid->lock); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci usb_unlink_urb(usbhid->urbctrl); 61862306a36Sopenharmony_ci spin_lock(&usbhid->lock); 61962306a36Sopenharmony_ci usb_unblock_urb(usbhid->urbctrl); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* Unlink might have stopped the queue */ 62262306a36Sopenharmony_ci if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 62362306a36Sopenharmony_ci usbhid_restart_ctrl_queue(usbhid); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* Now we can allow autosuspend again */ 62662306a36Sopenharmony_ci usb_autopm_put_interface_async(usbhid->intf); 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 63362306a36Sopenharmony_ci unsigned long flags; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci spin_lock_irqsave(&usbhid->lock, flags); 63662306a36Sopenharmony_ci __usbhid_submit_report(hid, report, dir); 63762306a36Sopenharmony_ci spin_unlock_irqrestore(&usbhid->lock, flags); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic int usbhid_wait_io(struct hid_device *hid) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (!wait_event_timeout(usbhid->wait, 64562306a36Sopenharmony_ci (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && 64662306a36Sopenharmony_ci !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), 64762306a36Sopenharmony_ci 10*HZ)) { 64862306a36Sopenharmony_ci dbg_hid("timeout waiting for ctrl or out queue to clear\n"); 64962306a36Sopenharmony_ci return -1; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci return 0; 65362306a36Sopenharmony_ci} 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_cistatic int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 65862306a36Sopenharmony_ci HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, 65962306a36Sopenharmony_ci ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic int hid_get_class_descriptor(struct usb_device *dev, int ifnum, 66362306a36Sopenharmony_ci unsigned char type, void *buf, int size) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci int result, retries = 4; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci memset(buf, 0, size); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci do { 67062306a36Sopenharmony_ci result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 67162306a36Sopenharmony_ci USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, 67262306a36Sopenharmony_ci (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); 67362306a36Sopenharmony_ci retries--; 67462306a36Sopenharmony_ci } while (result < size && retries); 67562306a36Sopenharmony_ci return result; 67662306a36Sopenharmony_ci} 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_cistatic int usbhid_open(struct hid_device *hid) 67962306a36Sopenharmony_ci{ 68062306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 68162306a36Sopenharmony_ci int res; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci mutex_lock(&usbhid->mutex); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci set_bit(HID_OPENED, &usbhid->iofl); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { 68862306a36Sopenharmony_ci res = 0; 68962306a36Sopenharmony_ci goto Done; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci res = usb_autopm_get_interface(usbhid->intf); 69362306a36Sopenharmony_ci /* the device must be awake to reliably request remote wakeup */ 69462306a36Sopenharmony_ci if (res < 0) { 69562306a36Sopenharmony_ci clear_bit(HID_OPENED, &usbhid->iofl); 69662306a36Sopenharmony_ci res = -EIO; 69762306a36Sopenharmony_ci goto Done; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci usbhid->intf->needs_remote_wakeup = 1; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci set_bit(HID_RESUME_RUNNING, &usbhid->iofl); 70362306a36Sopenharmony_ci set_bit(HID_IN_POLLING, &usbhid->iofl); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci res = hid_start_in(hid); 70662306a36Sopenharmony_ci if (res) { 70762306a36Sopenharmony_ci if (res != -ENOSPC) { 70862306a36Sopenharmony_ci hid_io_error(hid); 70962306a36Sopenharmony_ci res = 0; 71062306a36Sopenharmony_ci } else { 71162306a36Sopenharmony_ci /* no use opening if resources are insufficient */ 71262306a36Sopenharmony_ci res = -EBUSY; 71362306a36Sopenharmony_ci clear_bit(HID_OPENED, &usbhid->iofl); 71462306a36Sopenharmony_ci clear_bit(HID_IN_POLLING, &usbhid->iofl); 71562306a36Sopenharmony_ci usbhid->intf->needs_remote_wakeup = 0; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci usb_autopm_put_interface(usbhid->intf); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci /* 72262306a36Sopenharmony_ci * In case events are generated while nobody was listening, 72362306a36Sopenharmony_ci * some are released when the device is re-opened. 72462306a36Sopenharmony_ci * Wait 50 msec for the queue to empty before allowing events 72562306a36Sopenharmony_ci * to go through hid. 72662306a36Sopenharmony_ci */ 72762306a36Sopenharmony_ci if (res == 0) 72862306a36Sopenharmony_ci msleep(50); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci Done: 73362306a36Sopenharmony_ci mutex_unlock(&usbhid->mutex); 73462306a36Sopenharmony_ci return res; 73562306a36Sopenharmony_ci} 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_cistatic void usbhid_close(struct hid_device *hid) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci mutex_lock(&usbhid->mutex); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci /* 74462306a36Sopenharmony_ci * Make sure we don't restart data acquisition due to 74562306a36Sopenharmony_ci * a resumption we no longer care about by avoiding racing 74662306a36Sopenharmony_ci * with hid_start_in(). 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 74962306a36Sopenharmony_ci clear_bit(HID_OPENED, &usbhid->iofl); 75062306a36Sopenharmony_ci if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) 75162306a36Sopenharmony_ci clear_bit(HID_IN_POLLING, &usbhid->iofl); 75262306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) { 75562306a36Sopenharmony_ci hid_cancel_delayed_stuff(usbhid); 75662306a36Sopenharmony_ci usb_kill_urb(usbhid->urbin); 75762306a36Sopenharmony_ci usbhid->intf->needs_remote_wakeup = 0; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci mutex_unlock(&usbhid->mutex); 76162306a36Sopenharmony_ci} 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci/* 76462306a36Sopenharmony_ci * Initialize all reports 76562306a36Sopenharmony_ci */ 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_civoid usbhid_init_reports(struct hid_device *hid) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci struct hid_report *report; 77062306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 77162306a36Sopenharmony_ci struct hid_report_enum *report_enum; 77262306a36Sopenharmony_ci int err, ret; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci report_enum = &hid->report_enum[HID_INPUT_REPORT]; 77562306a36Sopenharmony_ci list_for_each_entry(report, &report_enum->report_list, list) 77662306a36Sopenharmony_ci usbhid_submit_report(hid, report, USB_DIR_IN); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci report_enum = &hid->report_enum[HID_FEATURE_REPORT]; 77962306a36Sopenharmony_ci list_for_each_entry(report, &report_enum->report_list, list) 78062306a36Sopenharmony_ci usbhid_submit_report(hid, report, USB_DIR_IN); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci err = 0; 78362306a36Sopenharmony_ci ret = usbhid_wait_io(hid); 78462306a36Sopenharmony_ci while (ret) { 78562306a36Sopenharmony_ci err |= ret; 78662306a36Sopenharmony_ci if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 78762306a36Sopenharmony_ci usb_kill_urb(usbhid->urbctrl); 78862306a36Sopenharmony_ci if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) 78962306a36Sopenharmony_ci usb_kill_urb(usbhid->urbout); 79062306a36Sopenharmony_ci ret = usbhid_wait_io(hid); 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci if (err) 79462306a36Sopenharmony_ci hid_warn(hid, "timeout initializing reports\n"); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci/* 79862306a36Sopenharmony_ci * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01). 79962306a36Sopenharmony_ci */ 80062306a36Sopenharmony_cistatic int hid_find_field_early(struct hid_device *hid, unsigned int page, 80162306a36Sopenharmony_ci unsigned int hid_code, struct hid_field **pfield) 80262306a36Sopenharmony_ci{ 80362306a36Sopenharmony_ci struct hid_report *report; 80462306a36Sopenharmony_ci struct hid_field *field; 80562306a36Sopenharmony_ci struct hid_usage *usage; 80662306a36Sopenharmony_ci int i, j; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { 80962306a36Sopenharmony_ci for (i = 0; i < report->maxfield; i++) { 81062306a36Sopenharmony_ci field = report->field[i]; 81162306a36Sopenharmony_ci for (j = 0; j < field->maxusage; j++) { 81262306a36Sopenharmony_ci usage = &field->usage[j]; 81362306a36Sopenharmony_ci if ((usage->hid & HID_USAGE_PAGE) == page && 81462306a36Sopenharmony_ci (usage->hid & 0xFFFF) == hid_code) { 81562306a36Sopenharmony_ci *pfield = field; 81662306a36Sopenharmony_ci return j; 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci } 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci return -1; 82262306a36Sopenharmony_ci} 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_cistatic void usbhid_set_leds(struct hid_device *hid) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci struct hid_field *field; 82762306a36Sopenharmony_ci int offset; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci if ((offset = hid_find_field_early(hid, HID_UP_LED, 0x01, &field)) != -1) { 83062306a36Sopenharmony_ci hid_set_field(field, offset, 0); 83162306a36Sopenharmony_ci usbhid_submit_report(hid, field->report, USB_DIR_OUT); 83262306a36Sopenharmony_ci } 83362306a36Sopenharmony_ci} 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci/* 83662306a36Sopenharmony_ci * Traverse the supplied list of reports and find the longest 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_cistatic void hid_find_max_report(struct hid_device *hid, unsigned int type, 83962306a36Sopenharmony_ci unsigned int *max) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci struct hid_report *report; 84262306a36Sopenharmony_ci unsigned int size; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci list_for_each_entry(report, &hid->report_enum[type].report_list, list) { 84562306a36Sopenharmony_ci size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered; 84662306a36Sopenharmony_ci if (*max < size) 84762306a36Sopenharmony_ci *max = size; 84862306a36Sopenharmony_ci } 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, 85662306a36Sopenharmony_ci &usbhid->inbuf_dma); 85762306a36Sopenharmony_ci usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, 85862306a36Sopenharmony_ci &usbhid->outbuf_dma); 85962306a36Sopenharmony_ci usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL); 86062306a36Sopenharmony_ci usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL, 86162306a36Sopenharmony_ci &usbhid->ctrlbuf_dma); 86262306a36Sopenharmony_ci if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr || 86362306a36Sopenharmony_ci !usbhid->ctrlbuf) 86462306a36Sopenharmony_ci return -1; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci return 0; 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic int usbhid_get_raw_report(struct hid_device *hid, 87062306a36Sopenharmony_ci unsigned char report_number, __u8 *buf, size_t count, 87162306a36Sopenharmony_ci unsigned char report_type) 87262306a36Sopenharmony_ci{ 87362306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 87462306a36Sopenharmony_ci struct usb_device *dev = hid_to_usb_dev(hid); 87562306a36Sopenharmony_ci struct usb_interface *intf = usbhid->intf; 87662306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 87762306a36Sopenharmony_ci int skipped_report_id = 0; 87862306a36Sopenharmony_ci int ret; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci /* Byte 0 is the report number. Report data starts at byte 1.*/ 88162306a36Sopenharmony_ci buf[0] = report_number; 88262306a36Sopenharmony_ci if (report_number == 0x0) { 88362306a36Sopenharmony_ci /* Offset the return buffer by 1, so that the report ID 88462306a36Sopenharmony_ci will remain in byte 0. */ 88562306a36Sopenharmony_ci buf++; 88662306a36Sopenharmony_ci count--; 88762306a36Sopenharmony_ci skipped_report_id = 1; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 89062306a36Sopenharmony_ci HID_REQ_GET_REPORT, 89162306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 89262306a36Sopenharmony_ci ((report_type + 1) << 8) | report_number, 89362306a36Sopenharmony_ci interface->desc.bInterfaceNumber, buf, count, 89462306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* count also the report id */ 89762306a36Sopenharmony_ci if (ret > 0 && skipped_report_id) 89862306a36Sopenharmony_ci ret++; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci return ret; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_cistatic int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum, 90462306a36Sopenharmony_ci __u8 *buf, size_t count, unsigned char rtype) 90562306a36Sopenharmony_ci{ 90662306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 90762306a36Sopenharmony_ci struct usb_device *dev = hid_to_usb_dev(hid); 90862306a36Sopenharmony_ci struct usb_interface *intf = usbhid->intf; 90962306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 91062306a36Sopenharmony_ci int ret, skipped_report_id = 0; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci /* Byte 0 is the report number. Report data starts at byte 1.*/ 91362306a36Sopenharmony_ci if ((rtype == HID_OUTPUT_REPORT) && 91462306a36Sopenharmony_ci (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORT_ID)) 91562306a36Sopenharmony_ci buf[0] = 0; 91662306a36Sopenharmony_ci else 91762306a36Sopenharmony_ci buf[0] = reportnum; 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci if (buf[0] == 0x0) { 92062306a36Sopenharmony_ci /* Don't send the Report ID */ 92162306a36Sopenharmony_ci buf++; 92262306a36Sopenharmony_ci count--; 92362306a36Sopenharmony_ci skipped_report_id = 1; 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 92762306a36Sopenharmony_ci HID_REQ_SET_REPORT, 92862306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 92962306a36Sopenharmony_ci ((rtype + 1) << 8) | reportnum, 93062306a36Sopenharmony_ci interface->desc.bInterfaceNumber, buf, count, 93162306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 93262306a36Sopenharmony_ci /* count also the report id, if this was a numbered report. */ 93362306a36Sopenharmony_ci if (ret > 0 && skipped_report_id) 93462306a36Sopenharmony_ci ret++; 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci return ret; 93762306a36Sopenharmony_ci} 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_cistatic int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count) 94062306a36Sopenharmony_ci{ 94162306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 94262306a36Sopenharmony_ci struct usb_device *dev = hid_to_usb_dev(hid); 94362306a36Sopenharmony_ci int actual_length, skipped_report_id = 0, ret; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci if (!usbhid->urbout) 94662306a36Sopenharmony_ci return -ENOSYS; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci if (buf[0] == 0x0) { 94962306a36Sopenharmony_ci /* Don't send the Report ID */ 95062306a36Sopenharmony_ci buf++; 95162306a36Sopenharmony_ci count--; 95262306a36Sopenharmony_ci skipped_report_id = 1; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, 95662306a36Sopenharmony_ci buf, count, &actual_length, 95762306a36Sopenharmony_ci USB_CTRL_SET_TIMEOUT); 95862306a36Sopenharmony_ci /* return the number of bytes transferred */ 95962306a36Sopenharmony_ci if (ret == 0) { 96062306a36Sopenharmony_ci ret = actual_length; 96162306a36Sopenharmony_ci /* count also the report id */ 96262306a36Sopenharmony_ci if (skipped_report_id) 96362306a36Sopenharmony_ci ret++; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci return ret; 96762306a36Sopenharmony_ci} 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_cistatic void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) 97062306a36Sopenharmony_ci{ 97162306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); 97462306a36Sopenharmony_ci usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); 97562306a36Sopenharmony_ci kfree(usbhid->cr); 97662306a36Sopenharmony_ci usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic int usbhid_parse(struct hid_device *hid) 98062306a36Sopenharmony_ci{ 98162306a36Sopenharmony_ci struct usb_interface *intf = to_usb_interface(hid->dev.parent); 98262306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 98362306a36Sopenharmony_ci struct usb_device *dev = interface_to_usbdev (intf); 98462306a36Sopenharmony_ci struct hid_descriptor *hdesc; 98562306a36Sopenharmony_ci u32 quirks = 0; 98662306a36Sopenharmony_ci unsigned int rsize = 0; 98762306a36Sopenharmony_ci char *rdesc; 98862306a36Sopenharmony_ci int ret, n; 98962306a36Sopenharmony_ci int num_descriptors; 99062306a36Sopenharmony_ci size_t offset = offsetof(struct hid_descriptor, desc); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci quirks = hid_lookup_quirk(hid); 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (quirks & HID_QUIRK_IGNORE) 99562306a36Sopenharmony_ci return -ENODEV; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci /* Many keyboards and mice don't like to be polled for reports, 99862306a36Sopenharmony_ci * so we will always set the HID_QUIRK_NOGET flag for them. */ 99962306a36Sopenharmony_ci if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { 100062306a36Sopenharmony_ci if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || 100162306a36Sopenharmony_ci interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) 100262306a36Sopenharmony_ci quirks |= HID_QUIRK_NOGET; 100362306a36Sopenharmony_ci } 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && 100662306a36Sopenharmony_ci (!interface->desc.bNumEndpoints || 100762306a36Sopenharmony_ci usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { 100862306a36Sopenharmony_ci dbg_hid("class descriptor not present\n"); 100962306a36Sopenharmony_ci return -ENODEV; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci if (hdesc->bLength < sizeof(struct hid_descriptor)) { 101362306a36Sopenharmony_ci dbg_hid("hid descriptor is too short\n"); 101462306a36Sopenharmony_ci return -EINVAL; 101562306a36Sopenharmony_ci } 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci hid->version = le16_to_cpu(hdesc->bcdHID); 101862306a36Sopenharmony_ci hid->country = hdesc->bCountryCode; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci num_descriptors = min_t(int, hdesc->bNumDescriptors, 102162306a36Sopenharmony_ci (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci for (n = 0; n < num_descriptors; n++) 102462306a36Sopenharmony_ci if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) 102562306a36Sopenharmony_ci rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { 102862306a36Sopenharmony_ci dbg_hid("weird size of report descriptor (%u)\n", rsize); 102962306a36Sopenharmony_ci return -EINVAL; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci rdesc = kmalloc(rsize, GFP_KERNEL); 103362306a36Sopenharmony_ci if (!rdesc) 103462306a36Sopenharmony_ci return -ENOMEM; 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, 103962306a36Sopenharmony_ci HID_DT_REPORT, rdesc, rsize); 104062306a36Sopenharmony_ci if (ret < 0) { 104162306a36Sopenharmony_ci dbg_hid("reading report descriptor failed\n"); 104262306a36Sopenharmony_ci kfree(rdesc); 104362306a36Sopenharmony_ci goto err; 104462306a36Sopenharmony_ci } 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci ret = hid_parse_report(hid, rdesc, rsize); 104762306a36Sopenharmony_ci kfree(rdesc); 104862306a36Sopenharmony_ci if (ret) { 104962306a36Sopenharmony_ci dbg_hid("parsing report descriptor failed\n"); 105062306a36Sopenharmony_ci goto err; 105162306a36Sopenharmony_ci } 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci hid->quirks |= quirks; 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci return 0; 105662306a36Sopenharmony_cierr: 105762306a36Sopenharmony_ci return ret; 105862306a36Sopenharmony_ci} 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_cistatic int usbhid_start(struct hid_device *hid) 106162306a36Sopenharmony_ci{ 106262306a36Sopenharmony_ci struct usb_interface *intf = to_usb_interface(hid->dev.parent); 106362306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 106462306a36Sopenharmony_ci struct usb_device *dev = interface_to_usbdev(intf); 106562306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 106662306a36Sopenharmony_ci unsigned int n, insize = 0; 106762306a36Sopenharmony_ci int ret; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci mutex_lock(&usbhid->mutex); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci clear_bit(HID_DISCONNECTED, &usbhid->iofl); 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci usbhid->bufsize = HID_MIN_BUFFER_SIZE; 107462306a36Sopenharmony_ci hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); 107562306a36Sopenharmony_ci hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); 107662306a36Sopenharmony_ci hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) 107962306a36Sopenharmony_ci usbhid->bufsize = HID_MAX_BUFFER_SIZE; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci hid_find_max_report(hid, HID_INPUT_REPORT, &insize); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci if (insize > HID_MAX_BUFFER_SIZE) 108462306a36Sopenharmony_ci insize = HID_MAX_BUFFER_SIZE; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci if (hid_alloc_buffers(dev, hid)) { 108762306a36Sopenharmony_ci ret = -ENOMEM; 108862306a36Sopenharmony_ci goto fail; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci for (n = 0; n < interface->desc.bNumEndpoints; n++) { 109262306a36Sopenharmony_ci struct usb_endpoint_descriptor *endpoint; 109362306a36Sopenharmony_ci int pipe; 109462306a36Sopenharmony_ci int interval; 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci endpoint = &interface->endpoint[n].desc; 109762306a36Sopenharmony_ci if (!usb_endpoint_xfer_int(endpoint)) 109862306a36Sopenharmony_ci continue; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci interval = endpoint->bInterval; 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci /* Some vendors give fullspeed interval on highspeed devides */ 110362306a36Sopenharmony_ci if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL && 110462306a36Sopenharmony_ci dev->speed == USB_SPEED_HIGH) { 110562306a36Sopenharmony_ci interval = fls(endpoint->bInterval*8); 110662306a36Sopenharmony_ci pr_info("%s: Fixing fullspeed to highspeed interval: %d -> %d\n", 110762306a36Sopenharmony_ci hid->name, endpoint->bInterval, interval); 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci /* Change the polling interval of mice, joysticks 111162306a36Sopenharmony_ci * and keyboards. 111262306a36Sopenharmony_ci */ 111362306a36Sopenharmony_ci switch (hid->collection->usage) { 111462306a36Sopenharmony_ci case HID_GD_MOUSE: 111562306a36Sopenharmony_ci if (hid_mousepoll_interval > 0) 111662306a36Sopenharmony_ci interval = hid_mousepoll_interval; 111762306a36Sopenharmony_ci break; 111862306a36Sopenharmony_ci case HID_GD_JOYSTICK: 111962306a36Sopenharmony_ci if (hid_jspoll_interval > 0) 112062306a36Sopenharmony_ci interval = hid_jspoll_interval; 112162306a36Sopenharmony_ci break; 112262306a36Sopenharmony_ci case HID_GD_KEYBOARD: 112362306a36Sopenharmony_ci if (hid_kbpoll_interval > 0) 112462306a36Sopenharmony_ci interval = hid_kbpoll_interval; 112562306a36Sopenharmony_ci break; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci ret = -ENOMEM; 112962306a36Sopenharmony_ci if (usb_endpoint_dir_in(endpoint)) { 113062306a36Sopenharmony_ci if (usbhid->urbin) 113162306a36Sopenharmony_ci continue; 113262306a36Sopenharmony_ci if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) 113362306a36Sopenharmony_ci goto fail; 113462306a36Sopenharmony_ci pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); 113562306a36Sopenharmony_ci usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, 113662306a36Sopenharmony_ci hid_irq_in, hid, interval); 113762306a36Sopenharmony_ci usbhid->urbin->transfer_dma = usbhid->inbuf_dma; 113862306a36Sopenharmony_ci usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 113962306a36Sopenharmony_ci } else { 114062306a36Sopenharmony_ci if (usbhid->urbout) 114162306a36Sopenharmony_ci continue; 114262306a36Sopenharmony_ci if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) 114362306a36Sopenharmony_ci goto fail; 114462306a36Sopenharmony_ci pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); 114562306a36Sopenharmony_ci usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, 114662306a36Sopenharmony_ci hid_irq_out, hid, interval); 114762306a36Sopenharmony_ci usbhid->urbout->transfer_dma = usbhid->outbuf_dma; 114862306a36Sopenharmony_ci usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci } 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); 115362306a36Sopenharmony_ci if (!usbhid->urbctrl) { 115462306a36Sopenharmony_ci ret = -ENOMEM; 115562306a36Sopenharmony_ci goto fail; 115662306a36Sopenharmony_ci } 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, 115962306a36Sopenharmony_ci usbhid->ctrlbuf, 1, hid_ctrl, hid); 116062306a36Sopenharmony_ci usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; 116162306a36Sopenharmony_ci usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci set_bit(HID_STARTED, &usbhid->iofl); 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { 116662306a36Sopenharmony_ci ret = usb_autopm_get_interface(usbhid->intf); 116762306a36Sopenharmony_ci if (ret) 116862306a36Sopenharmony_ci goto fail; 116962306a36Sopenharmony_ci set_bit(HID_IN_POLLING, &usbhid->iofl); 117062306a36Sopenharmony_ci usbhid->intf->needs_remote_wakeup = 1; 117162306a36Sopenharmony_ci ret = hid_start_in(hid); 117262306a36Sopenharmony_ci if (ret) { 117362306a36Sopenharmony_ci dev_err(&hid->dev, 117462306a36Sopenharmony_ci "failed to start in urb: %d\n", ret); 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci usb_autopm_put_interface(usbhid->intf); 117762306a36Sopenharmony_ci } 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci /* Some keyboards don't work until their LEDs have been set. 118062306a36Sopenharmony_ci * Since BIOSes do set the LEDs, it must be safe for any device 118162306a36Sopenharmony_ci * that supports the keyboard boot protocol. 118262306a36Sopenharmony_ci * In addition, enable remote wakeup by default for all keyboard 118362306a36Sopenharmony_ci * devices supporting the boot protocol. 118462306a36Sopenharmony_ci */ 118562306a36Sopenharmony_ci if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && 118662306a36Sopenharmony_ci interface->desc.bInterfaceProtocol == 118762306a36Sopenharmony_ci USB_INTERFACE_PROTOCOL_KEYBOARD) { 118862306a36Sopenharmony_ci usbhid_set_leds(hid); 118962306a36Sopenharmony_ci device_set_wakeup_enable(&dev->dev, 1); 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci mutex_unlock(&usbhid->mutex); 119362306a36Sopenharmony_ci return 0; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_cifail: 119662306a36Sopenharmony_ci usb_free_urb(usbhid->urbin); 119762306a36Sopenharmony_ci usb_free_urb(usbhid->urbout); 119862306a36Sopenharmony_ci usb_free_urb(usbhid->urbctrl); 119962306a36Sopenharmony_ci usbhid->urbin = NULL; 120062306a36Sopenharmony_ci usbhid->urbout = NULL; 120162306a36Sopenharmony_ci usbhid->urbctrl = NULL; 120262306a36Sopenharmony_ci hid_free_buffers(dev, hid); 120362306a36Sopenharmony_ci mutex_unlock(&usbhid->mutex); 120462306a36Sopenharmony_ci return ret; 120562306a36Sopenharmony_ci} 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_cistatic void usbhid_stop(struct hid_device *hid) 120862306a36Sopenharmony_ci{ 120962306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci if (WARN_ON(!usbhid)) 121262306a36Sopenharmony_ci return; 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { 121562306a36Sopenharmony_ci clear_bit(HID_IN_POLLING, &usbhid->iofl); 121662306a36Sopenharmony_ci usbhid->intf->needs_remote_wakeup = 0; 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci mutex_lock(&usbhid->mutex); 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci clear_bit(HID_STARTED, &usbhid->iofl); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ 122462306a36Sopenharmony_ci set_bit(HID_DISCONNECTED, &usbhid->iofl); 122562306a36Sopenharmony_ci while (usbhid->ctrltail != usbhid->ctrlhead) { 122662306a36Sopenharmony_ci if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_OUT) { 122762306a36Sopenharmony_ci kfree(usbhid->ctrl[usbhid->ctrltail].raw_report); 122862306a36Sopenharmony_ci usbhid->ctrl[usbhid->ctrltail].raw_report = NULL; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci usbhid->ctrltail = (usbhid->ctrltail + 1) & 123262306a36Sopenharmony_ci (HID_CONTROL_FIFO_SIZE - 1); 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci usb_kill_urb(usbhid->urbin); 123762306a36Sopenharmony_ci usb_kill_urb(usbhid->urbout); 123862306a36Sopenharmony_ci usb_kill_urb(usbhid->urbctrl); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci hid_cancel_delayed_stuff(usbhid); 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci hid->claimed = 0; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci usb_free_urb(usbhid->urbin); 124562306a36Sopenharmony_ci usb_free_urb(usbhid->urbctrl); 124662306a36Sopenharmony_ci usb_free_urb(usbhid->urbout); 124762306a36Sopenharmony_ci usbhid->urbin = NULL; /* don't mess up next start */ 124862306a36Sopenharmony_ci usbhid->urbctrl = NULL; 124962306a36Sopenharmony_ci usbhid->urbout = NULL; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci hid_free_buffers(hid_to_usb_dev(hid), hid); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci mutex_unlock(&usbhid->mutex); 125462306a36Sopenharmony_ci} 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_cistatic int usbhid_power(struct hid_device *hid, int lvl) 125762306a36Sopenharmony_ci{ 125862306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 125962306a36Sopenharmony_ci int r = 0; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci switch (lvl) { 126262306a36Sopenharmony_ci case PM_HINT_FULLON: 126362306a36Sopenharmony_ci r = usb_autopm_get_interface(usbhid->intf); 126462306a36Sopenharmony_ci break; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci case PM_HINT_NORMAL: 126762306a36Sopenharmony_ci usb_autopm_put_interface(usbhid->intf); 126862306a36Sopenharmony_ci break; 126962306a36Sopenharmony_ci } 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci return r; 127262306a36Sopenharmony_ci} 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_cistatic void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype) 127562306a36Sopenharmony_ci{ 127662306a36Sopenharmony_ci switch (reqtype) { 127762306a36Sopenharmony_ci case HID_REQ_GET_REPORT: 127862306a36Sopenharmony_ci usbhid_submit_report(hid, rep, USB_DIR_IN); 127962306a36Sopenharmony_ci break; 128062306a36Sopenharmony_ci case HID_REQ_SET_REPORT: 128162306a36Sopenharmony_ci usbhid_submit_report(hid, rep, USB_DIR_OUT); 128262306a36Sopenharmony_ci break; 128362306a36Sopenharmony_ci } 128462306a36Sopenharmony_ci} 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistatic int usbhid_raw_request(struct hid_device *hid, unsigned char reportnum, 128762306a36Sopenharmony_ci __u8 *buf, size_t len, unsigned char rtype, 128862306a36Sopenharmony_ci int reqtype) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci switch (reqtype) { 129162306a36Sopenharmony_ci case HID_REQ_GET_REPORT: 129262306a36Sopenharmony_ci return usbhid_get_raw_report(hid, reportnum, buf, len, rtype); 129362306a36Sopenharmony_ci case HID_REQ_SET_REPORT: 129462306a36Sopenharmony_ci return usbhid_set_raw_report(hid, reportnum, buf, len, rtype); 129562306a36Sopenharmony_ci default: 129662306a36Sopenharmony_ci return -EIO; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci} 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_cistatic int usbhid_idle(struct hid_device *hid, int report, int idle, 130162306a36Sopenharmony_ci int reqtype) 130262306a36Sopenharmony_ci{ 130362306a36Sopenharmony_ci struct usb_device *dev = hid_to_usb_dev(hid); 130462306a36Sopenharmony_ci struct usb_interface *intf = to_usb_interface(hid->dev.parent); 130562306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 130662306a36Sopenharmony_ci int ifnum = interface->desc.bInterfaceNumber; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci if (reqtype != HID_REQ_SET_IDLE) 130962306a36Sopenharmony_ci return -EINVAL; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci return hid_set_idle(dev, ifnum, report, idle); 131262306a36Sopenharmony_ci} 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic bool usbhid_may_wakeup(struct hid_device *hid) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci struct usb_device *dev = hid_to_usb_dev(hid); 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci return device_may_wakeup(&dev->dev); 131962306a36Sopenharmony_ci} 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_cistatic const struct hid_ll_driver usb_hid_driver = { 132262306a36Sopenharmony_ci .parse = usbhid_parse, 132362306a36Sopenharmony_ci .start = usbhid_start, 132462306a36Sopenharmony_ci .stop = usbhid_stop, 132562306a36Sopenharmony_ci .open = usbhid_open, 132662306a36Sopenharmony_ci .close = usbhid_close, 132762306a36Sopenharmony_ci .power = usbhid_power, 132862306a36Sopenharmony_ci .request = usbhid_request, 132962306a36Sopenharmony_ci .wait = usbhid_wait_io, 133062306a36Sopenharmony_ci .raw_request = usbhid_raw_request, 133162306a36Sopenharmony_ci .output_report = usbhid_output_report, 133262306a36Sopenharmony_ci .idle = usbhid_idle, 133362306a36Sopenharmony_ci .may_wakeup = usbhid_may_wakeup, 133462306a36Sopenharmony_ci}; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_cibool hid_is_usb(const struct hid_device *hdev) 133762306a36Sopenharmony_ci{ 133862306a36Sopenharmony_ci return hdev->ll_driver == &usb_hid_driver; 133962306a36Sopenharmony_ci} 134062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hid_is_usb); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_cistatic int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) 134362306a36Sopenharmony_ci{ 134462306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 134562306a36Sopenharmony_ci struct usb_device *dev = interface_to_usbdev(intf); 134662306a36Sopenharmony_ci struct usbhid_device *usbhid; 134762306a36Sopenharmony_ci struct hid_device *hid; 134862306a36Sopenharmony_ci unsigned int n, has_in = 0; 134962306a36Sopenharmony_ci size_t len; 135062306a36Sopenharmony_ci int ret; 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci dbg_hid("HID probe called for ifnum %d\n", 135362306a36Sopenharmony_ci intf->altsetting->desc.bInterfaceNumber); 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_ci for (n = 0; n < interface->desc.bNumEndpoints; n++) 135662306a36Sopenharmony_ci if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) 135762306a36Sopenharmony_ci has_in++; 135862306a36Sopenharmony_ci if (!has_in) { 135962306a36Sopenharmony_ci hid_err(intf, "couldn't find an input interrupt endpoint\n"); 136062306a36Sopenharmony_ci return -ENODEV; 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci hid = hid_allocate_device(); 136462306a36Sopenharmony_ci if (IS_ERR(hid)) 136562306a36Sopenharmony_ci return PTR_ERR(hid); 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci usb_set_intfdata(intf, hid); 136862306a36Sopenharmony_ci hid->ll_driver = &usb_hid_driver; 136962306a36Sopenharmony_ci hid->ff_init = hid_pidff_init; 137062306a36Sopenharmony_ci#ifdef CONFIG_USB_HIDDEV 137162306a36Sopenharmony_ci hid->hiddev_connect = hiddev_connect; 137262306a36Sopenharmony_ci hid->hiddev_disconnect = hiddev_disconnect; 137362306a36Sopenharmony_ci hid->hiddev_hid_event = hiddev_hid_event; 137462306a36Sopenharmony_ci hid->hiddev_report_event = hiddev_report_event; 137562306a36Sopenharmony_ci#endif 137662306a36Sopenharmony_ci hid->dev.parent = &intf->dev; 137762306a36Sopenharmony_ci hid->bus = BUS_USB; 137862306a36Sopenharmony_ci hid->vendor = le16_to_cpu(dev->descriptor.idVendor); 137962306a36Sopenharmony_ci hid->product = le16_to_cpu(dev->descriptor.idProduct); 138062306a36Sopenharmony_ci hid->version = le16_to_cpu(dev->descriptor.bcdDevice); 138162306a36Sopenharmony_ci hid->name[0] = 0; 138262306a36Sopenharmony_ci if (intf->cur_altsetting->desc.bInterfaceProtocol == 138362306a36Sopenharmony_ci USB_INTERFACE_PROTOCOL_MOUSE) 138462306a36Sopenharmony_ci hid->type = HID_TYPE_USBMOUSE; 138562306a36Sopenharmony_ci else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0) 138662306a36Sopenharmony_ci hid->type = HID_TYPE_USBNONE; 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci if (dev->manufacturer) 138962306a36Sopenharmony_ci strscpy(hid->name, dev->manufacturer, sizeof(hid->name)); 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci if (dev->product) { 139262306a36Sopenharmony_ci if (dev->manufacturer) 139362306a36Sopenharmony_ci strlcat(hid->name, " ", sizeof(hid->name)); 139462306a36Sopenharmony_ci strlcat(hid->name, dev->product, sizeof(hid->name)); 139562306a36Sopenharmony_ci } 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (!strlen(hid->name)) 139862306a36Sopenharmony_ci snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", 139962306a36Sopenharmony_ci le16_to_cpu(dev->descriptor.idVendor), 140062306a36Sopenharmony_ci le16_to_cpu(dev->descriptor.idProduct)); 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci usb_make_path(dev, hid->phys, sizeof(hid->phys)); 140362306a36Sopenharmony_ci strlcat(hid->phys, "/input", sizeof(hid->phys)); 140462306a36Sopenharmony_ci len = strlen(hid->phys); 140562306a36Sopenharmony_ci if (len < sizeof(hid->phys) - 1) 140662306a36Sopenharmony_ci snprintf(hid->phys + len, sizeof(hid->phys) - len, 140762306a36Sopenharmony_ci "%d", intf->altsetting[0].desc.bInterfaceNumber); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) 141062306a36Sopenharmony_ci hid->uniq[0] = 0; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL); 141362306a36Sopenharmony_ci if (usbhid == NULL) { 141462306a36Sopenharmony_ci ret = -ENOMEM; 141562306a36Sopenharmony_ci goto err; 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci hid->driver_data = usbhid; 141962306a36Sopenharmony_ci usbhid->hid = hid; 142062306a36Sopenharmony_ci usbhid->intf = intf; 142162306a36Sopenharmony_ci usbhid->ifnum = interface->desc.bInterfaceNumber; 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci init_waitqueue_head(&usbhid->wait); 142462306a36Sopenharmony_ci INIT_WORK(&usbhid->reset_work, hid_reset); 142562306a36Sopenharmony_ci timer_setup(&usbhid->io_retry, hid_retry_timeout, 0); 142662306a36Sopenharmony_ci spin_lock_init(&usbhid->lock); 142762306a36Sopenharmony_ci mutex_init(&usbhid->mutex); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci ret = hid_add_device(hid); 143062306a36Sopenharmony_ci if (ret) { 143162306a36Sopenharmony_ci if (ret != -ENODEV) 143262306a36Sopenharmony_ci hid_err(intf, "can't add hid device: %d\n", ret); 143362306a36Sopenharmony_ci goto err_free; 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci return 0; 143762306a36Sopenharmony_cierr_free: 143862306a36Sopenharmony_ci kfree(usbhid); 143962306a36Sopenharmony_cierr: 144062306a36Sopenharmony_ci hid_destroy_device(hid); 144162306a36Sopenharmony_ci return ret; 144262306a36Sopenharmony_ci} 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_cistatic void usbhid_disconnect(struct usb_interface *intf) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(intf); 144762306a36Sopenharmony_ci struct usbhid_device *usbhid; 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci if (WARN_ON(!hid)) 145062306a36Sopenharmony_ci return; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci usbhid = hid->driver_data; 145362306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ 145462306a36Sopenharmony_ci set_bit(HID_DISCONNECTED, &usbhid->iofl); 145562306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 145662306a36Sopenharmony_ci hid_destroy_device(hid); 145762306a36Sopenharmony_ci kfree(usbhid); 145862306a36Sopenharmony_ci} 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_cistatic void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) 146162306a36Sopenharmony_ci{ 146262306a36Sopenharmony_ci del_timer_sync(&usbhid->io_retry); 146362306a36Sopenharmony_ci cancel_work_sync(&usbhid->reset_work); 146462306a36Sopenharmony_ci} 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_cistatic void hid_cease_io(struct usbhid_device *usbhid) 146762306a36Sopenharmony_ci{ 146862306a36Sopenharmony_ci del_timer_sync(&usbhid->io_retry); 146962306a36Sopenharmony_ci usb_kill_urb(usbhid->urbin); 147062306a36Sopenharmony_ci usb_kill_urb(usbhid->urbctrl); 147162306a36Sopenharmony_ci usb_kill_urb(usbhid->urbout); 147262306a36Sopenharmony_ci} 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_cistatic void hid_restart_io(struct hid_device *hid) 147562306a36Sopenharmony_ci{ 147662306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 147762306a36Sopenharmony_ci int clear_halt = test_bit(HID_CLEAR_HALT, &usbhid->iofl); 147862306a36Sopenharmony_ci int reset_pending = test_bit(HID_RESET_PENDING, &usbhid->iofl); 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 148162306a36Sopenharmony_ci clear_bit(HID_SUSPENDED, &usbhid->iofl); 148262306a36Sopenharmony_ci usbhid_mark_busy(usbhid); 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci if (clear_halt || reset_pending) 148562306a36Sopenharmony_ci schedule_work(&usbhid->reset_work); 148662306a36Sopenharmony_ci usbhid->retry_delay = 0; 148762306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci if (reset_pending || !test_bit(HID_STARTED, &usbhid->iofl)) 149062306a36Sopenharmony_ci return; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci if (!clear_halt) { 149362306a36Sopenharmony_ci if (hid_start_in(hid) < 0) 149462306a36Sopenharmony_ci hid_io_error(hid); 149562306a36Sopenharmony_ci } 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 149862306a36Sopenharmony_ci if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) 149962306a36Sopenharmony_ci usbhid_restart_out_queue(usbhid); 150062306a36Sopenharmony_ci if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) 150162306a36Sopenharmony_ci usbhid_restart_ctrl_queue(usbhid); 150262306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 150362306a36Sopenharmony_ci} 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci/* Treat USB reset pretty much the same as suspend/resume */ 150662306a36Sopenharmony_cistatic int hid_pre_reset(struct usb_interface *intf) 150762306a36Sopenharmony_ci{ 150862306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(intf); 150962306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 151262306a36Sopenharmony_ci set_bit(HID_RESET_PENDING, &usbhid->iofl); 151362306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 151462306a36Sopenharmony_ci hid_cease_io(usbhid); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci return 0; 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci/* Same routine used for post_reset and reset_resume */ 152062306a36Sopenharmony_cistatic int hid_post_reset(struct usb_interface *intf) 152162306a36Sopenharmony_ci{ 152262306a36Sopenharmony_ci struct usb_device *dev = interface_to_usbdev (intf); 152362306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(intf); 152462306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 152562306a36Sopenharmony_ci struct usb_host_interface *interface = intf->cur_altsetting; 152662306a36Sopenharmony_ci int status; 152762306a36Sopenharmony_ci char *rdesc; 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci /* Fetch and examine the HID report descriptor. If this 153062306a36Sopenharmony_ci * has changed, then rebind. Since usbcore's check of the 153162306a36Sopenharmony_ci * configuration descriptors passed, we already know that 153262306a36Sopenharmony_ci * the size of the HID report descriptor has not changed. 153362306a36Sopenharmony_ci */ 153462306a36Sopenharmony_ci rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL); 153562306a36Sopenharmony_ci if (!rdesc) 153662306a36Sopenharmony_ci return -ENOMEM; 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_ci status = hid_get_class_descriptor(dev, 153962306a36Sopenharmony_ci interface->desc.bInterfaceNumber, 154062306a36Sopenharmony_ci HID_DT_REPORT, rdesc, hid->dev_rsize); 154162306a36Sopenharmony_ci if (status < 0) { 154262306a36Sopenharmony_ci dbg_hid("reading report descriptor failed (post_reset)\n"); 154362306a36Sopenharmony_ci kfree(rdesc); 154462306a36Sopenharmony_ci return status; 154562306a36Sopenharmony_ci } 154662306a36Sopenharmony_ci status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize); 154762306a36Sopenharmony_ci kfree(rdesc); 154862306a36Sopenharmony_ci if (status != 0) { 154962306a36Sopenharmony_ci dbg_hid("report descriptor changed\n"); 155062306a36Sopenharmony_ci return -EPERM; 155162306a36Sopenharmony_ci } 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* No need to do another reset or clear a halted endpoint */ 155462306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 155562306a36Sopenharmony_ci clear_bit(HID_RESET_PENDING, &usbhid->iofl); 155662306a36Sopenharmony_ci clear_bit(HID_CLEAR_HALT, &usbhid->iofl); 155762306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 155862306a36Sopenharmony_ci hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci hid_restart_io(hid); 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci return 0; 156362306a36Sopenharmony_ci} 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci#ifdef CONFIG_PM 156662306a36Sopenharmony_cistatic int hid_resume_common(struct hid_device *hid, bool driver_suspended) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci int status = 0; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci hid_restart_io(hid); 157162306a36Sopenharmony_ci if (driver_suspended) 157262306a36Sopenharmony_ci status = hid_driver_resume(hid); 157362306a36Sopenharmony_ci return status; 157462306a36Sopenharmony_ci} 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_cistatic int hid_suspend(struct usb_interface *intf, pm_message_t message) 157762306a36Sopenharmony_ci{ 157862306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(intf); 157962306a36Sopenharmony_ci struct usbhid_device *usbhid = hid->driver_data; 158062306a36Sopenharmony_ci int status = 0; 158162306a36Sopenharmony_ci bool driver_suspended = false; 158262306a36Sopenharmony_ci unsigned int ledcount; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci if (PMSG_IS_AUTO(message)) { 158562306a36Sopenharmony_ci ledcount = hidinput_count_leds(hid); 158662306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); /* Sync with error handler */ 158762306a36Sopenharmony_ci if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) 158862306a36Sopenharmony_ci && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) 158962306a36Sopenharmony_ci && !test_bit(HID_OUT_RUNNING, &usbhid->iofl) 159062306a36Sopenharmony_ci && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl) 159162306a36Sopenharmony_ci && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) 159262306a36Sopenharmony_ci && (!ledcount || ignoreled)) 159362306a36Sopenharmony_ci { 159462306a36Sopenharmony_ci set_bit(HID_SUSPENDED, &usbhid->iofl); 159562306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 159662306a36Sopenharmony_ci status = hid_driver_suspend(hid, message); 159762306a36Sopenharmony_ci if (status < 0) 159862306a36Sopenharmony_ci goto failed; 159962306a36Sopenharmony_ci driver_suspended = true; 160062306a36Sopenharmony_ci } else { 160162306a36Sopenharmony_ci usbhid_mark_busy(usbhid); 160262306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 160362306a36Sopenharmony_ci return -EBUSY; 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_ci } else { 160762306a36Sopenharmony_ci /* TODO: resume() might need to handle suspend failure */ 160862306a36Sopenharmony_ci status = hid_driver_suspend(hid, message); 160962306a36Sopenharmony_ci driver_suspended = true; 161062306a36Sopenharmony_ci spin_lock_irq(&usbhid->lock); 161162306a36Sopenharmony_ci set_bit(HID_SUSPENDED, &usbhid->iofl); 161262306a36Sopenharmony_ci spin_unlock_irq(&usbhid->lock); 161362306a36Sopenharmony_ci if (usbhid_wait_io(hid) < 0) 161462306a36Sopenharmony_ci status = -EIO; 161562306a36Sopenharmony_ci } 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci hid_cancel_delayed_stuff(usbhid); 161862306a36Sopenharmony_ci hid_cease_io(usbhid); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { 162162306a36Sopenharmony_ci /* lost race against keypresses */ 162262306a36Sopenharmony_ci status = -EBUSY; 162362306a36Sopenharmony_ci goto failed; 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci dev_dbg(&intf->dev, "suspend\n"); 162662306a36Sopenharmony_ci return status; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci failed: 162962306a36Sopenharmony_ci hid_resume_common(hid, driver_suspended); 163062306a36Sopenharmony_ci return status; 163162306a36Sopenharmony_ci} 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_cistatic int hid_resume(struct usb_interface *intf) 163462306a36Sopenharmony_ci{ 163562306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata (intf); 163662306a36Sopenharmony_ci int status; 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci status = hid_resume_common(hid, true); 163962306a36Sopenharmony_ci dev_dbg(&intf->dev, "resume status %d\n", status); 164062306a36Sopenharmony_ci return 0; 164162306a36Sopenharmony_ci} 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_cistatic int hid_reset_resume(struct usb_interface *intf) 164462306a36Sopenharmony_ci{ 164562306a36Sopenharmony_ci struct hid_device *hid = usb_get_intfdata(intf); 164662306a36Sopenharmony_ci int status; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci status = hid_post_reset(intf); 164962306a36Sopenharmony_ci if (status >= 0) { 165062306a36Sopenharmony_ci int ret = hid_driver_reset_resume(hid); 165162306a36Sopenharmony_ci if (ret < 0) 165262306a36Sopenharmony_ci status = ret; 165362306a36Sopenharmony_ci } 165462306a36Sopenharmony_ci return status; 165562306a36Sopenharmony_ci} 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci#endif /* CONFIG_PM */ 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_cistatic const struct usb_device_id hid_usb_ids[] = { 166062306a36Sopenharmony_ci { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, 166162306a36Sopenharmony_ci .bInterfaceClass = USB_INTERFACE_CLASS_HID }, 166262306a36Sopenharmony_ci { } /* Terminating entry */ 166362306a36Sopenharmony_ci}; 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ciMODULE_DEVICE_TABLE (usb, hid_usb_ids); 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_cistatic struct usb_driver hid_driver = { 166862306a36Sopenharmony_ci .name = "usbhid", 166962306a36Sopenharmony_ci .probe = usbhid_probe, 167062306a36Sopenharmony_ci .disconnect = usbhid_disconnect, 167162306a36Sopenharmony_ci#ifdef CONFIG_PM 167262306a36Sopenharmony_ci .suspend = hid_suspend, 167362306a36Sopenharmony_ci .resume = hid_resume, 167462306a36Sopenharmony_ci .reset_resume = hid_reset_resume, 167562306a36Sopenharmony_ci#endif 167662306a36Sopenharmony_ci .pre_reset = hid_pre_reset, 167762306a36Sopenharmony_ci .post_reset = hid_post_reset, 167862306a36Sopenharmony_ci .id_table = hid_usb_ids, 167962306a36Sopenharmony_ci .supports_autosuspend = 1, 168062306a36Sopenharmony_ci}; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_cistruct usb_interface *usbhid_find_interface(int minor) 168362306a36Sopenharmony_ci{ 168462306a36Sopenharmony_ci return usb_find_interface(&hid_driver, minor); 168562306a36Sopenharmony_ci} 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_cistatic int __init hid_init(void) 168862306a36Sopenharmony_ci{ 168962306a36Sopenharmony_ci int retval; 169062306a36Sopenharmony_ci 169162306a36Sopenharmony_ci retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS); 169262306a36Sopenharmony_ci if (retval) 169362306a36Sopenharmony_ci goto usbhid_quirks_init_fail; 169462306a36Sopenharmony_ci retval = usb_register(&hid_driver); 169562306a36Sopenharmony_ci if (retval) 169662306a36Sopenharmony_ci goto usb_register_fail; 169762306a36Sopenharmony_ci pr_info(KBUILD_MODNAME ": " DRIVER_DESC "\n"); 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci return 0; 170062306a36Sopenharmony_ciusb_register_fail: 170162306a36Sopenharmony_ci hid_quirks_exit(BUS_USB); 170262306a36Sopenharmony_ciusbhid_quirks_init_fail: 170362306a36Sopenharmony_ci return retval; 170462306a36Sopenharmony_ci} 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_cistatic void __exit hid_exit(void) 170762306a36Sopenharmony_ci{ 170862306a36Sopenharmony_ci usb_deregister(&hid_driver); 170962306a36Sopenharmony_ci hid_quirks_exit(BUS_USB); 171062306a36Sopenharmony_ci} 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_cimodule_init(hid_init); 171362306a36Sopenharmony_cimodule_exit(hid_exit); 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ciMODULE_AUTHOR("Andreas Gal"); 171662306a36Sopenharmony_ciMODULE_AUTHOR("Vojtech Pavlik"); 171762306a36Sopenharmony_ciMODULE_AUTHOR("Jiri Kosina"); 171862306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC); 171962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1720