@@ -2008,6 +2008,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
@@ -874,6 +874,9 @@
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002
#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000
+#define USB_VENDOR_ID_SINO_LITE 0x1345
+#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008
+
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046
@@ -50,6 +50,7 @@
#define MOTION_CONTROLLER_BT BIT(8)
#define NAVIGATION_CONTROLLER_USB BIT(9)
#define NAVIGATION_CONTROLLER_BT BIT(10)
+#define NYKO_CORE_CONTROLLER BIT(11)
#define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -59,11 +60,11 @@
DUALSHOCK4_CONTROLLER_BT)
#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\
DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\
- NAVIGATION_CONTROLLER)
+ NAVIGATION_CONTROLLER | NYKO_CORE_CONTROLLER)
#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER)
#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\
- MOTION_CONTROLLER)
+ MOTION_CONTROLLER | NYKO_CORE_CONTROLLER)
#define MAX_LEDS 4
@@ -1002,6 +1003,28 @@ union sixaxis_output_report_01 {
__u8 buf[36];
};
+struct nyko_rumble {
+ u8 right_duration; /* Right motor duration (0xff means forever) */
+ u8 right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
+ u8 left_duration; /* Left motor duration (0xff means forever) */
+ u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */
+ u8 padding[4];
+} __packed;
+
+struct nyko_output_report {
+ u8 report_id;
+ struct nyko_rumble rumble;
+ u8 leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
+ struct sixaxis_led led[4]; /* LEDx at (4 - x) */
+ struct sixaxis_led _reserved; /* LED5, not actually soldered */
+ u8 padding;
+} __packed;
+
+union nyko_output_report_01 {
+ struct nyko_output_report data;
+ u8 buf[36];
+};
+
struct motion_output_report_02 {
u8 type, zero;
u8 r, g, b;
@@ -1116,6 +1139,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
{
struct sony_sc *sc = hid_get_drvdata(hdev);
+ if (sc->quirks & NYKO_CORE_CONTROLLER)
+ return rdesc;
+
/*
* Some Sony RF receivers wrongly declare the mouse pointer as a
* a constant non-data variable.
@@ -1393,6 +1419,7 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
const int buf_size =
max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
__u8 *buf;
+ struct sony_sc *sc = hid_get_drvdata(hdev);
int ret;
buf = kmalloc(buf_size, GFP_KERNEL);
@@ -1406,6 +1433,9 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev)
goto out;
}
+ if (sc->quirks & NYKO_CORE_CONTROLLER)
+ goto out;
+
/*
* Some compatible controllers like the Speedlink Strike FX and
* Gasia need another query plus an USB interrupt to get operational.
@@ -1568,7 +1598,8 @@ static void sony_led_set_brightness(struct led_classdev *led,
* controller to avoid having to toggle the state of an LED just to
* stop the flashing later on.
*/
- force_update = !!(drv_data->quirks & SIXAXIS_CONTROLLER_USB);
+ force_update = !!(drv_data->quirks &
+ (SIXAXIS_CONTROLLER_USB | NYKO_CORE_CONTROLLER));
for (n = 0; n < drv_data->led_count; n++) {
if (led == drv_data->leds[n] && (force_update ||
@@ -1803,6 +1834,7 @@ static void sixaxis_state_worker(struct work_struct *work)
0x00, 0x00, 0x00, 0x00, 0x00
}
};
+
struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
struct sixaxis_output_report *report =
(struct sixaxis_output_report *)sc->output_report_dmabuf;
@@ -1846,6 +1878,62 @@ static void sixaxis_state_worker(struct work_struct *work)
HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
}
+static void nyko_state_worker(struct work_struct *work)
+{
+ static const union nyko_output_report_01 default_report = {
+ .buf = {
+ 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x30, 0x27, 0x30, 0x30, 0xff,
+ 0x30, 0x27, 0x30, 0x30, 0xff,
+ 0x30, 0x27, 0x30, 0x30, 0xff,
+ 0x30, 0x27, 0x30, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+ }
+ };
+
+ struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
+ struct nyko_output_report *report =
+ (struct nyko_output_report *)sc->output_report_dmabuf;
+ int n;
+
+ /* Initialize the report with default values */
+ memcpy(report, &default_report, sizeof(struct nyko_output_report));
+
+#ifdef CONFIG_SONY_FF
+ report->rumble.left_motor_force = (sc->right / 2) + (sc->left * 2);
+ report->rumble.right_duration = 0x00;
+ report->rumble.left_duration = 0xff;
+#endif
+
+ report->leds_bitmap |= sc->led_state[0] << 1;
+ report->leds_bitmap |= sc->led_state[1] << 2;
+ report->leds_bitmap |= sc->led_state[2] << 3;
+ report->leds_bitmap |= sc->led_state[3] << 4;
+
+ /*
+ * The LEDs in the report are indexed in reverse order to their
+ * corresponding light on the controller.
+ * Index 0 = LED 4, index 1 = LED 3, etc...
+ *
+ * In the case of both delay values being zero (blinking disabled) the
+ * default report values should be used or the controller LED will be
+ * always off.
+ */
+ for (n = 0; n < 4; n++) {
+ if (sc->led_delay_on[n] || sc->led_delay_off[n]) {
+ report->led[3 - n].duty_off = sc->led_delay_off[n];
+ report->led[3 - n].duty_on = sc->led_delay_on[n];
+ }
+ }
+
+ hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
+ sizeof(struct nyko_output_report),
+ HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+
+}
+
static void dualshock4_state_worker(struct work_struct *work)
{
struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
@@ -1917,7 +2005,8 @@ static void motion_state_worker(struct work_struct *work)
static int sony_allocate_output_report(struct sony_sc *sc)
{
if ((sc->quirks & SIXAXIS_CONTROLLER) ||
- (sc->quirks & NAVIGATION_CONTROLLER))
+ (sc->quirks & NAVIGATION_CONTROLLER) ||
+ (sc->quirks & NYKO_CORE_CONTROLLER))
sc->output_report_dmabuf =
kmalloc(sizeof(union sixaxis_output_report_01),
GFP_KERNEL);
@@ -2170,7 +2259,8 @@ static int sony_check_add(struct sony_sc *sc)
memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
- (sc->quirks & NAVIGATION_CONTROLLER_USB)) {
+ (sc->quirks & NAVIGATION_CONTROLLER_USB) ||
+ (sc->quirks & NYKO_CORE_CONTROLLER)) {
buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -2218,7 +2308,8 @@ static int sony_set_device_id(struct sony_sc *sc)
* All others are set to -1.
*/
if ((sc->quirks & SIXAXIS_CONTROLLER) ||
- (sc->quirks & DUALSHOCK4_CONTROLLER)) {
+ (sc->quirks & DUALSHOCK4_CONTROLLER) ||
+ (sc->quirks & NYKO_CORE_CONTROLLER)) {
ret = ida_simple_get(&sony_device_id_allocator, 0, 0,
GFP_KERNEL);
if (ret < 0) {
@@ -2320,6 +2411,9 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
ret = sixaxis_set_operational_usb(hdev);
sony_init_work(sc, sixaxis_state_worker);
+ } else if (sc->quirks & NYKO_CORE_CONTROLLER) {
+ ret = sixaxis_set_operational_usb(hdev);
+ sony_init_work(sc, nyko_state_worker);
} else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) ||
(sc->quirks & NAVIGATION_CONTROLLER_BT)) {
/*
@@ -2458,6 +2552,9 @@ static const struct hid_device_id sony_devices[] = {
.driver_data = DUALSHOCK4_CONTROLLER_USB },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
.driver_data = DUALSHOCK4_CONTROLLER_BT },
+ /* Nyko Core Controller for PS3 */
+ { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
+ .driver_data = NYKO_CORE_CONTROLLER },
{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);