aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2021-03-24 20:48:04 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2021-03-24 20:48:04 +0200
commit301f7fa87fa2bafbd9ed3436aa7eb865b341563c (patch)
tree1bda82c0cd2f0093d74fb423da626fde0f17dd0a
parentc2be549438657a7e0b863a1ed58ba17e8fb5ff33 (diff)
downloadhid-tmff2-301f7fa87fa2bafbd9ed3436aa7eb865b341563c.tar.gz
hid-tmff2-301f7fa87fa2bafbd9ed3436aa7eb865b341563c.zip
Merge branch 'minalloc'
-rw-r--r--.gitmodules3
-rw-r--r--Makefile20
-rw-r--r--README.md2
-rw-r--r--hid-tm.h48
m---------hid-tminit0
-rw-r--r--hid-tminit.c131
-rw-r--r--hid-tminit.h18
-rw-r--r--hid-tmt300rs.c2216
-rw-r--r--hid-tmt300rs.h148
-rw-r--r--usbhid.h95
10 files changed, 1241 insertions, 1440 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..9415bdf
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "hid-tminit"]
+ path = hid-tminit
+ url = https://github.com/scarburato/hid-tminit.git
diff --git a/Makefile b/Makefile
index 5182dbf..1b4e1f4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,17 @@
-obj-m += hid-tminit.o
obj-m += hid-tmt300rs.o
+KDIR ?= /lib/modules/$(shell uname -r)/build
-all:
- make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
-install:
- make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules_install
+all: hid-tminit
+ $(MAKE) -C $(KDIR) M=$(shell pwd) modules
+
+install: hid-tminit
+ $(MAKE) -C $(KDIR) M=$(shell pwd) modules_install
depmod -A
-clean:
- make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
+clean: hid-tminit
+ $(MAKE) -C $(KDIR) M=$(shell pwd) clean
+
+
+.PHONY: hid-tminit
+hid-tminit:
+ $(MAKE) -C hid-tminit $(MAKECMDGOALS)
diff --git a/README.md b/README.md
index 798fea2..d824b1f 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ With that in mind,
## Installation
+ Unplug wheel from computer
-+ `git clone https://github.com/Kimplul/hid-tmff2.git`
++ `git clone --recurse-submodules https://github.com/Kimplul/hid-tmff2.git`
+ `make`
+ `sudo make install`
+ Plug wheel back in
diff --git a/hid-tm.h b/hid-tm.h
deleted file mode 100644
index e0117ae..0000000
--- a/hid-tm.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <linux/hid.h>
-#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#define USB_VENDOR_ID_THRUSTMASTER 0x044f
-
-struct api_context {
- struct completion done;
- int status;
-};
-
-struct api_context ctx;
-
-int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
-{
- unsigned long expire;
- int retval;
-
- init_completion(&ctx.done);
- urb->context = &ctx;
- urb->actual_length = 0;
- retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (unlikely(retval))
- goto out;
-
- expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
- if (!wait_for_completion_timeout(&ctx.done, expire)) {
- usb_kill_urb(urb);
- retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
-
- dev_dbg(&urb->dev->dev,
- "%s timed out on ep%d%s len=%u/%u\n",
- current->comm,
- usb_endpoint_num(&urb->ep->desc),
- usb_urb_dir_in(urb) ? "in" : "out",
- urb->actual_length,
- urb->transfer_buffer_length);
- } else
- retval = ctx.status;
-out:
- if (actual_length)
- *actual_length = urb->actual_length;
-
- usb_free_urb(urb);
- return retval;
-}
diff --git a/hid-tminit b/hid-tminit
new file mode 160000
+Subproject 8b9802ac40ade7a09c6bc52298e3501cfdc0732
diff --git a/hid-tminit.c b/hid-tminit.c
deleted file mode 100644
index b4b7b90..0000000
--- a/hid-tminit.c
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "hid-tminit.h"
-
-static void tminit_callback(struct urb *urb){
- if(urb->status){
- hid_info(urb->dev, "urb status %d received\n", urb->status);
- }
-
- usb_free_urb(urb);
-}
-
-/* for some godawful reason these interrupts are absolutely necessary, otherwise
- * the whole kernel crashes. I have no idea why.
- * */
-static void tminit_interrupts(struct hid_device *hdev){
- int ret, trans, i, b_ep;
- u8 *send_buf = kmalloc(256, GFP_KERNEL);
-
- struct usb_host_endpoint *ep;
- struct device *dev = &hdev->dev;
- struct usb_interface *usbif = to_usb_interface(dev->parent);
- struct usb_device *usbdev = interface_to_usbdev(usbif);
-
- ep = &usbif->cur_altsetting->endpoint[1];
- b_ep = ep->desc.bEndpointAddress;
-
- for(i = 0; i < ARRAY_SIZE(setup_arr); ++i){
- memcpy(send_buf, setup_arr[i], setup_arr_sizes[i]);
-
- ret = usb_interrupt_msg(usbdev,
- usb_sndintpipe(usbdev, b_ep),
- send_buf,
- setup_arr_sizes[i],
- &trans,
- USB_CTRL_SET_TIMEOUT
- );
-
- if(ret){
- hid_err(hdev, "setup data couldn't be sent\n");
- return;
- }
-
- }
-
- kfree(send_buf);
-}
-
-int tminit(struct hid_device *hdev){
- struct urb *urb;
- u8 *setup_packet, *transfer_buffer;
- struct device *dev = &hdev->dev;
- struct usb_interface *usbif = to_usb_interface(dev->parent);
- struct usb_device *usbdev = interface_to_usbdev(usbif);
- int ret;
- u8 *transfer = kzalloc(64, GFP_ATOMIC);
-
- tminit_interrupts(hdev);
-
- setup_packet = kmalloc(8, GFP_ATOMIC);
- transfer_buffer = kmalloc(8, GFP_ATOMIC);
-
- memcpy(setup_packet, hw_rq_out, 8);
- memcpy(transfer_buffer, hw_rq_in, 8);
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
-
- usb_fill_control_urb(urb,
- usbdev,
- usb_sndctrlpipe(usbdev, 0),
- setup_packet,
- transfer_buffer,
- 8,
- tminit_callback,
- hdev);
-
- /* we sort of have to go on faith that the message is sent, because the
- * wheel usually completely dies as soon as it receives the message.
- * No need to even check the return value.
- */
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- kfree(setup_packet);
- kfree(transfer_buffer);
- kfree(transfer);
- return ret;
-}
-
-static void tminit_remove(struct hid_device *hdev){
- /* we are dead, hopefully without any serious side effects */
- hid_hw_stop(hdev);
-}
-
-static int tminit_probe(struct hid_device *hdev, const struct hid_device_id *id){
- int ret;
-
- ret = hid_parse(hdev);
- if(ret){
- hid_err(hdev, "parse failed\n");
- goto err;
- }
-
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
- if(ret){
- hid_err(hdev, "hw start failed\n");
- goto err;
- }
-
- ret = tminit(hdev);
- if(ret){
- hid_err(hdev, "tminit exited, error might be intended behaviour\n");
- goto err;
- }
-
-err:
- return ret;
-}
-
-static const struct hid_device_id tminit_devices[] = {
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65d)},
- {}
-};
-
-MODULE_DEVICE_TABLE(hid, tminit_devices);
-
-static struct hid_driver tminit_driver = {
- .name = "thrustmaster init",
- .id_table = tminit_devices,
- .probe = tminit_probe,
- .remove = tminit_remove,
-};
-module_hid_driver(tminit_driver);
-
-MODULE_LICENSE("GPL");
diff --git a/hid-tminit.h b/hid-tminit.h
deleted file mode 100644
index cd12f9b..0000000
--- a/hid-tminit.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "hid-tm.h"
-
-u8 hw_rq_in[] = { 0xc1, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 };
-u8 hw_rq_out[] = { 0x41, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-u8 setup_0[] = { 0x42, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-u8 setup_1[] = { 0x0a, 0x04, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00 };
-u8 setup_2[] = { 0x0a, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00 };
-u8 setup_3[] = { 0x0a, 0x04, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00 };
-u8 setup_4[] = { 0x0a, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 };
-u8 *setup_arr[] = { setup_0, setup_1, setup_2, setup_3, setup_4 };
-unsigned int setup_arr_sizes[] = {
- ARRAY_SIZE(setup_0),
- ARRAY_SIZE(setup_1),
- ARRAY_SIZE(setup_2),
- ARRAY_SIZE(setup_3),
- ARRAY_SIZE(setup_4)
-};
diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c
index a7fd0c1..6abe149 100644
--- a/hid-tmt300rs.c
+++ b/hid-tmt300rs.c
@@ -18,1511 +18,1541 @@ MODULE_PARM_DESC(friction_level, "Level of friction force (0-100), as per Overst
static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev){
- struct t300rs_data *drv_data;
- struct t300rs_device_entry *t300rs;
+ struct t300rs_data *drv_data;
+ struct t300rs_device_entry *t300rs;
- spin_lock_irqsave(&lock, lock_flags);
- drv_data = hid_get_drvdata(hdev);
- if(!drv_data){
- hid_err(hdev, "private data not found\n");
- return NULL;
- }
+ spin_lock_irqsave(&lock, lock_flags);
+ drv_data = hid_get_drvdata(hdev);
+ if(!drv_data){
+ hid_err(hdev, "private data not found\n");
+ return NULL;
+ }
- t300rs = drv_data->device_props;
- if(!t300rs){
- hid_err(hdev, "device properties not found\n");
- return NULL;
- }
- spin_unlock_irqrestore(&lock, lock_flags);
- return t300rs;
+ t300rs = drv_data->device_props;
+ if(!t300rs){
+ hid_err(hdev, "device properties not found\n");
+ return NULL;
+ }
+ spin_unlock_irqrestore(&lock, lock_flags);
+ return t300rs;
}
static int t300rs_send_int(struct input_dev *dev, u8 *send_buffer, int *trans){
- struct hid_device *hdev = input_get_drvdata(dev);
- struct t300rs_device_entry *t300rs;
- int i;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ int i;
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- for(i = 0; i < T300RS_BUFFER_LENGTH; ++i){
- t300rs->ff_field->value[i] = send_buffer[i];
- }
+ for(i = 0; i < T300RS_BUFFER_LENGTH; ++i){
+ t300rs->ff_field->value[i] = send_buffer[i];
+ }
- hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT);
+ hid_hw_request(t300rs->hdev, t300rs->report, HID_REQ_SET_REPORT);
- return 0;
+ memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
+
+ return 0;
}
static int t300rs_play_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- int ret, trans;
+ u8 *send_buffer = t300rs->send_buffer;
+ int ret, trans;
+
+
+ send_buffer[1] = state->effect.id + 1;
+ send_buffer[2] = 0x89;
+ send_buffer[3] = 0x01;
-
- send_buffer[1] = state->effect.id + 1;
- send_buffer[2] = 0x89;
- send_buffer[3] = 0x01;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed starting effect play\n");
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed starting effect play\n");
- }
- kfree(send_buffer);
- return ret;
+ return ret;
}
static int t300rs_stop_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- int ret, trans;
+ u8 *send_buffer = t300rs->send_buffer;
+ int ret, trans;
+
+
+ send_buffer[1] = state->effect.id + 1;
+ send_buffer[2] = 0x89;
-
- send_buffer[1] = state->effect.id + 1;
- send_buffer[2] = 0x89;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed stopping effect play\n");
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed stopping effect play\n");
- }
- kfree(send_buffer);
- return ret;
+ return ret;
}
static void t300rs_fill_envelope(u8 *send_buffer, int i, s16 level, u16 duration, struct ff_envelope *envelope){
- u16 attack_length = (duration * envelope->attack_length) / 0x7fff;
- u16 attack_level = (level * envelope->attack_level) / 0x7fff;
- u16 fade_length = (duration * envelope->fade_length) / 0x7fff;
- u16 fade_level = (level * envelope->fade_level) / 0x7fff;
+ u16 attack_length = (duration * envelope->attack_length) / 0x7fff;
+ u16 attack_level = (level * envelope->attack_level) / 0x7fff;
+ u16 fade_length = (duration * envelope->fade_length) / 0x7fff;
+ u16 fade_level = (level * envelope->fade_level) / 0x7fff;
- send_buffer[i ] = attack_length & 0xff;
- send_buffer[i + 1] = attack_length >> 8;
- send_buffer[i + 2] = attack_level & 0xff;
- send_buffer[i + 3] = attack_level >> 8;
- send_buffer[i + 4] = fade_length & 0xff;
- send_buffer[i + 5] = fade_length >> 8;
- send_buffer[i + 6] = fade_level & 0xff;
- send_buffer[i + 7] = fade_level >> 8;
+ send_buffer[i ] = attack_length & 0xff;
+ send_buffer[i + 1] = attack_length >> 8;
+ send_buffer[i + 2] = attack_level & 0xff;
+ send_buffer[i + 3] = attack_level >> 8;
+ send_buffer[i + 4] = fade_length & 0xff;
+ send_buffer[i + 5] = fade_length >> 8;
+ send_buffer[i + 6] = fade_level & 0xff;
+ send_buffer[i + 7] = fade_level >> 8;
}
static int t300rs_modify_envelope(struct t300rs_device_entry *t300rs,
- struct t300rs_effect_state *state,
- u8 *send_buffer,
- s16 level,
- u16 duration,
- u8 id,
- struct ff_envelope envelope,
- struct ff_envelope envelope_old
- ){
- u16 attack_length, attack_level, fade_length, fade_level;
- int ret = 0, trans;
+ struct t300rs_effect_state *state,
+ u8 *send_buffer,
+ s16 level,
+ u16 duration,
+ u8 id,
+ struct ff_envelope envelope,
+ struct ff_envelope envelope_old
+ ){
+ u16 attack_length, attack_level, fade_length, fade_level;
+ int ret = 0, trans;
- if(duration == 0){
- duration = 0xffff;
- }
+ if(duration == 0){
+ duration = 0xffff;
+ }
- 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;
+ 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;
-
- send_buffer[1] = id + 1;
- send_buffer[2] = 0x31;
- if(envelope.attack_length != envelope_old.attack_length){
- send_buffer[3] = 0x81;
+ send_buffer[1] = id + 1;
+ send_buffer[2] = 0x31;
- send_buffer[4] = attack_length & 0xff;
- send_buffer[5] = attack_length >> 8;
+ if(envelope.attack_length != envelope_old.attack_length){
+ send_buffer[3] = 0x81;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying effect envelope\n");
- goto error;
- }
- }
+ send_buffer[4] = attack_length & 0xff;
+ send_buffer[5] = attack_length >> 8;
- if(envelope.attack_level != envelope_old.attack_level){
- send_buffer[3] = 0x82;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying effect envelope\n");
+ goto error;
+ }
+ }
- send_buffer[4] = attack_level & 0xff;
- send_buffer[5] = attack_level >> 8;
+ if(envelope.attack_level != envelope_old.attack_level){
+ send_buffer[3] = 0x82;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying effect envelope\n");
- goto error;
- }
- }
+ send_buffer[4] = attack_level & 0xff;
+ send_buffer[5] = attack_level >> 8;
- if(envelope.fade_length != envelope_old.fade_length){
- send_buffer[3] = 0x84;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying effect envelope\n");
+ goto error;
+ }
+ }
- send_buffer[4] = fade_length & 0xff;
- send_buffer[5] = fade_length >> 8;
+ if(envelope.fade_length != envelope_old.fade_length){
+ send_buffer[3] = 0x84;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying effect envelope\n");
- goto error;
- }
- }
+ send_buffer[4] = fade_length & 0xff;
+ send_buffer[5] = fade_length >> 8;
- if(envelope.fade_level != envelope_old.fade_level){
- send_buffer[3] = 0x88;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying effect envelope\n");
+ goto error;
+ }
+ }
- send_buffer[4] = fade_level & 0xff;
- send_buffer[5] = fade_level >> 8;
+ if(envelope.fade_level != envelope_old.fade_level){
+ send_buffer[3] = 0x88;
+
+ send_buffer[4] = fade_level & 0xff;
+ send_buffer[5] = fade_level >> 8;
+
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying effect envelope\n");
+ goto error;
+ }
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying effect envelope\n");
- goto error;
- }
- }
-
error:
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- return ret;
+ return ret;
}
static int t300rs_modify_duration(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, u8 *send_buffer){
- struct ff_effect effect = state->effect;
- struct ff_effect old = state->old;
- u16 duration;
- int ret = 0, trans;
-
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
+ struct ff_effect effect = state->effect;
+ struct ff_effect old = state->old;
+ u16 duration;
+ int ret = 0, trans;
+
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
+
+ if(effect.replay.length != old.replay.length){
- if(effect.replay.length != old.replay.length){
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x49;
- send_buffer[4] = 0x41;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x49;
+ send_buffer[4] = 0x41;
- send_buffer[5] = duration & 0xff;
- send_buffer[6] = duration >> 8;
+ send_buffer[5] = duration & 0xff;
+ send_buffer[6] = duration >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying duration\n");
- goto error;
- }
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying duration\n");
+ goto error;
+ }
+ }
error:
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- return ret;
+ return ret;
}
static int t300rs_modify_constant(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, u8 *send_buffer){
- 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;
- int ret, trans;
- s16 level;
+ 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;
+ int ret, trans;
+ s16 level;
- level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
+ level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- if(constant.level != constant_old.level){
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0a;
+ if(constant.level != constant_old.level){
- send_buffer[3] = level & 0xff;
- send_buffer[4] = level >> 8;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0a;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying constant effect\n");
- goto error;
- }
+ send_buffer[3] = level & 0xff;
+ send_buffer[4] = level >> 8;
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying constant effect\n");
+ goto error;
+ }
- ret = t300rs_modify_envelope(t300rs,
- state,
- send_buffer,
- 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_modify_duration(t300rs, state, send_buffer);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying constant duration\n");
- goto error;
- }
+ ret = t300rs_modify_envelope(t300rs,
+ state,
+ send_buffer,
+ 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_modify_duration(t300rs, state, send_buffer);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying constant duration\n");
+ goto error;
+ }
error:
- kfree(send_buffer);
- return ret;
+
+ return ret;
}
static int t300rs_modify_ramp(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, u8 *send_buffer){
- 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;
- int ret, trans;
+ 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;
+ int ret, trans;
- u16 difference, top, bottom;
- s16 level;
+ u16 difference, top, bottom;
+ s16 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;
+ 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;
+ difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- level = (top * 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){
+ if(ramp.start_level != ramp_old.start_level || ramp.end_level != ramp_old.end_level){
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x03;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x03;
- send_buffer[4] = difference & 0xff;
- send_buffer[5] = difference >> 8;
+ send_buffer[4] = difference & 0xff;
+ send_buffer[5] = difference >> 8;
- send_buffer[6] = level & 0xff;
- send_buffer[7] = level >> 8;
+ send_buffer[6] = level & 0xff;
+ send_buffer[7] = level >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying ramp effect\n");
- goto error;
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying ramp effect\n");
+ goto error;
+ }
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ }
- ret = t300rs_modify_envelope(t300rs,
- state,
- send_buffer,
- level,
- effect.replay.length,
- effect.id,
- ramp.envelope,
- ramp_old.envelope
- );
+ ret = t300rs_modify_envelope(t300rs,
+ state,
+ send_buffer,
+ level,
+ effect.replay.length,
+ effect.id,
+ ramp.envelope,
+ ramp_old.envelope
+ );
- if(ret){
- hid_err(t300rs->hdev, "failed modifying ramp envelope\n");
- goto error;
- }
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying ramp envelope\n");
+ goto error;
+ }
- ret = t300rs_modify_duration(t300rs, state, send_buffer);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying ramp duration\n");
- goto error;
- }
+ ret = t300rs_modify_duration(t300rs, state, send_buffer);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying ramp duration\n");
+ goto error;
+ }
error:
- kfree(send_buffer);
- return ret;
+
+ return ret;
}
static int t300rs_modify_damper(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, u8 *send_buffer){
- 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];
- int ret, trans, input_level;
+ 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];
+ int ret, trans, 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;
- input_level = damper_level;
- if(state->effect.type == FF_FRICTION)
- input_level = friction_level;
+ if(damper.right_coeff != damper_old.right_coeff){
+ s16 coeff = damper.right_coeff * input_level / 100;
- if(state->effect.type == FF_SPRING)
- input_level = spring_level;
- if(damper.right_coeff != damper_old.right_coeff){
- s16 coeff = damper.right_coeff * input_level / 100;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x41;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x41;
+ send_buffer[4] = coeff & 0xff;
+ send_buffer[5] = coeff >> 8;
- send_buffer[4] = coeff & 0xff;
- send_buffer[5] = coeff >> 8;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying damper rc\n");
+ goto error;
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying damper rc\n");
- goto error;
- }
+ }
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ if(damper.left_coeff != damper_old.left_coeff){
+ s16 coeff = damper.left_coeff * input_level / 100;
- if(damper.left_coeff != damper_old.left_coeff){
- s16 coeff = damper.left_coeff * input_level / 100;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x42;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x42;
- send_buffer[4] = coeff & 0xff;
- send_buffer[5] = coeff >> 8;
+ send_buffer[4] = coeff & 0xff;
+ send_buffer[5] = coeff >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying damper lc\n");
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying damper lc\n");
+ }
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
-
- if((damper.deadband != damper_old.deadband) ||
- (damper.center != damper_old.center)){
- u16 deadband_right = 0xfffe - damper.deadband - damper.center;
- u16 deadband_left = 0xfffe - damper.deadband + damper.center;
-
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x4c;
+ }
- send_buffer[4] = deadband_right & 0xff;
- send_buffer[5] = deadband_right >> 8;
+ if((damper.deadband != damper_old.deadband) ||
+ (damper.center != damper_old.center)){
+ u16 deadband_right = 0xfffe - damper.deadband - damper.center;
+ u16 deadband_left = 0xfffe - damper.deadband + damper.center;
- send_buffer[6] = deadband_left & 0xff;
- send_buffer[7] = deadband_left >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying damper deadband\n");
- }
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x4c;
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ send_buffer[4] = deadband_right & 0xff;
+ send_buffer[5] = deadband_right >> 8;
- ret = t300rs_modify_duration(t300rs, state, send_buffer);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying damper duration\n");
- goto error;
- }
+ send_buffer[6] = deadband_left & 0xff;
+ send_buffer[7] = deadband_left >> 8;
+
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying damper deadband\n");
+ }
+
+ }
+
+ ret = t300rs_modify_duration(t300rs, state, send_buffer);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying damper duration\n");
+ goto error;
+ }
error:
- kfree(send_buffer);
- return ret;
+
+ return ret;
}
static int t300rs_modify_periodic(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state, u8 *send_buffer){
- 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;
- int ret, trans;
- s16 level;
+ 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;
+ int ret, trans;
+ s16 level;
- level = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
+ level = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- if(periodic.magnitude != periodic_old.magnitude){
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x01;
+ if(periodic.magnitude != periodic_old.magnitude){
- send_buffer[4] = level & 0xff;
- send_buffer[5] = level >> 8;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x01;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying periodic magnitude\n");
- goto error;
- }
+ send_buffer[4] = level & 0xff;
+ send_buffer[5] = level >> 8;
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying periodic magnitude\n");
+ goto error;
+ }
- if(periodic.offset != periodic_old.offset){
- s16 offset = periodic.offset;
+ }
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x02;
+ if(periodic.offset != periodic_old.offset){
+ s16 offset = periodic.offset;
- send_buffer[4] = offset & 0xff;
- send_buffer[5] = offset >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying periodic offset\n");
- }
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x02;
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
-
- if(periodic.phase != periodic_old.phase){
- s16 phase = periodic.phase;
+ send_buffer[4] = offset & 0xff;
+ send_buffer[5] = offset >> 8;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x04;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying periodic offset\n");
+ }
- send_buffer[4] = phase & 0xff;
- send_buffer[5] = phase >> 8;
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying periodic phase\n");
- }
+ if(periodic.phase != periodic_old.phase){
+ s16 phase = periodic.phase;
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
- if(periodic.period != periodic_old.period){
- s16 period = periodic.period;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x04;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x0e;
- send_buffer[3] = 0x08;
+ send_buffer[4] = phase & 0xff;
+ send_buffer[5] = phase >> 8;
- send_buffer[4] = period & 0xff;
- send_buffer[5] = period >> 8;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying periodic phase\n");
+ }
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying periodic period\n");
- }
+ }
- memset(send_buffer, 0, T300RS_BUFFER_LENGTH);
- }
+ if(periodic.period != periodic_old.period){
+ s16 period = periodic.period;
- ret = t300rs_modify_envelope(t300rs,
- state,
- send_buffer,
- level,
- 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_modify_duration(t300rs, state, send_buffer);
- if(ret){
- hid_err(t300rs->hdev, "failed modifying periodic duration\n");
- goto error;
- }
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x0e;
+ send_buffer[3] = 0x08;
+
+ send_buffer[4] = period & 0xff;
+ send_buffer[5] = period >> 8;
+
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying periodic period\n");
+ }
+
+ }
+
+ ret = t300rs_modify_envelope(t300rs,
+ state,
+ send_buffer,
+ level,
+ 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_modify_duration(t300rs, state, send_buffer);
+ if(ret){
+ hid_err(t300rs->hdev, "failed modifying periodic duration\n");
+ goto error;
+ }
error:
- kfree(send_buffer);
- return ret;
+
+ return ret;
}
static int t300rs_upload_constant(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- struct ff_effect effect = state->effect;
- struct ff_constant_effect constant = state->effect.u.constant;
- s16 level;
- u16 duration, offset;
+ u8 *send_buffer = t300rs->send_buffer;
+ struct ff_effect effect = state->effect;
+ struct ff_constant_effect constant = state->effect.u.constant;
+ s16 level;
+ u16 duration, offset;
+
+ int ret, trans;
- int ret, trans;
+ /* some games, such as DiRT Rally 2 have a weird feeling to them, sort of
+ * like the wheel pulls just a bit to the right or left and then it just
+ * stops. I wouldn't be surprised if it's got something to do with the
+ * constant envelope, but right now I don't know. */
- /* some games, such as DiRT Rally 2 have a weird feeling to them, sort of
- * like the wheel pulls just a bit to the right or left and then it just
- * stops. I wouldn't be surprised if it's got something to do with the
- * constant envelope, but right now I don't know. */
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
+ test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ return t300rs_modify_constant(t300rs, state, send_buffer);
+ }
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
- test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- return t300rs_modify_constant(t300rs, state, send_buffer);
- }
+ level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
- level = (constant.level * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
+ offset = effect.replay.delay;
- offset = effect.replay.delay;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x6a;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x6a;
- send_buffer[3] = level & 0xff;
- send_buffer[4] = level >> 8;
+ send_buffer[3] = level & 0xff;
+ send_buffer[4] = level >> 8;
- t300rs_fill_envelope(send_buffer, 5, level,
- duration, &constant.envelope);
+ t300rs_fill_envelope(send_buffer, 5, level,
+ duration, &constant.envelope);
- send_buffer[14] = 0x4f;
+ send_buffer[14] = 0x4f;
- send_buffer[15] = duration & 0xff;
- send_buffer[16] = duration >> 8;
+ send_buffer[15] = duration & 0xff;
+ send_buffer[16] = duration >> 8;
- send_buffer[19] = offset & 0xff;
- send_buffer[20] = offset >> 8;
+ send_buffer[19] = offset & 0xff;
+ send_buffer[20] = offset >> 8;
- send_buffer[22] = 0xff;
- send_buffer[23] = 0xff;
+ send_buffer[22] = 0xff;
+ send_buffer[23] = 0xff;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading constant effect\n");
- }
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading constant effect\n");
+ }
- kfree(send_buffer);
- return ret;
+
+ return ret;
}
static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- struct ff_effect effect = state->effect;
- struct ff_ramp_effect ramp = state->effect.u.ramp;
- int ret, trans;
- u16 difference, offset, top, bottom, duration;
- s16 level;
+ u8 *send_buffer = t300rs->send_buffer;
+ struct ff_effect effect = state->effect;
+ struct ff_ramp_effect ramp = state->effect.u.ramp;
+ int ret, trans;
+ u16 difference, offset, top, bottom, duration;
+ s16 level;
+
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
+ test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ return t300rs_modify_ramp(t300rs, state, send_buffer);
+ }
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
- test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- return t300rs_modify_ramp(t300rs, state, send_buffer);
- }
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
+ 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;
- 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;
- difference = ((top - bottom) * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- level = (top * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- offset = effect.replay.delay;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x6b;
-
- send_buffer[3] = difference & 0xff;
- send_buffer[4] = difference >> 8;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x6b;
- send_buffer[5] = level & 0xff;
- send_buffer[6] = level >> 8;
+ send_buffer[3] = difference & 0xff;
+ send_buffer[4] = difference >> 8;
- send_buffer[9] = duration & 0xff;
- send_buffer[10] = duration >> 8;
+ send_buffer[5] = level & 0xff;
+ send_buffer[6] = level >> 8;
- send_buffer[12] = 0x80;
+ send_buffer[9] = duration & 0xff;
+ send_buffer[10] = duration >> 8;
- t300rs_fill_envelope(send_buffer, 13, level,
- effect.replay.length, &ramp.envelope);
+ send_buffer[12] = 0x80;
- send_buffer[22] = ramp.end_level > ramp.start_level ? 0x04 : 0x05;
- send_buffer[23] = 0x4f;
+ t300rs_fill_envelope(send_buffer, 13, level,
+ effect.replay.length, &ramp.envelope);
- send_buffer[24] = duration & 0xff;
- send_buffer[25] = duration >> 8;
+ send_buffer[22] = ramp.end_level > ramp.start_level ? 0x04 : 0x05;
+ send_buffer[23] = 0x4f;
- send_buffer[28] = offset & 0xff;
- send_buffer[29] = offset >> 8;
+ send_buffer[24] = duration & 0xff;
+ send_buffer[25] = duration >> 8;
- send_buffer[31] = 0xff;
- send_buffer[32] = 0xff;
+ send_buffer[28] = offset & 0xff;
+ send_buffer[29] = offset >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading ramp");
- }
+ send_buffer[31] = 0xff;
+ send_buffer[32] = 0xff;
- kfree(send_buffer);
- return ret;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading ramp");
+ }
+
+
+ return ret;
}
static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- struct ff_effect effect = state->effect;
- /* we only care about the first axis */
- struct ff_condition_effect spring = state->effect.u.condition[0];
- int ret, trans;
- u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset;
-
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
- test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- return t300rs_modify_damper(t300rs, state, send_buffer);
- }
+ u8 *send_buffer = t300rs->send_buffer;
+ struct ff_effect effect = state->effect;
+ /* we only care about the first axis */
+ struct ff_condition_effect spring = state->effect.u.condition[0];
+ int ret, trans;
+ u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset;
+
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
+ test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ return t300rs_modify_damper(t300rs, state, send_buffer);
+ }
+
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x64;
-
- right_coeff = spring.right_coeff * spring_level / 100;
- left_coeff = spring.left_coeff * spring_level / 100;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x64;
- deadband_right = 0xfffe - spring.deadband - spring.center;
- deadband_left = 0xfffe - spring.deadband + spring.center;
+ right_coeff = spring.right_coeff * spring_level / 100;
+ left_coeff = spring.left_coeff * spring_level / 100;
- offset = effect.replay.delay;
+ deadband_right = 0xfffe - spring.deadband - spring.center;
+ deadband_left = 0xfffe - spring.deadband + spring.center;
- send_buffer[3] = right_coeff & 0xff;
- send_buffer[4] = right_coeff >> 8;
+ offset = effect.replay.delay;
- send_buffer[5] = left_coeff & 0xff;
- send_buffer[6] = left_coeff >> 8;
+ send_buffer[3] = right_coeff & 0xff;
+ send_buffer[4] = right_coeff >> 8;
- send_buffer[7] = deadband_right & 0xff;
- send_buffer[8] = deadband_right >> 8;
+ send_buffer[5] = left_coeff & 0xff;
+ send_buffer[6] = left_coeff >> 8;
- send_buffer[9] = deadband_left & 0xff;
- send_buffer[10] = deadband_left >> 8;
+ send_buffer[7] = deadband_right & 0xff;
+ send_buffer[8] = deadband_right >> 8;
- memcpy(&send_buffer[11], spring_values, ARRAY_SIZE(spring_values));
- send_buffer[28] = 0x4f;
+ send_buffer[9] = deadband_left & 0xff;
+ send_buffer[10] = deadband_left >> 8;
- send_buffer[29] = duration & 0xff;
- send_buffer[30] = duration >> 8;
+ memcpy(&send_buffer[11], spring_values, ARRAY_SIZE(spring_values));
+ send_buffer[28] = 0x4f;
- send_buffer[33] = offset & 0xff;
- send_buffer[34] = offset >> 8;
+ send_buffer[29] = duration & 0xff;
+ send_buffer[30] = duration >> 8;
- send_buffer[36] = 0xff;
- send_buffer[37] = 0xff;
+ send_buffer[33] = offset & 0xff;
+ send_buffer[34] = offset >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading spring\n");
- }
+ send_buffer[36] = 0xff;
+ send_buffer[37] = 0xff;
- kfree(send_buffer);
- return ret;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading spring\n");
+ }
+
+
+ return ret;
}
static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- struct ff_effect effect = state->effect;
- /* we only care about the first axis */
- struct ff_condition_effect spring = state->effect.u.condition[0];
- int ret, trans, input_level;
- u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset;
-
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
- test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- return t300rs_modify_damper(t300rs, state, send_buffer);
- }
+ u8 *send_buffer = t300rs->send_buffer;
+ struct ff_effect effect = state->effect;
+ /* we only care about the first axis */
+ struct ff_condition_effect spring = state->effect.u.condition[0];
+ int ret, trans, input_level;
+ u16 duration, right_coeff, left_coeff, deadband_right, deadband_left, offset;
+
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
+ test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ return t300rs_modify_damper(t300rs, state, send_buffer);
+ }
+
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
+ input_level = damper_level;
+ if(state->effect.type == FF_FRICTION)
+ input_level = friction_level;
- input_level = damper_level;
- if(state->effect.type == FF_FRICTION)
- input_level = friction_level;
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x64;
-
- right_coeff = spring.right_coeff * input_level / 100;
- left_coeff = spring.left_coeff * input_level / 100;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x64;
- deadband_right = 0xfffe - spring.deadband - spring.center;
- deadband_left = 0xfffe - spring.deadband + spring.center;
+ right_coeff = spring.right_coeff * input_level / 100;
+ left_coeff = spring.left_coeff * input_level / 100;
- offset = effect.replay.delay;
+ deadband_right = 0xfffe - spring.deadband - spring.center;
+ deadband_left = 0xfffe - spring.deadband + spring.center;
- send_buffer[3] = right_coeff & 0xff;
- send_buffer[4] = right_coeff >> 8;
+ offset = effect.replay.delay;
- send_buffer[5] = left_coeff & 0xff;
- send_buffer[6] = left_coeff >> 8;
+ send_buffer[3] = right_coeff & 0xff;
+ send_buffer[4] = right_coeff >> 8;
- send_buffer[7] = deadband_right & 0xff;
- send_buffer[8] = deadband_right >> 8;
+ send_buffer[5] = left_coeff & 0xff;
+ send_buffer[6] = left_coeff >> 8;
- send_buffer[9] = deadband_left & 0xff;
- send_buffer[10] = deadband_left >> 8;
+ send_buffer[7] = deadband_right & 0xff;
+ send_buffer[8] = deadband_right >> 8;
- memcpy(&send_buffer[11], damper_values, ARRAY_SIZE(damper_values));
- send_buffer[28] = 0x4f;
+ send_buffer[9] = deadband_left & 0xff;
+ send_buffer[10] = deadband_left >> 8;
- send_buffer[29] = duration & 0xff;
- send_buffer[30] = duration >> 8;
+ memcpy(&send_buffer[11], damper_values, ARRAY_SIZE(damper_values));
+ send_buffer[28] = 0x4f;
- send_buffer[33] = offset & 0xff;
- send_buffer[34] = offset >> 8;
+ send_buffer[29] = duration & 0xff;
+ send_buffer[30] = duration >> 8;
- send_buffer[36] = 0xff;
- send_buffer[37] = 0xff;
+ send_buffer[33] = offset & 0xff;
+ send_buffer[34] = offset >> 8;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading spring\n");
- }
+ send_buffer[36] = 0xff;
+ send_buffer[37] = 0xff;
- kfree(send_buffer);
- return ret;
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading spring\n");
+ }
+
+
+ return ret;
}
static int t300rs_upload_periodic(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- struct ff_effect effect = state->effect;
- struct ff_periodic_effect periodic = state->effect.u.periodic;
- int ret, trans;
- u16 duration, magnitude, phase, period, offset;
- s16 periodic_offset;
+ u8 *send_buffer = t300rs->send_buffer;
+ struct ff_effect effect = state->effect;
+ struct ff_periodic_effect periodic = state->effect.u.periodic;
+ int ret, trans;
+ u16 duration, magnitude, phase, period, offset;
+ s16 periodic_offset;
+
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
+ test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ return t300rs_modify_periodic(t300rs, state, send_buffer);
+ }
+
+ if(effect.replay.length == 0){
+ duration = 0xffff;
+ } else {
+ duration = effect.replay.length;
+ }
+
+ magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) &&
- test_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- return t300rs_modify_periodic(t300rs, state, send_buffer);
- }
+ phase = periodic.phase;
+ periodic_offset = periodic.offset;
+ period = periodic.period;
+ offset = effect.replay.delay;
- if(effect.replay.length == 0){
- duration = 0xffff;
- } else {
- duration = effect.replay.length;
- }
- magnitude = (periodic.magnitude * fixp_sin16(effect.direction * 360 / 0x10000)) / 0x7fff;
+ send_buffer[1] = effect.id + 1;
+ send_buffer[2] = 0x6b;
- phase = periodic.phase;
- periodic_offset = periodic.offset;
- period = periodic.period;
- offset = effect.replay.delay;
-
-
- send_buffer[1] = effect.id + 1;
- send_buffer[2] = 0x6b;
-
- send_buffer[3] = magnitude & 0xff;
- send_buffer[4] = magnitude >> 8;
+ send_buffer[3] = magnitude & 0xff;
+ send_buffer[4] = magnitude >> 8;
- send_buffer[7] = phase & 0xff;
- send_buffer[8] = phase >> 8;
+ send_buffer[7] = phase & 0xff;
+ send_buffer[8] = phase >> 8;
- send_buffer[5] = periodic_offset & 0xff;
- send_buffer[6] = periodic_offset >> 8;
+ send_buffer[5] = periodic_offset & 0xff;
+ send_buffer[6] = periodic_offset >> 8;
- send_buffer[9] = period & 0xff;
- send_buffer[10] = period >> 8;
+ send_buffer[9] = period & 0xff;
+ send_buffer[10] = period >> 8;
- send_buffer[12] = 0x80;
+ send_buffer[12] = 0x80;
- t300rs_fill_envelope(send_buffer, 13, magnitude,
- effect.replay.length, &periodic.envelope);
+ t300rs_fill_envelope(send_buffer, 13, magnitude,
+ effect.replay.length, &periodic.envelope);
- send_buffer[21] = periodic.waveform - 0x57;
- send_buffer[22] = 0x4f;
+ send_buffer[21] = periodic.waveform - 0x57;
+ send_buffer[22] = 0x4f;
- send_buffer[23] = duration & 0xff;
- send_buffer[24] = duration >> 8;
+ send_buffer[23] = duration & 0xff;
+ send_buffer[24] = duration >> 8;
- send_buffer[27] = offset & 0xff;
- send_buffer[28] = offset >> 8;
+ send_buffer[27] = offset & 0xff;
+ send_buffer[28] = offset >> 8;
- send_buffer[30] = 0xff;
- send_buffer[31] = 0xff;
-
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading periodic effect");
- }
-
- kfree(send_buffer);
- return ret;
+ send_buffer[30] = 0xff;
+ send_buffer[31] = 0xff;
+
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading periodic effect");
+ }
+
+
+ return ret;
}
static int t300rs_upload_effect(struct t300rs_device_entry *t300rs, struct t300rs_effect_state *state){
- 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;
- }
+ 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_timer_helper(struct t300rs_device_entry *t300rs){
- struct t300rs_effect_state *state;
- unsigned long jiffies_now = JIFFIES2MS(jiffies);
- int max_count = 0, effect_id, ret;
-
- for(effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id){
-
- state = &t300rs->states[effect_id];
+ struct t300rs_effect_state *state;
+ unsigned long jiffies_now = JIFFIES2MS(jiffies);
+ int max_count = 0, effect_id, ret;
+
+ for(effect_id = 0; effect_id < T300RS_MAX_EFFECTS; ++effect_id){
- if(test_bit(FF_EFFECT_PLAYING, &state->flags) && state->effect.replay.length){
- if((jiffies_now - state->start_time) >= state->effect.replay.length){
- __clear_bit(FF_EFFECT_PLAYING, &state->flags);
+ state = &t300rs->states[effect_id];
- /* lazy bum fix? */
- __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
+ if(test_bit(FF_EFFECT_PLAYING, &state->flags) && state->effect.replay.length){
+ if((jiffies_now - state->start_time) >= state->effect.replay.length){
+ __clear_bit(FF_EFFECT_PLAYING, &state->flags);
- if(state->count){
- state->count--;
- }
+ /* lazy bum fix? */
+ __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
- if(state->count){
- __set_bit(FF_EFFECT_QUEUE_START, &state->flags);
- }
- }
- }
+ if(state->count){
+ state->count--;
+ }
- if(test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ if(state->count){
+ __set_bit(FF_EFFECT_QUEUE_START, &state->flags);
+ }
+ }
+ }
- ret = t300rs_upload_effect(t300rs, state);
- if(ret){
- hid_err(t300rs->hdev, "failed uploading effects");
- return ret;
- }
- }
+ if(test_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- if(test_bit(FF_EFFECT_QUEUE_START, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_START, &state->flags);
- __set_bit(FF_EFFECT_PLAYING, &state->flags);
+ ret = t300rs_upload_effect(t300rs, state);
+ if(ret){
+ hid_err(t300rs->hdev, "failed uploading effects");
+ return ret;
+ }
+ }
- ret = t300rs_play_effect(t300rs, state);
- if(ret){
- hid_err(t300rs->hdev, "failed starting effects\n");
- return ret;
- }
+ if(test_bit(FF_EFFECT_QUEUE_START, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_START, &state->flags);
+ __set_bit(FF_EFFECT_PLAYING, &state->flags);
- }
+ ret = t300rs_play_effect(t300rs, state);
+ if(ret){
+ hid_err(t300rs->hdev, "failed starting effects\n");
+ return ret;
+ }
- if(test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)){
- __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
- __clear_bit(FF_EFFECT_PLAYING, &state->flags);
+ }
- ret = t300rs_stop_effect(t300rs, state);
- if(ret){
- hid_err(t300rs->hdev, "failed stopping effect\n");
- return ret;
- }
- }
+ if(test_bit(FF_EFFECT_QUEUE_STOP, &state->flags)){
+ __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
+ __clear_bit(FF_EFFECT_PLAYING, &state->flags);
- if(state->count > max_count){
- max_count = state->count;
- }
- }
+ ret = t300rs_stop_effect(t300rs, state);
+ if(ret){
+ hid_err(t300rs->hdev, "failed stopping effect\n");
+ return ret;
+ }
+ }
- return max_count;
+ if(state->count > max_count){
+ max_count = state->count;
+ }
+ }
+
+ return max_count;
}
static enum hrtimer_restart t300rs_timer(struct hrtimer *t){
- struct t300rs_device_entry *t300rs = container_of(t, struct t300rs_device_entry, hrtimer);
- int max_count;
+ struct t300rs_device_entry *t300rs = container_of(t, struct t300rs_device_entry, hrtimer);
+ int max_count;
+
+ max_count = t300rs_timer_helper(t300rs);
- max_count = t300rs_timer_helper(t300rs);
-
- if(max_count > 0){
- hrtimer_forward_now(&t300rs->hrtimer, ms_to_ktime(timer_msecs));
- return HRTIMER_RESTART;
- } else {
- return HRTIMER_NORESTART;
- }
+ if(max_count > 0){
+ hrtimer_forward_now(&t300rs->hrtimer, ms_to_ktime(timer_msecs));
+ return HRTIMER_RESTART;
+ } else {
+ return HRTIMER_NORESTART;
+ }
}
static int t300rs_upload(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old){
- struct hid_device *hdev = input_get_drvdata(dev);
- struct t300rs_device_entry *t300rs;
- struct t300rs_effect_state *state;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ struct t300rs_effect_state *state;
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- if(effect->type == FF_PERIODIC && effect->u.periodic.period == 0){
- return -EINVAL;
- }
+ if(effect->type == FF_PERIODIC && effect->u.periodic.period == 0){
+ return -EINVAL;
+ }
- if(effect->id > t300rs->max_id){
- t300rs->max_id = effect->id;
- }
+ state = &t300rs->states[effect->id];
- state = &t300rs->states[effect->id];
+ spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags);
- spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags);
+ state->effect = *effect;
+ if(old){
+ state->old = *old;
+ __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
+ } else {
+ __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
+ }
+ __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
- state->effect = *effect;
- if(old){
- state->old = *old;
- __set_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
- } else {
- __clear_bit(FF_EFFECT_QUEUE_UPDATE, &state->flags);
- }
- __set_bit(FF_EFFECT_QUEUE_UPLOAD, &state->flags);
+ spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags);
- spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags);
-
- return 0;
+ return 0;
}
static int t300rs_play(struct input_dev *dev, int effect_id, int value){
- struct hid_device *hdev = input_get_drvdata(dev);
- struct t300rs_device_entry *t300rs;
- struct t300rs_effect_state *state;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ struct t300rs_effect_state *state;
+
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ state = &t300rs->states[effect_id];
- state = &t300rs->states[effect_id];
+ if(&state->effect == 0)
+ return 0;
- if(&state->effect == 0)
- return 0;
-
- spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags);
+ spin_lock_irqsave(&t300rs->lock, t300rs->lock_flags);
- if(value > 0){
- state->count = value;
- state->start_time = JIFFIES2MS(jiffies);
- __set_bit(FF_EFFECT_QUEUE_START, &state->flags);
+ if(value > 0){
+ state->count = value;
+ state->start_time = JIFFIES2MS(jiffies);
+ __set_bit(FF_EFFECT_QUEUE_START, &state->flags);
- if(test_bit(FF_EFFECT_QUEUE_STOP, &state->flags))
- __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
+ if(test_bit(FF_EFFECT_QUEUE_STOP, &state->flags))
+ __clear_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
- } else {
- __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
- }
+ } else {
+ __set_bit(FF_EFFECT_QUEUE_STOP, &state->flags);
+ }
- if(!hrtimer_active(&t300rs->hrtimer)){
- hrtimer_start(&t300rs->hrtimer, ms_to_ktime(timer_msecs), HRTIMER_MODE_REL);
- }
+ if(!hrtimer_active(&t300rs->hrtimer)){
+ hrtimer_start(&t300rs->hrtimer, ms_to_ktime(timer_msecs), HRTIMER_MODE_REL);
+ }
- spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags);
- return 0;
+ spin_unlock_irqrestore(&t300rs->lock, t300rs->lock_flags);
+ return 0;
}
static ssize_t t300rs_spring_level_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count){
- unsigned value = simple_strtoul(buf, NULL, 10);
+ const char *buf, size_t count){
+ unsigned value = simple_strtoul(buf, NULL, 10);
- if(value > 100)
- value = 100;
+ if(value > 100)
+ value = 100;
- spring_level = value;
+ spring_level = value;
- return count;
+ return count;
}
static ssize_t t300rs_spring_level_show(struct device *dev, struct device_attribute *attr, char *buf){
- size_t count;
+ size_t count;
- count = scnprintf(buf, PAGE_SIZE, "%u\n", spring_level);
+ count = scnprintf(buf, PAGE_SIZE, "%u\n", spring_level);
- return count;
+ return count;
}
static DEVICE_ATTR(spring_level, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_spring_level_show, t300rs_spring_level_store);
static ssize_t t300rs_damper_level_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count){
- unsigned value = simple_strtoul(buf, NULL, 10);
+ const char *buf, size_t count){
+ unsigned value = simple_strtoul(buf, NULL, 10);
- if(value > 100)
- value = 100;
+ if(value > 100)
+ value = 100;
- damper_level = value;
+ damper_level = value;
- return count;
+ return count;
}
static ssize_t t300rs_damper_level_show(struct device *dev, struct device_attribute *attr, char *buf){
- size_t count;
+ size_t count;
- count = scnprintf(buf, PAGE_SIZE, "%u\n", damper_level);
+ count = scnprintf(buf, PAGE_SIZE, "%u\n", damper_level);
- return count;
+ return count;
}
static DEVICE_ATTR(damper_level, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_damper_level_show, t300rs_damper_level_store);
static ssize_t t300rs_friction_level_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count){
- unsigned value = simple_strtoul(buf, NULL, 10);
+ const char *buf, size_t count){
+ unsigned value = simple_strtoul(buf, NULL, 10);
- if(value > 100)
- value = 100;
+ if(value > 100)
+ value = 100;
- friction_level = value;
+ friction_level = value;
- return count;
+ return count;
}
static ssize_t t300rs_friction_level_show(struct device *dev, struct device_attribute *attr, char *buf){
- size_t count;
+ size_t count;
- count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level);
+ count = scnprintf(buf, PAGE_SIZE, "%u\n", friction_level);
- return count;
+ return count;
}
static DEVICE_ATTR(friction_level, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_friction_level_show, t300rs_friction_level_store);
/* we should set a default range */
static ssize_t t300rs_range_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count){
- struct hid_device *hdev = to_hid_device(dev);
- struct t300rs_device_entry *t300rs;
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- u16 range = simple_strtoul(buf, NULL, 10);
- int ret, trans;
+ const char *buf, size_t count){
+ struct hid_device *hdev = to_hid_device(dev);
+ struct t300rs_device_entry *t300rs;
+ u8 *send_buffer;
+ u16 range = simple_strtoul(buf, NULL, 10);
+ int ret, trans;
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- if(range < 40){
- range = 40;
- }
+ send_buffer = t300rs->send_buffer;
- if(range > 1080){
- range = 1080;
- }
+ if(range < 40){
+ range = 40;
+ }
- range *= 0x3c;
+ if(range > 1080){
+ range = 1080;
+ }
-
- send_buffer[0] = 0x08;
- send_buffer[1] = 0x11;
- send_buffer[2] = range & 0xff;
- send_buffer[3] = range >> 8;
+ range *= 0x3c;
- ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed sending interrupts\n");
- return -1;
- }
- t300rs->range = range / 0x3c;
- kfree(send_buffer);
- return count;
+ send_buffer[0] = 0x08;
+ send_buffer[1] = 0x11;
+ send_buffer[2] = range & 0xff;
+ send_buffer[3] = range >> 8;
+
+ ret = t300rs_send_int(t300rs->input_dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed sending interrupts\n");
+ return -1;
+ }
+
+ t300rs->range = range / 0x3c;
+
+ return count;
}
static ssize_t t300rs_range_show(struct device *dev, struct device_attribute *attr,
- char *buf){
- struct hid_device *hdev = to_hid_device(dev);
- struct t300rs_device_entry *t300rs;
- size_t count = 0;
+ char *buf){
+ struct hid_device *hdev = to_hid_device(dev);
+ struct t300rs_device_entry *t300rs;
+ size_t count = 0;
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- count = scnprintf(buf, PAGE_SIZE, "%u\n", t300rs->range);
- return count;
+ count = scnprintf(buf, PAGE_SIZE, "%u\n", t300rs->range);
+ return count;
}
static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_range_show, t300rs_range_store);
static void t300rs_set_autocenter(struct input_dev *dev, u16 value){
- struct hid_device *hdev = input_get_drvdata(dev);
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- int ret, trans;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ u8 *send_buffer;
+ int ret, trans;
+
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return;
+ }
-
- send_buffer[0] = 0x08;
- send_buffer[1] = 0x04;
- send_buffer[2] = 0x01;
-
- ret = t300rs_send_int(dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed setting autocenter");
- }
+ send_buffer = t300rs->send_buffer;
- send_buffer[0] = 0x08;
- send_buffer[1] = 0x03;
-
- send_buffer[2] = value & 0xff;
- send_buffer[3] = value >> 8;
- ret = t300rs_send_int(dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed setting autocenter");
- }
+ send_buffer[0] = 0x08;
+ send_buffer[1] = 0x04;
+ send_buffer[2] = 0x01;
+
+ ret = t300rs_send_int(dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed setting autocenter");
+ }
+
+ send_buffer[0] = 0x08;
+ send_buffer[1] = 0x03;
+
+ send_buffer[2] = value & 0xff;
+ send_buffer[3] = value >> 8;
+
+ ret = t300rs_send_int(dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed setting autocenter");
+ }
+
- kfree(send_buffer);
}
static void t300rs_set_gain(struct input_dev *dev, u16 gain){
- struct hid_device *hdev = input_get_drvdata(dev);
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- int ret, trans;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ u8 *send_buffer;
+ int ret, trans;
+
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return;
+ }
+
+ send_buffer = t300rs->send_buffer;
+ send_buffer[0] = 0x02;
+ send_buffer[1] = SCALE_VALUE_U16(gain, 8);
+
+ ret = t300rs_send_int(dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed setting gain: %i\n", ret);
+ }
-
- send_buffer[0] = 0x02;
- send_buffer[1] = SCALE_VALUE_U16(gain, 8);
-
- ret = t300rs_send_int(dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed setting gain: %i\n", ret);
- }
- kfree(send_buffer);
}
static void t300rs_destroy(struct ff_device *ff){
- /* maybe not necessary? */
- return;
+ /* maybe not necessary? */
+ return;
}
static int t300rs_open(struct input_dev *dev){
- struct t300rs_device_entry *t300rs;
- struct hid_device *hdev = input_get_drvdata(dev);
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
- int ret, trans;
-
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return -1;
- }
+ struct t300rs_device_entry *t300rs;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ u8 *send_buffer;
+ int ret, trans;
+
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return -1;
+ }
- send_buffer[0] = 0x01;
- send_buffer[1] = 0x05;
+ send_buffer = t300rs->send_buffer;
+
+ send_buffer[0] = 0x01;
+ send_buffer[1] = 0x05;
+
+ ret = t300rs_send_int(dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed sending interrupts\n");
+ goto err;
+ }
- ret = t300rs_send_int(dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed sending interrupts\n");
- goto err;
- }
-
err:
- kfree(send_buffer);
- return t300rs->open(dev);
+
+ return t300rs->open(dev);
}
static void t300rs_close(struct input_dev *dev){
- int ret, trans;
- struct hid_device *hdev = input_get_drvdata(dev);
- struct t300rs_device_entry *t300rs;
- u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC);
-
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return;
- }
+ int ret, trans;
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct t300rs_device_entry *t300rs;
+ u8 *send_buffer;
+
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return;
+ }
- send_buffer[0] = 0x01;
+ send_buffer = t300rs->send_buffer;
- ret = t300rs_send_int(dev, send_buffer, &trans);
- if(ret){
- hid_err(hdev, "failed sending interrupts\n");
- goto err;
- }
+ send_buffer[0] = 0x01;
+
+ ret = t300rs_send_int(dev, send_buffer, &trans);
+ if(ret){
+ hid_err(hdev, "failed sending interrupts\n");
+ goto err;
+ }
err:
- kfree(send_buffer);
- t300rs->close(dev);
- return;
+
+ t300rs->close(dev);
+ return;
}
-int t300rs_init(struct hid_device *hdev, const signed short *ff_bits){
- struct t300rs_device_entry *t300rs;
- struct t300rs_data *drv_data;
- struct list_head *report_list;
- struct hid_input *hidinput = list_entry(hdev->inputs.next,
- struct hid_input, list);
- struct input_dev *input_dev = hidinput->input;
- struct device *dev = &hdev->dev;
- struct usb_interface *usbif = to_usb_interface(dev->parent);
- struct usb_device *usbdev = interface_to_usbdev(usbif);
- struct hid_report *report;
- struct ff_device *ff;
- u8 *transfer = kzalloc(64, GFP_ATOMIC);
- char range[10] = "900"; /* max */
- int i, ret;
+static int t300rs_create_files(struct hid_device *hdev){
+ int ret;
- drv_data = hid_get_drvdata(hdev);
- if(!drv_data){
- hid_err(hdev, "private driver data not allocated\n");
- ret = -ENOMEM;
- goto err;
- }
+ ret = device_create_file(&hdev->dev, &dev_attr_range);
+ if(ret){
+ hid_warn(hdev, "unable to create sysfs interface for range\n");
+ goto attr_range_err;
+ }
- t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_ATOMIC);
- if(!t300rs){
- hid_err(hdev, "device entry could not be created\n");
- ret = -ENOMEM;
- goto t300rs_err;
- }
+ ret = device_create_file(&hdev->dev, &dev_attr_spring_level);
+ if(ret){
+ hid_warn(hdev, "unable to create sysfs interface for spring_level\n");
+ goto attr_spring_err;
+ }
- t300rs->input_dev = input_dev;
- t300rs->hdev = hdev;
- t300rs->usbdev = usbdev;
- t300rs->usbif = usbif;
- t300rs->max_id = 0;
- t300rs->states = kmalloc(sizeof(struct t300rs_effect_state) * 0x60, GFP_ATOMIC);
+ ret = device_create_file(&hdev->dev, &dev_attr_damper_level);
+ if(ret){
+ hid_warn(hdev, "unable to create sysfs interface for damper_level\n");
+ goto attr_damper_err;
+ }
- if(!t300rs->states){
- hid_err(hdev, "effect states could not be created\n");
- ret = -ENOMEM;
- goto states_err;
- }
+ ret = device_create_file(&hdev->dev, &dev_attr_friction_level);
+ if(ret){
+ hid_warn(hdev, "unable to create sysfs interface for friction_level\n");
+ goto attr_friction_err;
+ }
- spin_lock_init(&t300rs->lock);
+ return ret;
+
+ // if the creation of dev_attr_friction fails, we don't need to remove it
+ // device_remove_file(&hdev->dev, &dev_attr_friction_level);
+attr_friction_err:
+ device_remove_file(&hdev->dev, &dev_attr_damper_level);
+attr_damper_err:
+ device_remove_file(&hdev->dev, &dev_attr_spring_level);
+attr_spring_err:
+ device_remove_file(&hdev->dev, &dev_attr_range);
+attr_range_err:
+ return ret;
+}
- drv_data->device_props = t300rs;
+static int t300rs_init(struct hid_device *hdev, const signed short *ff_bits){
+ struct t300rs_device_entry *t300rs;
+ struct t300rs_data *drv_data;
+ struct list_head *report_list;
+ struct hid_input *hidinput = list_entry(hdev->inputs.next,
+ struct hid_input, list);
+ struct input_dev *input_dev = hidinput->input;
+ struct device *dev = &hdev->dev;
+ struct usb_interface *usbif = to_usb_interface(dev->parent);
+ struct usb_device *usbdev = interface_to_usbdev(usbif);
+ struct ff_device *ff;
+ char range[10] = "900"; // max
+ int i, ret;
- report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
- list_for_each_entry(report, report_list, list){
- int fieldnum;
+ drv_data = hid_get_drvdata(hdev);
+ if(!drv_data){
+ hid_err(hdev, "private driver data not allocated\n");
+ ret = -ENOMEM;
+ goto err;
+ }
- for(fieldnum = 0; fieldnum < report->maxfield; ++fieldnum){
- struct hid_field *field = report->field[fieldnum];
+ t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_KERNEL);
+ if(!t300rs){
+ hid_err(hdev, "device entry could not be created\n");
+ ret = -ENOMEM;
+ goto t300rs_err;
+ }
- if(field->maxusage <= 0){
- continue;
- }
+ t300rs->input_dev = input_dev;
+ t300rs->hdev = hdev;
+ t300rs->usbdev = usbdev;
+ t300rs->usbif = usbif;
- switch(field->usage[0].hid){
- case 0xff000060:
- if(field->report_count < 2){
- hid_warn(hdev, "ignoring FF field with report_count < 2\n");
- continue;
- }
+ t300rs->states = kzalloc(sizeof(struct t300rs_effect_state) * T300RS_MAX_EFFECTS, GFP_KERNEL);
+ if(!t300rs->states){
+ hid_err(hdev, "effect states could not be created\n");
+ ret = -ENOMEM;
+ goto states_err;
+ }
- if(field->logical_maximum == field->logical_minimum){
- hid_warn(hdev, "ignoring FF field with l_max == l_min");
- continue;
- }
+ t300rs->send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_KERNEL);
+ if(!t300rs->send_buffer){
+ hid_err(hdev, "send_buffer could not be created\n");
+ ret = -ENOMEM;
+ goto send_err;
+ }
- if(t300rs->report && t300rs->report != report){
- hid_warn(hdev, "ignoring FF field in other report\n");
- continue;
- }
+ t300rs->firmware_response = kzalloc(sizeof(struct t300rs_firmware_response), GFP_KERNEL);
+ if(!t300rs->firmware_response){
+ hid_err(hdev, "firmware_response could not be created\n");
+ ret = -ENOMEM;
+ goto firmware_err;
+ }
- if(t300rs->ff_field && t300rs->ff_field != field){
- hid_warn(hdev, "ignoring duplicate FF field\n");
- continue;
- }
+ // Check firmware version
+ ret = usb_control_msg(t300rs->usbdev,
+ usb_rcvctrlpipe(t300rs->usbdev, 0),
+ t300rs_firmware_request.bRequest,
+ t300rs_firmware_request.bRequestType,
+ t300rs_firmware_request.wValue,
+ t300rs_firmware_request.wIndex,
+ t300rs->firmware_response,
+ t300rs_firmware_request.wLength,
+ USB_CTRL_SET_TIMEOUT
+ );
- t300rs->report = report;
- t300rs->ff_field = field;
+ // Educated guess
+ if(t300rs->firmware_response->firmware_version < 31 && ret >= 0){
+ hid_err(t300rs->hdev,
+ "firmware version %i is too old, please update the firmware "
+ "using the official Thrustmaster tools. This will have to "
+ "be done outside of Linux.\n",
+ t300rs->firmware_response->firmware_version
+ );
- for(i = 0; ff_bits[i] >= 0; ++i){
- set_bit(ff_bits[i], input_dev->ffbit);
- }
+ ret = -ENOSYS;
+ goto out;
+ }
- break;
+ spin_lock_init(&t300rs->lock);
- default:
- hid_warn(hdev, "ignoring unknown output usage: %i\n", field->usage[0].hid);
- continue;
- }
- }
- }
+ drv_data->device_props = t300rs;
- if(!t300rs->report){
- hid_err(hdev, "can't find FF field in output reports\n");
- ret = -ENODEV;
- goto out;
- }
+ report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
- ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS);
- if(ret){
- hid_err(hdev, "could not create input_ff\n");
- goto out;
- }
+ // 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];
- ff = input_dev->ff;
- ff->upload = t300rs_upload;
- ff->playback = t300rs_play;
- ff->set_gain = t300rs_set_gain;
- ff->set_autocenter = t300rs_set_autocenter;
- ff->destroy = t300rs_destroy;
+ // set ff capabilities
+ for(i = 0; ff_bits[i] >= 0; ++i){
+ __set_bit(ff_bits[i], input_dev->ffbit);
+ }
- t300rs->open = input_dev->open;
- t300rs->close = input_dev->close;
+ ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS);
+ if(ret){
+ hid_err(hdev, "could not create input_ff\n");
+ goto out;
+ }
- input_dev->open = t300rs_open;
- input_dev->close = t300rs_close;
+ ff = input_dev->ff;
+ ff->upload = t300rs_upload;
+ ff->playback = t300rs_play;
+ ff->set_gain = t300rs_set_gain;
+ ff->set_autocenter = t300rs_set_autocenter;
+ ff->destroy = t300rs_destroy;
- ret = device_create_file(&hdev->dev, &dev_attr_range);
- if(ret){
- hid_warn(hdev, "unable to create sysfs interface for range\n");
- goto out;
- }
+ t300rs->open = input_dev->open;
+ t300rs->close = input_dev->close;
- ret = device_create_file(&hdev->dev, &dev_attr_spring_level);
- if(ret){
- hid_warn(hdev, "unable to create sysfs interface for spring_level\n");
- goto out;
- }
+ input_dev->open = t300rs_open;
+ input_dev->close = t300rs_close;
- ret = device_create_file(&hdev->dev, &dev_attr_damper_level);
- if(ret){
- hid_warn(hdev, "unable to create sysfs interface for damper_level\n");
- goto out;
- }
+ ret = t300rs_create_files(hdev);
+ if(ret){
+ // this might not be a catastrophic issue, but it could affect
+ // programs such as oversteer, best play it safe
+ hid_err(hdev, "could not create sysfs files\n");
+ goto out;
+ }
- ret = device_create_file(&hdev->dev, &dev_attr_friction_level);
- if(ret){
- hid_warn(hdev, "unable to create sysfs interface for friction_level\n");
- goto out;
- }
- hrtimer_init(&t300rs->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- t300rs->hrtimer.function = t300rs_timer;
-
- t300rs_range_store(dev, &dev_attr_range, range, 10);
- t300rs_set_gain(input_dev, 0xffff);
+ hrtimer_init(&t300rs->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ t300rs->hrtimer.function = t300rs_timer;
- kfree(transfer);
+ t300rs_range_store(dev, &dev_attr_range, range, 10);
+ t300rs_set_gain(input_dev, 0xffff);
- hid_info(hdev, "force feedback for T300RS\n");
- return 0;
+ hid_info(hdev, "force feedback for T300RS\n");
+ return 0;
out:
- kfree(t300rs->states);
+ kfree(t300rs->firmware_response);
+firmware_err:
+ kfree(t300rs->send_buffer);
+send_err:
+ kfree(t300rs->states);
states_err:
- kfree(t300rs);
+ kfree(t300rs);
t300rs_err:
- kfree(drv_data);
+ kfree(drv_data);
err:
- hid_err(hdev, "failed creating force feedback device\n");
- return ret;
+ hid_err(hdev, "failed creating force feedback device\n");
+ return ret;
}
static int t300rs_probe(struct hid_device *hdev, const struct hid_device_id *id){
- int ret;
- struct t300rs_data *drv_data;
+ int ret;
+ struct t300rs_data *drv_data;
- spin_lock_init(&lock);
+ spin_lock_init(&lock);
- drv_data = kzalloc(sizeof(struct t300rs_data), GFP_ATOMIC);
- if(!drv_data){
- hid_err(hdev, "out of memory\n");
- ret = -ENOMEM;
- goto err;
- }
+ drv_data = kzalloc(sizeof(struct t300rs_data), GFP_KERNEL);
+ if(!drv_data){
+ hid_err(hdev, "out of memory\n");
+ ret = -ENOMEM;
+ goto err;
+ }
- drv_data->quirks = id->driver_data;
- hid_set_drvdata(hdev, (void*)drv_data);
+ drv_data->quirks = id->driver_data;
+ hid_set_drvdata(hdev, (void*)drv_data);
- ret = hid_parse(hdev);
- if(ret){
- hid_err(hdev, "parse failed\n");
- goto err;
- }
+ ret = hid_parse(hdev);
+ if(ret){
+ hid_err(hdev, "parse failed\n");
+ goto err;
+ }
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
- if(ret){
- hid_err(hdev, "hw start failed\n");
- goto err;
- }
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+ if(ret){
+ hid_err(hdev, "hw start failed\n");
+ goto err;
+ }
- ret = t300rs_init(hdev, (void*)id->driver_data);
- if(ret){
- hid_err(hdev, "t300rs_init failed\n");
- goto err;
- }
- return 0;
+ ret = t300rs_init(hdev, (void*)id->driver_data);
+ if(ret){
+ hid_err(hdev, "t300rs_init failed\n");
+ goto err;
+ }
+ return 0;
err:
- kfree(drv_data);
- return ret;
+ return ret;
}
static void t300rs_remove(struct hid_device *hdev){
- struct t300rs_device_entry *t300rs;
- struct t300rs_data *drv_data;
+ struct t300rs_device_entry *t300rs;
+ struct t300rs_data *drv_data;
- drv_data = hid_get_drvdata(hdev);
- t300rs = t300rs_get_device(hdev);
- if(!t300rs){
- hid_err(hdev, "could not get device\n");
- return;
- }
+ drv_data = hid_get_drvdata(hdev);
+ t300rs = t300rs_get_device(hdev);
+ if(!t300rs){
+ hid_err(hdev, "could not get device\n");
+ return;
+ }
- hrtimer_cancel(&t300rs->hrtimer);
+ hrtimer_cancel(&t300rs->hrtimer);
- device_remove_file(&hdev->dev, &dev_attr_range);
- device_remove_file(&hdev->dev, &dev_attr_spring_level);
- device_remove_file(&hdev->dev, &dev_attr_damper_level);
- device_remove_file(&hdev->dev, &dev_attr_friction_level);
+ device_remove_file(&hdev->dev, &dev_attr_range);
+ device_remove_file(&hdev->dev, &dev_attr_spring_level);
+ device_remove_file(&hdev->dev, &dev_attr_damper_level);
+ device_remove_file(&hdev->dev, &dev_attr_friction_level);
- hid_hw_stop(hdev);
- kfree(t300rs->states);
- kfree(drv_data);
- kfree(t300rs);
+ hid_hw_stop(hdev);
+ kfree(t300rs->states);
+ kfree(t300rs->send_buffer);
+ kfree(t300rs->firmware_response);
+ kfree(t300rs);
+ kfree(drv_data);
- return;
+ return;
}
static __u8 *t300rs_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize){
- rdesc = t300rs_rdesc_fixed;
- *rsize = sizeof(t300rs_rdesc_fixed);
- return rdesc;
+ rdesc = t300rs_rdesc_fixed;
+ *rsize = sizeof(t300rs_rdesc_fixed);
+ return rdesc;
}
static const struct hid_device_id t300rs_devices[] = {
- {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e),
- .driver_data = (unsigned long)t300rs_ff_effects},
- {}
+ {HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb66e),
+ .driver_data = (unsigned long)t300rs_ff_effects},
+ {}
};
MODULE_DEVICE_TABLE(hid, t300rs_devices);
static struct hid_driver t300rs_driver = {
- .name = "t300rs",
- .id_table = t300rs_devices,
- .probe = t300rs_probe,
- .remove = t300rs_remove,
- .report_fixup = t300rs_report_fixup,
+ .name = "t300rs",
+ .id_table = t300rs_devices,
+ .probe = t300rs_probe,
+ .remove = t300rs_remove,
+ .report_fixup = t300rs_report_fixup,
};
module_hid_driver(t300rs_driver);
diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h
index 2eef09d..28b44ab 100644
--- a/hid-tmt300rs.h
+++ b/hid-tmt300rs.h
@@ -1,10 +1,14 @@
-#include "hid-tm.h"
-#include "usbhid.h"
+#include <linux/hid.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/slab.h>
#include <linux/ktime.h>
#include <linux/fixp-arith.h>
+#define USB_VENDOR_ID_THRUSTMASTER 0x044f
+
#define T300RS_MAX_EFFECTS 16
#define T300RS_BUFFER_LENGTH 63
@@ -33,69 +37,119 @@ spinlock_t data_lock;
unsigned long data_flags;
static const signed short t300rs_ff_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
+ 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 t300rs_effect_state {
- struct ff_effect effect;
- struct ff_effect old;
- bool old_set;
- unsigned long flags;
- unsigned long start_time;
- unsigned long count;
+ struct ff_effect effect;
+ struct ff_effect old;
+ bool old_set;
+ unsigned long flags;
+ unsigned long start_time;
+ unsigned long count;
+};
+
+struct __packed t300rs_firmware_response {
+ uint8_t unknown0;
+ uint8_t unknown1;
+ uint8_t firmware_version;
+ uint8_t unknown2;
};
+
+struct usb_ctrlrequest t300rs_firmware_request = {
+ .bRequestType = 0xc1,
+ .bRequest = 86,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = 8
+};
+
+
struct t300rs_device_entry {
- struct hid_device *hdev;
- struct input_dev *input_dev;
- struct hid_report *report;
- struct hid_field *ff_field;
- struct usb_device *usbdev;
- struct usb_interface *usbif;
- struct t300rs_effect_state *states;
- struct hrtimer hrtimer;
+ struct hid_device *hdev;
+ struct input_dev *input_dev;
+ struct hid_report *report;
+ struct hid_field *ff_field;
+ struct usb_device *usbdev;
+ struct usb_interface *usbif;
+ struct t300rs_effect_state *states;
+ struct t300rs_firmware_response *firmware_response;
+ struct hrtimer hrtimer;
- int (*open)(struct input_dev *dev);
- void (*close)(struct input_dev *dev);
+ int (*open)(struct input_dev *dev);
+ void (*close)(struct input_dev *dev);
- spinlock_t lock;
- unsigned long lock_flags;
+ spinlock_t lock;
+ unsigned long lock_flags;
- int open_count;
-
- int max_id;
- u16 range;
- u8 effects_used;
+ u8 *send_buffer;
+
+ u16 range;
+ u8 effects_used;
};
struct t300rs_data{
- unsigned long quirks;
- void *device_props;
+ unsigned long quirks;
+ void *device_props;
};
-static __u8 t300rs_rdesc_fixed[] = {0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x07, 0x09, 0x30, 0x15, 0x00, 0x27, 0xff, 0xff, 0x00, 0x00, 0x35, 0x00, 0x47, 0xff, 0xff, 0x00, 0x00, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 0x09, 0x35, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x32, 0x81, 0x02, 0x09, 0x31, 0x81, 0x02, 0x81, 0x03, 0x05, 0x09, 0x19, 0x01, 0x29, 0x0d, 0x25, 0x01, 0x45, 0x01, 0x75, 0x01, 0x95, 0x0d, 0x81, 0x02, 0x75, 0x0b, 0x95, 0x01, 0x81, 0x03, 0x05, 0x01, 0x09, 0x39, 0x25, 0x07, 0x46, 0x3b, 0x01, 0x55, 0x00, 0x65, 0x14, 0x75, 0x04, 0x81, 0x42, 0x65, 0x00, 0x81, 0x03, 0x85, 0x60, // here 0x0a
- 0x06, 0x00, 0xff, 0x09, 0x60, // here 0x0a
- 0x75, 0x08, 0x95, 0x3f, 0x26, 0xff, 0x7f, 0x15, 0x00, 0x46, 0xff, 0x7f, 0x36, 0x00, 0x80, 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14, 0x81, 0x02, 0xc0, 0xc0,};
+static __u8 t300rs_rdesc_fixed[] = {
+ 0x05, 0x01, 0x09, 0x04, 0xa1,
+ 0x01, 0x09, 0x01, 0xa1, 0x00,
+ 0x85, 0x07, 0x09, 0x30, 0x15,
+ 0x00, 0x27, 0xff, 0xff, 0x00,
+ 0x00, 0x35, 0x00, 0x47, 0xff,
+ 0xff, 0x00, 0x00, 0x75, 0x10,
+ 0x95, 0x01, 0x81, 0x02, 0x09,
+ 0x35, 0x26, 0xff, 0x03, 0x46,
+ 0xff, 0x03, 0x81, 0x02, 0x09,
+ 0x32, 0x81, 0x02, 0x09, 0x31,
+ 0x81, 0x02, 0x81, 0x03, 0x05,
+ 0x09, 0x19, 0x01, 0x29, 0x0d,
+ 0x25, 0x01, 0x45, 0x01, 0x75,
+ 0x01, 0x95, 0x0d, 0x81, 0x02,
+ 0x75, 0x0b, 0x95, 0x01, 0x81,
+ 0x03, 0x05, 0x01, 0x09, 0x39,
+ 0x25, 0x07, 0x46, 0x3b, 0x01,
+ 0x55, 0x00, 0x65, 0x14, 0x75,
+ 0x04, 0x81, 0x42, 0x65, 0x00,
+ 0x81, 0x03, 0x85, 0x60, // here 0x0a
+ 0x06, 0x00, 0xff, 0x09, 0x60, // here 0x0a
+ 0x75, 0x08, 0x95, 0x3f, 0x26,
+ 0xff, 0x7f, 0x15, 0x00, 0x46,
+ 0xff, 0x7f, 0x36, 0x00, 0x80,
+ 0x91, 0x02, 0x85, 0x02, 0x09,
+ 0x02, 0x81, 0x02, 0x09, 0x14,
+ 0x85, 0x14, 0x81, 0x02, 0xc0,
+ 0xc0,
+};
static u8 spring_values[] = {
- 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xdf, 0x58, 0xa6, 0x6a, 0x06
+ 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
+ 0xfc, 0x7f, 0xfc, 0x7f, 0xfe,
+ 0xff, 0xfe, 0xff, 0xfe, 0xff,
+ 0xfe, 0xff, 0xfc, 0x7f, 0xfc,
+ 0x7f, 0x07
};
diff --git a/usbhid.h b/usbhid.h
deleted file mode 100644
index 8ab2917..0000000
--- a/usbhid.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef __USBHID_H
-#define __USBHID_H
-
-/*
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik
- * Copyright (c) 2006 Jiri Kosina
- */
-
-/*
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/input.h>
-
-/* API provided by hid-core.c for USB HID drivers */
-void usbhid_init_reports(struct hid_device *hid);
-struct usb_interface *usbhid_find_interface(int minor);
-
-/* iofl flags */
-#define HID_CTRL_RUNNING 1
-#define HID_OUT_RUNNING 2
-#define HID_IN_RUNNING 3
-#define HID_RESET_PENDING 4
-#define HID_SUSPENDED 5
-#define HID_CLEAR_HALT 6
-#define HID_DISCONNECTED 7
-#define HID_STARTED 8
-#define HID_KEYS_PRESSED 10
-#define HID_NO_BANDWIDTH 11
-#define HID_RESUME_RUNNING 12
-/*
- * The device is opened, meaning there is a client that is interested
- * in data coming from the device.
- */
-#define HID_OPENED 13
-/*
- * We are polling input endpoint by [re]submitting IN URB, because
- * either HID device is opened or ALWAYS POLL quirk is set for the
- * device.
- */
-#define HID_IN_POLLING 14
-
-/*
- * USB-specific HID struct, to be pointed to
- * from struct hid_device->driver_data
- */
-
-struct usbhid_device {
- struct hid_device *hid; /* pointer to corresponding HID dev */
-
- struct usb_interface *intf; /* USB interface */
- int ifnum; /* USB interface number */
-
- unsigned int bufsize; /* URB buffer size */
-
- struct urb *urbin; /* Input URB */
- char *inbuf; /* Input buffer */
- dma_addr_t inbuf_dma; /* Input buffer dma */
-
- struct urb *urbctrl; /* Control URB */
- struct usb_ctrlrequest *cr; /* Control request struct */
- struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
- unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
- char *ctrlbuf; /* Control buffer */
- dma_addr_t ctrlbuf_dma; /* Control buffer dma */
- unsigned long last_ctrl; /* record of last output for timeouts */
-
- struct urb *urbout; /* Output URB */
- struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
- unsigned char outhead, outtail; /* Output pipe fifo head & tail */
- char *outbuf; /* Output buffer */
- dma_addr_t outbuf_dma; /* Output buffer dma */
- unsigned long last_out; /* record of last output for timeouts */
-
- spinlock_t lock; /* fifo spinlock */
- unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
- struct timer_list io_retry; /* Retry timer */
- unsigned long stop_retry; /* Time to give up, in jiffies */
- unsigned int retry_delay; /* Delay length in ms */
- struct work_struct reset_work; /* Task context for resets */
- wait_queue_head_t wait; /* For sleeping */
-};
-
-#define hid_to_usb_dev(hid_dev) \
- to_usb_device(hid_dev->dev.parent->parent)
-
-#endif