aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/hid.h
diff options
context:
space:
mode:
authorAndrew de los Reyes <adlr@chromium.org>2013-02-18 12:20:21 -0500
committerJiri Kosina <jkosina@suse.cz>2013-03-01 08:13:07 -0500
commitc849a6143bec520aff2a6646518b0d041402428b (patch)
tree95da329533d67acdd1ee0152a6212346062707a5 /include/linux/hid.h
parent48a732dfaa77a4dfec803aa8f248373998704f76 (diff)
HID: Separate struct hid_device's driver_lock into two locks.
This patch separates struct hid_device's driver_lock into two. The goal is to allow hid device drivers to receive input during their probe() or remove() function calls. This is necessary because some drivers need to communicate with the device to determine parameters needed during probe (e.g., size of a multi-touch surface), and if possible, may perfer to communicate with a device on host-initiated disconnect (e.g., to put it into a low-power state). Historically, three functions used driver_lock: - hid_device_probe: blocks to acquire lock - hid_device_remove: blocks to acquire lock - hid_input_report: if locked returns -EBUSY, else acquires lock This patch adds another lock (driver_input_lock) which is used to block input from occurring. The lock behavior is now: - hid_device_probe: blocks to acq. driver_lock, then driver_input_lock - hid_device_remove: blocks to acq. driver_lock, then driver_input_lock - hid_input_report: if driver_input_lock locked returns -EBUSY, else acquires driver_input_lock This patch also adds two helper functions to be called during probe() or remove(): hid_device_io_start() and hid_device_io_stop(). These functions lock and unlock, respectively, driver_input_lock; they also make a note of whether they did so that hid-core knows if a driver has changed the lock state. This patch results in no behavior change for existing devices and drivers. However, during a probe() or remove() function call in a driver, that driver may now selectively call hid_device_io_start() to let input events come through, then optionally call hid_device_io_stop() to stop them. Signed-off-by: Andrew de los Reyes <adlr@chromium.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'include/linux/hid.h')
-rw-r--r--include/linux/hid.h46
1 files changed, 45 insertions, 1 deletions
diff --git a/include/linux/hid.h b/include/linux/hid.h
index e14b465b1146..895b85639dec 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -456,7 +456,8 @@ struct hid_device { /* device report descriptor */
456 unsigned country; /* HID country */ 456 unsigned country; /* HID country */
457 struct hid_report_enum report_enum[HID_REPORT_TYPES]; 457 struct hid_report_enum report_enum[HID_REPORT_TYPES];
458 458
459 struct semaphore driver_lock; /* protects the current driver */ 459 struct semaphore driver_lock; /* protects the current driver, except during input */
460 struct semaphore driver_input_lock; /* protects the current driver */
460 struct device dev; /* device */ 461 struct device dev; /* device */
461 struct hid_driver *driver; 462 struct hid_driver *driver;
462 struct hid_ll_driver *ll_driver; 463 struct hid_ll_driver *ll_driver;
@@ -477,6 +478,7 @@ struct hid_device { /* device report descriptor */
477 unsigned int status; /* see STAT flags above */ 478 unsigned int status; /* see STAT flags above */
478 unsigned claimed; /* Claimed by hidinput, hiddev? */ 479 unsigned claimed; /* Claimed by hidinput, hiddev? */
479 unsigned quirks; /* Various quirks the device can pull on us */ 480 unsigned quirks; /* Various quirks the device can pull on us */
481 bool io_started; /* Protected by driver_lock. If IO has started */
480 482
481 struct list_head inputs; /* The list of inputs */ 483 struct list_head inputs; /* The list of inputs */
482 void *hiddev; /* The hiddev structure */ 484 void *hiddev; /* The hiddev structure */
@@ -599,6 +601,10 @@ struct hid_usage_id {
599 * @resume: invoked on resume if device was not reset (NULL means nop) 601 * @resume: invoked on resume if device was not reset (NULL means nop)
600 * @reset_resume: invoked on resume if device was reset (NULL means nop) 602 * @reset_resume: invoked on resume if device was reset (NULL means nop)
601 * 603 *
604 * probe should return -errno on error, or 0 on success. During probe,
605 * input will not be passed to raw_event unless hid_device_io_start is
606 * called.
607 *
602 * raw_event and event should return 0 on no action performed, 1 when no 608 * raw_event and event should return 0 on no action performed, 1 when no
603 * further processing should be done and negative on error 609 * further processing should be done and negative on error
604 * 610 *
@@ -738,6 +744,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev,
738s32 hid_snto32(__u32 value, unsigned n); 744s32 hid_snto32(__u32 value, unsigned n);
739 745
740/** 746/**
747 * hid_device_io_start - enable HID input during probe, remove
748 *
749 * @hid - the device
750 *
751 * This should only be called during probe or remove and only be
752 * called by the thread calling probe or remove. It will allow
753 * incoming packets to be delivered to the driver.
754 */
755static inline void hid_device_io_start(struct hid_device *hid) {
756 if (hid->io_started) {
757 dev_warn(&hid->dev, "io already started");
758 return;
759 }
760 hid->io_started = true;
761 up(&hid->driver_input_lock);
762}
763
764/**
765 * hid_device_io_stop - disable HID input during probe, remove
766 *
767 * @hid - the device
768 *
769 * Should only be called after hid_device_io_start. It will prevent
770 * incoming packets from going to the driver for the duration of
771 * probe, remove. If called during probe, packets will still go to the
772 * driver after probe is complete. This function should only be called
773 * by the thread calling probe or remove.
774 */
775static inline void hid_device_io_stop(struct hid_device *hid) {
776 if (!hid->io_started) {
777 dev_warn(&hid->dev, "io already stopped");
778 return;
779 }
780 hid->io_started = false;
781 down(&hid->driver_input_lock);
782}
783
784/**
741 * hid_map_usage - map usage input bits 785 * hid_map_usage - map usage input bits
742 * 786 *
743 * @hidinput: hidinput which we are interested in 787 * @hidinput: hidinput which we are interested in