diff options
| -rw-r--r-- | drivers/hid/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-picolcd.c | 439 |
2 files changed, 423 insertions, 18 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 34f6593ea3b6..a2ecd83bfe89 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -281,9 +281,9 @@ config HID_PICOLCD | |||
| 281 | - Backlight control (needs CONFIG_BACKLIGHT_CLASS_DEVICE) | 281 | - Backlight control (needs CONFIG_BACKLIGHT_CLASS_DEVICE) |
| 282 | - Contrast control (needs CONFIG_LCD_CLASS_DEVICE) | 282 | - Contrast control (needs CONFIG_LCD_CLASS_DEVICE) |
| 283 | - General purpose outputs (needs CONFIG_LEDS_CLASS) | 283 | - General purpose outputs (needs CONFIG_LEDS_CLASS) |
| 284 | - EEProm / Flash access (via debugfs) | ||
| 284 | Features that are not (yet) supported: | 285 | Features that are not (yet) supported: |
| 285 | - IR | 286 | - IR |
| 286 | - EEProm / Flash access | ||
| 287 | 287 | ||
| 288 | config HID_QUANTA | 288 | config HID_QUANTA |
| 289 | tristate "Quanta Optical Touch" | 289 | tristate "Quanta Optical Touch" |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 517677305ef9..66f9cfd41abe 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
| @@ -169,6 +169,10 @@ struct picolcd_pending { | |||
| 169 | struct picolcd_data { | 169 | struct picolcd_data { |
| 170 | struct hid_device *hdev; | 170 | struct hid_device *hdev; |
| 171 | #ifdef CONFIG_DEBUG_FS | 171 | #ifdef CONFIG_DEBUG_FS |
| 172 | struct dentry *debug_reset; | ||
| 173 | struct dentry *debug_eeprom; | ||
| 174 | struct dentry *debug_flash; | ||
| 175 | struct mutex mutex_flash; | ||
| 172 | int addr_sz; | 176 | int addr_sz; |
| 173 | #endif | 177 | #endif |
| 174 | u8 version[2]; | 178 | u8 version[2]; |
| @@ -1314,6 +1318,357 @@ static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, | |||
| 1314 | 1318 | ||
| 1315 | #ifdef CONFIG_DEBUG_FS | 1319 | #ifdef CONFIG_DEBUG_FS |
| 1316 | /* | 1320 | /* |
| 1321 | * The "reset" file | ||
| 1322 | */ | ||
| 1323 | static int picolcd_debug_reset_show(struct seq_file *f, void *p) | ||
| 1324 | { | ||
| 1325 | if (picolcd_fbinfo((struct picolcd_data *)f->private)) | ||
| 1326 | seq_printf(f, "all fb\n"); | ||
| 1327 | else | ||
| 1328 | seq_printf(f, "all\n"); | ||
| 1329 | return 0; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | static int picolcd_debug_reset_open(struct inode *inode, struct file *f) | ||
| 1333 | { | ||
| 1334 | return single_open(f, picolcd_debug_reset_show, inode->i_private); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf, | ||
| 1338 | size_t count, loff_t *ppos) | ||
| 1339 | { | ||
| 1340 | struct picolcd_data *data = ((struct seq_file *)f->private_data)->private; | ||
| 1341 | char buf[32]; | ||
| 1342 | size_t cnt = min(count, sizeof(buf)-1); | ||
| 1343 | if (copy_from_user(buf, user_buf, cnt)) | ||
| 1344 | return -EFAULT; | ||
| 1345 | |||
| 1346 | while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n')) | ||
| 1347 | cnt--; | ||
| 1348 | buf[cnt] = '\0'; | ||
| 1349 | if (strcmp(buf, "all") == 0) { | ||
| 1350 | picolcd_reset(data->hdev); | ||
| 1351 | picolcd_fb_reset(data, 1); | ||
| 1352 | } else if (strcmp(buf, "fb") == 0) { | ||
| 1353 | picolcd_fb_reset(data, 1); | ||
| 1354 | } else { | ||
| 1355 | return -EINVAL; | ||
| 1356 | } | ||
| 1357 | return count; | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | static const struct file_operations picolcd_debug_reset_fops = { | ||
| 1361 | .owner = THIS_MODULE, | ||
| 1362 | .open = picolcd_debug_reset_open, | ||
| 1363 | .read = seq_read, | ||
| 1364 | .llseek = seq_lseek, | ||
| 1365 | .write = picolcd_debug_reset_write, | ||
| 1366 | .release = single_release, | ||
| 1367 | }; | ||
| 1368 | |||
| 1369 | /* | ||
| 1370 | * The "eeprom" file | ||
| 1371 | */ | ||
| 1372 | static int picolcd_debug_eeprom_open(struct inode *i, struct file *f) | ||
| 1373 | { | ||
| 1374 | f->private_data = i->i_private; | ||
| 1375 | return 0; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, | ||
| 1379 | size_t s, loff_t *off) | ||
| 1380 | { | ||
| 1381 | struct picolcd_data *data = f->private_data; | ||
| 1382 | struct picolcd_pending *resp; | ||
| 1383 | u8 raw_data[3]; | ||
| 1384 | ssize_t ret = -EIO; | ||
| 1385 | |||
| 1386 | if (s == 0) | ||
| 1387 | return -EINVAL; | ||
| 1388 | if (*off > 0x0ff) | ||
| 1389 | return 0; | ||
| 1390 | |||
| 1391 | /* prepare buffer with info about what we want to read (addr & len) */ | ||
| 1392 | raw_data[0] = *off & 0xff; | ||
| 1393 | raw_data[1] = (*off >> 8) && 0xff; | ||
| 1394 | raw_data[2] = s < 20 ? s : 20; | ||
| 1395 | if (*off + raw_data[2] > 0xff) | ||
| 1396 | raw_data[2] = 0x100 - *off; | ||
| 1397 | resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data, | ||
| 1398 | sizeof(raw_data)); | ||
| 1399 | if (!resp) | ||
| 1400 | return -EIO; | ||
| 1401 | |||
| 1402 | if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { | ||
| 1403 | /* successful read :) */ | ||
| 1404 | ret = resp->raw_data[2]; | ||
| 1405 | if (ret > s) | ||
| 1406 | ret = s; | ||
| 1407 | if (copy_to_user(u, resp->raw_data+3, ret)) | ||
| 1408 | ret = -EFAULT; | ||
| 1409 | else | ||
| 1410 | *off += ret; | ||
| 1411 | } /* anything else is some kind of IO error */ | ||
| 1412 | |||
| 1413 | kfree(resp); | ||
| 1414 | return ret; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, | ||
| 1418 | size_t s, loff_t *off) | ||
| 1419 | { | ||
| 1420 | struct picolcd_data *data = f->private_data; | ||
| 1421 | struct picolcd_pending *resp; | ||
| 1422 | ssize_t ret = -EIO; | ||
| 1423 | u8 raw_data[23]; | ||
| 1424 | |||
| 1425 | if (s == 0) | ||
| 1426 | return -EINVAL; | ||
| 1427 | if (*off > 0x0ff) | ||
| 1428 | return -ENOSPC; | ||
| 1429 | |||
| 1430 | memset(raw_data, 0, sizeof(raw_data)); | ||
| 1431 | raw_data[0] = *off & 0xff; | ||
| 1432 | raw_data[1] = (*off >> 8) && 0xff; | ||
| 1433 | raw_data[2] = s < 20 ? s : 20; | ||
| 1434 | if (*off + raw_data[2] > 0xff) | ||
| 1435 | raw_data[2] = 0x100 - *off; | ||
| 1436 | |||
| 1437 | if (copy_from_user(raw_data+3, u, raw_data[2])) | ||
| 1438 | return -EFAULT; | ||
| 1439 | resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, | ||
| 1440 | sizeof(raw_data)); | ||
| 1441 | |||
| 1442 | if (!resp) | ||
| 1443 | return -EIO; | ||
| 1444 | |||
| 1445 | if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) { | ||
| 1446 | /* check if written data matches */ | ||
| 1447 | if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) { | ||
| 1448 | *off += raw_data[2]; | ||
| 1449 | ret = raw_data[2]; | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | kfree(resp); | ||
| 1453 | return ret; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | /* | ||
| 1457 | * Notes: | ||
| 1458 | * - read/write happens in chunks of at most 20 bytes, it's up to userspace | ||
| 1459 | * to loop in order to get more data. | ||
| 1460 | * - on write errors on otherwise correct write request the bytes | ||
| 1461 | * that should have been written are in undefined state. | ||
| 1462 | */ | ||
| 1463 | static const struct file_operations picolcd_debug_eeprom_fops = { | ||
| 1464 | .owner = THIS_MODULE, | ||
| 1465 | .open = picolcd_debug_eeprom_open, | ||
| 1466 | .read = picolcd_debug_eeprom_read, | ||
| 1467 | .write = picolcd_debug_eeprom_write, | ||
| 1468 | .llseek = generic_file_llseek, | ||
| 1469 | }; | ||
| 1470 | |||
| 1471 | /* | ||
| 1472 | * The "flash" file | ||
| 1473 | */ | ||
| 1474 | static int picolcd_debug_flash_open(struct inode *i, struct file *f) | ||
| 1475 | { | ||
| 1476 | f->private_data = i->i_private; | ||
| 1477 | return 0; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | /* record a flash address to buf (bounds check to be done by caller) */ | ||
| 1481 | static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off) | ||
| 1482 | { | ||
| 1483 | buf[0] = off & 0xff; | ||
| 1484 | buf[1] = (off >> 8) & 0xff; | ||
| 1485 | if (data->addr_sz == 3) | ||
| 1486 | buf[2] = (off >> 16) & 0xff; | ||
| 1487 | return data->addr_sz == 2 ? 2 : 3; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | /* read a given size of data (bounds check to be done by caller) */ | ||
| 1491 | static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id, | ||
| 1492 | char __user *u, size_t s, loff_t *off) | ||
| 1493 | { | ||
| 1494 | struct picolcd_pending *resp; | ||
| 1495 | u8 raw_data[4]; | ||
| 1496 | ssize_t ret = 0; | ||
| 1497 | int len_off, err = -EIO; | ||
| 1498 | |||
| 1499 | while (s > 0) { | ||
| 1500 | err = -EIO; | ||
| 1501 | len_off = _picolcd_flash_setaddr(data, raw_data, *off); | ||
| 1502 | raw_data[len_off] = s > 32 ? 32 : s; | ||
| 1503 | resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1); | ||
| 1504 | if (!resp || !resp->in_report) | ||
| 1505 | goto skip; | ||
| 1506 | if (resp->in_report->id == REPORT_MEMORY || | ||
| 1507 | resp->in_report->id == REPORT_BL_READ_MEMORY) { | ||
| 1508 | if (memcmp(raw_data, resp->raw_data, len_off+1) != 0) | ||
| 1509 | goto skip; | ||
| 1510 | if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) { | ||
| 1511 | err = -EFAULT; | ||
| 1512 | goto skip; | ||
| 1513 | } | ||
| 1514 | *off += raw_data[len_off]; | ||
| 1515 | s -= raw_data[len_off]; | ||
| 1516 | ret += raw_data[len_off]; | ||
| 1517 | err = 0; | ||
| 1518 | } | ||
| 1519 | skip: | ||
| 1520 | kfree(resp); | ||
| 1521 | if (err) | ||
| 1522 | return ret > 0 ? ret : err; | ||
| 1523 | } | ||
| 1524 | return ret; | ||
| 1525 | } | ||
| 1526 | |||
| 1527 | static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u, | ||
| 1528 | size_t s, loff_t *off) | ||
| 1529 | { | ||
| 1530 | struct picolcd_data *data = f->private_data; | ||
| 1531 | |||
| 1532 | if (s == 0) | ||
| 1533 | return -EINVAL; | ||
| 1534 | if (*off > 0x05fff) | ||
| 1535 | return 0; | ||
| 1536 | if (*off + s > 0x05fff) | ||
| 1537 | s = 0x06000 - *off; | ||
| 1538 | |||
| 1539 | if (data->status & PICOLCD_BOOTLOADER) | ||
| 1540 | return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off); | ||
| 1541 | else | ||
| 1542 | return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off); | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | /* erase block aligned to 64bytes boundary */ | ||
| 1546 | static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id, | ||
| 1547 | loff_t *off) | ||
| 1548 | { | ||
| 1549 | struct picolcd_pending *resp; | ||
| 1550 | u8 raw_data[3]; | ||
| 1551 | int len_off; | ||
| 1552 | ssize_t ret = -EIO; | ||
| 1553 | |||
| 1554 | if (*off & 0x3f) | ||
| 1555 | return -EINVAL; | ||
| 1556 | |||
| 1557 | len_off = _picolcd_flash_setaddr(data, raw_data, *off); | ||
| 1558 | resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off); | ||
| 1559 | if (!resp || !resp->in_report) | ||
| 1560 | goto skip; | ||
| 1561 | if (resp->in_report->id == REPORT_MEMORY || | ||
| 1562 | resp->in_report->id == REPORT_BL_ERASE_MEMORY) { | ||
| 1563 | if (memcmp(raw_data, resp->raw_data, len_off) != 0) | ||
| 1564 | goto skip; | ||
| 1565 | ret = 0; | ||
| 1566 | } | ||
| 1567 | skip: | ||
| 1568 | kfree(resp); | ||
| 1569 | return ret; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | /* write a given size of data (bounds check to be done by caller) */ | ||
| 1573 | static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id, | ||
| 1574 | const char __user *u, size_t s, loff_t *off) | ||
| 1575 | { | ||
| 1576 | struct picolcd_pending *resp; | ||
| 1577 | u8 raw_data[36]; | ||
| 1578 | ssize_t ret = 0; | ||
| 1579 | int len_off, err = -EIO; | ||
| 1580 | |||
| 1581 | while (s > 0) { | ||
| 1582 | err = -EIO; | ||
| 1583 | len_off = _picolcd_flash_setaddr(data, raw_data, *off); | ||
| 1584 | raw_data[len_off] = s > 32 ? 32 : s; | ||
| 1585 | if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) { | ||
| 1586 | err = -EFAULT; | ||
| 1587 | goto skip; | ||
| 1588 | } | ||
| 1589 | resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, | ||
| 1590 | len_off+1+raw_data[len_off]); | ||
| 1591 | if (!resp || !resp->in_report) | ||
| 1592 | goto skip; | ||
| 1593 | if (resp->in_report->id == REPORT_MEMORY || | ||
| 1594 | resp->in_report->id == REPORT_BL_WRITE_MEMORY) { | ||
| 1595 | if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0) | ||
| 1596 | goto skip; | ||
| 1597 | *off += raw_data[len_off]; | ||
| 1598 | s -= raw_data[len_off]; | ||
| 1599 | ret += raw_data[len_off]; | ||
| 1600 | err = 0; | ||
| 1601 | } | ||
| 1602 | skip: | ||
| 1603 | kfree(resp); | ||
| 1604 | if (err) | ||
| 1605 | break; | ||
| 1606 | } | ||
| 1607 | return ret > 0 ? ret : err; | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, | ||
| 1611 | size_t s, loff_t *off) | ||
| 1612 | { | ||
| 1613 | struct picolcd_data *data = f->private_data; | ||
| 1614 | ssize_t err, ret = 0; | ||
| 1615 | int report_erase, report_write; | ||
| 1616 | |||
| 1617 | if (s == 0) | ||
| 1618 | return -EINVAL; | ||
| 1619 | if (*off > 0x5fff) | ||
| 1620 | return -ENOSPC; | ||
| 1621 | if (s & 0x3f) | ||
| 1622 | return -EINVAL; | ||
| 1623 | if (*off & 0x3f) | ||
| 1624 | return -EINVAL; | ||
| 1625 | |||
| 1626 | if (data->status & PICOLCD_BOOTLOADER) { | ||
| 1627 | report_erase = REPORT_BL_ERASE_MEMORY; | ||
| 1628 | report_write = REPORT_BL_WRITE_MEMORY; | ||
| 1629 | } else { | ||
| 1630 | report_erase = REPORT_ERASE_MEMORY; | ||
| 1631 | report_write = REPORT_WRITE_MEMORY; | ||
| 1632 | } | ||
| 1633 | mutex_lock(&data->mutex_flash); | ||
| 1634 | while (s > 0) { | ||
| 1635 | err = _picolcd_flash_erase64(data, report_erase, off); | ||
| 1636 | if (err) | ||
| 1637 | break; | ||
| 1638 | err = _picolcd_flash_write(data, report_write, u, 64, off); | ||
| 1639 | if (err < 0) | ||
| 1640 | break; | ||
| 1641 | ret += err; | ||
| 1642 | *off += err; | ||
| 1643 | s -= err; | ||
| 1644 | if (err != 64) | ||
| 1645 | break; | ||
| 1646 | } | ||
| 1647 | mutex_unlock(&data->mutex_flash); | ||
| 1648 | return ret > 0 ? ret : err; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | /* | ||
| 1652 | * Notes: | ||
| 1653 | * - concurrent writing is prevented by mutex and all writes must be | ||
| 1654 | * n*64 bytes and 64-byte aligned, each write being preceeded by an | ||
| 1655 | * ERASE which erases a 64byte block. | ||
| 1656 | * If less than requested was written or an error is returned for an | ||
| 1657 | * otherwise correct write request the next 64-byte block which should | ||
| 1658 | * have been written is in undefined state (mostly: original, erased, | ||
| 1659 | * (half-)written with write error) | ||
| 1660 | * - reading can happend without special restriction | ||
| 1661 | */ | ||
| 1662 | static const struct file_operations picolcd_debug_flash_fops = { | ||
| 1663 | .owner = THIS_MODULE, | ||
| 1664 | .open = picolcd_debug_flash_open, | ||
| 1665 | .read = picolcd_debug_flash_read, | ||
| 1666 | .write = picolcd_debug_flash_write, | ||
| 1667 | .llseek = generic_file_llseek, | ||
| 1668 | }; | ||
| 1669 | |||
| 1670 | |||
| 1671 | /* | ||
| 1317 | * Helper code for HID report level dumping/debugging | 1672 | * Helper code for HID report level dumping/debugging |
| 1318 | */ | 1673 | */ |
| 1319 | static const char *error_codes[] = { | 1674 | static const char *error_codes[] = { |
| @@ -1788,9 +2143,66 @@ static void picolcd_debug_raw_event(struct picolcd_data *data, | |||
| 1788 | wake_up_interruptible(&hdev->debug_wait); | 2143 | wake_up_interruptible(&hdev->debug_wait); |
| 1789 | kfree(buff); | 2144 | kfree(buff); |
| 1790 | } | 2145 | } |
| 2146 | |||
| 2147 | static void picolcd_init_devfs(struct picolcd_data *data, | ||
| 2148 | struct hid_report *eeprom_r, struct hid_report *eeprom_w, | ||
| 2149 | struct hid_report *flash_r, struct hid_report *flash_w, | ||
| 2150 | struct hid_report *reset) | ||
| 2151 | { | ||
| 2152 | struct hid_device *hdev = data->hdev; | ||
| 2153 | |||
| 2154 | mutex_init(&data->mutex_flash); | ||
| 2155 | |||
| 2156 | /* reset */ | ||
| 2157 | if (reset) | ||
| 2158 | data->debug_reset = debugfs_create_file("reset", 0600, | ||
| 2159 | hdev->debug_dir, data, &picolcd_debug_reset_fops); | ||
| 2160 | |||
| 2161 | /* eeprom */ | ||
| 2162 | if (eeprom_r || eeprom_w) | ||
| 2163 | data->debug_eeprom = debugfs_create_file("eeprom", | ||
| 2164 | (eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0), | ||
| 2165 | hdev->debug_dir, data, &picolcd_debug_eeprom_fops); | ||
| 2166 | |||
| 2167 | /* flash */ | ||
| 2168 | if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8) | ||
| 2169 | data->addr_sz = flash_r->field[0]->report_count - 1; | ||
| 2170 | else | ||
| 2171 | data->addr_sz = -1; | ||
| 2172 | if (data->addr_sz == 2 || data->addr_sz == 3) { | ||
| 2173 | data->debug_flash = debugfs_create_file("flash", | ||
| 2174 | (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), | ||
| 2175 | hdev->debug_dir, data, &picolcd_debug_flash_fops); | ||
| 2176 | } else if (flash_r || flash_w) | ||
| 2177 | dev_warn(&hdev->dev, "Unexpected FLASH access reports, " | ||
| 2178 | "please submit rdesc for review\n"); | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | static void picolcd_exit_devfs(struct picolcd_data *data) | ||
| 2182 | { | ||
| 2183 | struct dentry *dent; | ||
| 2184 | |||
| 2185 | dent = data->debug_reset; | ||
| 2186 | data->debug_reset = NULL; | ||
| 2187 | if (dent) | ||
| 2188 | debugfs_remove(dent); | ||
| 2189 | dent = data->debug_eeprom; | ||
| 2190 | data->debug_eeprom = NULL; | ||
| 2191 | if (dent) | ||
| 2192 | debugfs_remove(dent); | ||
| 2193 | dent = data->debug_flash; | ||
| 2194 | data->debug_flash = NULL; | ||
| 2195 | if (dent) | ||
| 2196 | debugfs_remove(dent); | ||
| 2197 | mutex_destroy(&data->mutex_flash); | ||
| 2198 | } | ||
| 1791 | #else | 2199 | #else |
| 1792 | #define picolcd_debug_raw_event(data, hdev, report, raw_data, size) | 2200 | #define picolcd_debug_raw_event(data, hdev, report, raw_data, size) |
| 1793 | #endif | 2201 | #define picolcd_init_devfs(data, eeprom_r, eeprom_w, flash_r, flash_w, reset) |
| 2202 | static void picolcd_exit_devfs(struct picolcd_data *data) | ||
| 2203 | { | ||
| 2204 | } | ||
| 2205 | #endif /* CONFIG_DEBUG_FS */ | ||
| 1794 | 2206 | ||
| 1795 | /* | 2207 | /* |
| 1796 | * Handle raw report as sent by device | 2208 | * Handle raw report as sent by device |
| @@ -1900,7 +2312,6 @@ static inline void picolcd_exit_cir(struct picolcd_data *data) | |||
| 1900 | 2312 | ||
| 1901 | static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) | 2313 | static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) |
| 1902 | { | 2314 | { |
| 1903 | struct hid_report *report; | ||
| 1904 | int error; | 2315 | int error; |
| 1905 | 2316 | ||
| 1906 | error = picolcd_check_version(hdev); | 2317 | error = picolcd_check_version(hdev); |
| @@ -1942,13 +2353,11 @@ static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) | |||
| 1942 | if (error) | 2353 | if (error) |
| 1943 | goto err; | 2354 | goto err; |
| 1944 | 2355 | ||
| 1945 | #ifdef CONFIG_DEBUG_FS | 2356 | picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev), |
| 1946 | report = picolcd_out_report(REPORT_READ_MEMORY, hdev); | 2357 | picolcd_out_report(REPORT_EE_WRITE, hdev), |
| 1947 | if (report && report->maxfield == 1 && report->field[0]->report_size == 8) | 2358 | picolcd_out_report(REPORT_READ_MEMORY, hdev), |
| 1948 | data->addr_sz = report->field[0]->report_count - 1; | 2359 | picolcd_out_report(REPORT_WRITE_MEMORY, hdev), |
| 1949 | else | 2360 | picolcd_out_report(REPORT_RESET, hdev)); |
| 1950 | data->addr_sz = -1; | ||
| 1951 | #endif | ||
| 1952 | return 0; | 2361 | return 0; |
| 1953 | err: | 2362 | err: |
| 1954 | picolcd_exit_leds(data); | 2363 | picolcd_exit_leds(data); |
| @@ -1962,7 +2371,6 @@ err: | |||
| 1962 | 2371 | ||
| 1963 | static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) | 2372 | static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data) |
| 1964 | { | 2373 | { |
| 1965 | struct hid_report *report; | ||
| 1966 | int error; | 2374 | int error; |
| 1967 | 2375 | ||
| 1968 | error = picolcd_check_version(hdev); | 2376 | error = picolcd_check_version(hdev); |
| @@ -1974,13 +2382,9 @@ static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data | |||
| 1974 | "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", | 2382 | "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", |
| 1975 | dev_name(&hdev->dev)); | 2383 | dev_name(&hdev->dev)); |
| 1976 | 2384 | ||
| 1977 | #ifdef CONFIG_DEBUG_FS | 2385 | picolcd_init_devfs(data, NULL, NULL, |
| 1978 | report = picolcd_out_report(REPORT_BL_READ_MEMORY, hdev); | 2386 | picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), |
| 1979 | if (report && report->maxfield == 1 && report->field[0]->report_size == 8) | 2387 | picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL); |
| 1980 | data->addr_sz = report->field[0]->report_count - 1; | ||
| 1981 | else | ||
| 1982 | data->addr_sz = -1; | ||
| 1983 | #endif | ||
| 1984 | return 0; | 2388 | return 0; |
| 1985 | } | 2389 | } |
| 1986 | 2390 | ||
| @@ -2073,6 +2477,7 @@ static void picolcd_remove(struct hid_device *hdev) | |||
| 2073 | data->status |= PICOLCD_FAILED; | 2477 | data->status |= PICOLCD_FAILED; |
| 2074 | spin_unlock_irqrestore(&data->lock, flags); | 2478 | spin_unlock_irqrestore(&data->lock, flags); |
| 2075 | 2479 | ||
| 2480 | picolcd_exit_devfs(data); | ||
| 2076 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); | 2481 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); |
| 2077 | hdev->ll_driver->close(hdev); | 2482 | hdev->ll_driver->close(hdev); |
| 2078 | hid_hw_stop(hdev); | 2483 | hid_hw_stop(hdev); |
