2 * $Id: iforce.c,v 1.7 2000/06/04 14:03:36 vojtech Exp $
4 * Copyright (c) 2000 Vojtech Pavlik
6 * USB/RS232 I-Force joysticks and wheels.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
28 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
31 #include <linux/kernel.h>
32 #include <linux/malloc.h>
33 #include <linux/input.h>
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/usb.h>
37 #include <linux/serio.h>
38 #include <linux/config.h>
40 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
42 #define USB_VENDOR_ID_LOGITECH 0x046d
43 #define USB_DEVICE_ID_LOGITECH_WMFORCE 0xc281
45 #define IFORCE_MAX_LENGTH 16
47 #if defined(CONFIG_INPUT_IFORCE_232) || defined(CONFIG_INPUT_IFORCE_232_MODULE)
50 #if defined(CONFIG_INPUT_IFORCE_USB) || defined(CONFIG_INPUT_IFORCE_USB_MODULE)
55 signed char data
[IFORCE_MAX_LENGTH
];
59 int idx
, pkt
, len
, id
;
66 } iforce_hat_to_axis
[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
68 static char *iforce_name
= "I-Force joystick/wheel";
70 static void iforce_process_packet(struct input_dev
*dev
, unsigned char id
, int idx
, unsigned char *data
)
74 case 1: /* joystick position data */
75 case 3: /* wheel position data */
78 input_report_abs(dev
, ABS_X
, (__s16
) (((__s16
)data
[1] << 8) | data
[0]));
79 input_report_abs(dev
, ABS_Y
, (__s16
) (((__s16
)data
[3] << 8) | data
[2]));
80 input_report_abs(dev
, ABS_THROTTLE
, 255 - data
[4]);
82 input_report_abs(dev
, ABS_WHEEL
, (__s16
) (((__s16
)data
[1] << 8) | data
[0]));
83 input_report_abs(dev
, ABS_GAS
, 255 - data
[2]);
84 input_report_abs(dev
, ABS_BRAKE
, 255 - data
[3]);
87 input_report_abs(dev
, ABS_HAT0X
, iforce_hat_to_axis
[data
[6] >> 4].x
);
88 input_report_abs(dev
, ABS_HAT0Y
, iforce_hat_to_axis
[data
[6] >> 4].y
);
90 input_report_key(dev
, BTN_TRIGGER
, data
[5] & 0x01);
91 input_report_key(dev
, BTN_TOP
, data
[5] & 0x02);
92 input_report_key(dev
, BTN_THUMB
, data
[5] & 0x04);
93 input_report_key(dev
, BTN_TOP2
, data
[5] & 0x08);
94 input_report_key(dev
, BTN_BASE
, data
[5] & 0x10);
95 input_report_key(dev
, BTN_BASE2
, data
[5] & 0x20);
96 input_report_key(dev
, BTN_BASE3
, data
[5] & 0x40);
97 input_report_key(dev
, BTN_BASE4
, data
[5] & 0x80);
98 input_report_key(dev
, BTN_BASE5
, data
[6] & 0x01);
99 input_report_key(dev
, BTN_A
, data
[6] & 0x02);
100 input_report_key(dev
, BTN_B
, data
[6] & 0x04);
101 input_report_key(dev
, BTN_C
, data
[6] & 0x08);
104 case 2: /* force feedback effect status */
110 static int iforce_open(struct input_dev
*dev
)
112 struct iforce
*iforce
= dev
->private;
114 if (dev
->idbus
== BUS_USB
&& !iforce
->open
++)
115 if (usb_submit_urb(&iforce
->irq
))
121 static void iforce_close(struct input_dev
*dev
)
123 struct iforce
*iforce
= dev
->private;
125 if (dev
->idbus
== BUS_USB
&& !--iforce
->open
)
126 usb_unlink_urb(&iforce
->irq
);
129 static void iforce_input_setup(struct iforce
*iforce
)
133 iforce
->dev
.evbit
[0] = BIT(EV_KEY
) | BIT(EV_ABS
);
134 iforce
->dev
.keybit
[LONG(BTN_JOYSTICK
)] |= BIT(BTN_TRIGGER
) | BIT(BTN_TOP
) | BIT(BTN_THUMB
) | BIT(BTN_TOP2
) |
135 BIT(BTN_BASE
) | BIT(BTN_BASE2
) | BIT(BTN_BASE3
) | BIT(BTN_BASE4
) | BIT(BTN_BASE5
);
136 iforce
->dev
.keybit
[LONG(BTN_GAMEPAD
)] |= BIT(BTN_A
) | BIT(BTN_B
) | BIT(BTN_C
);
137 iforce
->dev
.absbit
[0] = BIT(ABS_X
) | BIT(ABS_Y
) | BIT(ABS_THROTTLE
) | BIT(ABS_HAT0X
) | BIT(ABS_HAT0Y
)
138 | BIT(ABS_WHEEL
) | BIT(ABS_GAS
) | BIT(ABS_BRAKE
);
140 for (i
= ABS_X
; i
<= ABS_Y
; i
++) {
141 iforce
->dev
.absmax
[i
] = 1920;
142 iforce
->dev
.absmin
[i
] = -1920;
143 iforce
->dev
.absflat
[i
] = 128;
144 iforce
->dev
.absfuzz
[i
] = 16;
147 for (i
= ABS_THROTTLE
; i
<= ABS_RUDDER
; i
++) {
148 iforce
->dev
.absmax
[i
] = 255;
149 iforce
->dev
.absmin
[i
] = 0;
152 for (i
= ABS_HAT0X
; i
<= ABS_HAT0Y
; i
++) {
153 iforce
->dev
.absmax
[i
] = 1;
154 iforce
->dev
.absmin
[i
] = -1;
157 iforce
->dev
.private = iforce
;
158 iforce
->dev
.open
= iforce_open
;
159 iforce
->dev
.close
= iforce_close
;
161 input_register_device(&iforce
->dev
);
166 static void iforce_usb_irq(struct urb
*urb
)
168 struct iforce
*iforce
= urb
->context
;
169 if (urb
->status
) return;
170 iforce_process_packet(&iforce
->dev
, iforce
->data
[0], 8, iforce
->data
+ 1);
173 static void *iforce_usb_probe(struct usb_device
*dev
, unsigned int ifnum
)
175 struct usb_endpoint_descriptor
*endpoint
;
176 struct iforce
*iforce
;
178 if (dev
->descriptor
.idVendor
!= USB_VENDOR_ID_LOGITECH
||
179 dev
->descriptor
.idProduct
!= USB_DEVICE_ID_LOGITECH_WMFORCE
)
182 endpoint
= dev
->config
[0].interface
[ifnum
].altsetting
[0].endpoint
+ 0;
184 if (!(iforce
= kmalloc(sizeof(struct iforce
), GFP_KERNEL
))) return NULL
;
185 memset(iforce
, 0, sizeof(struct iforce
));
187 iforce
->dev
.name
= iforce_name
;
188 iforce
->dev
.idbus
= BUS_USB
;
189 iforce
->dev
.idvendor
= dev
->descriptor
.idVendor
;
190 iforce
->dev
.idproduct
= dev
->descriptor
.idProduct
;
191 iforce
->dev
.idversion
= dev
->descriptor
.bcdDevice
;
193 FILL_INT_URB(&iforce
->irq
, dev
, usb_rcvintpipe(dev
, endpoint
->bEndpointAddress
),
194 iforce
->data
, 8, iforce_usb_irq
, iforce
, endpoint
->bInterval
);
196 iforce_input_setup(iforce
);
198 printk(KERN_INFO
"input%d: %s on usb%d:%d.%d\n",
199 iforce
->dev
.number
, iforce_name
, dev
->bus
->busnum
, dev
->devnum
, ifnum
);
204 static void iforce_usb_disconnect(struct usb_device
*dev
, void *ptr
)
206 struct iforce
*iforce
= ptr
;
207 usb_unlink_urb(&iforce
->irq
);
208 input_unregister_device(&iforce
->dev
);
212 static struct usb_driver iforce_usb_driver
= {
214 probe
: iforce_usb_probe
,
215 disconnect
: iforce_usb_disconnect
,
222 static void iforce_serio_irq(struct serio
*serio
, unsigned char data
, unsigned int flags
)
224 struct iforce
* iforce
= serio
->private;
244 if (data
> IFORCE_MAX_LENGTH
) {
253 if (iforce
->idx
< iforce
->len
) {
254 iforce
->csum
+= iforce
->data
[iforce
->idx
++] = data
;
258 if (iforce
->idx
== iforce
->len
) {
259 iforce_process_packet(&iforce
->dev
, iforce
->id
, iforce
->idx
, iforce
->data
);
268 static void iforce_serio_connect(struct serio
*serio
, struct serio_dev
*dev
)
270 struct iforce
*iforce
;
272 if (serio
->type
!= (SERIO_RS232
| SERIO_IFORCE
))
275 if (!(iforce
= kmalloc(sizeof(struct iforce
), GFP_KERNEL
))) return;
276 memset(iforce
, 0, sizeof(struct iforce
));
278 iforce
->dev
.name
= iforce_name
;
279 iforce
->dev
.idbus
= BUS_RS232
;
280 iforce
->dev
.idvendor
= SERIO_IFORCE
;
281 iforce
->dev
.idproduct
= 0x0001;
282 iforce
->dev
.idversion
= 0x0100;
284 serio
->private = iforce
;
286 if (serio_open(serio
, dev
)) {
291 iforce_input_setup(iforce
);
293 printk(KERN_INFO
"input%d: %s on serio%d\n",
294 iforce
->dev
.number
, iforce_name
, serio
->number
);
297 static void iforce_serio_disconnect(struct serio
*serio
)
299 struct iforce
* iforce
= serio
->private;
300 input_unregister_device(&iforce
->dev
);
305 static struct serio_dev iforce_serio_dev
= {
306 interrupt
: iforce_serio_irq
,
307 connect
: iforce_serio_connect
,
308 disconnect
: iforce_serio_disconnect
,
313 static int __init
iforce_init(void)
316 usb_register(&iforce_usb_driver
);
319 serio_register_device(&iforce_serio_dev
);
324 static void __exit
iforce_exit(void)
327 usb_deregister(&iforce_usb_driver
);
330 serio_unregister_device(&iforce_serio_dev
);
334 module_init(iforce_init
);
335 module_exit(iforce_exit
);