diff options
| author | RaySlash <stevemathewjoy@gmail.com> | 2023-10-02 13:08:52 +1000 |
|---|---|---|
| committer | RaySlash <stevemathewjoy@gmail.com> | 2023-10-02 22:14:57 +1000 |
| commit | 75006183d0a379a2b0fa844fc32b3e27d229f368 (patch) | |
| tree | e69dcd71c1071fb973ea61c5f41f22d48c7b5d9b /hid-tmt300rs.c | |
| parent | b2872a893afd0f9cd0bfd4644348f3b8645edbed (diff) | |
| download | hid-tmff2-75006183d0a379a2b0fa844fc32b3e27d229f368.tar.gz hid-tmff2-75006183d0a379a2b0fa844fc32b3e27d229f368.zip | |
src: initial refactoring
Diffstat (limited to 'hid-tmt300rs.c')
| -rw-r--r-- | hid-tmt300rs.c | 1714 |
1 files changed, 0 insertions, 1714 deletions
diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c deleted file mode 100644 index 4499687..0000000 --- a/hid-tmt300rs.c +++ /dev/null @@ -1,1714 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#include <linux/usb.h> -#include <linux/hid.h> -#include "hid-tmff2.h" - -#define T300RS_MAX_EFFECTS 16 -#define T300RS_NORM_BUFFER_LENGTH 63 -#define T300RS_PS4_BUFFER_LENGTH 31 - -#define T300RS_DEFAULT_ATTACHMENT 0x06 -#define T300RS_F1_ATTACHMENT 0x03 - -static const unsigned long t300rs_params = - PARAM_SPRING_LEVEL - | PARAM_DAMPER_LEVEL - | PARAM_FRICTION_LEVEL - | PARAM_GAIN - | PARAM_RANGE - | PARAM_ALT_MODE - ; - -static const signed short t300rs_effects[] = { - FF_CONSTANT, - FF_RAMP, - FF_SPRING, - FF_DAMPER, - FF_FRICTION, - FF_INERTIA, - FF_PERIODIC, - FF_SINE, - FF_TRIANGLE, - FF_SQUARE, - FF_SAW_UP, - FF_SAW_DOWN, - FF_AUTOCENTER, - FF_GAIN, - -1 -}; - -struct __packed t300rs_fw_response { - uint8_t unused1[2]; - uint8_t fw_version; - uint8_t unused2; -}; - - -struct __packed t300rs_packet_header { - uint8_t zero1; - uint8_t id; - uint8_t code; -}; - -struct __packed t300rs_setup_header { - uint8_t cmd; - uint8_t code; -}; - -struct __packed t300rs_packet_envelope { - uint16_t attack_length; - uint16_t attack_level; - uint16_t fade_length; - uint16_t fade_level; -}; - -struct __packed t300rs_packet_timing { - uint8_t start_marker; - uint16_t duration; - uint8_t zero1[2]; - uint16_t offset; - uint8_t zero2; - uint16_t end_marker; -}; - -struct usb_ctrlrequest t300rs_fw_request = { - .bRequestType = 0xc1, - .bRequest = 86, - .wValue = 0, - .wIndex = 0, - .wLength = 8 -}; - -struct t300rs_data { - unsigned long quirks; - void *device_props; -}; - -static u8 t300rs_rdesc_nrm_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x04, /* Usage (Joystick) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x85, 0x07, /* Report ID (7) */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) (Brake) */ - 0x26, 0xff, 0x03, /* Logical maximum (1023) */ - 0x46, 0xff, 0x03, /* Physical maximum (1023) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x32, /* Usage (Z) (Gas) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) (Clutch) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x0d, /* Usage maximum (13) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x45, 0x01, /* Physical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x0d, /* Report count (13) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x75, 0x0b, /* Report size (13) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x03, /* Usage (Variable, Absolute, Constant) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x25, 0x07, /* Logical maximum (7) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x55, 0x00, /* Unit exponent (0) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Unit (None) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x85, 0x60, /* Report ID (96), prev 10 */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x60, /* Usage (96), prev 10 */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x3f, /* Report count (63) */ - 0x26, 0xff, 0x7f, /* Logical maximum (32767) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x46, 0xff, 0x7f, /* Physical maximum (32767) */ - 0x36, 0x00, 0x80, /* Physical minimum (-32768) */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x02, /* Report ID (2) */ - 0x09, 0x02, /* Usage (2) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x14, /* Usage (20) */ - 0x85, 0x14, /* Report ID (20) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0xc0, /* End collection */ - 0xc0, /* End collection */ -}; - -static u8 t300rs_rdesc_adv_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x04, /* Usage (Joystick) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x85, 0x07, /* Report ID (7) */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x31, /* Usage (Y) */ - 0x26, 0xff, 0x03, /* Logical maximum (1023) */ - 0x46, 0xff, 0x03, /* Physical maximum (1023) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x35, /* Usage (Rz) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x36, /* Usage (Slider) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) ? */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x19, /* Usage maximum (25) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x45, 0x01, /* Physical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x19, /* Report count (25) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x75, 0x03, /* Report size (3) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x03, /* Input (Variable, Absolute, Constant) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x25, 0x07, /* Logical maximum (7) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x55, 0x00, /* Unit exponent (0) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Unit (None) */ - 0x85, 0x60, /* Report ID (96), prev 10 */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x60, /* Usage (96), prev 10 (why?) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x3f, /* Report count (63) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x46, 0xff, 0x00, /* Physical maximum (255) */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x02, /* Report ID (2) */ - 0x09, 0x02, /* Usage (Mouse) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x14, /* Usage (20) */ - 0x85, 0x14, /* Report ID (20) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0xc0, /* End collection */ - 0xc0, /* End collection */ -}; - -static u8 t300rs_rdesc_ps4_fixed[] = { - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x05, /* Usage (GamePad) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x85, 0x01, /* Report ID (1) */ - 0x09, 0x00, /* Usage (U) (was X) */ - 0x09, 0x00, /* Usage (U) (was Y) */ - 0x09, 0x00, /* Usage (U) (was Z) */ - 0x09, 0x00, /* Usage (U) (was Rz)*/ - 0x15, 0x00, /* Logical minimum (0) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x04, /* Report count (4) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x09, 0x39, /* Usage (Hat Switch) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x25, 0x07, /* Logical maximum (7)*/ - 0x35, 0x00, /* Physical minimum (0) */ - 0x46, 0x3b, 0x01, /* Physical maximum (315) */ - 0x65, 0x14, /* Unit (Eng Rot, Angular Pos) */ - 0x75, 0x04, /* Report size (4) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x42, /* Input (Variable, Absolute, NullState) */ - 0x65, 0x00, /* Input (None) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x01, /* Usage minimum (1) */ - 0x29, 0x0e, /* Usage maximum (14) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x0e, /* Report size (14) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x06, 0x00, 0xff, /* Usage page (Vendor 1) */ - 0x09, 0x20, /* Usage (32) */ - 0x75, 0x06, /* Report size (6) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x00, /* Usage (U) (was Rx)*/ - 0x09, 0x00, /* Usage (U) (was Ry) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x26, 0xff, 0x00, /* Logical maximum (255) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x02, /* Report count (2) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - 0x05, 0x01, /* Usage page (Vendor 1) */ - /* constant zero? */ - 0x09, 0x00, /* Usage (33) */ - 0x95, 0x21, /* Report count (33) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* wheel */ - 0x09, 0x30, /* Usage (X) */ - 0x15, 0x00, /* Logical minimum (0) */ - 0x27, 0xff, 0xff, 0x00, 0x00, /* Logical maximum (65535) */ - 0x35, 0x00, /* Physical minimum (0) */ - 0x47, 0xff, 0xff, 0x00, 0x00, /* Physical maximum (65535) */ - 0x75, 0x10, /* Report size (16) */ - 0x95, 0x01, /* Report count (1) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* gas */ - 0x09, 0x31, /* Usage (Y) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* brake */ - 0x09, 0x32, /* Usage (Z) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* clutch */ - 0x09, 0x35, /* Usage (Rz) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* stick shifter (check model no) */ - 0x05, 0x09, /* Usage page (Button) */ - 0x19, 0x0f, /* Usage minimum (15) */ - 0x29, 0x17, /* Usage maximum (23) */ - 0x15, 0x00, /* Logical minimum (1) */ - 0x25, 0x01, /* Logical maximum (1) */ - 0x75, 0x01, /* Report size (1) */ - 0x95, 0x08, /* Report count (8) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* no clue */ - 0x05, 0x01, /* Usage page (Generic Desktop) */ - 0x09, 0x00, /* Usage (U) */ - 0x75, 0x08, /* Report size (8) */ - 0x95, 0x0c, /* Report count (12) */ - 0x81, 0x02, /* Input (Variable, Absolute) */ - /* continue unmodified */ - 0x06, 0x00, 0xff, /* Usage page (Vendor defined 1) */ - 0x85, 0x60, /* Report ID (5) (change to 0x60?) */ - 0x09, 0x60, /* Usage (34) (change to 0x60?) */ - 0x95, 0x1f, /* Report count (31) () */ - 0x91, 0x02, /* Output (Variable, Absolute) */ - 0x85, 0x03, /* Report ID (3) */ - 0x0a, 0x21, 0x27, /* ??? */ - 0x95, 0x2f, /* Report count (47) */ - 0xb1, 0x02, /* Feature (Data, Var, Abs) */ - 0xc0, /* End collection */ - - /* From here on out no clue */ - 0x06, 0xf0, - 0xff, 0x09, - 0x40, 0xa1, - 0x01, 0x85, - 0xf0, 0x09, - 0x47, 0x95, - 0x3f, 0xb1, - 0x02, 0x85, - 0xf1, 0x09, - 0x48, 0x95, - 0x3f, 0xb1, - 0x02, 0x85, - 0xf2, 0x09, - 0x49, 0x95, - 0x0f, 0xb1, - 0x02, 0x85, - 0xf3, 0x0a, - 0x01, 0x47, - 0x95, 0x07, - 0xb1, 0x02, - 0xc0, -}; - -static u8 spring_values[] = { - 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xdf, 0x58, 0xa6, - 0x6a, 0x06 -}; - -static u8 damper_values[] = { - 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xfc, 0x7f, 0xfc, - 0x7f, 0x07 -}; - -int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) -{ - int i; - /* check that send_buffer fits into our report */ - if (len > t300rs->buffer_length) - return -EINVAL; - - /* fill with actual data */ - for (i = 0; i < len; ++i) - t300rs->ff_field->value[i] = send_buffer[i]; - - /* fill the rest with zeroes */ - for (i = len; i < t300rs->buffer_length; ++i) - t300rs->ff_field->value[i] = 0; - - hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT); - return 0; -} - -int t300rs_send_int(struct t300rs_device_entry *t300rs) -{ - t300rs_send_buf(t300rs, t300rs->send_buffer, t300rs->buffer_length); - memset(t300rs->send_buffer, 0, t300rs->buffer_length); - - return 0; -} - -static void t300rs_fill_header(struct t300rs_packet_header *packet_header, - uint8_t id, uint8_t code) -{ - packet_header->id = id + 1; - packet_header->code = code; -} - -int t300rs_play_effect(void *data, struct tmff2_effect_state *state) -{ - struct t300rs_device_entry *t300rs = data; - struct __packed t300rs_packet_play { - struct t300rs_packet_header header; - uint8_t value; - } *play_packet = (struct t300rs_packet_play *)t300rs->send_buffer; - - int ret; - - - t300rs_fill_header(&play_packet->header, state->effect.id, 0x89); - play_packet->value = 0x01; - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed starting effect play\n"); - - return ret; -} - -int t300rs_stop_effect(void *data, struct tmff2_effect_state *state) -{ - struct t300rs_device_entry *t300rs = data; - struct __packed t300rs_packet_stop { - struct t300rs_packet_header header; - uint8_t value; - } *stop_packet = (struct t300rs_packet_stop *)t300rs->send_buffer; - - int ret; - - - t300rs_fill_header(&stop_packet->header, state->effect.id, 0x89); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed stopping effect play\n"); - - return ret; -} - -static void t300rs_fill_envelope(struct t300rs_packet_envelope *packet_envelope, - int16_t level, uint16_t duration, struct ff_envelope *envelope) -{ - uint16_t attack_length = (duration * envelope->attack_length) / 0x7fff; - uint16_t attack_level = (level * envelope->attack_level) / 0x7fff; - uint16_t fade_length = (duration * envelope->fade_length) / 0x7fff; - uint16_t fade_level = (level * envelope->fade_level) / 0x7fff; - - packet_envelope->attack_length = cpu_to_le16(attack_length); - packet_envelope->attack_level = cpu_to_le16(attack_level); - packet_envelope->fade_length = cpu_to_le16(fade_length); - packet_envelope->fade_level = cpu_to_le16(fade_level); -} - -static void t300rs_fill_timing(struct t300rs_packet_timing *packet_timing, - uint16_t duration, uint16_t offset){ - packet_timing->start_marker = 0x4f; - - packet_timing->duration = cpu_to_le16(duration); - packet_timing->offset = cpu_to_le16(offset); - - packet_timing->end_marker = 0xffff; -} - -static int t300rs_update_envelope(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, - int16_t level, - uint16_t duration, - uint8_t id, - struct ff_envelope envelope, - struct ff_envelope envelope_old - ) -{ - struct __packed t300rs_packet_mod_envelope { - struct t300rs_packet_header header; - uint8_t attribute; - uint16_t value; - } *packet_mod_envelope = (struct t300rs_packet_mod_envelope *)t300rs->send_buffer; - - uint16_t attack_length, attack_level, fade_length, fade_level; - int ret = 0; - - duration = duration - 1; - - attack_length = (duration * envelope.attack_length) / 0x7fff; - attack_level = (level * envelope.attack_level) / 0x7fff; - fade_length = (duration * envelope.fade_length) / 0x7fff; - fade_level = (level * envelope.fade_level) / 0x7fff; - - if (envelope.attack_length != envelope_old.attack_length) { - t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); - packet_mod_envelope->attribute = 0x81; - packet_mod_envelope->value = cpu_to_le16(attack_length); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.attack_level != envelope_old.attack_level) { - t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); - packet_mod_envelope->attribute = 0x82; - packet_mod_envelope->value = cpu_to_le16(attack_level); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.fade_length != envelope_old.fade_length) { - t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); - packet_mod_envelope->attribute = 0x84; - packet_mod_envelope->value = cpu_to_le16(fade_length); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - - if (envelope.fade_level != envelope_old.fade_level) { - t300rs_fill_header(&packet_mod_envelope->header, id, 0x31); - packet_mod_envelope->attribute = 0x88; - packet_mod_envelope->value = cpu_to_le16(fade_level); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying effect envelope\n"); - goto error; - } - } - -error: - return ret; -} - -static int t300rs_update_simple_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, unsigned type) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint16_t marker; - uint16_t duration; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); - packet_mod_duration->marker = cpu_to_le16(0x4100 + type); - packet_mod_duration->duration = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_periodic_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state, unsigned type) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint8_t type; - uint8_t marker; - uint16_t duration; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x49); - packet_mod_duration->type = type; - packet_mod_duration->marker = 0x41; - packet_mod_duration->duration = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_ramp_duration(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct __packed t300rs_packet_mod_duration { - struct t300rs_packet_header header; - uint8_t marker0; - uint16_t duration0; - uint8_t marker1; - uint8_t marker2; - uint16_t duration1; - } *packet_mod_duration = (struct t300rs_packet_mod_duration *)t300rs->send_buffer; - - uint16_t duration; - int ret = 0; - - duration = effect.replay.length - 1; - - t300rs_fill_header(&packet_mod_duration->header, effect.id, 0x4e); - packet_mod_duration->marker0 = 0x08; - packet_mod_duration->duration0 = cpu_to_le16(duration); - packet_mod_duration->marker1 = 0x05; - packet_mod_duration->marker2 = 0x41; - packet_mod_duration->duration1 = cpu_to_le16(duration); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_constant(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_effect old = state->old; - struct ff_constant_effect constant = effect.u.constant; - struct ff_constant_effect constant_old = old.u.constant; - struct __packed t300rs_packet_mod_constant { - struct t300rs_packet_header header; - uint16_t level; - } *packet_mod_constant = (struct t300rs_packet_mod_constant *)t300rs->send_buffer; - int ret; - int16_t level; - - level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - - if ((constant.level != constant_old.level) || (effect.direction != old.direction)) { - - t300rs_fill_header(&packet_mod_constant->header, effect.id, 0x0a); - packet_mod_constant->level = cpu_to_le16(level); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant effect\n"); - goto error; - } - - } - - ret = t300rs_update_envelope(t300rs, - state, - level, - effect.replay.length, - effect.id, - constant.envelope, - constant_old.envelope - ); - - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant envelope\n"); - goto error; - } - - ret = t300rs_update_simple_duration(t300rs, state, 0x00); - if (ret) { - hid_err(t300rs->hdev, "failed modifying constant duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_ramp(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_effect old = state->old; - struct ff_ramp_effect ramp = effect.u.ramp; - struct ff_ramp_effect ramp_old = old.u.ramp; - struct __packed t300rs_packet_mod_ramp { - struct t300rs_packet_header header; - uint8_t attribute; - uint16_t difference; - uint16_t level; - } *packet_mod_ramp = (struct t300rs_packet_mod_ramp *)t300rs->send_buffer; - - int ret; - - uint16_t difference, top, bottom; - int16_t level; - - top = ramp.end_level > ramp.start_level ? ramp.end_level : ramp.start_level; - bottom = ramp.end_level > ramp.start_level ? ramp.start_level : ramp.end_level; - - - difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - - - level = (top * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - - if ((ramp.start_level != ramp_old.start_level) - || (ramp.end_level != ramp_old.end_level) - || (effect.direction != old.direction)) { - - t300rs_fill_header(&packet_mod_ramp->header, effect.id, 0x0e); - packet_mod_ramp->attribute = 0x03; - packet_mod_ramp->difference = cpu_to_le16(difference); - packet_mod_ramp->level = cpu_to_le16(level); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying ramp effect\n"); - goto error; - } - - } - - ret = t300rs_update_envelope(t300rs, - state, - level, - effect.replay.length, - effect.id, - ramp.envelope, - ramp_old.envelope - ); - - - if (ret) { - hid_err(t300rs->hdev, "failed modifying ramp envelope\n"); - goto error; - } - - ret = t300rs_update_ramp_duration(t300rs, state); - if (ret) { - hid_err(t300rs->hdev, "failed modifying ramp duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_damper(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_effect old = state->old; - struct ff_condition_effect damper = effect.u.condition[0]; - struct ff_condition_effect damper_old = old.u.condition[0]; - struct __packed t300rs_packet_mod_damper { - struct t300rs_packet_header header; - uint8_t attribute; - uint16_t value0; - uint16_t value1; - } *packet_mod_damper = (struct t300rs_packet_mod_damper *)t300rs->send_buffer; - - int ret, input_level; - - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; - - if (state->effect.type == FF_SPRING) - input_level = spring_level; - - if (damper.right_coeff != damper_old.right_coeff) { - int16_t coeff = damper.right_coeff * input_level / 100; - - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x41; - packet_mod_damper->value0 = cpu_to_le16(coeff); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying damper rc\n"); - goto error; - } - - } - - if (damper.left_coeff != damper_old.left_coeff) { - int16_t coeff = damper.left_coeff * input_level / 100; - - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x42; - packet_mod_damper->value0 = cpu_to_le16(coeff); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying damper lc\n"); - goto error; - } - - } - - if ((damper.deadband != damper_old.deadband) - || (damper.center != damper_old.center)) { - - uint16_t right_deadband = 0xfffe - damper.deadband - damper.center; - uint16_t left_deadband = 0xfffe - damper.deadband + damper.center; - - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x4c; - packet_mod_damper->value0 = cpu_to_le16(right_deadband); - packet_mod_damper->value1 = cpu_to_le16(left_deadband); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying damper deadband\n"); - goto error; - } - - } - - ret = t300rs_update_simple_duration(t300rs, state, 0x06); - if (ret) { - hid_err(t300rs->hdev, "failed modifying damper duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_update_spring(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - return t300rs_update_damper(t300rs, state); -} - - -static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_effect old = state->old; - struct ff_periodic_effect periodic = effect.u.periodic; - struct ff_periodic_effect periodic_old = old.u.periodic; - struct __packed t300rs_packet_mod_periodic { - struct t300rs_packet_header header; - uint8_t attribute; - uint16_t value; - } *packet_mod_periodic = (struct t300rs_packet_mod_periodic *)t300rs->send_buffer; - - int ret; - int16_t magnitude, phase; - - magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - phase = periodic.phase; - - if ((periodic.magnitude != periodic_old.magnitude) - || (effect.direction != old.direction)) { - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x01; - packet_mod_periodic->value = cpu_to_le16(magnitude); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic magnitude\n"); - goto error; - } - - } - - if (periodic.offset != periodic_old.offset) { - uint16_t offset = periodic.offset; - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x02; - packet_mod_periodic->value = cpu_to_le16(offset); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic offset\n"); - goto error; - } - - } - - if (periodic.phase != periodic_old.phase) { - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x04; - packet_mod_periodic->value = cpu_to_le16(phase); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic phase\n"); - goto error; - } - - } - - if (periodic.period != periodic_old.period) { - int16_t period = periodic.period; - - t300rs_fill_header(&packet_mod_periodic->header, effect.id, 0x0e); - packet_mod_periodic->attribute = 0x08; - packet_mod_periodic->value = cpu_to_le16(period); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic period\n"); - goto error; - } - - } - - ret = t300rs_update_envelope(t300rs, - state, - magnitude, - effect.replay.length, - effect.id, - periodic.envelope, - periodic_old.envelope - ); - - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic envelope\n"); - goto error; - } - - ret = t300rs_update_periodic_duration(t300rs, state, periodic.waveform - 0x57); - if (ret) { - hid_err(t300rs->hdev, "failed modifying periodic duration\n"); - goto error; - } - -error: - return ret; -} - -static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_constant_effect constant = state->effect.u.constant; - struct __packed t300rs_packet_constant { - struct t300rs_packet_header header; - uint16_t level; - struct t300rs_packet_envelope envelope; - uint8_t zero; - struct t300rs_packet_timing timing; - } *packet_constant = (struct t300rs_packet_constant *)t300rs->send_buffer; - - int16_t level; - uint16_t duration, offset; - - int ret; - - level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - duration = effect.replay.length - 1; - - offset = effect.replay.delay; - - t300rs_fill_header(&packet_constant->header, effect.id, 0x6a); - - packet_constant->level = cpu_to_le16(level); - - t300rs_fill_envelope(&packet_constant->envelope, level, duration, - &constant.envelope); - t300rs_fill_timing(&packet_constant->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading constant effect\n"); - - return ret; -} - -static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_ramp_effect ramp = state->effect.u.ramp; - struct __packed t300rs_packet_ramp { - struct t300rs_packet_header header; - uint16_t difference; - uint16_t level; - uint8_t zero1[2]; - uint16_t duration; - uint16_t marker; - struct t300rs_packet_envelope envelope; - uint8_t direction; - struct t300rs_packet_timing timing; - } *packet_ramp = (struct t300rs_packet_ramp *)t300rs->send_buffer; - - int ret; - uint16_t difference, offset, top, bottom, duration; - int16_t level; - - duration = effect.replay.length - 1; - - top = ramp.end_level > ramp.start_level ? ramp.end_level : ramp.start_level; - bottom = ramp.end_level > ramp.start_level ? ramp.start_level : ramp.end_level; - - - difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - level = (top * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - offset = effect.replay.delay; - - - t300rs_fill_header(&packet_ramp->header, effect.id, 0x6b); - - packet_ramp->difference = cpu_to_le16(difference); - packet_ramp->level = cpu_to_le16(level); - packet_ramp->duration = cpu_to_le16(duration); - - packet_ramp->marker = cpu_to_le16(0x8000); - - t300rs_fill_envelope(&packet_ramp->envelope, level, duration, - &ramp.envelope); - - packet_ramp->direction = ramp.end_level > ramp.start_level ? 0x04 : 0x05; - t300rs_fill_timing(&packet_ramp->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading ramp"); - - return ret; -} - -static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - struct __packed t300rs_packet_spring { - struct t300rs_packet_header header; - uint16_t right_coeff; - uint16_t left_coeff; - uint16_t right_deadband; - uint16_t left_deadband; - uint8_t spring_start[17]; - struct t300rs_packet_timing timing; - } *packet_spring = (struct t300rs_packet_spring *)t300rs->send_buffer; - - int ret; - uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; - - duration = effect.replay.length - 1; - - right_coeff = spring.right_coeff * spring_level / 100; - left_coeff = spring.left_coeff * spring_level / 100; - - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; - - offset = effect.replay.delay; - - t300rs_fill_header(&packet_spring->header, effect.id, 0x64); - - packet_spring->right_coeff = cpu_to_le16(right_coeff); - packet_spring->left_coeff = cpu_to_le16(left_coeff); - packet_spring->right_deadband = cpu_to_le16(right_deadband); - packet_spring->left_deadband = cpu_to_le16(left_deadband); - - memcpy(&packet_spring->spring_start, spring_values, ARRAY_SIZE(spring_values)); - t300rs_fill_timing(&packet_spring->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading spring\n"); - - return ret; -} - -static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - - struct ff_effect effect = state->effect; - /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - struct __packed t300rs_packet_damper { - struct t300rs_packet_header header; - uint16_t right_coeff; - uint16_t left_coeff; - uint16_t right_deadband; - uint16_t left_deadband; - uint8_t damper_start[17]; - struct t300rs_packet_timing timing; - } *packet_damper = (struct t300rs_packet_damper *)t300rs->send_buffer; - - int ret, input_level; - uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; - - duration = effect.replay.length - 1; - - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; - - right_coeff = spring.right_coeff * input_level / 100; - left_coeff = spring.left_coeff * input_level / 100; - - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; - - offset = effect.replay.delay; - - t300rs_fill_header(&packet_damper->header, effect.id, 0x64); - - packet_damper->right_coeff = cpu_to_le16(right_coeff); - packet_damper->left_coeff = cpu_to_le16(left_coeff); - packet_damper->right_deadband = cpu_to_le16(right_deadband); - packet_damper->left_deadband = cpu_to_le16(left_deadband); - - memcpy(&packet_damper->damper_start, damper_values, ARRAY_SIZE(damper_values)); - t300rs_fill_timing(&packet_damper->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading spring\n"); - - return ret; -} - -static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - struct ff_effect effect = state->effect; - struct ff_periodic_effect periodic = state->effect.u.periodic; - struct __packed t300rs_packet_periodic { - struct t300rs_packet_header header; - uint16_t magnitude; - uint16_t periodic_offset; - uint16_t phase; - uint16_t period; - uint16_t marker; - struct t300rs_packet_envelope envelope; - uint8_t waveform; - struct t300rs_packet_timing timing; - } *packet_periodic = (struct t300rs_packet_periodic *)t300rs->send_buffer; - - int ret; - uint16_t duration, period, offset, periodic_offset; - int16_t phase, magnitude; - - duration = effect.replay.length - 1; - magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff; - - phase = periodic.phase; - periodic_offset = periodic.offset; - - period = periodic.period; - offset = effect.replay.delay; - - t300rs_fill_header(&packet_periodic->header, effect.id, 0x6b); - - packet_periodic->magnitude = cpu_to_le16(magnitude); - packet_periodic->periodic_offset = cpu_to_le16(periodic_offset); - packet_periodic->phase = cpu_to_le16(phase); - packet_periodic->period = cpu_to_le16(period); - - packet_periodic->marker = cpu_to_le16(0x8000); - - t300rs_fill_envelope(&packet_periodic->envelope, magnitude, duration, - &periodic.envelope); - - packet_periodic->waveform = periodic.waveform - 0x57; - - t300rs_fill_timing(&packet_periodic->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading periodic effect"); - - return ret; -} - -int t300rs_update_effect(void *data, struct tmff2_effect_state *state) -{ - struct t300rs_device_entry *t300rs = data; - switch (state->effect.type) { - case FF_CONSTANT: - return t300rs_update_constant(t300rs, state); - case FF_RAMP: - return t300rs_update_ramp(t300rs, state); - case FF_SPRING: - return t300rs_update_spring(t300rs, state); - case FF_DAMPER: - case FF_FRICTION: - case FF_INERTIA: - return t300rs_update_damper(t300rs, state); - case FF_PERIODIC: - return t300rs_update_periodic(t300rs, state); - default: - hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); - return -1; - } -} - -int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) -{ - struct t300rs_device_entry *t300rs = data; - switch (state->effect.type) { - case FF_CONSTANT: - return t300rs_upload_constant(t300rs, state); - case FF_RAMP: - return t300rs_upload_ramp(t300rs, state); - case FF_SPRING: - return t300rs_upload_spring(t300rs, state); - case FF_DAMPER: - case FF_FRICTION: - case FF_INERTIA: - return t300rs_upload_damper(t300rs, state); - case FF_PERIODIC: - return t300rs_upload_periodic(t300rs, state); - default: - hid_err(t300rs->hdev, "invalid effect type: %x", state->effect.type); - return -1; - } -} - -static int t300rs_switch_mode(void *data, uint16_t mode) -{ - struct t300rs_device_entry *t300rs = data; - if (!t300rs) - return -ENODEV; - - if(t300rs->mode == mode) /* already in specified mode */ - return 0; - - if (mode == 0) - /* go to normal mode */ - usb_control_msg(t300rs->usbdev, - usb_sndctrlpipe(t300rs->usbdev, 0), - 83, 0x41, 5, 0, 0, 0, - USB_CTRL_SET_TIMEOUT - ); - else if (mode == 1) - /* go to advanced mode */ - usb_control_msg(t300rs->usbdev, - usb_sndctrlpipe(t300rs->usbdev, 0), - 83, 0x41, 3, 0, 0, 0, - USB_CTRL_SET_TIMEOUT - ); - else - hid_warn(t300rs->hdev, "mode %i not supported\n", mode); - - - return 0; -} - -static struct t300rs_alt_modes { - char *id; - char *label; - uint16_t mode; -} t300rs_modes[] = { - {"base", "T300RS base", 0}, - {"F1", "T300RS with F1 wheel attachment", 1} -}; - -static ssize_t t300rs_alt_mode_show(void *data, char *buf) -{ - struct t300rs_device_entry *t300rs = data; - ssize_t count = 0; - int i; - if (!t300rs) - return -ENODEV; - - if (t300rs->attachment != T300RS_F1_ATTACHMENT) - /* we only support one base mode */ - return scnprintf(buf, PAGE_SIZE, "%s: %s *\n", - t300rs_modes[0].id, t300rs_modes[0].label); - - for (i = 0; i < ARRAY_SIZE(t300rs_modes); ++i) { - count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s", - t300rs_modes[i].id, t300rs_modes[i].label); - - if (count >= PAGE_SIZE - 1) - return count; - - if (t300rs_modes[i].mode == t300rs->mode) - count += scnprintf(buf + count, PAGE_SIZE - count, " *\n"); - else - count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); - - if (count >= PAGE_SIZE - 1) - return count; - } - - return count; -} - -static ssize_t t300rs_alt_mode_store(void *data, const char *buf, size_t count) -{ - struct t300rs_device_entry *t300rs = data; - int i, len, mode_len; - char *lbuf; - if (!t300rs) - return -ENODEV; - - if (t300rs->attachment != T300RS_F1_ATTACHMENT) - return count; /* don't do anything */ - - lbuf = kasprintf(GFP_KERNEL, "%s", buf); - if (!lbuf) - return -ENOMEM; - - len = strlen(buf); - for (i = 0; i < ARRAY_SIZE(t300rs_modes); ++i) { - mode_len = strlen(t300rs_modes[i].id); - if (mode_len > len) - continue; - - if (strncmp(lbuf, t300rs_modes[i].id, mode_len) == 0) { - t300rs_switch_mode(data, t300rs_modes[i].mode); - break; - } - } - - kfree(lbuf); - return count; -} - -int t300rs_set_autocenter(void *data, uint16_t value) -{ - struct t300rs_device_entry *t300rs = data; - struct __packed t300rs_packet_autocenter { - struct t300rs_setup_header header; - uint16_t value; - } *autocenter_packet; - int ret; - - if (!t300rs) - return -ENODEV; - - /* TODO: this should probably also use a separately allocated buffer? */ - autocenter_packet = (struct t300rs_packet_autocenter *)t300rs->send_buffer; - - autocenter_packet->header.cmd = 0x08; - autocenter_packet->header.code = 0x04; - autocenter_packet->value = cpu_to_le16(0x01); - - if ((ret = t300rs_send_int(t300rs))) { - hid_err(t300rs->hdev, "failed setting autocenter"); - return ret; - } - - autocenter_packet->header.cmd = 0x08; - autocenter_packet->header.code = 0x03; - - autocenter_packet->value = cpu_to_le16(value); - - if ((ret = t300rs_send_int(t300rs))) - hid_err(t300rs->hdev, "failed setting autocenter"); - - return ret; -} - -int t300rs_set_gain(void *data, uint16_t gain) -{ - struct t300rs_device_entry *t300rs = data; - struct __packed t300rs_packet_gain { - struct t300rs_setup_header header; - } *gain_packet; - int ret; - - if (!t300rs) - return -ENODEV; - - gain_packet = (struct t300rs_packet_gain *)t300rs->send_buffer; - gain_packet->header.cmd = 0x02; - gain_packet->header.code = (gain >> 8) & 0xff; - - if ((ret = t300rs_send_int(t300rs))) - hid_err(t300rs->hdev, "failed setting gain: %i\n", ret); - - return ret; -} - -int t300rs_set_range(void *data, uint16_t value) -{ - struct t300rs_device_entry *t300rs = data; - /* it's important that we don't use t300rs->send_buffer, as range can be - * set from outside of the FFB environment, and we don't want to - * accidentally overwrite any data. */ - u8 *send_buffer = kzalloc(t300rs->buffer_length, GFP_KERNEL); - uint16_t scaled_value; - int ret; - - if (value < 40) { - hid_info(t300rs->hdev, "value %i too small, clamping to 40\n", value); - value = 40; - } - - if (value > 1080) { - hid_info(t300rs->hdev, "value %i too large, clamping to 1080\n", value); - value = 1080; - } - - if (!send_buffer) { - ret = -EINVAL; - hid_err(t300rs->hdev, "could not allocate send_buffer\n"); - goto err; - } - - scaled_value = value * 0x3c; - send_buffer[0] = 0x08; - send_buffer[1] = 0x11; - send_buffer[2] = scaled_value & 0xff; - send_buffer[3] = scaled_value >> 8; - - if ((ret = t300rs_send_buf(t300rs, send_buffer, t300rs->buffer_length))) - hid_warn(t300rs->hdev, "failed setting range\n"); - - /* since everythin went OK, update the current range */ - range = value; -err: - kfree(send_buffer); - return ret; -} - -static int t300rs_send_open(struct t300rs_device_entry *t300rs) -{ - struct __packed t300rs_packet_open { - struct t300rs_setup_header header; - } *open_packet; - - open_packet = (struct t300rs_packet_open *)t300rs->send_buffer; - open_packet->header.cmd = 0x01; - open_packet->header.code = 0x05; - - return t300rs_send_int(t300rs); -} - -static int t300rs_send_close(struct t300rs_device_entry *t300rs) -{ - struct __packed t300rs_packet_open { - struct t300rs_setup_header header; - } *open_packet; - - open_packet = (struct t300rs_packet_open *)t300rs->send_buffer; - open_packet->header.cmd = 0x01; - - return t300rs_send_int(t300rs); -} - -int t300rs_open(void *data, int open_mode) -{ - struct t300rs_device_entry *t300rs = data; - if (!t300rs) - return -ENODEV; - - if (open_mode && t300rs_send_open(t300rs)) - hid_warn(t300rs->hdev, "failed sending open command\n"); - - return t300rs->open(t300rs->input_dev); -} - -int t300rs_close(void *data, int open_mode) -{ - struct t300rs_device_entry *t300rs = data; - int ret; - - if (!t300rs) - return -ENODEV; - - if (open_mode && (ret = t300rs_send_close(t300rs))) - hid_warn(t300rs->hdev, "failed sending close command\n"); - - t300rs->close(t300rs->input_dev); - return ret; -} - -static int t300rs_check_firmware(struct t300rs_device_entry *t300rs) -{ - int ret; - struct t300rs_fw_response *fw_response = - kzalloc(sizeof(struct t300rs_fw_response), GFP_KERNEL); - - if (!fw_response) { - hid_err(t300rs->hdev, "could not allocate fw_response\n"); - return -ENOMEM; - } - - /* Fetch firmware version */ - ret = usb_control_msg(t300rs->usbdev, - usb_rcvctrlpipe(t300rs->usbdev, 0), - t300rs_fw_request.bRequest, - t300rs_fw_request.bRequestType, - t300rs_fw_request.wValue, - t300rs_fw_request.wIndex, - fw_response, - t300rs_fw_request.wLength, - USB_CTRL_SET_TIMEOUT - ); - - if (ret < 0) { - hid_err(t300rs->hdev, "could not fetch firmware version: %i\n", ret); - goto out; - } - - /* Educated guess */ - if (fw_response->fw_version < 31 && ret >= 0) { - hid_err(t300rs->hdev, - "firmware version %i is too old, please update.\n", - fw_response->fw_version - ); - - hid_info(t300rs->hdev, "note: this has to be done through Windows.\n"); - - ret = -EINVAL; - goto out; - } - - /* everything OK */ - ret = 0; - -out: - kfree(fw_response); - return ret; -} - -static int t300rs_get_attachment(struct t300rs_device_entry *t300rs) -{ - /* taken directly from hid_tminit */ - struct __packed t300rs_attachment_response - { - uint16_t type; - - union { - struct __packed { - uint16_t field0; - uint16_t field1; - uint8_t attachment; - uint8_t model; - uint16_t field2; - uint16_t field3; - uint16_t field4; - uint16_t field5; - } a; - - struct __packed { - uint16_t field0; - uint16_t field1; - uint8_t attachment; - uint8_t model; - } b; - }; - } *response = kzalloc(GFP_KERNEL, sizeof(struct t300rs_attachment_response)); - struct usb_ctrlrequest t300rs_attachment_rq = { - .bRequestType = 0xc1, - .bRequest = 73, - .wValue = 0, - .wIndex = 0, - .wLength = sizeof(struct t300rs_attachment_response) - }; - int ret, attachment; - if (!response) - return -ENODEV; - - ret = usb_control_msg(t300rs->usbdev, - usb_rcvctrlpipe(t300rs->usbdev, 0), - t300rs_attachment_rq.bRequest, - t300rs_attachment_rq.bRequestType, - t300rs_attachment_rq.wValue, - t300rs_attachment_rq.wIndex, - response, - sizeof(struct t300rs_attachment_response), - USB_CTRL_SET_TIMEOUT - ); - - if (ret < 0) { - hid_err(t300rs->hdev, "could not fetch attachment: %i\n", ret); - goto out; - } - - if (response->type == cpu_to_le16(0x49)) { - attachment = response->a.attachment; - } else if (response->type == cpu_to_le16(0x47)) { - attachment = response->b.attachment; - } else { - hid_err(t300rs->hdev, "unknown packet type %hx\n, please contact a maintainer", - response->type); - ret = -EINVAL; - goto out; - } - - kfree(response); - return attachment; - -out: - kfree(response); - return ret; -} - -static int t300rs_wheel_init(struct tmff2_device_entry *tmff2, int open_mode) -{ - struct t300rs_device_entry *t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL); - struct list_head *report_list; - int ret; - - if (!t300rs) { - ret = -ENOMEM; - goto t300rs_err; - } - - t300rs->hdev = tmff2->hdev; - t300rs->input_dev = tmff2->input_dev; - t300rs->usbdev = to_usb_device(tmff2->hdev->dev.parent->parent); - - if(t300rs->hdev->product == TMT300RS_PS4_NORM_ID) - t300rs->buffer_length = T300RS_PS4_BUFFER_LENGTH; - else - t300rs->buffer_length = T300RS_NORM_BUFFER_LENGTH; - - t300rs->send_buffer = kzalloc(t300rs->buffer_length, GFP_KERNEL); - if (!t300rs->send_buffer) { - ret = -ENOMEM; - goto send_err; - } - - if ((ret = t300rs_check_firmware(t300rs))) - goto firmware_err; - - report_list = &t300rs->hdev->report_enum[HID_OUTPUT_REPORT].report_list; - - /* because we set the rdesc, we know exactly which report and field to use */ - t300rs->report = list_entry(report_list->next, struct hid_report, list); - t300rs->ff_field = t300rs->report->field[0]; - - t300rs->open = t300rs->input_dev->open; - t300rs->close = t300rs->input_dev->close; - - /* TODO: PS4 advanced mode? */ - alt_mode = (t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID)); - if ((t300rs->attachment = t300rs_get_attachment(t300rs)) < 0) - t300rs->attachment = T300RS_DEFAULT_ATTACHMENT; - - /* everythin went OK */ - tmff2->data = t300rs; - tmff2->params = t300rs_params; - tmff2->max_effects = T300RS_MAX_EFFECTS; - memcpy(tmff2->supported_effects, t300rs_effects, sizeof(t300rs_effects)); - - if (!open_mode) - t300rs_send_open(t300rs); - - hid_info(t300rs->hdev, "force feedback for T300RS\n"); - return 0; - -firmware_err: - kfree(t300rs->send_buffer); -send_err: - kfree(t300rs); -t300rs_err: - hid_err(tmff2->hdev, "failed initializing T300RS\n"); - return ret; -} - -static int t300rs_wheel_destroy(void *data) -{ - struct t300rs_device_entry *t300rs = data; - if (!t300rs) - return -ENODEV; - - kfree(t300rs->send_buffer); - kfree(t300rs); - return 0; -} - -static __u8 *t300rs_wheel_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -{ - switch (hdev->product) { - case TMT300RS_PS3_NORM_ID: - /* normal PS3 mode */ - rdesc = t300rs_rdesc_nrm_fixed; - *rsize = sizeof(t300rs_rdesc_nrm_fixed); - break; - - case TMT300RS_PS4_NORM_ID: - /* PS4 normal mode */ - rdesc = t300rs_rdesc_ps4_fixed; - *rsize = sizeof(t300rs_rdesc_ps4_fixed); - break; - - case TMT300RS_PS3_ADV_ID: - /* PS3 advanced mode */ - rdesc = t300rs_rdesc_adv_fixed; - *rsize = sizeof(t300rs_rdesc_adv_fixed); - break; - } - - return rdesc; -} - -int t300rs_populate_api(struct tmff2_device_entry *tmff2) -{ - /* set callbacks */ - tmff2->play_effect = t300rs_play_effect; - tmff2->upload_effect = t300rs_upload_effect; - tmff2->update_effect = t300rs_update_effect; - tmff2->stop_effect = t300rs_stop_effect; - - tmff2->wheel_init = t300rs_wheel_init; - tmff2->wheel_destroy = t300rs_wheel_destroy; - - tmff2->open = t300rs_open; - tmff2->close = t300rs_close; - tmff2->set_gain = t300rs_set_gain; - tmff2->set_range = t300rs_set_range; - tmff2->switch_mode = t300rs_switch_mode; - tmff2->alt_mode_show = t300rs_alt_mode_show; - tmff2->alt_mode_store = t300rs_alt_mode_store; - tmff2->set_autocenter = t300rs_set_autocenter; - tmff2->wheel_fixup = t300rs_wheel_fixup; - - return 0; -} |
