aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-input.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2013-03-22 13:38:28 -0400
committerJiri Kosina <jkosina@suse.cz>2013-03-27 09:02:45 -0400
commit4f22decf9b6329acfe59091c5cba6b378b9b31db (patch)
treefddbec2a0158f8d93cfe6fc886d459b3c2f81664 /drivers/hid/hid-input.c
parentb3fecf8cab6441527ab057c99d7e6a6d7f6713e5 (diff)
HID: input: don't register unmapped input devices
There is no need to register an input device containing no events. This allows drivers using the quirk MULTI_INPUT to register one input per report effectively used. For backward compatibility, we need to add a quirk to request this behavior. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r--drivers/hid/hid-input.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 21b196c394b1..945b8158ec4c 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
1198 return hidinput; 1198 return hidinput;
1199} 1199}
1200 1200
1201static bool hidinput_has_been_populated(struct hid_input *hidinput)
1202{
1203 int i;
1204 unsigned long r = 0;
1205
1206 for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++)
1207 r |= hidinput->input->evbit[i];
1208
1209 for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
1210 r |= hidinput->input->keybit[i];
1211
1212 for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
1213 r |= hidinput->input->relbit[i];
1214
1215 for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
1216 r |= hidinput->input->absbit[i];
1217
1218 for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
1219 r |= hidinput->input->mscbit[i];
1220
1221 for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++)
1222 r |= hidinput->input->ledbit[i];
1223
1224 for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++)
1225 r |= hidinput->input->sndbit[i];
1226
1227 for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++)
1228 r |= hidinput->input->ffbit[i];
1229
1230 for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++)
1231 r |= hidinput->input->swbit[i];
1232
1233 return !!r;
1234}
1235
1236static void hidinput_cleanup_hidinput(struct hid_device *hid,
1237 struct hid_input *hidinput)
1238{
1239 struct hid_report *report;
1240 int i, k;
1241
1242 list_del(&hidinput->list);
1243 input_free_device(hidinput->input);
1244
1245 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
1246 if (k == HID_OUTPUT_REPORT &&
1247 hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
1248 continue;
1249
1250 list_for_each_entry(report, &hid->report_enum[k].report_list,
1251 list) {
1252
1253 for (i = 0; i < report->maxfield; i++)
1254 if (report->field[i]->hidinput == hidinput)
1255 report->field[i]->hidinput = NULL;
1256 }
1257 }
1258
1259 kfree(hidinput);
1260}
1261
1201/* 1262/*
1202 * Register the input device; print a message. 1263 * Register the input device; print a message.
1203 * Configure the input layer interface 1264 * Configure the input layer interface
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
1249 hidinput_configure_usage(hidinput, report->field[i], 1310 hidinput_configure_usage(hidinput, report->field[i],
1250 report->field[i]->usage + j); 1311 report->field[i]->usage + j);
1251 1312
1313 if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
1314 !hidinput_has_been_populated(hidinput))
1315 continue;
1316
1252 if (hid->quirks & HID_QUIRK_MULTI_INPUT) { 1317 if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
1253 /* This will leave hidinput NULL, so that it 1318 /* This will leave hidinput NULL, so that it
1254 * allocates another one if we have more inputs on 1319 * allocates another one if we have more inputs on
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
1265 } 1330 }
1266 } 1331 }
1267 1332
1333 if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
1334 !hidinput_has_been_populated(hidinput)) {
1335 /* no need to register an input device not populated */
1336 hidinput_cleanup_hidinput(hid, hidinput);
1337 hidinput = NULL;
1338 }
1339
1340 if (list_empty(&hid->inputs)) {
1341 hid_err(hid, "No inputs registered, leaving\n");
1342 goto out_unwind;
1343 }
1344
1268 if (hidinput) { 1345 if (hidinput) {
1269 if (drv->input_configured) 1346 if (drv->input_configured)
1270 drv->input_configured(hid, hidinput); 1347 drv->input_configured(hid, hidinput);