diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2013-03-22 13:38:28 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-03-27 09:02:45 -0400 |
commit | 4f22decf9b6329acfe59091c5cba6b378b9b31db (patch) | |
tree | fddbec2a0158f8d93cfe6fc886d459b3c2f81664 /drivers/hid/hid-input.c | |
parent | b3fecf8cab6441527ab057c99d7e6a6d7f6713e5 (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.c | 77 |
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 | ||
1201 | static 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 | |||
1236 | static 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); |