|
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
|
|
|
return hidinput;
|
|
|
}
|
|
|
|
|
|
+static bool hidinput_has_been_populated(struct hid_input *hidinput)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ unsigned long r = 0;
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++)
|
|
|
+ r |= hidinput->input->evbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
|
|
|
+ r |= hidinput->input->keybit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
|
|
|
+ r |= hidinput->input->relbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
|
|
|
+ r |= hidinput->input->absbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
|
|
|
+ r |= hidinput->input->mscbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++)
|
|
|
+ r |= hidinput->input->ledbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++)
|
|
|
+ r |= hidinput->input->sndbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++)
|
|
|
+ r |= hidinput->input->ffbit[i];
|
|
|
+
|
|
|
+ for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++)
|
|
|
+ r |= hidinput->input->swbit[i];
|
|
|
+
|
|
|
+ return !!r;
|
|
|
+}
|
|
|
+
|
|
|
+static void hidinput_cleanup_hidinput(struct hid_device *hid,
|
|
|
+ struct hid_input *hidinput)
|
|
|
+{
|
|
|
+ struct hid_report *report;
|
|
|
+ int i, k;
|
|
|
+
|
|
|
+ list_del(&hidinput->list);
|
|
|
+ input_free_device(hidinput->input);
|
|
|
+
|
|
|
+ for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
|
|
|
+ if (k == HID_OUTPUT_REPORT &&
|
|
|
+ hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ list_for_each_entry(report, &hid->report_enum[k].report_list,
|
|
|
+ list) {
|
|
|
+
|
|
|
+ for (i = 0; i < report->maxfield; i++)
|
|
|
+ if (report->field[i]->hidinput == hidinput)
|
|
|
+ report->field[i]->hidinput = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ kfree(hidinput);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Register the input device; print a message.
|
|
|
* Configure the input layer interface
|
|
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
|
|
hidinput_configure_usage(hidinput, report->field[i],
|
|
|
report->field[i]->usage + j);
|
|
|
|
|
|
+ if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
|
|
+ !hidinput_has_been_populated(hidinput))
|
|
|
+ continue;
|
|
|
+
|
|
|
if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
|
|
|
/* This will leave hidinput NULL, so that it
|
|
|
* allocates another one if we have more inputs on
|
|
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
|
|
+ !hidinput_has_been_populated(hidinput)) {
|
|
|
+ /* no need to register an input device not populated */
|
|
|
+ hidinput_cleanup_hidinput(hid, hidinput);
|
|
|
+ hidinput = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (list_empty(&hid->inputs)) {
|
|
|
+ hid_err(hid, "No inputs registered, leaving\n");
|
|
|
+ goto out_unwind;
|
|
|
+ }
|
|
|
+
|
|
|
if (hidinput) {
|
|
|
if (drv->input_configured)
|
|
|
drv->input_configured(hid, hidinput);
|