From db12c7bead4154929668badaade14db135dab6d9 Mon Sep 17 00:00:00 2001 From: kimi Date: Wed, 8 Jul 2020 11:17:48 -0400 Subject: initial commit for memory --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index ba704a9..d666a97 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -obj-m += hid-tmff2.o +obj-m += hid-tminit.o all: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules -- cgit v1.3 From bec11109dd3d5792b54044e04eba044048484dba Mon Sep 17 00:00:00 2001 From: kimi Date: Thu, 9 Jul 2020 06:49:27 -0400 Subject: big changes --- Makefile | 1 + hid-tminit.c | 4 +- hid-tmt300rs.c | 385 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- hid-tmt300rs.h | 50 ++++++++ 4 files changed, 438 insertions(+), 2 deletions(-) create mode 100644 hid-tmt300rs.h (limited to 'Makefile') diff --git a/Makefile b/Makefile index d666a97..6675c23 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ obj-m += hid-tminit.o +obj-m += hid-tmt300rs.o all: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules diff --git a/hid-tminit.c b/hid-tminit.c index e48b419..e20126b 100644 --- a/hid-tminit.c +++ b/hid-tminit.c @@ -1,5 +1,7 @@ #include "hid-tminit.h" + + static void tminit_callback(struct urb *urb){ ctx.status = urb->status; hid_info(urb->dev, "urb status %d received\n", urb->status); @@ -26,7 +28,7 @@ int tminit(struct hid_device *hdev){ usb_sndctrlpipe(usbdev, 0), setup_packet, transfer_buffer, - 0, + 8, tminit_callback, hdev); diff --git a/hid-tmt300rs.c b/hid-tmt300rs.c index 3c3684c..1368a62 100644 --- a/hid-tmt300rs.c +++ b/hid-tmt300rs.c @@ -1 +1,384 @@ -/* empty for now */ +#include "hid-tmt300rs.h" + +static struct t300rs_device_entry *t300rs_get_device(struct hid_device *hdev){ + 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; + } + + 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; + struct usb_device *usbdev; + struct usb_interface *usbif; + struct usb_host_endpoint *ep; + int b_ep; + + t300rs = t300rs_get_device(hdev); + + usbdev = t300rs->usbdev; + usbif = t300rs->usbif; + ep = &usbif->cur_altsetting->endpoint[1]; + b_ep = ep->desc.bEndpointAddress; + + return usb_interrupt_msg(usbdev, + usb_sndintpipe(usbdev, b_ep), + send_buffer, + T300RS_BUFFER_LENGTH, + trans, + USB_CTRL_SET_TIMEOUT); +} + +static int t300rs_upload(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old){ + /* temp */ + return 0; +} + +static int t300rs_play(struct input_dev *dev, int effect_id, int value){ + /* temp */ + return 0; +} + +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; + + t300rs = t300rs_get_device(hdev); + + if(range < 0x097b){ + range = 0x097b; + } + + send_buffer[0] = 0x60; + send_buffer[1] = 0x08; + send_buffer[2] = 0x11; + send_buffer[3] = range & 0xff; + send_buffer[4] = 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; + kfree(send_buffer); + 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; + + t300rs = t300rs_get_device(hdev); + + return t300rs->range; +} + +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, t300rs_range_show, t300rs_range_store); + +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; + + send_buffer[0] = 0x60; + send_buffer[1] = 0x02; + send_buffer[2] = SCALE_VALUE_U16(gain, sizeof(char)); + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + } +} + +static void t300rs_destroy(struct ff_device *ff){ + /* maybe not temp? */ + return; +} + + +static int t300rs_open(struct input_dev *dev){ + struct hid_device *hdev = input_get_drvdata(dev); + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + int ret, trans; + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + send_buffer[2] = 0x04; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + memset(send_buffer, 0, T300RS_BUFFER_LENGTH); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x12; + send_buffer[2] = 0xbf; + send_buffer[3] = 0x04; + send_buffer[6] = 0x03; + send_buffer[7] = 0xb7; + send_buffer[8] = 0x1e; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + memset(send_buffer, 0, T300RS_BUFFER_LENGTH); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + send_buffer[2] = 0x05; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } + +err: + kfree(send_buffer); + return ret; +} + +static void t300rs_close(struct input_dev *dev){ + int ret, trans; + struct hid_device *hdev = input_get_drvdata(dev); + u8 *send_buffer = kzalloc(T300RS_BUFFER_LENGTH, GFP_ATOMIC); + + send_buffer[0] = 0x60; + send_buffer[1] = 0x01; + + ret = t300rs_send_int(dev, send_buffer, &trans); + if(ret){ + hid_err(hdev, "failed sending interrupts\n"); + goto err; + } +err: + kfree(send_buffer); + 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; + int i, ret; + + drv_data = hid_get_drvdata(hdev); + if(!drv_data){ + hid_err(hdev, "private driver data not allocated\n"); + ret = -ENOMEM; + goto err; + } + + t300rs = kzalloc(sizeof(struct t300rs_device_entry), GFP_ATOMIC); + if(!t300rs){ + return -ENOMEM; + } + + t300rs->input_dev = input_dev; + t300rs->hdev = hdev; + t300rs->usbdev = usbdev; + t300rs->usbif = usbif; + spin_lock_init(&t300rs->lock); + + drv_data->device_props = t300rs; + + + report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; + list_for_each_entry(report, report_list, list){ + int fieldnum; + + for(fieldnum = 0; fieldnum < report->maxfield; ++fieldnum){ + struct hid_field *field = report->field[fieldnum]; + + if(field->maxusage <= 0){ + continue; + } + + switch(field->usage[0].hid){ + case 0xff00000a: + if(field->report_count < 2){ + hid_warn(hdev, "ignoring FF field with report_count < 2\n"); + continue; + } + + if(field->logical_maximum == field->logical_minimum){ + hid_warn(hdev, "ignoring FF field with l_max == l_min"); + continue; + } + + if(t300rs->report && t300rs->report != report){ + hid_warn(hdev, "ignoring FF field in other report\n"); + continue; + } + + if(t300rs->ff_field && t300rs->ff_field != field){ + hid_warn(hdev, "ignoring duplicate FF field\n"); + continue; + } + + t300rs->report = report; + t300rs->ff_field = field; + + for(i = 0; ff_bits[i] >= 0; ++i){ + set_bit(ff_bits[i], input_dev->ffbit); + } + + break; + + default: + hid_warn(hdev, "ignoring unknown output usage\n"); + continue; + } + } + } + + if(!t300rs->report){ + hid_err(hdev, "can't find FF field in output reports\n"); + ret = -ENODEV; + goto err; + } + + ret = input_ff_create(input_dev, T300RS_MAX_EFFECTS); + if(ret){ + hid_err(hdev, "could not create input_ff\n"); + goto err; + } + + ff = input_dev->ff; + ff->upload = t300rs_upload; + ff->playback = t300rs_play; + ff->set_gain = t300rs_set_gain; + ff->destroy = t300rs_destroy; + + input_dev->open = t300rs_open; + input_dev->close = t300rs_close; + + ret = device_create_file(&hdev->dev, &dev_attr_range); + if(ret){ + hid_warn(hdev, "unable to create sysfs interface for range\n"); + } + + hid_info(hdev, "force feedback for T300RS\n"); + return 0; +err: + kfree(t300rs); + 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; + + spin_lock_init(&lock); + spin_lock_irqsave(&lock, lock_flags); + + 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->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_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; + } + + spin_unlock_irqrestore(&lock, lock_flags); + return 0; +err: + kfree(drv_data); + spin_unlock_irqrestore(&lock, lock_flags); + return ret; +} + +static void t300rs_remove(struct hid_device *hdev){ + struct t300rs_device_entry *t300rs; + struct t300rs_data *drv_data; + + device_remove_file(&hdev->dev, &dev_attr_range); + + drv_data = hid_get_drvdata(hdev); + t300rs = t300rs_get_device(hdev); + + kfree(drv_data); + kfree(t300rs); + hid_hw_stop(hdev); + 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; +} + +static const struct hid_device_id t300rs_devices[] = { + {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, +}; +module_hid_driver(t300rs_driver); + +MODULE_LICENSE("GPL"); diff --git a/hid-tmt300rs.h b/hid-tmt300rs.h new file mode 100644 index 0000000..876f778 --- /dev/null +++ b/hid-tmt300rs.h @@ -0,0 +1,50 @@ +#include "hid-tm.h" + +#define T300RS_MAX_EFFECTS FF_MAX_EFFECTS +#define T300RS_BUFFER_LENGTH 64 + +#define CLAMP_VALUE_U16(x) ((unsigned short)((x) > 0xffff ? 0xffff : (x))) +#define SCALE_VALUE_U16(x, bits) (CLAMP_VALUE_U16(x) >> (16 - bits)) + +spinlock_t lock; +unsigned long lock_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 +}; + +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; + + spinlock_t lock; + unsigned long lock_flags; + + u16 range; +}; + +struct t300rs_data{ + 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, 0x31, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x81, 0x02, 0x09, 0x35, 0x81, 0x02, 0x09, 0x36, 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, 0x0a, 0x06, 0x00, 0xff, 0x09, 0x0a, 0x75, 0x08, 0x95, 0x3f, 0x26, 0xff, 0x7f, 0x16, 0x00, 0x80, 0x46, 0xff, 0x7f, 0x36, 0x00, 0x80, 0x91, 0x02, 0x85, 0x02, 0x09, 0x02, 0x81, 0x02, 0x09, 0x14, 0x85, 0x14, 0x81, 0x02, 0xc0, 0xc0,}; + -- cgit v1.3