From 41c46e46415bfe9d393a5a3858f0c58f0a914c6b Mon Sep 17 00:00:00 2001 From: Kimplul Date: Fri, 25 Mar 2022 14:14:18 +0200 Subject: change alternate mode handling --- hid-tmff2.c | 45 ++++++++++++++++------------------ hid-tmff2.h | 5 ++++ hid-tmt300rs.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 27 deletions(-) diff --git a/hid-tmff2.c b/hid-tmff2.c index f5202ae..12e8e25 100644 --- a/hid-tmff2.c +++ b/hid-tmff2.c @@ -199,40 +199,34 @@ static ssize_t range_show(struct device *dev, } static DEVICE_ATTR_RW(range); -static ssize_t alt_mode_store(struct device *dev, +static ssize_t alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); - unsigned int value; - int ret; - if (!tmff2) return -ENODEV; - if ((ret = kstrtouint(buf, 0, &value))) { - hid_err(tmff2->hdev, "kstrtouint failed at alt_mode_store: %i", ret); - return ret; - } - - if (tmff2->switch_mode) { - if ((ret = tmff2->switch_mode(tmff2->data, value))) - return ret; - } + if (tmff2->alt_mode_store) + return tmff2->alt_mode_store(tmff2->data, buf, count); - return count; + return 0; } -static ssize_t alt_mode_show(struct device *dev, +static ssize_t alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf) { - /* TODO: could be cool to add in something like a small menu that gives - * names and corresponding index to modes, or maybe parsing modes - * directly? */ + struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev)); - return scnprintf(buf, PAGE_SIZE, "%i\n", alt_mode); + if (!tmff2) + return -ENODEV; + + if (tmff2->alt_mode_show) + return tmff2->alt_mode_show(tmff2->data, buf); + + return 0; } -static DEVICE_ATTR_RW(alt_mode); +static DEVICE_ATTR_RW(alternate_modes); static ssize_t gain_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -484,8 +478,8 @@ static int tmff2_create_files(struct tmff2_device_entry *tmff2) } if (tmff2->params & PARAM_ALT_MODE) { - if ((ret = device_create_file(dev, &dev_attr_alt_mode))) { - hid_err(tmff2->hdev, "unable to create sysfs for alt_mode\n"); + if ((ret = device_create_file(dev, &dev_attr_alternate_modes))) { + hid_err(tmff2->hdev, "unable to create sysfs for alternate_modes\n"); goto alt_err; } } @@ -527,7 +521,7 @@ damper_err: spring_err: device_remove_file(dev, &dev_attr_range); range_err: - device_remove_file(dev, &dev_attr_alt_mode); + device_remove_file(dev, &dev_attr_alternate_modes); alt_err: device_remove_file(dev, &dev_attr_gain); gain_err: @@ -589,6 +583,9 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2) if (tmff2->set_range) tmff2->set_range(tmff2->data, range); + if (tmff2->switch_mode) + tmff2->switch_mode(tmff2->data, alt_mode); + /* create files */ if ((ret = tmff2_create_files(tmff2))) goto err; @@ -701,7 +698,7 @@ static void tmff2_remove(struct hid_device *hdev) device_remove_file(dev, &dev_attr_range); if (tmff2->params & PARAM_ALT_MODE) - device_remove_file(dev, &dev_attr_alt_mode); + device_remove_file(dev, &dev_attr_alternate_modes); if (tmff2->params & PARAM_GAIN) device_remove_file(dev, &dev_attr_gain); diff --git a/hid-tmff2.h b/hid-tmff2.h index 765f071..a57b434 100644 --- a/hid-tmff2.h +++ b/hid-tmff2.h @@ -86,7 +86,11 @@ struct tmff2_device_entry { int (*close)(void *data); int (*set_gain)(void *data, uint16_t gain); int (*set_range)(void *data, uint16_t range); + /* switch_mode has to not do anything if we're alredy in the specified + * mode */ int (*switch_mode)(void *data, uint16_t mode); + ssize_t (*alt_mode_show)(void *data, char *buf); + ssize_t (*alt_mode_store)(void *data, const char *buf, size_t count); int (*set_autocenter)(void *data, uint16_t autocenter); __u8 *(*wheel_fixup)(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize); @@ -117,6 +121,7 @@ struct t300rs_device_entry { int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); + int mode; u8 buffer_length; u8 *send_buffer; }; diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 5e4a848..687832f 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1167,25 +1167,94 @@ static int t300rs_switch_mode(void *data, uint16_t mode) if (!t300rs) return -ENODEV; - if(alt_mode == mode) /* already in specified mode */ + 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 + 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[] = { + {"native", "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; + + 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 tmff2_device_entry *t300rs = data; + int i, len, mode_len; + char *lbuf; + if (!t300rs) + return -ENODEV; + + 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; @@ -1413,7 +1482,7 @@ static int t300rs_wheel_init(struct tmff2_device_entry *tmff2) t300rs->close = t300rs->input_dev->close; /* TODO: PS4 advanced mode? */ - alt_mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); + t300rs->mode = (t300rs->hdev->product == TMT300RS_PS3_ADV_ID); /* everythin went OK */ tmff2->data = t300rs; @@ -1486,6 +1555,8 @@ int t300rs_populate_api(struct tmff2_device_entry *tmff2) 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; -- cgit v1.3