diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-sony.c | 147 |
1 files changed, 113 insertions, 34 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bc4269e559f1..b6e610289e9d 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -798,6 +798,12 @@ union sixaxis_output_report_01 { | |||
798 | __u8 buf[36]; | 798 | __u8 buf[36]; |
799 | }; | 799 | }; |
800 | 800 | ||
801 | #define DS4_REPORT_0x02_SIZE 37 | ||
802 | #define DS4_REPORT_0x05_SIZE 32 | ||
803 | #define DS4_REPORT_0x11_SIZE 78 | ||
804 | #define DS4_REPORT_0x81_SIZE 7 | ||
805 | #define SIXAXIS_REPORT_0xF2_SIZE 18 | ||
806 | |||
801 | static spinlock_t sony_dev_list_lock; | 807 | static spinlock_t sony_dev_list_lock; |
802 | static LIST_HEAD(sony_device_list); | 808 | static LIST_HEAD(sony_device_list); |
803 | static DEFINE_IDA(sony_device_id_allocator); | 809 | static DEFINE_IDA(sony_device_id_allocator); |
@@ -811,6 +817,7 @@ struct sony_sc { | |||
811 | struct work_struct state_worker; | 817 | struct work_struct state_worker; |
812 | struct power_supply battery; | 818 | struct power_supply battery; |
813 | int device_id; | 819 | int device_id; |
820 | __u8 *output_report_dmabuf; | ||
814 | 821 | ||
815 | #ifdef CONFIG_SONY_FF | 822 | #ifdef CONFIG_SONY_FF |
816 | __u8 left; | 823 | __u8 left; |
@@ -1142,9 +1149,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) | |||
1142 | 1149 | ||
1143 | static int sixaxis_set_operational_bt(struct hid_device *hdev) | 1150 | static int sixaxis_set_operational_bt(struct hid_device *hdev) |
1144 | { | 1151 | { |
1145 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; | 1152 | static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; |
1146 | return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), | 1153 | __u8 *buf; |
1154 | int ret; | ||
1155 | |||
1156 | buf = kmemdup(report, sizeof(report), GFP_KERNEL); | ||
1157 | if (!buf) | ||
1158 | return -ENOMEM; | ||
1159 | |||
1160 | ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), | ||
1147 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | 1161 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
1162 | |||
1163 | kfree(buf); | ||
1164 | |||
1165 | return ret; | ||
1148 | } | 1166 | } |
1149 | 1167 | ||
1150 | /* | 1168 | /* |
@@ -1153,10 +1171,19 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) | |||
1153 | */ | 1171 | */ |
1154 | static int dualshock4_set_operational_bt(struct hid_device *hdev) | 1172 | static int dualshock4_set_operational_bt(struct hid_device *hdev) |
1155 | { | 1173 | { |
1156 | __u8 buf[37] = { 0 }; | 1174 | __u8 *buf; |
1175 | int ret; | ||
1157 | 1176 | ||
1158 | return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf), | 1177 | buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); |
1178 | if (!buf) | ||
1179 | return -ENOMEM; | ||
1180 | |||
1181 | ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, | ||
1159 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1182 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
1183 | |||
1184 | kfree(buf); | ||
1185 | |||
1186 | return ret; | ||
1160 | } | 1187 | } |
1161 | 1188 | ||
1162 | static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) | 1189 | static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) |
@@ -1471,9 +1498,7 @@ error_leds: | |||
1471 | 1498 | ||
1472 | static void sixaxis_state_worker(struct work_struct *work) | 1499 | static void sixaxis_state_worker(struct work_struct *work) |
1473 | { | 1500 | { |
1474 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 1501 | static const union sixaxis_output_report_01 default_report = { |
1475 | int n; | ||
1476 | union sixaxis_output_report_01 report = { | ||
1477 | .buf = { | 1502 | .buf = { |
1478 | 0x01, | 1503 | 0x01, |
1479 | 0x00, 0xff, 0x00, 0xff, 0x00, | 1504 | 0x00, 0xff, 0x00, 0xff, 0x00, |
@@ -1485,20 +1510,27 @@ static void sixaxis_state_worker(struct work_struct *work) | |||
1485 | 0x00, 0x00, 0x00, 0x00, 0x00 | 1510 | 0x00, 0x00, 0x00, 0x00, 0x00 |
1486 | } | 1511 | } |
1487 | }; | 1512 | }; |
1513 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | ||
1514 | struct sixaxis_output_report *report = | ||
1515 | (struct sixaxis_output_report *)sc->output_report_dmabuf; | ||
1516 | int n; | ||
1517 | |||
1518 | /* Initialize the report with default values */ | ||
1519 | memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); | ||
1488 | 1520 | ||
1489 | #ifdef CONFIG_SONY_FF | 1521 | #ifdef CONFIG_SONY_FF |
1490 | report.data.rumble.right_motor_on = sc->right ? 1 : 0; | 1522 | report->rumble.right_motor_on = sc->right ? 1 : 0; |
1491 | report.data.rumble.left_motor_force = sc->left; | 1523 | report->rumble.left_motor_force = sc->left; |
1492 | #endif | 1524 | #endif |
1493 | 1525 | ||
1494 | report.data.leds_bitmap |= sc->led_state[0] << 1; | 1526 | report->leds_bitmap |= sc->led_state[0] << 1; |
1495 | report.data.leds_bitmap |= sc->led_state[1] << 2; | 1527 | report->leds_bitmap |= sc->led_state[1] << 2; |
1496 | report.data.leds_bitmap |= sc->led_state[2] << 3; | 1528 | report->leds_bitmap |= sc->led_state[2] << 3; |
1497 | report.data.leds_bitmap |= sc->led_state[3] << 4; | 1529 | report->leds_bitmap |= sc->led_state[3] << 4; |
1498 | 1530 | ||
1499 | /* Set flag for all leds off, required for 3rd party INTEC controller */ | 1531 | /* Set flag for all leds off, required for 3rd party INTEC controller */ |
1500 | if ((report.data.leds_bitmap & 0x1E) == 0) | 1532 | if ((report->leds_bitmap & 0x1E) == 0) |
1501 | report.data.leds_bitmap |= 0x20; | 1533 | report->leds_bitmap |= 0x20; |
1502 | 1534 | ||
1503 | /* | 1535 | /* |
1504 | * The LEDs in the report are indexed in reverse order to their | 1536 | * The LEDs in the report are indexed in reverse order to their |
@@ -1511,28 +1543,30 @@ static void sixaxis_state_worker(struct work_struct *work) | |||
1511 | */ | 1543 | */ |
1512 | for (n = 0; n < 4; n++) { | 1544 | for (n = 0; n < 4; n++) { |
1513 | if (sc->led_delay_on[n] || sc->led_delay_off[n]) { | 1545 | if (sc->led_delay_on[n] || sc->led_delay_off[n]) { |
1514 | report.data.led[3 - n].duty_off = sc->led_delay_off[n]; | 1546 | report->led[3 - n].duty_off = sc->led_delay_off[n]; |
1515 | report.data.led[3 - n].duty_on = sc->led_delay_on[n]; | 1547 | report->led[3 - n].duty_on = sc->led_delay_on[n]; |
1516 | } | 1548 | } |
1517 | } | 1549 | } |
1518 | 1550 | ||
1519 | hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf, | 1551 | hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, |
1520 | sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 1552 | sizeof(struct sixaxis_output_report), |
1553 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | ||
1521 | } | 1554 | } |
1522 | 1555 | ||
1523 | static void dualshock4_state_worker(struct work_struct *work) | 1556 | static void dualshock4_state_worker(struct work_struct *work) |
1524 | { | 1557 | { |
1525 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 1558 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); |
1526 | struct hid_device *hdev = sc->hdev; | 1559 | struct hid_device *hdev = sc->hdev; |
1560 | __u8 *buf = sc->output_report_dmabuf; | ||
1527 | int offset; | 1561 | int offset; |
1528 | 1562 | ||
1529 | __u8 buf[78] = { 0 }; | ||
1530 | |||
1531 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 1563 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
1564 | memset(buf, 0, DS4_REPORT_0x05_SIZE); | ||
1532 | buf[0] = 0x05; | 1565 | buf[0] = 0x05; |
1533 | buf[1] = 0xFF; | 1566 | buf[1] = 0xFF; |
1534 | offset = 4; | 1567 | offset = 4; |
1535 | } else { | 1568 | } else { |
1569 | memset(buf, 0, DS4_REPORT_0x11_SIZE); | ||
1536 | buf[0] = 0x11; | 1570 | buf[0] = 0x11; |
1537 | buf[1] = 0xB0; | 1571 | buf[1] = 0xB0; |
1538 | buf[3] = 0x0F; | 1572 | buf[3] = 0x0F; |
@@ -1560,12 +1594,33 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
1560 | buf[offset++] = sc->led_delay_off[3]; | 1594 | buf[offset++] = sc->led_delay_off[3]; |
1561 | 1595 | ||
1562 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 1596 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
1563 | hid_hw_output_report(hdev, buf, 32); | 1597 | hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); |
1564 | else | 1598 | else |
1565 | hid_hw_raw_request(hdev, 0x11, buf, 78, | 1599 | hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, |
1566 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 1600 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
1567 | } | 1601 | } |
1568 | 1602 | ||
1603 | static int sony_allocate_output_report(struct sony_sc *sc) | ||
1604 | { | ||
1605 | if (sc->quirks & SIXAXIS_CONTROLLER) | ||
1606 | sc->output_report_dmabuf = | ||
1607 | kmalloc(sizeof(union sixaxis_output_report_01), | ||
1608 | GFP_KERNEL); | ||
1609 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) | ||
1610 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, | ||
1611 | GFP_KERNEL); | ||
1612 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | ||
1613 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, | ||
1614 | GFP_KERNEL); | ||
1615 | else | ||
1616 | return 0; | ||
1617 | |||
1618 | if (!sc->output_report_dmabuf) | ||
1619 | return -ENOMEM; | ||
1620 | |||
1621 | return 0; | ||
1622 | } | ||
1623 | |||
1569 | #ifdef CONFIG_SONY_FF | 1624 | #ifdef CONFIG_SONY_FF |
1570 | static int sony_play_effect(struct input_dev *dev, void *data, | 1625 | static int sony_play_effect(struct input_dev *dev, void *data, |
1571 | struct ff_effect *effect) | 1626 | struct ff_effect *effect) |
@@ -1754,6 +1809,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) | |||
1754 | 1809 | ||
1755 | static int sony_check_add(struct sony_sc *sc) | 1810 | static int sony_check_add(struct sony_sc *sc) |
1756 | { | 1811 | { |
1812 | __u8 *buf = NULL; | ||
1757 | int n, ret; | 1813 | int n, ret; |
1758 | 1814 | ||
1759 | if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || | 1815 | if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || |
@@ -1769,36 +1825,44 @@ static int sony_check_add(struct sony_sc *sc) | |||
1769 | return 0; | 1825 | return 0; |
1770 | } | 1826 | } |
1771 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 1827 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
1772 | __u8 buf[7]; | 1828 | buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); |
1829 | if (!buf) | ||
1830 | return -ENOMEM; | ||
1773 | 1831 | ||
1774 | /* | 1832 | /* |
1775 | * The MAC address of a DS4 controller connected via USB can be | 1833 | * The MAC address of a DS4 controller connected via USB can be |
1776 | * retrieved with feature report 0x81. The address begins at | 1834 | * retrieved with feature report 0x81. The address begins at |
1777 | * offset 1. | 1835 | * offset 1. |
1778 | */ | 1836 | */ |
1779 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf), | 1837 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, |
1780 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1838 | DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, |
1839 | HID_REQ_GET_REPORT); | ||
1781 | 1840 | ||
1782 | if (ret != 7) { | 1841 | if (ret != DS4_REPORT_0x81_SIZE) { |
1783 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); | 1842 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); |
1784 | return ret < 0 ? ret : -EINVAL; | 1843 | ret = ret < 0 ? ret : -EINVAL; |
1844 | goto out_free; | ||
1785 | } | 1845 | } |
1786 | 1846 | ||
1787 | memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); | 1847 | memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); |
1788 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { | 1848 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { |
1789 | __u8 buf[18]; | 1849 | buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); |
1850 | if (!buf) | ||
1851 | return -ENOMEM; | ||
1790 | 1852 | ||
1791 | /* | 1853 | /* |
1792 | * The MAC address of a Sixaxis controller connected via USB can | 1854 | * The MAC address of a Sixaxis controller connected via USB can |
1793 | * be retrieved with feature report 0xf2. The address begins at | 1855 | * be retrieved with feature report 0xf2. The address begins at |
1794 | * offset 4. | 1856 | * offset 4. |
1795 | */ | 1857 | */ |
1796 | ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf), | 1858 | ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, |
1797 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1859 | SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, |
1860 | HID_REQ_GET_REPORT); | ||
1798 | 1861 | ||
1799 | if (ret != 18) { | 1862 | if (ret != SIXAXIS_REPORT_0xF2_SIZE) { |
1800 | hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); | 1863 | hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); |
1801 | return ret < 0 ? ret : -EINVAL; | 1864 | ret = ret < 0 ? ret : -EINVAL; |
1865 | goto out_free; | ||
1802 | } | 1866 | } |
1803 | 1867 | ||
1804 | /* | 1868 | /* |
@@ -1811,7 +1875,13 @@ static int sony_check_add(struct sony_sc *sc) | |||
1811 | return 0; | 1875 | return 0; |
1812 | } | 1876 | } |
1813 | 1877 | ||
1814 | return sony_check_add_dev_list(sc); | 1878 | ret = sony_check_add_dev_list(sc); |
1879 | |||
1880 | out_free: | ||
1881 | |||
1882 | kfree(buf); | ||
1883 | |||
1884 | return ret; | ||
1815 | } | 1885 | } |
1816 | 1886 | ||
1817 | static int sony_set_device_id(struct sony_sc *sc) | 1887 | static int sony_set_device_id(struct sony_sc *sc) |
@@ -1895,6 +1965,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1895 | return ret; | 1965 | return ret; |
1896 | } | 1966 | } |
1897 | 1967 | ||
1968 | ret = sony_allocate_output_report(sc); | ||
1969 | if (ret < 0) { | ||
1970 | hid_err(hdev, "failed to allocate the output report buffer\n"); | ||
1971 | goto err_stop; | ||
1972 | } | ||
1973 | |||
1898 | ret = sony_set_device_id(sc); | 1974 | ret = sony_set_device_id(sc); |
1899 | if (ret < 0) { | 1975 | if (ret < 0) { |
1900 | hid_err(hdev, "failed to allocate the device id\n"); | 1976 | hid_err(hdev, "failed to allocate the device id\n"); |
@@ -1984,6 +2060,7 @@ err_stop: | |||
1984 | if (sc->quirks & SONY_BATTERY_SUPPORT) | 2060 | if (sc->quirks & SONY_BATTERY_SUPPORT) |
1985 | sony_battery_remove(sc); | 2061 | sony_battery_remove(sc); |
1986 | sony_cancel_work_sync(sc); | 2062 | sony_cancel_work_sync(sc); |
2063 | kfree(sc->output_report_dmabuf); | ||
1987 | sony_remove_dev_list(sc); | 2064 | sony_remove_dev_list(sc); |
1988 | sony_release_device_id(sc); | 2065 | sony_release_device_id(sc); |
1989 | hid_hw_stop(hdev); | 2066 | hid_hw_stop(hdev); |
@@ -2004,6 +2081,8 @@ static void sony_remove(struct hid_device *hdev) | |||
2004 | 2081 | ||
2005 | sony_cancel_work_sync(sc); | 2082 | sony_cancel_work_sync(sc); |
2006 | 2083 | ||
2084 | kfree(sc->output_report_dmabuf); | ||
2085 | |||
2007 | sony_remove_dev_list(sc); | 2086 | sony_remove_dev_list(sc); |
2008 | 2087 | ||
2009 | sony_release_device_id(sc); | 2088 | sony_release_device_id(sc); |