diff options
Diffstat (limited to 'drivers/hid/hid-core.c')
| -rw-r--r-- | drivers/hid/hid-core.c | 120 |
1 files changed, 109 insertions, 11 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 40df3e1b4bd..5d7640e49dc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | ||
| 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| 1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
| 1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
| 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
| 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
| 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | ||
| 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | ||
| 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
| 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
| 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
| 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
| 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, |
| 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | ||
| 1272 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
| 1273 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
| 1274 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
| @@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, | 1276 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, |
| 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, | 1277 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, |
| 1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, | 1278 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, |
| 1282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) }, | ||
| 1283 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, | 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, |
| 1284 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, |
| 1285 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | 1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, |
| @@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, |
| 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
| 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
| 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, | ||
| 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
| 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1302 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
| 1303 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
| 1304 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
| 1302 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | ||
| 1305 | 1303 | ||
| 1306 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, | 1304 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, |
| 1307 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, | 1305 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
| 1308 | { } | 1306 | { } |
| 1309 | }; | 1307 | }; |
| 1310 | 1308 | ||
| 1309 | struct hid_dynid { | ||
| 1310 | struct list_head list; | ||
| 1311 | struct hid_device_id id; | ||
| 1312 | }; | ||
| 1313 | |||
| 1314 | /** | ||
| 1315 | * store_new_id - add a new HID device ID to this driver and re-probe devices | ||
| 1316 | * @driver: target device driver | ||
| 1317 | * @buf: buffer for scanning device ID data | ||
| 1318 | * @count: input size | ||
| 1319 | * | ||
| 1320 | * Adds a new dynamic hid device ID to this driver, | ||
| 1321 | * and causes the driver to probe for all devices again. | ||
| 1322 | */ | ||
| 1323 | static ssize_t store_new_id(struct device_driver *drv, const char *buf, | ||
| 1324 | size_t count) | ||
| 1325 | { | ||
| 1326 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | ||
| 1327 | struct hid_dynid *dynid; | ||
| 1328 | __u32 bus, vendor, product; | ||
| 1329 | unsigned long driver_data = 0; | ||
| 1330 | int ret; | ||
| 1331 | |||
| 1332 | ret = sscanf(buf, "%x %x %x %lx", | ||
| 1333 | &bus, &vendor, &product, &driver_data); | ||
| 1334 | if (ret < 3) | ||
| 1335 | return -EINVAL; | ||
| 1336 | |||
| 1337 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); | ||
| 1338 | if (!dynid) | ||
| 1339 | return -ENOMEM; | ||
| 1340 | |||
| 1341 | dynid->id.bus = bus; | ||
| 1342 | dynid->id.vendor = vendor; | ||
| 1343 | dynid->id.product = product; | ||
| 1344 | dynid->id.driver_data = driver_data; | ||
| 1345 | |||
| 1346 | spin_lock(&hdrv->dyn_lock); | ||
| 1347 | list_add_tail(&dynid->list, &hdrv->dyn_list); | ||
| 1348 | spin_unlock(&hdrv->dyn_lock); | ||
| 1349 | |||
| 1350 | ret = 0; | ||
| 1351 | if (get_driver(&hdrv->driver)) { | ||
| 1352 | ret = driver_attach(&hdrv->driver); | ||
| 1353 | put_driver(&hdrv->driver); | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | return ret ? : count; | ||
| 1357 | } | ||
| 1358 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | ||
| 1359 | |||
| 1360 | static void hid_free_dynids(struct hid_driver *hdrv) | ||
| 1361 | { | ||
| 1362 | struct hid_dynid *dynid, *n; | ||
| 1363 | |||
| 1364 | spin_lock(&hdrv->dyn_lock); | ||
| 1365 | list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) { | ||
| 1366 | list_del(&dynid->list); | ||
| 1367 | kfree(dynid); | ||
| 1368 | } | ||
| 1369 | spin_unlock(&hdrv->dyn_lock); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | static const struct hid_device_id *hid_match_device(struct hid_device *hdev, | ||
| 1373 | struct hid_driver *hdrv) | ||
| 1374 | { | ||
| 1375 | struct hid_dynid *dynid; | ||
| 1376 | |||
| 1377 | spin_lock(&hdrv->dyn_lock); | ||
| 1378 | list_for_each_entry(dynid, &hdrv->dyn_list, list) { | ||
| 1379 | if (hid_match_one_id(hdev, &dynid->id)) { | ||
| 1380 | spin_unlock(&hdrv->dyn_lock); | ||
| 1381 | return &dynid->id; | ||
| 1382 | } | ||
| 1383 | } | ||
| 1384 | spin_unlock(&hdrv->dyn_lock); | ||
| 1385 | |||
| 1386 | return hid_match_id(hdev, hdrv->id_table); | ||
| 1387 | } | ||
| 1388 | |||
| 1311 | static int hid_bus_match(struct device *dev, struct device_driver *drv) | 1389 | static int hid_bus_match(struct device *dev, struct device_driver *drv) |
| 1312 | { | 1390 | { |
| 1313 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | 1391 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); |
| 1314 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | 1392 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
| 1315 | 1393 | ||
| 1316 | if (!hid_match_id(hdev, hdrv->id_table)) | 1394 | if (!hid_match_device(hdev, hdrv)) |
| 1317 | return 0; | 1395 | return 0; |
| 1318 | 1396 | ||
| 1319 | /* generic wants all non-blacklisted */ | 1397 | /* generic wants all non-blacklisted */ |
| @@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev) | |||
| 1332 | int ret = 0; | 1410 | int ret = 0; |
| 1333 | 1411 | ||
| 1334 | if (!hdev->driver) { | 1412 | if (!hdev->driver) { |
| 1335 | id = hid_match_id(hdev, hdrv->id_table); | 1413 | id = hid_match_device(hdev, hdrv); |
| 1336 | if (id == NULL) | 1414 | if (id == NULL) |
| 1337 | return -ENODEV; | 1415 | return -ENODEV; |
| 1338 | 1416 | ||
| @@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1420 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, | 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, |
| 1421 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, | 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, |
| 1422 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, | 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, |
| 1501 | { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, | ||
| 1423 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
| 1424 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
| 1425 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
| @@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
| 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1656 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
| 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1657 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1658 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
| 1659 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
| 1660 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
| 1661 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1662 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1663 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1582 | { } | 1664 | { } |
| @@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev) | |||
| 1618 | if (hid_ignore(hdev)) | 1700 | if (hid_ignore(hdev)) |
| 1619 | return -ENODEV; | 1701 | return -ENODEV; |
| 1620 | 1702 | ||
| 1621 | /* XXX hack, any other cleaner solution < 20 bus_id bytes? */ | 1703 | /* XXX hack, any other cleaner solution after the driver core |
| 1622 | sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus, | 1704 | * is converted to allow more than 20 bytes as the device name? */ |
| 1623 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | 1705 | dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, |
| 1706 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | ||
| 1624 | 1707 | ||
| 1625 | ret = device_add(&hdev->dev); | 1708 | ret = device_add(&hdev->dev); |
| 1626 | if (!ret) | 1709 | if (!ret) |
| @@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device); | |||
| 1695 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | 1778 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, |
| 1696 | const char *mod_name) | 1779 | const char *mod_name) |
| 1697 | { | 1780 | { |
| 1781 | int ret; | ||
| 1782 | |||
| 1698 | hdrv->driver.name = hdrv->name; | 1783 | hdrv->driver.name = hdrv->name; |
| 1699 | hdrv->driver.bus = &hid_bus_type; | 1784 | hdrv->driver.bus = &hid_bus_type; |
| 1700 | hdrv->driver.owner = owner; | 1785 | hdrv->driver.owner = owner; |
| 1701 | hdrv->driver.mod_name = mod_name; | 1786 | hdrv->driver.mod_name = mod_name; |
| 1702 | 1787 | ||
| 1703 | return driver_register(&hdrv->driver); | 1788 | INIT_LIST_HEAD(&hdrv->dyn_list); |
| 1789 | spin_lock_init(&hdrv->dyn_lock); | ||
| 1790 | |||
| 1791 | ret = driver_register(&hdrv->driver); | ||
| 1792 | if (ret) | ||
| 1793 | return ret; | ||
| 1794 | |||
| 1795 | ret = driver_create_file(&hdrv->driver, &driver_attr_new_id); | ||
| 1796 | if (ret) | ||
| 1797 | driver_unregister(&hdrv->driver); | ||
| 1798 | |||
| 1799 | return ret; | ||
| 1704 | } | 1800 | } |
| 1705 | EXPORT_SYMBOL_GPL(__hid_register_driver); | 1801 | EXPORT_SYMBOL_GPL(__hid_register_driver); |
| 1706 | 1802 | ||
| 1707 | void hid_unregister_driver(struct hid_driver *hdrv) | 1803 | void hid_unregister_driver(struct hid_driver *hdrv) |
| 1708 | { | 1804 | { |
| 1805 | driver_remove_file(&hdrv->driver, &driver_attr_new_id); | ||
| 1709 | driver_unregister(&hdrv->driver); | 1806 | driver_unregister(&hdrv->driver); |
| 1807 | hid_free_dynids(hdrv); | ||
| 1710 | } | 1808 | } |
| 1711 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | 1809 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
| 1712 | 1810 | ||
