* [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-17 2:21 ` Peta Blaha
0 siblings, 0 replies; 11+ messages in thread
From: Peta Blaha @ 2009-03-17 2:21 UTC (permalink / raw)
To: linux-input, linux-usb; +Cc: linux-kernel
Driver for Fortius 1942 device.
Signed-off-by: Petr Blaha <blahapeta@gmail.com>
---
--- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
01:00:00.000000000 +0100
+++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000 +0100
@@ -0,0 +1,394 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ *
+ * Info.
+ * First unimpemented feature Heart Sensor.
+ * Use bit 12 and 14(beginning 0), maybe 13 also.Emmisions
+ * from computer affect measuring.
+ *
+ * Second is Active Brake
+ * Can be maybe used as force feedback. Problem is slowness in
+ * switching from state to state, its electric motor, it has delay can
+ * be fragile.
+ * Try it by changing BRAKE_POS from 0 to 10.
+ *
+ * Thirth unimpemented is sending 0x01, when pedal magnet meets frame sensor.
+ *
+ * Pedalling works fine. Your wheel can have other size tan mime. Feel free
+ * to change constant in usb_tfor_irq, when counting value of gasolina.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <linux/time.h>
+
+
+#define DRIVER_VERSION "v0.0.2"
+#define DRIVER_DESC "USB Tacx Fortius 1942 driver"
+#define DRIVER_LICENSE "GPL"
+#define DRIVER_AUTHOR "Petr Blaha <blahapeta@gmail.com>"
+
+
+/*Don't put here lesser values*/
+/*read*/
+#define BIT_IN_DEVICE_1942 64
+/*write*/
+#define BIT_OUT_DEVICE_1942 12
+/*read*/
+#define BULK_IN_INTERFACE_1942 82
+/*write*/
+#define BULK_OUT_INTERFACE_1942 02
+
+
+#define BRAKE_POS 2
+
+
+/*11 states of brake,in beginning active brake helps, later add
+difficulty to cycling.0x00 0x00 is neutral*/
+#define ARRAYINT { {0x4d, 0xf3}, {0xa7, 0xf9}, {0x00, 0x00}, {0x59, 0x06}, \
+{0xb3, 0x0c}, {0x0c, 0x13}, {0x66, 0x19}, {0xbf, 0x1f}, {0x18, 0x26}, {0x72, \
+0x2c}, {0xcb, 0x32} }
+
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+ unsigned long difference = 0;
+ /*time measure*/
+ struct timeval time, time_before;
+ /*guessed fastest speed a man can possibly ride-incitating full
+ throttle*/
+ unsigned int fastest_wheel_rotate = 1000;
+ /*actual state of path reached in one cycle*/
+ unsigned int ride = 0, old_ride = 0;
+
+struct usb_tfor {
+ char name[128];
+ char phys[64];
+ struct usb_device *usbdev;
+ struct input_dev *input;
+
+ struct urb *irq;
+ unsigned char *data;
+ dma_addr_t idata_dma;
+
+ struct urb *out;
+ unsigned char *data_device;
+ dma_addr_t odata_dma;
+ /*brake position*/
+ unsigned int brake_pos;
+};
+
+static void tfor_disconnect(struct usb_interface *intf)
+{
+ struct usb_tfor *tfor = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+ if (tfor) {
+ /*urb*/
+ usb_kill_urb(tfor->out);
+ usb_kill_urb(tfor->irq);
+ /*device*/
+ input_unregister_device(tfor->input);
+ /*urb*/
+ usb_free_urb(tfor->out);
+ usb_free_urb(tfor->irq);
+ /*buffer free*/
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data_device, \
+ tfor->odata_dma);
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data, \
+ tfor->idata_dma);
+ /*free memory*/
+ kfree(tfor);
+ }
+}
+
+static int usb_tfor_open(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ tfor->irq->dev = tfor->usbdev;
+ usb_submit_urb(tfor->irq, GFP_KERNEL);
+ tfor->out->dev = tfor->usbdev;
+ usb_submit_urb(tfor->out, GFP_KERNEL);
+
+ return 0;
+}
+
+static void usb_tfor_close(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ usb_kill_urb(tfor->irq);
+ usb_kill_urb(tfor->out);
+}
+
+static struct usb_device_id tfor_ids[] = {
+ { USB_DEVICE(0x3561, 0x1942), .driver_info = 0 },
+ { }
+};
+
+static void usb_tfor_out(struct urb *urb)
+{ struct usb_tfor *tfor = urb->context;
+ unsigned int brake_bits[11][2] = ARRAYINT;
+ int retval;
+ tfor->brake_pos = BRAKE_POS;
+ /*URB to device*/
+ /*constant*/
+ tfor->data_device[0] = 0x01;
+ /*constant*/
+ tfor->data_device[1] = 0x08;
+ /*constant*/
+ tfor->data_device[2] = 0x01;
+ /*constant*/
+ tfor->data_device[3] = 0x00;
+ /*brake_bits*/
+ tfor->data_device[4] = brake_bits[tfor->brake_pos][0];
+ /*brake_bits*/
+ tfor->data_device[5] = brake_bits[tfor->brake_pos][1];
+ /*0x01 is turn,when frame sensor meets pedal magnet,
+ i don't see reason for implementation, nor know how device knows it*/
+ tfor->data_device[6] = 0x00;
+ /*constant*/
+ tfor->data_device[7] = 0x00;
+ /*constant*/
+ tfor->data_device[8] = 0x02;
+ /*constant*/
+ tfor->data_device[9] = 0x52;
+ /*constant*/
+ tfor->data_device[10] = 0x10;
+ /*constant*/
+ tfor->data_device[11] = 0x04;
+
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ break;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ }
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __func__, retval);
+}
+
+static void usb_tfor_irq(struct urb *urb)
+{
+ struct usb_tfor *tfor = urb->context;
+ unsigned char *data = tfor->data;
+ struct input_dev *dev = tfor->input;
+ int status;
+ int gasolina;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* ±this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, \
+ urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, \
+ urb->status);
+ goto resubmit;
+ }
+
+ /*Get actual time*/
+ do_gettimeofday(&time);
+ /*Ride counter in velociped is small,avoid mistake here*/
+ if ((data[28]*255+data[29]) < ride)
+ ride = 0;
+ /*We get new data, set new val. of ride counter &time counter*/
+ if ((data[28]*255+data[29]) > ride) {
+ old_ride = ride;
+ ride = (data[28]*255+data[29]);
+ difference = \
+ ((time.tv_usec-time_before.tv_usec)\
+ +(time.tv_sec-time_before.tv_sec)*1000000);
+ do_gettimeofday(&time_before);
+ if (difference == 0)
+ dbg("Something is not good \n");
+ }
+ /*Prevent division by 0*/
+ if (difference != 0)
+ /*"speed=path/time",change constant 1000
+ to naturalize it for your speed*/
+ gasolina = (ride-old_ride)/(difference/1000);
+ else
+ gasolina = 0;
+ input_report_abs(dev, ABS_GAS, gasolina);
+ input_report_key(dev, BTN_RIGHT, data[13] & 0x01);
+ input_report_key(dev, BTN_BACK, data[13] & 0x02);
+ input_report_key(dev, BTN_FORWARD, data[13] & 0x04);
+ input_report_key(dev, BTN_LEFT, data[13] & 0x08);
+ input_report_abs(dev, ABS_WHEEL, (((data[18]+((data[19] & 0x0f)*225))-\
+ (689+170))*-1));
+
+ /* event termination */
+ input_sync(dev);
+
+resubmit:
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ err("can't resubmit intr, %s-%s/input0, status %d",
+ tfor->usbdev->bus->bus_name, tfor->usbdev->devpath, status);
+
+}
+
+static int tfor_probe(struct usb_interface *intf, const struct
usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_tfor *tfor;
+ struct input_dev *input_dev;
+ unsigned int err = -ENOMEM;
+
+
+ tfor = kzalloc(sizeof(struct usb_tfor), GFP_KERNEL);
+
+ input_dev = input_allocate_device();
+ if (!tfor || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+ /*initilization of time counter*/
+ do_gettimeofday(&time);
+ time_before.tv_usec = time.tv_usec;
+ time_before.tv_sec = time.tv_sec;
+
+ tfor->data = usb_buffer_alloc(dev, BIT_IN_DEVICE_1942, GFP_KERNEL, \
+ &tfor->idata_dma);
+ if (!tfor->data) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->data_device = usb_buffer_alloc(dev, BIT_OUT_DEVICE_1942, \
+ GFP_KERNEL, &tfor->odata_dma);
+ if (!tfor->data_device) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ tfor->out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail3;
+ }
+
+ tfor->usbdev = dev;
+ tfor->input = input_dev;
+
+ usb_make_path(dev, tfor->phys, sizeof(tfor->phys));
+ strlcat(tfor->phys, "/input0", sizeof(tfor->phys));
+
+ input_dev->name = "Tacx Fortius 1942";
+ input_dev->phys = tfor->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+ input_set_drvdata(input_dev, tfor);
+ input_dev->open = usb_tfor_open;
+ input_dev->close = usb_tfor_close;
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ /*handlebar*/
+ input_set_abs_params(input_dev, ABS_WHEEL, -170, 170, 0, 20);
+ /*plyn*/
+ input_set_abs_params(input_dev, ABS_GAS, 0, 40, 2, 0);
+ /*buttons*/
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+ set_bit(BTN_FORWARD, input_dev->keybit);
+ set_bit(BTN_BACK, input_dev->keybit);
+
+ usb_fill_bulk_urb(tfor->irq, dev, usb_rcvbulkpipe(dev, \
+ BULK_IN_INTERFACE_1942), tfor->data, BIT_IN_DEVICE_1942, \
+ usb_tfor_irq, tfor);
+ tfor->irq->transfer_dma = tfor->idata_dma;
+ tfor->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /*
+ * urb sends data to machine
+ */
+
+ usb_fill_bulk_urb(tfor->out, dev, usb_sndbulkpipe(dev, \
+ BULK_OUT_INTERFACE_1942), tfor->data_device, BIT_OUT_DEVICE_1942, \
+ usb_tfor_out, tfor);
+ tfor->out->transfer_dma = tfor->odata_dma;
+ tfor->out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ err = input_register_device(tfor->input);
+ if (err)
+ goto fail2;
+
+ usb_set_intfdata(intf, tfor);
+
+ return 0;
+
+ fail3: usb_buffer_free(dev, BIT_OUT_DEVICE_1942, tfor->data_device, \
+ tfor->odata_dma);
+ fail2: usb_buffer_free(dev, BIT_IN_DEVICE_1942, tfor->data, tfor->idata_dma);
+ fail1: input_free_device(input_dev);
+ kfree(tfor);
+ return err;
+}
+
+static struct usb_driver tfor_driver = {
+ .name = "fortius_1942",
+ .probe = tfor_probe,
+ .disconnect = tfor_disconnect,
+ .id_table = tfor_ids,
+};
+
+static int __init tfor_init(void)
+{
+ int retval;
+ retval = usb_register(&tfor_driver);
+ if (retval)
+ goto out;
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" \
+ DRIVER_DESC "\n");
+out:
+ return retval;
+}
+
+static void __exit tfor_exit(void)
+{
+ usb_deregister(&tfor_driver);
+}
+
+module_init(tfor_init);
+module_exit(tfor_exit);
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-17 2:21 ` Peta Blaha
0 siblings, 0 replies; 11+ messages in thread
From: Peta Blaha @ 2009-03-17 2:21 UTC (permalink / raw)
To: linux-input, linux-usb; +Cc: linux-kernel
Driver for Fortius 1942 device.
Signed-off-by: Petr Blaha <blahapeta@gmail.com>
---
--- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
01:00:00.000000000 +0100
+++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000 +0100
@@ -0,0 +1,394 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ *
+ * Info.
+ * First unimpemented feature Heart Sensor.
+ * Use bit 12 and 14(beginning 0), maybe 13 also.Emmisions
+ * from computer affect measuring.
+ *
+ * Second is Active Brake
+ * Can be maybe used as force feedback. Problem is slowness in
+ * switching from state to state, its electric motor, it has delay can
+ * be fragile.
+ * Try it by changing BRAKE_POS from 0 to 10.
+ *
+ * Thirth unimpemented is sending 0x01, when pedal magnet meets frame sensor.
+ *
+ * Pedalling works fine. Your wheel can have other size tan mime. Feel free
+ * to change constant in usb_tfor_irq, when counting value of gasolina.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <linux/time.h>
+
+
+#define DRIVER_VERSION "v0.0.2"
+#define DRIVER_DESC "USB Tacx Fortius 1942 driver"
+#define DRIVER_LICENSE "GPL"
+#define DRIVER_AUTHOR "Petr Blaha <blahapeta@gmail.com>"
+
+
+/*Don't put here lesser values*/
+/*read*/
+#define BIT_IN_DEVICE_1942 64
+/*write*/
+#define BIT_OUT_DEVICE_1942 12
+/*read*/
+#define BULK_IN_INTERFACE_1942 82
+/*write*/
+#define BULK_OUT_INTERFACE_1942 02
+
+
+#define BRAKE_POS 2
+
+
+/*11 states of brake,in beginning active brake helps, later add
+difficulty to cycling.0x00 0x00 is neutral*/
+#define ARRAYINT { {0x4d, 0xf3}, {0xa7, 0xf9}, {0x00, 0x00}, {0x59, 0x06}, \
+{0xb3, 0x0c}, {0x0c, 0x13}, {0x66, 0x19}, {0xbf, 0x1f}, {0x18, 0x26}, {0x72, \
+0x2c}, {0xcb, 0x32} }
+
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+ unsigned long difference = 0;
+ /*time measure*/
+ struct timeval time, time_before;
+ /*guessed fastest speed a man can possibly ride-incitating full
+ throttle*/
+ unsigned int fastest_wheel_rotate = 1000;
+ /*actual state of path reached in one cycle*/
+ unsigned int ride = 0, old_ride = 0;
+
+struct usb_tfor {
+ char name[128];
+ char phys[64];
+ struct usb_device *usbdev;
+ struct input_dev *input;
+
+ struct urb *irq;
+ unsigned char *data;
+ dma_addr_t idata_dma;
+
+ struct urb *out;
+ unsigned char *data_device;
+ dma_addr_t odata_dma;
+ /*brake position*/
+ unsigned int brake_pos;
+};
+
+static void tfor_disconnect(struct usb_interface *intf)
+{
+ struct usb_tfor *tfor = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+ if (tfor) {
+ /*urb*/
+ usb_kill_urb(tfor->out);
+ usb_kill_urb(tfor->irq);
+ /*device*/
+ input_unregister_device(tfor->input);
+ /*urb*/
+ usb_free_urb(tfor->out);
+ usb_free_urb(tfor->irq);
+ /*buffer free*/
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data_device, \
+ tfor->odata_dma);
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data, \
+ tfor->idata_dma);
+ /*free memory*/
+ kfree(tfor);
+ }
+}
+
+static int usb_tfor_open(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ tfor->irq->dev = tfor->usbdev;
+ usb_submit_urb(tfor->irq, GFP_KERNEL);
+ tfor->out->dev = tfor->usbdev;
+ usb_submit_urb(tfor->out, GFP_KERNEL);
+
+ return 0;
+}
+
+static void usb_tfor_close(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ usb_kill_urb(tfor->irq);
+ usb_kill_urb(tfor->out);
+}
+
+static struct usb_device_id tfor_ids[] = {
+ { USB_DEVICE(0x3561, 0x1942), .driver_info = 0 },
+ { }
+};
+
+static void usb_tfor_out(struct urb *urb)
+{ struct usb_tfor *tfor = urb->context;
+ unsigned int brake_bits[11][2] = ARRAYINT;
+ int retval;
+ tfor->brake_pos = BRAKE_POS;
+ /*URB to device*/
+ /*constant*/
+ tfor->data_device[0] = 0x01;
+ /*constant*/
+ tfor->data_device[1] = 0x08;
+ /*constant*/
+ tfor->data_device[2] = 0x01;
+ /*constant*/
+ tfor->data_device[3] = 0x00;
+ /*brake_bits*/
+ tfor->data_device[4] = brake_bits[tfor->brake_pos][0];
+ /*brake_bits*/
+ tfor->data_device[5] = brake_bits[tfor->brake_pos][1];
+ /*0x01 is turn,when frame sensor meets pedal magnet,
+ i don't see reason for implementation, nor know how device knows it*/
+ tfor->data_device[6] = 0x00;
+ /*constant*/
+ tfor->data_device[7] = 0x00;
+ /*constant*/
+ tfor->data_device[8] = 0x02;
+ /*constant*/
+ tfor->data_device[9] = 0x52;
+ /*constant*/
+ tfor->data_device[10] = 0x10;
+ /*constant*/
+ tfor->data_device[11] = 0x04;
+
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ break;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ }
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __func__, retval);
+}
+
+static void usb_tfor_irq(struct urb *urb)
+{
+ struct usb_tfor *tfor = urb->context;
+ unsigned char *data = tfor->data;
+ struct input_dev *dev = tfor->input;
+ int status;
+ int gasolina;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* ±this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, \
+ urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, \
+ urb->status);
+ goto resubmit;
+ }
+
+ /*Get actual time*/
+ do_gettimeofday(&time);
+ /*Ride counter in velociped is small,avoid mistake here*/
+ if ((data[28]*255+data[29]) < ride)
+ ride = 0;
+ /*We get new data, set new val. of ride counter &time counter*/
+ if ((data[28]*255+data[29]) > ride) {
+ old_ride = ride;
+ ride = (data[28]*255+data[29]);
+ difference = \
+ ((time.tv_usec-time_before.tv_usec)\
+ +(time.tv_sec-time_before.tv_sec)*1000000);
+ do_gettimeofday(&time_before);
+ if (difference == 0)
+ dbg("Something is not good \n");
+ }
+ /*Prevent division by 0*/
+ if (difference != 0)
+ /*"speed=path/time",change constant 1000
+ to naturalize it for your speed*/
+ gasolina = (ride-old_ride)/(difference/1000);
+ else
+ gasolina = 0;
+ input_report_abs(dev, ABS_GAS, gasolina);
+ input_report_key(dev, BTN_RIGHT, data[13] & 0x01);
+ input_report_key(dev, BTN_BACK, data[13] & 0x02);
+ input_report_key(dev, BTN_FORWARD, data[13] & 0x04);
+ input_report_key(dev, BTN_LEFT, data[13] & 0x08);
+ input_report_abs(dev, ABS_WHEEL, (((data[18]+((data[19] & 0x0f)*225))-\
+ (689+170))*-1));
+
+ /* event termination */
+ input_sync(dev);
+
+resubmit:
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ err("can't resubmit intr, %s-%s/input0, status %d",
+ tfor->usbdev->bus->bus_name, tfor->usbdev->devpath, status);
+
+}
+
+static int tfor_probe(struct usb_interface *intf, const struct
usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_tfor *tfor;
+ struct input_dev *input_dev;
+ unsigned int err = -ENOMEM;
+
+
+ tfor = kzalloc(sizeof(struct usb_tfor), GFP_KERNEL);
+
+ input_dev = input_allocate_device();
+ if (!tfor || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+ /*initilization of time counter*/
+ do_gettimeofday(&time);
+ time_before.tv_usec = time.tv_usec;
+ time_before.tv_sec = time.tv_sec;
+
+ tfor->data = usb_buffer_alloc(dev, BIT_IN_DEVICE_1942, GFP_KERNEL, \
+ &tfor->idata_dma);
+ if (!tfor->data) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->data_device = usb_buffer_alloc(dev, BIT_OUT_DEVICE_1942, \
+ GFP_KERNEL, &tfor->odata_dma);
+ if (!tfor->data_device) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ tfor->out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail3;
+ }
+
+ tfor->usbdev = dev;
+ tfor->input = input_dev;
+
+ usb_make_path(dev, tfor->phys, sizeof(tfor->phys));
+ strlcat(tfor->phys, "/input0", sizeof(tfor->phys));
+
+ input_dev->name = "Tacx Fortius 1942";
+ input_dev->phys = tfor->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+ input_set_drvdata(input_dev, tfor);
+ input_dev->open = usb_tfor_open;
+ input_dev->close = usb_tfor_close;
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ /*handlebar*/
+ input_set_abs_params(input_dev, ABS_WHEEL, -170, 170, 0, 20);
+ /*plyn*/
+ input_set_abs_params(input_dev, ABS_GAS, 0, 40, 2, 0);
+ /*buttons*/
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+ set_bit(BTN_FORWARD, input_dev->keybit);
+ set_bit(BTN_BACK, input_dev->keybit);
+
+ usb_fill_bulk_urb(tfor->irq, dev, usb_rcvbulkpipe(dev, \
+ BULK_IN_INTERFACE_1942), tfor->data, BIT_IN_DEVICE_1942, \
+ usb_tfor_irq, tfor);
+ tfor->irq->transfer_dma = tfor->idata_dma;
+ tfor->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /*
+ * urb sends data to machine
+ */
+
+ usb_fill_bulk_urb(tfor->out, dev, usb_sndbulkpipe(dev, \
+ BULK_OUT_INTERFACE_1942), tfor->data_device, BIT_OUT_DEVICE_1942, \
+ usb_tfor_out, tfor);
+ tfor->out->transfer_dma = tfor->odata_dma;
+ tfor->out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ err = input_register_device(tfor->input);
+ if (err)
+ goto fail2;
+
+ usb_set_intfdata(intf, tfor);
+
+ return 0;
+
+ fail3: usb_buffer_free(dev, BIT_OUT_DEVICE_1942, tfor->data_device, \
+ tfor->odata_dma);
+ fail2: usb_buffer_free(dev, BIT_IN_DEVICE_1942, tfor->data, tfor->idata_dma);
+ fail1: input_free_device(input_dev);
+ kfree(tfor);
+ return err;
+}
+
+static struct usb_driver tfor_driver = {
+ .name = "fortius_1942",
+ .probe = tfor_probe,
+ .disconnect = tfor_disconnect,
+ .id_table = tfor_ids,
+};
+
+static int __init tfor_init(void)
+{
+ int retval;
+ retval = usb_register(&tfor_driver);
+ if (retval)
+ goto out;
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" \
+ DRIVER_DESC "\n");
+out:
+ return retval;
+}
+
+static void __exit tfor_exit(void)
+{
+ usb_deregister(&tfor_driver);
+}
+
+module_init(tfor_init);
+module_exit(tfor_exit);
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-17 2:25 ` Greg KH
0 siblings, 0 replies; 11+ messages in thread
From: Greg KH @ 2009-03-17 2:25 UTC (permalink / raw)
To: Peta Blaha; +Cc: linux-input, linux-usb, linux-kernel
On Tue, Mar 17, 2009 at 03:21:18AM +0100, Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
> Signed-off-by: Petr Blaha <blahapeta@gmail.com>
> ---
>
> --- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
> 01:00:00.000000000 +0100
Your patch is linewrapped :(
> +++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000 +0100
> @@ -0,0 +1,394 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
Are you sure about "any later version"?
> + unsigned long difference = 0;
> + /*time measure*/
> + struct timeval time, time_before;
> + /*guessed fastest speed a man can possibly ride-incitating full
> + throttle*/
> + unsigned int fastest_wheel_rotate = 1000;
> + /*actual state of path reached in one cycle*/
> + unsigned int ride = 0, old_ride = 0;
These should all be static.
Have you run your code through scripts/checkpatch.pl?
> +struct usb_tfor {
> + char name[128];
Tabs are eaten by your email client :(
Care to try again?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-17 2:25 ` Greg KH
0 siblings, 0 replies; 11+ messages in thread
From: Greg KH @ 2009-03-17 2:25 UTC (permalink / raw)
To: Peta Blaha
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Tue, Mar 17, 2009 at 03:21:18AM +0100, Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
> Signed-off-by: Petr Blaha <blahapeta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>
> --- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
> 01:00:00.000000000 +0100
Your patch is linewrapped :(
> +++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000 +0100
> @@ -0,0 +1,394 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
Are you sure about "any later version"?
> + unsigned long difference = 0;
> + /*time measure*/
> + struct timeval time, time_before;
> + /*guessed fastest speed a man can possibly ride-incitating full
> + throttle*/
> + unsigned int fastest_wheel_rotate = 1000;
> + /*actual state of path reached in one cycle*/
> + unsigned int ride = 0, old_ride = 0;
These should all be static.
Have you run your code through scripts/checkpatch.pl?
> +struct usb_tfor {
> + char name[128];
Tabs are eaten by your email client :(
Care to try again?
thanks,
greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-21 5:46 ` Dmitry Torokhov
0 siblings, 0 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2009-03-21 5:46 UTC (permalink / raw)
To: Peta Blaha; +Cc: linux-input, linux-usb, linux-kernel
Hi Peta,
On Monday 16 March 2009 19:21:18 Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
Thank you very much for your patch, overall it looks pretty nice.
It looks like your mailer ate whitespace; I also have some
requests for you with regard to the driver.
> Signed-off-by: Petr Blaha <blahapeta@gmail.com>
Did you misspell your first name in the signed-off-by by
any chance?
> ---
>
> --- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
> 01:00:00.000000000 +0100
> +++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000
> +0100 @@ -0,0 +1,394 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + *
> + *
> + * Info.
> + * First unimpemented feature Heart Sensor.
> + * Use bit 12 and 14(beginning 0), maybe 13 also.Emmisions
> + * from computer affect measuring.
> + *
> + * Second is Active Brake
> + * Can be maybe used as force feedback. Problem is slowness in
> + * switching from state to state, its electric motor, it has delay can
> + * be fragile.
> + * Try it by changing BRAKE_POS from 0 to 10.
> + *
> + * Thirth unimpemented is sending 0x01, when pedal magnet meets frame
> sensor. + *
> + * Pedalling works fine. Your wheel can have other size tan mime. Feel
> free + * to change constant in usb_tfor_irq, when counting value of
> gasolina. + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/usb/input.h>
> +#include <linux/time.h>
> +
> +
> +#define DRIVER_VERSION "v0.0.2"
> +#define DRIVER_DESC "USB Tacx Fortius 1942 driver"
> +#define DRIVER_LICENSE "GPL"
> +#define DRIVER_AUTHOR "Petr Blaha <blahapeta@gmail.com>"
> +
> +
> +/*Don't put here lesser values*/
> +/*read*/
> +#define BIT_IN_DEVICE_1942 64
> +/*write*/
> +#define BIT_OUT_DEVICE_1942 12
> +/*read*/
> +#define BULK_IN_INTERFACE_1942 82
> +/*write*/
> +#define BULK_OUT_INTERFACE_1942 02
> +
> +
> +#define BRAKE_POS 2
> +
> +
> +/*11 states of brake,in beginning active brake helps, later add
> +difficulty to cycling.0x00 0x00 is neutral*/
> +#define ARRAYINT { {0x4d, 0xf3}, {0xa7, 0xf9}, {0x00, 0x00}, {0x59, 0x06},
> \ +{0xb3, 0x0c}, {0x0c, 0x13}, {0x66, 0x19}, {0xbf, 0x1f}, {0x18, 0x26},
> {0x72, \ +0x2c}, {0xcb, 0x32} }
> +
> +
> +MODULE_AUTHOR(DRIVER_AUTHOR);
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE(DRIVER_LICENSE);
> +
> + unsigned long difference = 0;
Make it static? Also there is no need to initialize to 0.
> + /*time measure*/
> + struct timeval time, time_before;
> + /*guessed fastest speed a man can possibly ride-incitating full
> + throttle*/
> + unsigned int fastest_wheel_rotate = 1000;
> + /*actual state of path reached in one cycle*/
> + unsigned int ride = 0, old_ride = 0;
Same here. You really want to mark everything static unless
it is used from another module.
> +
> +struct usb_tfor {
> + char name[128];
> + char phys[64];
> + struct usb_device *usbdev;
> + struct input_dev *input;
> +
> + struct urb *irq;
> + unsigned char *data;
> + dma_addr_t idata_dma;
> +
> + struct urb *out;
> + unsigned char *data_device;
> + dma_addr_t odata_dma;
> + /*brake position*/
> + unsigned int brake_pos;
> +};
> +
> +static void tfor_disconnect(struct usb_interface *intf)
Mark it as __devexit please.
> +{
> + struct usb_tfor *tfor = usb_get_intfdata(intf);
> +
> + usb_set_intfdata(intf, NULL);
> + if (tfor) {
Why do we check this? Can it ever be NULL and still
tfor_disconnect be called for this interface?
> + /*urb*/
> + usb_kill_urb(tfor->out);
> + usb_kill_urb(tfor->irq);
You have implemented close method which is guaranteed to
be called if open succeeded. These is no need to kill
URBs here.
> + /*device*/
> + input_unregister_device(tfor->input);
> + /*urb*/
> + usb_free_urb(tfor->out);
> + usb_free_urb(tfor->irq);
> + /*buffer free*/
> + usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data_device, \
> + tfor->odata_dma);
> + usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data, \
> + tfor->idata_dma);
> + /*free memory*/
> + kfree(tfor);
> + }
> +}
> +
> +static int usb_tfor_open(struct input_dev *dev)
> +{
> + struct usb_tfor *tfor = input_get_drvdata(dev);
Blank line after variable declarations please.
> + tfor->irq->dev = tfor->usbdev;
This kind of setup should be moved into _probe().
> + usb_submit_urb(tfor->irq, GFP_KERNEL);
> + tfor->out->dev = tfor->usbdev;
This one as well, so the only thing left in _open should
be calls to usb_submit_urb().
> + usb_submit_urb(tfor->out, GFP_KERNEL);
> +
> + return 0;
> +}
> +
> +static void usb_tfor_close(struct input_dev *dev)
> +{
> + struct usb_tfor *tfor = input_get_drvdata(dev);
> + usb_kill_urb(tfor->irq);
> + usb_kill_urb(tfor->out);
> +}
> +
> +static struct usb_device_id tfor_ids[] = {
> + { USB_DEVICE(0x3561, 0x1942), .driver_info = 0 },
> + { }
> +};
> +
> +static void usb_tfor_out(struct urb *urb)
> +{ struct usb_tfor *tfor = urb->context;
> + unsigned int brake_bits[11][2] = ARRAYINT;
> + int retval;
> + tfor->brake_pos = BRAKE_POS;
> + /*URB to device*/
> + /*constant*/
> + tfor->data_device[0] = 0x01;
> + /*constant*/
> + tfor->data_device[1] = 0x08;
> + /*constant*/
> + tfor->data_device[2] = 0x01;
> + /*constant*/
> + tfor->data_device[3] = 0x00;
> + /*brake_bits*/
> + tfor->data_device[4] = brake_bits[tfor->brake_pos][0];
> + /*brake_bits*/
> + tfor->data_device[5] = brake_bits[tfor->brake_pos][1];
> + /*0x01 is turn,when frame sensor meets pedal magnet,
> + i don't see reason for implementation, nor know how device knows it*/
> + tfor->data_device[6] = 0x00;
> + /*constant*/
> + tfor->data_device[7] = 0x00;
> + /*constant*/
> + tfor->data_device[8] = 0x02;
> + /*constant*/
> + tfor->data_device[9] = 0x52;
> + /*constant*/
> + tfor->data_device[10] = 0x10;
> + /*constant*/
> + tfor->data_device[11] = 0x04;
> +
> +
> + switch (urb->status) {
> + case 0:
> + /* success */
> + break;
> + case -ECONNRESET:
> + case -ENOENT:
> + case -ESHUTDOWN:
> + /* this urb is terminated, clean up */
> + dbg("%s - urb shutting down with status: %d", __func__, urb->status);
> + break;
> + default:
> + dbg("%s - nonzero urb status received: %d", __func__, urb->status);
> + }
> + retval = usb_submit_urb(urb, GFP_ATOMIC);
> + if (retval)
> + err("%s - usb_submit_urb failed with result %d",
> + __func__, retval);
> +}
> +
> +static void usb_tfor_irq(struct urb *urb)
> +{
> + struct usb_tfor *tfor = urb->context;
> + unsigned char *data = tfor->data;
> + struct input_dev *dev = tfor->input;
> + int status;
> + int gasolina;
> +
> + switch (urb->status) {
> + case 0:
> + /* success */
> + break;
> + case -ECONNRESET:
> + case -ENOENT:
> + case -ESHUTDOWN:
> + /* ±this urb is terminated, clean up */
> + dbg("%s - urb shutting down with status: %d", __func__, \
> + urb->status);
> + return;
> + default:
> + dbg("%s - nonzero urb status received: %d", __func__, \
> + urb->status);
> + goto resubmit;
> + }
> +
> + /*Get actual time*/
> + do_gettimeofday(&time);
> + /*Ride counter in velociped is small,avoid mistake here*/
> + if ((data[28]*255+data[29]) < ride)
> + ride = 0;
> + /*We get new data, set new val. of ride counter &time counter*/
> + if ((data[28]*255+data[29]) > ride) {
> + old_ride = ride;
> + ride = (data[28]*255+data[29]);
> + difference = \
> + ((time.tv_usec-time_before.tv_usec)\
> + +(time.tv_sec-time_before.tv_sec)*1000000);
> + do_gettimeofday(&time_before);
> + if (difference == 0)
> + dbg("Something is not good \n");
> + }
> + /*Prevent division by 0*/
> + if (difference != 0)
> + /*"speed=path/time",change constant 1000
> + to naturalize it for your speed*/
> + gasolina = (ride-old_ride)/(difference/1000);
> + else
> + gasolina = 0;
We should probably rename this variable to accel[eration].
> + input_report_abs(dev, ABS_GAS, gasolina);
> + input_report_key(dev, BTN_RIGHT, data[13] & 0x01);
> + input_report_key(dev, BTN_BACK, data[13] & 0x02);
> + input_report_key(dev, BTN_FORWARD, data[13] & 0x04);
> + input_report_key(dev, BTN_LEFT, data[13] & 0x08);
> + input_report_abs(dev, ABS_WHEEL, (((data[18]+((data[19] & 0x0f)*225))-\
> + (689+170))*-1));
> +
> + /* event termination */
> + input_sync(dev);
> +
> +resubmit:
> + status = usb_submit_urb(urb, GFP_ATOMIC);
> + if (status)
> + err("can't resubmit intr, %s-%s/input0, status %d",
> + tfor->usbdev->bus->bus_name, tfor->usbdev->devpath, status);
We should not use bus_name directly, i think there is a helper
in driver core for that. Or you can use dev->phys instead.
> +
> +}
> +
> +static int tfor_probe(struct usb_interface *intf, const struct
> usb_device_id *id)
I think we can mark it __devinit.
> +{
> + struct usb_device *dev = interface_to_usbdev(intf);
> + struct usb_tfor *tfor;
> + struct input_dev *input_dev;
> + unsigned int err = -ENOMEM;
> +
> +
> + tfor = kzalloc(sizeof(struct usb_tfor), GFP_KERNEL);
> +
> + input_dev = input_allocate_device();
> + if (!tfor || !input_dev) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> + /*initilization of time counter*/
> + do_gettimeofday(&time);
> + time_before.tv_usec = time.tv_usec;
> + time_before.tv_sec = time.tv_sec;
> +
> + tfor->data = usb_buffer_alloc(dev, BIT_IN_DEVICE_1942, GFP_KERNEL, \
> + &tfor->idata_dma);
> + if (!tfor->data) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> +
> + tfor->data_device = usb_buffer_alloc(dev, BIT_OUT_DEVICE_1942, \
> + GFP_KERNEL, &tfor->odata_dma);
> + if (!tfor->data_device) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> +
> + tfor->irq = usb_alloc_urb(0, GFP_KERNEL);
> + if (!tfor->irq) {
> + err = -ENOMEM;
> + goto fail2;
> + }
> +
> + tfor->out = usb_alloc_urb(0, GFP_KERNEL);
> + if (!tfor->irq) {
> + err = -ENOMEM;
> + goto fail3;
> + }
> +
> + tfor->usbdev = dev;
> + tfor->input = input_dev;
> +
> + usb_make_path(dev, tfor->phys, sizeof(tfor->phys));
> + strlcat(tfor->phys, "/input0", sizeof(tfor->phys));
> +
> + input_dev->name = "Tacx Fortius 1942";
> + input_dev->phys = tfor->phys;
> + usb_to_input_id(dev, &input_dev->id);
> + input_dev->dev.parent = &intf->dev;
> + input_set_drvdata(input_dev, tfor);
> + input_dev->open = usb_tfor_open;
> + input_dev->close = usb_tfor_close;
> + input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
> + /*handlebar*/
> + input_set_abs_params(input_dev, ABS_WHEEL, -170, 170, 0, 20);
> + /*plyn*/
> + input_set_abs_params(input_dev, ABS_GAS, 0, 40, 2, 0);
> + /*buttons*/
> + set_bit(BTN_LEFT, input_dev->keybit);
> + set_bit(BTN_RIGHT, input_dev->keybit);
> + set_bit(BTN_FORWARD, input_dev->keybit);
> + set_bit(BTN_BACK, input_dev->keybit);
> +
> + usb_fill_bulk_urb(tfor->irq, dev, usb_rcvbulkpipe(dev, \
> + BULK_IN_INTERFACE_1942), tfor->data, BIT_IN_DEVICE_1942, \
> + usb_tfor_irq, tfor);
> + tfor->irq->transfer_dma = tfor->idata_dma;
> + tfor->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> + /*
> + * urb sends data to machine
> + */
> +
> + usb_fill_bulk_urb(tfor->out, dev, usb_sndbulkpipe(dev, \
> + BULK_OUT_INTERFACE_1942), tfor->data_device, BIT_OUT_DEVICE_1942, \
> + usb_tfor_out, tfor);
> + tfor->out->transfer_dma = tfor->odata_dma;
> + tfor->out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> + err = input_register_device(tfor->input);
> + if (err)
> + goto fail2;
> +
> + usb_set_intfdata(intf, tfor);
> +
> + return 0;
> +
> + fail3: usb_buffer_free(dev, BIT_OUT_DEVICE_1942, tfor->data_device, \
> + tfor->odata_dma);
> + fail2: usb_buffer_free(dev, BIT_IN_DEVICE_1942, tfor->data,
> tfor->idata_dma); + fail1: input_free_device(input_dev);
> + kfree(tfor);
> + return err;
> +}
> +
> +static struct usb_driver tfor_driver = {
> + .name = "fortius_1942",
> + .probe = tfor_probe,
> + .disconnect = tfor_disconnect,
__devexit_p() here please.
> + .id_table = tfor_ids,
It would be very nice if the driver supported suspend and resume.
> +};
> +
> +static int __init tfor_init(void)
> +{
> + int retval;
> + retval = usb_register(&tfor_driver);
> + if (retval)
> + goto out;
> + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" \
> + DRIVER_DESC "\n");
Our boot is noisy enough, lets drop this message.
> +out:
> + return retval;
> +}
> +
> +static void __exit tfor_exit(void)
> +{
> + usb_deregister(&tfor_driver);
> +}
> +
> +module_init(tfor_init);
> +module_exit(tfor_exit);
Please CC me when you send updated version. Thanks!
--
Dmitry
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-21 5:46 ` Dmitry Torokhov
0 siblings, 0 replies; 11+ messages in thread
From: Dmitry Torokhov @ 2009-03-21 5:46 UTC (permalink / raw)
To: Peta Blaha
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Hi Peta,
On Monday 16 March 2009 19:21:18 Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
Thank you very much for your patch, overall it looks pretty nice.
It looks like your mailer ate whitespace; I also have some
requests for you with regard to the driver.
> Signed-off-by: Petr Blaha <blahapeta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Did you misspell your first name in the signed-off-by by
any chance?
> ---
>
> --- a/drivers/input/joystick/fortius_1942.c.orig 1970-01-01
> 01:00:00.000000000 +0100
> +++ b/drivers/input/joystick/fortius_1942.c 2009-03-17 03:17:01.000000000
> +0100 @@ -0,0 +1,394 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *
> + *
> + *
> + * Info.
> + * First unimpemented feature Heart Sensor.
> + * Use bit 12 and 14(beginning 0), maybe 13 also.Emmisions
> + * from computer affect measuring.
> + *
> + * Second is Active Brake
> + * Can be maybe used as force feedback. Problem is slowness in
> + * switching from state to state, its electric motor, it has delay can
> + * be fragile.
> + * Try it by changing BRAKE_POS from 0 to 10.
> + *
> + * Thirth unimpemented is sending 0x01, when pedal magnet meets frame
> sensor. + *
> + * Pedalling works fine. Your wheel can have other size tan mime. Feel
> free + * to change constant in usb_tfor_irq, when counting value of
> gasolina. + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/usb/input.h>
> +#include <linux/time.h>
> +
> +
> +#define DRIVER_VERSION "v0.0.2"
> +#define DRIVER_DESC "USB Tacx Fortius 1942 driver"
> +#define DRIVER_LICENSE "GPL"
> +#define DRIVER_AUTHOR "Petr Blaha <blahapeta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>"
> +
> +
> +/*Don't put here lesser values*/
> +/*read*/
> +#define BIT_IN_DEVICE_1942 64
> +/*write*/
> +#define BIT_OUT_DEVICE_1942 12
> +/*read*/
> +#define BULK_IN_INTERFACE_1942 82
> +/*write*/
> +#define BULK_OUT_INTERFACE_1942 02
> +
> +
> +#define BRAKE_POS 2
> +
> +
> +/*11 states of brake,in beginning active brake helps, later add
> +difficulty to cycling.0x00 0x00 is neutral*/
> +#define ARRAYINT { {0x4d, 0xf3}, {0xa7, 0xf9}, {0x00, 0x00}, {0x59, 0x06},
> \ +{0xb3, 0x0c}, {0x0c, 0x13}, {0x66, 0x19}, {0xbf, 0x1f}, {0x18, 0x26},
> {0x72, \ +0x2c}, {0xcb, 0x32} }
> +
> +
> +MODULE_AUTHOR(DRIVER_AUTHOR);
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_LICENSE(DRIVER_LICENSE);
> +
> + unsigned long difference = 0;
Make it static? Also there is no need to initialize to 0.
> + /*time measure*/
> + struct timeval time, time_before;
> + /*guessed fastest speed a man can possibly ride-incitating full
> + throttle*/
> + unsigned int fastest_wheel_rotate = 1000;
> + /*actual state of path reached in one cycle*/
> + unsigned int ride = 0, old_ride = 0;
Same here. You really want to mark everything static unless
it is used from another module.
> +
> +struct usb_tfor {
> + char name[128];
> + char phys[64];
> + struct usb_device *usbdev;
> + struct input_dev *input;
> +
> + struct urb *irq;
> + unsigned char *data;
> + dma_addr_t idata_dma;
> +
> + struct urb *out;
> + unsigned char *data_device;
> + dma_addr_t odata_dma;
> + /*brake position*/
> + unsigned int brake_pos;
> +};
> +
> +static void tfor_disconnect(struct usb_interface *intf)
Mark it as __devexit please.
> +{
> + struct usb_tfor *tfor = usb_get_intfdata(intf);
> +
> + usb_set_intfdata(intf, NULL);
> + if (tfor) {
Why do we check this? Can it ever be NULL and still
tfor_disconnect be called for this interface?
> + /*urb*/
> + usb_kill_urb(tfor->out);
> + usb_kill_urb(tfor->irq);
You have implemented close method which is guaranteed to
be called if open succeeded. These is no need to kill
URBs here.
> + /*device*/
> + input_unregister_device(tfor->input);
> + /*urb*/
> + usb_free_urb(tfor->out);
> + usb_free_urb(tfor->irq);
> + /*buffer free*/
> + usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data_device, \
> + tfor->odata_dma);
> + usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data, \
> + tfor->idata_dma);
> + /*free memory*/
> + kfree(tfor);
> + }
> +}
> +
> +static int usb_tfor_open(struct input_dev *dev)
> +{
> + struct usb_tfor *tfor = input_get_drvdata(dev);
Blank line after variable declarations please.
> + tfor->irq->dev = tfor->usbdev;
This kind of setup should be moved into _probe().
> + usb_submit_urb(tfor->irq, GFP_KERNEL);
> + tfor->out->dev = tfor->usbdev;
This one as well, so the only thing left in _open should
be calls to usb_submit_urb().
> + usb_submit_urb(tfor->out, GFP_KERNEL);
> +
> + return 0;
> +}
> +
> +static void usb_tfor_close(struct input_dev *dev)
> +{
> + struct usb_tfor *tfor = input_get_drvdata(dev);
> + usb_kill_urb(tfor->irq);
> + usb_kill_urb(tfor->out);
> +}
> +
> +static struct usb_device_id tfor_ids[] = {
> + { USB_DEVICE(0x3561, 0x1942), .driver_info = 0 },
> + { }
> +};
> +
> +static void usb_tfor_out(struct urb *urb)
> +{ struct usb_tfor *tfor = urb->context;
> + unsigned int brake_bits[11][2] = ARRAYINT;
> + int retval;
> + tfor->brake_pos = BRAKE_POS;
> + /*URB to device*/
> + /*constant*/
> + tfor->data_device[0] = 0x01;
> + /*constant*/
> + tfor->data_device[1] = 0x08;
> + /*constant*/
> + tfor->data_device[2] = 0x01;
> + /*constant*/
> + tfor->data_device[3] = 0x00;
> + /*brake_bits*/
> + tfor->data_device[4] = brake_bits[tfor->brake_pos][0];
> + /*brake_bits*/
> + tfor->data_device[5] = brake_bits[tfor->brake_pos][1];
> + /*0x01 is turn,when frame sensor meets pedal magnet,
> + i don't see reason for implementation, nor know how device knows it*/
> + tfor->data_device[6] = 0x00;
> + /*constant*/
> + tfor->data_device[7] = 0x00;
> + /*constant*/
> + tfor->data_device[8] = 0x02;
> + /*constant*/
> + tfor->data_device[9] = 0x52;
> + /*constant*/
> + tfor->data_device[10] = 0x10;
> + /*constant*/
> + tfor->data_device[11] = 0x04;
> +
> +
> + switch (urb->status) {
> + case 0:
> + /* success */
> + break;
> + case -ECONNRESET:
> + case -ENOENT:
> + case -ESHUTDOWN:
> + /* this urb is terminated, clean up */
> + dbg("%s - urb shutting down with status: %d", __func__, urb->status);
> + break;
> + default:
> + dbg("%s - nonzero urb status received: %d", __func__, urb->status);
> + }
> + retval = usb_submit_urb(urb, GFP_ATOMIC);
> + if (retval)
> + err("%s - usb_submit_urb failed with result %d",
> + __func__, retval);
> +}
> +
> +static void usb_tfor_irq(struct urb *urb)
> +{
> + struct usb_tfor *tfor = urb->context;
> + unsigned char *data = tfor->data;
> + struct input_dev *dev = tfor->input;
> + int status;
> + int gasolina;
> +
> + switch (urb->status) {
> + case 0:
> + /* success */
> + break;
> + case -ECONNRESET:
> + case -ENOENT:
> + case -ESHUTDOWN:
> + /* ±this urb is terminated, clean up */
> + dbg("%s - urb shutting down with status: %d", __func__, \
> + urb->status);
> + return;
> + default:
> + dbg("%s - nonzero urb status received: %d", __func__, \
> + urb->status);
> + goto resubmit;
> + }
> +
> + /*Get actual time*/
> + do_gettimeofday(&time);
> + /*Ride counter in velociped is small,avoid mistake here*/
> + if ((data[28]*255+data[29]) < ride)
> + ride = 0;
> + /*We get new data, set new val. of ride counter &time counter*/
> + if ((data[28]*255+data[29]) > ride) {
> + old_ride = ride;
> + ride = (data[28]*255+data[29]);
> + difference = \
> + ((time.tv_usec-time_before.tv_usec)\
> + +(time.tv_sec-time_before.tv_sec)*1000000);
> + do_gettimeofday(&time_before);
> + if (difference == 0)
> + dbg("Something is not good \n");
> + }
> + /*Prevent division by 0*/
> + if (difference != 0)
> + /*"speed=path/time",change constant 1000
> + to naturalize it for your speed*/
> + gasolina = (ride-old_ride)/(difference/1000);
> + else
> + gasolina = 0;
We should probably rename this variable to accel[eration].
> + input_report_abs(dev, ABS_GAS, gasolina);
> + input_report_key(dev, BTN_RIGHT, data[13] & 0x01);
> + input_report_key(dev, BTN_BACK, data[13] & 0x02);
> + input_report_key(dev, BTN_FORWARD, data[13] & 0x04);
> + input_report_key(dev, BTN_LEFT, data[13] & 0x08);
> + input_report_abs(dev, ABS_WHEEL, (((data[18]+((data[19] & 0x0f)*225))-\
> + (689+170))*-1));
> +
> + /* event termination */
> + input_sync(dev);
> +
> +resubmit:
> + status = usb_submit_urb(urb, GFP_ATOMIC);
> + if (status)
> + err("can't resubmit intr, %s-%s/input0, status %d",
> + tfor->usbdev->bus->bus_name, tfor->usbdev->devpath, status);
We should not use bus_name directly, i think there is a helper
in driver core for that. Or you can use dev->phys instead.
> +
> +}
> +
> +static int tfor_probe(struct usb_interface *intf, const struct
> usb_device_id *id)
I think we can mark it __devinit.
> +{
> + struct usb_device *dev = interface_to_usbdev(intf);
> + struct usb_tfor *tfor;
> + struct input_dev *input_dev;
> + unsigned int err = -ENOMEM;
> +
> +
> + tfor = kzalloc(sizeof(struct usb_tfor), GFP_KERNEL);
> +
> + input_dev = input_allocate_device();
> + if (!tfor || !input_dev) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> + /*initilization of time counter*/
> + do_gettimeofday(&time);
> + time_before.tv_usec = time.tv_usec;
> + time_before.tv_sec = time.tv_sec;
> +
> + tfor->data = usb_buffer_alloc(dev, BIT_IN_DEVICE_1942, GFP_KERNEL, \
> + &tfor->idata_dma);
> + if (!tfor->data) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> +
> + tfor->data_device = usb_buffer_alloc(dev, BIT_OUT_DEVICE_1942, \
> + GFP_KERNEL, &tfor->odata_dma);
> + if (!tfor->data_device) {
> + err = -ENOMEM;
> + goto fail1;
> + }
> +
> + tfor->irq = usb_alloc_urb(0, GFP_KERNEL);
> + if (!tfor->irq) {
> + err = -ENOMEM;
> + goto fail2;
> + }
> +
> + tfor->out = usb_alloc_urb(0, GFP_KERNEL);
> + if (!tfor->irq) {
> + err = -ENOMEM;
> + goto fail3;
> + }
> +
> + tfor->usbdev = dev;
> + tfor->input = input_dev;
> +
> + usb_make_path(dev, tfor->phys, sizeof(tfor->phys));
> + strlcat(tfor->phys, "/input0", sizeof(tfor->phys));
> +
> + input_dev->name = "Tacx Fortius 1942";
> + input_dev->phys = tfor->phys;
> + usb_to_input_id(dev, &input_dev->id);
> + input_dev->dev.parent = &intf->dev;
> + input_set_drvdata(input_dev, tfor);
> + input_dev->open = usb_tfor_open;
> + input_dev->close = usb_tfor_close;
> + input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
> + /*handlebar*/
> + input_set_abs_params(input_dev, ABS_WHEEL, -170, 170, 0, 20);
> + /*plyn*/
> + input_set_abs_params(input_dev, ABS_GAS, 0, 40, 2, 0);
> + /*buttons*/
> + set_bit(BTN_LEFT, input_dev->keybit);
> + set_bit(BTN_RIGHT, input_dev->keybit);
> + set_bit(BTN_FORWARD, input_dev->keybit);
> + set_bit(BTN_BACK, input_dev->keybit);
> +
> + usb_fill_bulk_urb(tfor->irq, dev, usb_rcvbulkpipe(dev, \
> + BULK_IN_INTERFACE_1942), tfor->data, BIT_IN_DEVICE_1942, \
> + usb_tfor_irq, tfor);
> + tfor->irq->transfer_dma = tfor->idata_dma;
> + tfor->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> + /*
> + * urb sends data to machine
> + */
> +
> + usb_fill_bulk_urb(tfor->out, dev, usb_sndbulkpipe(dev, \
> + BULK_OUT_INTERFACE_1942), tfor->data_device, BIT_OUT_DEVICE_1942, \
> + usb_tfor_out, tfor);
> + tfor->out->transfer_dma = tfor->odata_dma;
> + tfor->out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
> +
> + err = input_register_device(tfor->input);
> + if (err)
> + goto fail2;
> +
> + usb_set_intfdata(intf, tfor);
> +
> + return 0;
> +
> + fail3: usb_buffer_free(dev, BIT_OUT_DEVICE_1942, tfor->data_device, \
> + tfor->odata_dma);
> + fail2: usb_buffer_free(dev, BIT_IN_DEVICE_1942, tfor->data,
> tfor->idata_dma); + fail1: input_free_device(input_dev);
> + kfree(tfor);
> + return err;
> +}
> +
> +static struct usb_driver tfor_driver = {
> + .name = "fortius_1942",
> + .probe = tfor_probe,
> + .disconnect = tfor_disconnect,
__devexit_p() here please.
> + .id_table = tfor_ids,
It would be very nice if the driver supported suspend and resume.
> +};
> +
> +static int __init tfor_init(void)
> +{
> + int retval;
> + retval = usb_register(&tfor_driver);
> + if (retval)
> + goto out;
> + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" \
> + DRIVER_DESC "\n");
Our boot is noisy enough, lets drop this message.
> +out:
> + return retval;
> +}
> +
> +static void __exit tfor_exit(void)
> +{
> + usb_deregister(&tfor_driver);
> +}
> +
> +module_init(tfor_init);
> +module_exit(tfor_exit);
Please CC me when you send updated version. Thanks!
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-19 13:51 Peta Blaha
2009-03-19 13:39 ` Felipe Balbi
0 siblings, 1 reply; 11+ messages in thread
From: Peta Blaha @ 2009-03-19 13:51 UTC (permalink / raw)
To: linux-input, linux-usb; +Cc: linux-kernel
Driver for Fortius 1942 device.
Signed-off-by: Petr Blaha <blahapeta@gmail.com>
---
This is driver for bycicle Fortius 1942. checked, patch is signed.
It's a bit long. Patch for linux kernel and source are on page
http://code.google.com/p/fortius/
fortius_1942.patch2 is the patch
fortius_1942.0.0.2_doc.c is kernel module
It should be ok now.
Petr
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-19 13:39 ` Felipe Balbi
0 siblings, 0 replies; 11+ messages in thread
From: Felipe Balbi @ 2009-03-19 13:39 UTC (permalink / raw)
To: ext Peta Blaha; +Cc: linux-input, linux-usb, linux-kernel
On Thu, Mar 19, 2009 at 02:51:07PM +0100, ext Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
> Signed-off-by: Petr Blaha <blahapeta@gmail.com>
It's not that long. you can send it to the list.
It also makes our life easier when trying to comment on the patch. Just
run scripts/checkpatch.pl --strict on your patch file before sending it
and solve any issues reported by that tool.
Also, that Signed-off-by line is not needed in the driver itself.
--
balbi
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
@ 2009-03-19 13:39 ` Felipe Balbi
0 siblings, 0 replies; 11+ messages in thread
From: Felipe Balbi @ 2009-03-19 13:39 UTC (permalink / raw)
To: ext Peta Blaha
Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On Thu, Mar 19, 2009 at 02:51:07PM +0100, ext Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
> Signed-off-by: Petr Blaha <blahapeta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
It's not that long. you can send it to the list.
It also makes our life easier when trying to comment on the patch. Just
run scripts/checkpatch.pl --strict on your patch file before sending it
and solve any issues reported by that tool.
Also, that Signed-off-by line is not needed in the driver itself.
--
balbi
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] input/joystick: add driver fortius 1942
2009-03-16 22:20 ` Peta Blaha
@ 2009-03-16 22:39 ` Greg KH
0 siblings, 0 replies; 11+ messages in thread
From: Greg KH @ 2009-03-16 22:39 UTC (permalink / raw)
To: Peta Blaha; +Cc: linux-input, linux-usb
On Mon, Mar 16, 2009 at 11:20:09PM +0100, Peta Blaha wrote:
> Driver for Fortius 1942 device.
>
> Signed-off-by: Petr Blaha <blahapeta@gmail.com>
>
> ---
>
> Hi,
> i wrote driver for Fortius 1942 by re-ingeneering original driver for
> win.This is a bicycle from Tacx company, they have their own virtual
> reality sw. There is not linux support from this company.
> http://www.tacxvr.com/en/products/tacx-virtual-reality
> This driver handle bike as normal joystick, it is connected thru USB,
> this driver isn't for initializating, it is too complex for me.
> here is more info
> http://code.google.com/p/fortius/
>
> I would like to merge my work into kernel, is it ok?
Yes, that would be great, but can you resend the driver with the proper
"Signed-off-by:" line as documented in the file,
Documentation/SubmittingPatches?
thanks,
greg k-h
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] input/joystick: add driver fortius 1942
[not found] <739e73230903161446k1c8326dfwa817f14afb3749ee@mail.gmail.com>
@ 2009-03-16 22:20 ` Peta Blaha
2009-03-16 22:39 ` Greg KH
0 siblings, 1 reply; 11+ messages in thread
From: Peta Blaha @ 2009-03-16 22:20 UTC (permalink / raw)
To: linux-input, linux-usb
[-- Attachment #1: Type: text/plain, Size: 590 bytes --]
Driver for Fortius 1942 device.
Signed-off-by: Petr Blaha <blahapeta@gmail.com>
---
Hi,
i wrote driver for Fortius 1942 by re-ingeneering original driver for
win.This is a bicycle from Tacx company, they have their own virtual
reality sw. There is not linux support from this company.
http://www.tacxvr.com/en/products/tacx-virtual-reality
This driver handle bike as normal joystick, it is connected thru USB,
this driver isn't for initializating, it is too complex for me.
here is more info
http://code.google.com/p/fortius/
I would like to merge my work into kernel, is it ok?
Petr
[-- Attachment #2: fortius_1942 --]
[-- Type: application/octet-stream, Size: 9627 bytes --]
--- ./linux-2.6/drivers/input/joystick/fortius_1942.c.orig 1970-01-01 01:00:00.000000000 +0100
+++ ./linux-2.6/drivers/input/joystick/fortius_1942.c 2009-03-16 18:14:53.000000000 +0100
@@ -0,0 +1,348 @@
+/*This driver is under GPL version 2 or any later.No warranty.
+Look at http://www.gnu.org/licenses/ */
+
+
+/*
+Info for future developers
+Heart Sensor use bit 12 and 14(beginning 0), maybe 13 also.
+*/
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <linux/time.h>
+
+
+#define DRIVER_VERSION "v0.0.2"
+#define DRIVER_DESC "USB Tacx Fortius 1942 driver"
+#define DRIVER_LICENSE "GPL"
+#define DRIVER_AUTHOR "Petr Blaha <blahapeta@gmail.com>"
+
+
+/*Don't put here lesser values*/
+#define BIT_IN_DEVICE_1942 64 //read
+#define BIT_OUT_DEVICE_1942 12 //write
+
+#define BULK_IN_INTERFACE_1942 82 //read
+#define BULK_OUT_INTERFACE_1942 02 //write
+
+
+#define BRAKE_POS 2
+
+
+/*11 states of brake,in beginning active brake helps, later add difficulty to cycling. 0x00 0x00 is neutral*/
+#define ARRAYINT { {0x4d,0xf3}, {0xa7,0xf9}, {0x00,0x00}, {0x59,0x06}, {0xb3,0x0c}, {0x0c,0x13}, {0x66,0x19}, {0xbf,0x1f}, {0x18,0x26}, {0x72,0x2c}, {0xcb,0x32} }
+
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+ unsigned long difference=0;
+ /*time measure*/
+ struct timeval time,time_before;
+ /*guessed fastest speed a man can possibly ride-incitating full throttle*/
+ unsigned int fastest_wheel_rotate= 1000;
+ /*actual state of path reached in one cycle*/
+ unsigned int ride = 0, old_ride=0;
+
+struct usb_tfor {
+ char name[128];
+ char phys[64];
+ struct usb_device *usbdev;
+ struct input_dev *input;
+
+ struct urb *irq;
+ unsigned char *data;
+ dma_addr_t idata_dma;
+
+ struct urb *out;
+ unsigned char *data_device;
+ dma_addr_t odata_dma;
+ /*brake position*/
+ unsigned int brake_pos;
+};
+
+static void tfor_disconnect(struct usb_interface *intf)
+{
+ struct usb_tfor *tfor = usb_get_intfdata(intf);
+
+ usb_set_intfdata(intf, NULL);
+ if (tfor) {
+ /*urb*/
+ usb_kill_urb(tfor->out);
+ usb_kill_urb(tfor->irq);
+ /*device*/
+ input_unregister_device(tfor->input);
+ /*urb*/
+ usb_free_urb(tfor->out);
+ usb_free_urb(tfor->irq);
+ /*buffer free*/
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data_device, tfor->odata_dma);
+ usb_buffer_free(interface_to_usbdev(intf), 10, tfor->data, tfor->idata_dma);
+ /*free memory*/
+ kfree(tfor);
+ }
+}
+
+static int usb_tfor_open(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ tfor->irq->dev = tfor->usbdev;
+ usb_submit_urb(tfor->irq, GFP_KERNEL);
+ tfor->out->dev = tfor->usbdev;
+ usb_submit_urb(tfor->out, GFP_KERNEL);
+
+ return 0;
+}
+
+static void usb_tfor_close(struct input_dev *dev)
+{
+ struct usb_tfor *tfor = input_get_drvdata(dev);
+ usb_kill_urb(tfor->irq);
+ usb_kill_urb(tfor->out);
+}
+
+static struct usb_device_id tfor_ids[] = {
+ { USB_DEVICE(0x3561, 0x1942), .driver_info = 0 },
+ { }
+};
+
+static void usb_tfor_out(struct urb *urb)
+{ struct usb_tfor *tfor = urb->context;
+ unsigned int brake_bits[11][2] = ARRAYINT;
+ int retval;
+ tfor->brake_pos =BRAKE_POS;
+ /*URB to device*/
+ /*constant*/
+ tfor->data_device[0] = 0x01;
+ /*constant*/
+ tfor->data_device[1] = 0x08;
+ /*constant*/
+ tfor->data_device[2] = 0x01;
+ /*constant*/
+ tfor->data_device[3] = 0x00;
+ /*brake_bits*/
+ tfor->data_device[4] = brake_bits[tfor->brake_pos][0];
+ /*brake_bits*/
+ tfor->data_device[5] = brake_bits[tfor->brake_pos][1];
+ /*0x01 is turn,when frame sensor meets pedal magnet,
+ i don't see reason for implementation */
+ tfor->data_device[6] = 0x00;
+ /*constant*/
+ tfor->data_device[7] = 0x00;
+ /*constant*/
+ tfor->data_device[8] = 0x02;
+ /*constant*/
+ tfor->data_device[9] = 0x52;
+ /*constant*/
+ tfor->data_device[10] = 0x10;
+ /*constant*/
+ tfor->data_device[11] = 0x04;
+
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ break;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ }
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __func__, retval);
+}
+
+static void usb_tfor_irq(struct urb *urb)
+{
+ struct usb_tfor *tfor = urb->context;
+ unsigned char *data = tfor->data;
+ struct input_dev *dev = tfor->input;
+ int status;
+ int gasolina;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* ±this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __func__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __func__, urb->status);
+ goto resubmit;
+ }
+
+ /*Get actual time*/
+ do_gettimeofday(&time);
+ /*Ride counter in velociped is small,avoid mistake here*/
+ if((data[28]*255+data[29])<ride) ride =0;
+ /*If we get new data, set new values of ride counter and time counter*/
+ if((data[28]*255+data[29])>ride) {
+ old_ride = ride;
+ ride = (data[28]*255+data[29]);
+ difference=((time.tv_usec-time_before.tv_usec)+(time.tv_sec-time_before.tv_sec)*1000000);
+ do_gettimeofday(&time_before);
+ if(difference==0)
+ dbg("Something is not good \n");
+ }
+ /*Prevent division by 0*/
+ if(difference!=0)
+ /*"speed=path/time",change constant 1000
+ to naturalize it for your speed*/
+ gasolina=(ride-old_ride)/(difference/1000);
+ else gasolina =0;
+ input_report_abs(dev, ABS_GAS,gasolina);
+ input_report_key(dev, BTN_RIGHT, data[13] & 0x01);
+ input_report_key(dev, BTN_BACK , data[13] & 0x02);
+ input_report_key(dev, BTN_FORWARD, data[13] & 0x04);
+ input_report_key(dev, BTN_LEFT, data[13] & 0x08);
+ input_report_abs(dev, ABS_WHEEL,(((data[18]+((data[19] & 0x0f)*225))-(689+170))*-1));
+
+ /* event termination */
+ input_sync(dev);
+
+resubmit:
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ err("can't resubmit intr, %s-%s/input0, status %d",
+ tfor->usbdev->bus->bus_name, tfor->usbdev->devpath, status);
+
+}
+
+static int tfor_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *dev = interface_to_usbdev(intf);
+ struct usb_tfor *tfor;
+ struct input_dev *input_dev;
+ unsigned int err = -ENOMEM;
+
+
+ tfor = kzalloc(sizeof(struct usb_tfor), GFP_KERNEL);
+
+ input_dev = input_allocate_device();
+ if (!tfor || !input_dev) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+ /*initilization of time counter*/
+ do_gettimeofday(&time);
+ time_before.tv_usec=time.tv_usec;
+ time_before.tv_sec=time.tv_sec;
+
+ tfor->data = usb_buffer_alloc(dev, BIT_IN_DEVICE_1942, GFP_KERNEL, &tfor->idata_dma);
+ if (!tfor->data) {
+ err= -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->data_device = usb_buffer_alloc(dev, BIT_OUT_DEVICE_1942,GFP_KERNEL, &tfor->odata_dma);
+ if (!tfor->data_device) {
+ err= -ENOMEM;
+ goto fail1;
+ }
+
+ tfor->irq = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail2;
+ }
+
+ tfor->out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!tfor->irq) {
+ err = -ENOMEM;
+ goto fail3;
+ }
+
+ tfor->usbdev = dev;
+ tfor->input = input_dev;
+
+ usb_make_path(dev, tfor->phys, sizeof(tfor->phys));
+ strlcat(tfor->phys, "/input0", sizeof(tfor->phys));
+
+ input_dev->name = "Tacx Fortius 1942";
+ input_dev->phys = tfor->phys;
+ usb_to_input_id(dev, &input_dev->id);
+ input_dev->dev.parent = &intf->dev;
+ input_set_drvdata(input_dev, tfor);
+ input_dev->open = usb_tfor_open;
+ input_dev->close = usb_tfor_close;
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);// | BIT_MASK(EV_MSC) | BIT_MASK(EV_FF_STATUS);
+ /*handlebar*/
+ input_set_abs_params(input_dev,ABS_WHEEL,-170,170,0,20);
+ /*plyn*/
+ input_set_abs_params(input_dev,ABS_GAS,0,40,2,0);
+ /*buttons*/
+ set_bit(BTN_LEFT, input_dev->keybit);
+ set_bit(BTN_RIGHT, input_dev->keybit);
+ set_bit(BTN_FORWARD, input_dev->keybit);
+ set_bit(BTN_BACK, input_dev->keybit);
+
+ usb_fill_bulk_urb(tfor->irq, dev, usb_rcvbulkpipe(dev, BULK_IN_INTERFACE_1942),tfor->data,BIT_IN_DEVICE_1942,usb_tfor_irq, tfor);
+ tfor->irq->transfer_dma = tfor->idata_dma;
+ tfor->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ /*
+ * urb sends data to machine
+ */
+
+ usb_fill_bulk_urb(tfor->out, dev,
+ usb_sndbulkpipe(dev, BULK_OUT_INTERFACE_1942),
+ tfor->data_device, BIT_OUT_DEVICE_1942, usb_tfor_out, tfor);
+ tfor->out->transfer_dma = tfor->odata_dma;
+ tfor->out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+
+ err = input_register_device(tfor->input);
+ if (err)
+ goto fail2;
+
+ usb_set_intfdata(intf, tfor);
+
+
+ return 0;
+
+ fail3: usb_buffer_free(dev, BIT_OUT_DEVICE_1942, tfor->data_device, tfor->odata_dma);
+ fail2: usb_buffer_free(dev, BIT_IN_DEVICE_1942, tfor->data, tfor->idata_dma);
+ fail1: input_free_device(input_dev);
+ kfree(tfor);
+ return err;
+}
+
+static struct usb_driver tfor_driver = {
+ .name = "tfor",
+ .probe = tfor_probe,
+ .disconnect = tfor_disconnect,
+ .id_table = tfor_ids,
+};
+
+static int __init tfor_init(void)
+{
+ int retval;
+ retval = usb_register(&tfor_driver);
+ if (retval)
+ goto out;
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n");
+out:
+ return retval;
+}
+
+static void __exit tfor_exit(void)
+{
+ usb_deregister(&tfor_driver);
+}
+
+module_init(tfor_init);
+module_exit(tfor_exit);
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2009-03-21 5:46 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-17 2:21 [PATCH] input/joystick: add driver fortius 1942 Peta Blaha
2009-03-17 2:21 ` Peta Blaha
2009-03-17 2:25 ` Greg KH
2009-03-17 2:25 ` Greg KH
2009-03-21 5:46 ` Dmitry Torokhov
2009-03-21 5:46 ` Dmitry Torokhov
-- strict thread matches above, loose matches on Subject: below --
2009-03-19 13:51 Peta Blaha
2009-03-19 13:39 ` Felipe Balbi
2009-03-19 13:39 ` Felipe Balbi
[not found] <739e73230903161446k1c8326dfwa817f14afb3749ee@mail.gmail.com>
2009-03-16 22:20 ` Peta Blaha
2009-03-16 22:39 ` Greg KH
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.