aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-03-25 14:14:18 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2022-03-25 14:15:39 +0200
commit41c46e46415bfe9d393a5a3858f0c58f0a914c6b (patch)
tree2ec2abee75bd1d5bc487b79bcef15cd5ab747378
parent2814c3eb42a0ed97d40a42aaefa1bfcd79781bdc (diff)
downloadhid-tmff2-41c46e46415bfe9d393a5a3858f0c58f0a914c6b.tar.gz
hid-tmff2-41c46e46415bfe9d393a5a3858f0c58f0a914c6b.zip
change alternate mode handling
-rw-r--r--hid-tmff2.c45
-rw-r--r--hid-tmff2.h5
-rw-r--r--hid-tmt300rs.c77
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;