1 /* 2 * Copyright (c) 1998-2001 Vojtech Pavlik 3 */ 4 5 /* 6 * Genius Flight 2000 joystick driver for Linux 7 */ 8 9 /* 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 * Should you need to contact me, the author, you can do so either by 25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: 26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 27 */ 28 29 #include <linux/delay.h> 30 #include <linux/kernel.h> 31 #include <linux/slab.h> 32 #include <linux/module.h> 33 #include <linux/init.h> 34 #include <linux/input.h> 35 #include <linux/gameport.h> 36 #include <linux/jiffies.h> 37 38 #define DRIVER_DESC "Genius Flight 2000 joystick driver" 39 40 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 41 MODULE_DESCRIPTION(DRIVER_DESC); 42 MODULE_LICENSE("GPL"); 43 44 #define GF2K_START 400 /* The time we wait for the first bit [400 us] */ 45 #define GF2K_STROBE 40 /* The time we wait for the first bit [40 us] */ 46 #define GF2K_TIMEOUT 4 /* Wait for everything to settle [4 ms] */ 47 #define GF2K_LENGTH 80 /* Max number of triplets in a packet */ 48 49 /* 50 * Genius joystick ids ... 51 */ 52 53 #define GF2K_ID_G09 1 54 #define GF2K_ID_F30D 2 55 #define GF2K_ID_F30 3 56 #define GF2K_ID_F31D 4 57 #define GF2K_ID_F305 5 58 #define GF2K_ID_F23P 6 59 #define GF2K_ID_F31 7 60 #define GF2K_ID_MAX 7 61 62 static char gf2k_length[] = { 40, 40, 40, 40, 40, 40, 40, 40 }; 63 static char gf2k_hat_to_axis[][2] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; 64 65 static char *gf2k_names[] = {"", "Genius G-09D", "Genius F-30D", "Genius F-30", "Genius MaxFighter F-31D", 66 "Genius F-30-5", "Genius Flight2000 F-23", "Genius F-31"}; 67 static unsigned char gf2k_hats[] = { 0, 2, 0, 0, 2, 0, 2, 0 }; 68 static unsigned char gf2k_axes[] = { 0, 2, 0, 0, 4, 0, 4, 0 }; 69 static unsigned char gf2k_joys[] = { 0, 0, 0, 0,10, 0, 8, 0 }; 70 static unsigned char gf2k_pads[] = { 0, 6, 0, 0, 0, 0, 0, 0 }; 71 static unsigned char gf2k_lens[] = { 0,18, 0, 0,18, 0,18, 0 }; 72 73 static unsigned char gf2k_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_GAS, ABS_BRAKE }; 74 static short gf2k_btn_joy[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }; 75 static short gf2k_btn_pad[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_START, BTN_SELECT }; 76 77 78 static short gf2k_seq_reset[] = { 240, 340, 0 }; 79 static short gf2k_seq_digital[] = { 590, 320, 860, 0 }; 80 81 struct gf2k { 82 struct gameport *gameport; 83 struct input_dev *dev; 84 int reads; 85 int bads; 86 unsigned char id; 87 unsigned char length; 88 char phys[32]; 89 }; 90 91 /* 92 * gf2k_read_packet() reads a Genius Flight2000 packet. 93 */ 94 95 static int gf2k_read_packet(struct gameport *gameport, int length, char *data) 96 { 97 unsigned char u, v; 98 int i; 99 unsigned int t, p; 100 unsigned long flags; 101 102 t = gameport_time(gameport, GF2K_START); 103 p = gameport_time(gameport, GF2K_STROBE); 104 105 i = 0; 106 107 local_irq_save(flags); 108 109 gameport_trigger(gameport); 110 v = gameport_read(gameport); 111 112 while (t > 0 && i < length) { 113 t--; u = v; 114 v = gameport_read(gameport); 115 if (v & ~u & 0x10) { 116 data[i++] = v >> 5; 117 t = p; 118 } 119 } 120 121 local_irq_restore(flags); 122 123 return i; 124 } 125 126 /* 127 * gf2k_trigger_seq() initializes a Genius Flight2000 joystick 128 * into digital mode. 129 */ 130 131 static void gf2k_trigger_seq(struct gameport *gameport, short *seq) 132 { 133 134 unsigned long flags; 135 int i, t; 136 137 local_irq_save(flags); 138 139 i = 0; 140 do { 141 gameport_trigger(gameport); 142 t = gameport_time(gameport, GF2K_TIMEOUT * 1000); 143 while ((gameport_read(gameport) & 1) && t) t--; 144 udelay(seq[i]); 145 } while (seq[++i]); 146 147 gameport_trigger(gameport); 148 149 local_irq_restore(flags); 150 } 151 152 /* 153 * js_sw_get_bits() composes bits from the triplet buffer into a __u64. 154 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number 155 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits 156 * is number of bits per triplet. 157 */ 158 159 #define GB(p,n,s) gf2k_get_bits(data, p, n, s) 160 161 static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift) 162 { 163 __u64 data = 0; 164 int i; 165 166 for (i = 0; i < num / 3 + 2; i++) 167 data |= buf[pos / 3 + i] << (i * 3); 168 data >>= pos % 3; 169 data &= (1 << num) - 1; 170 data <<= shift; 171 172 return data; 173 } 174 175 static void gf2k_read(struct gf2k *gf2k, unsigned char *data) 176 { 177 struct input_dev *dev = gf2k->dev; 178 int i, t; 179 180 for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++) 181 input_report_abs(dev, gf2k_abs[i], GB(i<<3,8,0) | GB(i+46,1,8) | GB(i+50,1,9)); 182 183 for (i = 0; i < 2 && i < gf2k_axes[gf2k->id] - 4; i++) 184 input_report_abs(dev, gf2k_abs[i], GB(i*9+60,8,0) | GB(i+54,1,9)); 185 186 t = GB(40,4,0); 187 188 for (i = 0; i < gf2k_hats[gf2k->id]; i++) 189 input_report_abs(dev, ABS_HAT0X + i, gf2k_hat_to_axis[t][i]); 190 191 t = GB(44,2,0) | GB(32,8,2) | GB(78,2,10); 192 193 for (i = 0; i < gf2k_joys[gf2k->id]; i++) 194 input_report_key(dev, gf2k_btn_joy[i], (t >> i) & 1); 195 196 for (i = 0; i < gf2k_pads[gf2k->id]; i++) 197 input_report_key(dev, gf2k_btn_pad[i], (t >> i) & 1); 198 199 input_sync(dev); 200 } 201 202 /* 203 * gf2k_poll() reads and analyzes Genius joystick data. 204 */ 205 206 static void gf2k_poll(struct gameport *gameport) 207 { 208 struct gf2k *gf2k = gameport_get_drvdata(gameport); 209 unsigned char data[GF2K_LENGTH]; 210 211 gf2k->reads++; 212 213 if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id]) 214 gf2k->bads++; 215 else 216 gf2k_read(gf2k, data); 217 } 218 219 static int gf2k_open(struct input_dev *dev) 220 { 221 struct gf2k *gf2k = input_get_drvdata(dev); 222 223 gameport_start_polling(gf2k->gameport); 224 return 0; 225 } 226 227 static void gf2k_close(struct input_dev *dev) 228 { 229 struct gf2k *gf2k = input_get_drvdata(dev); 230 231 gameport_stop_polling(gf2k->gameport); 232 } 233 234 /* 235 * gf2k_connect() probes for Genius id joysticks. 236 */ 237 238 static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) 239 { 240 struct gf2k *gf2k; 241 struct input_dev *input_dev; 242 unsigned char data[GF2K_LENGTH]; 243 int i, err; 244 245 gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL); 246 input_dev = input_allocate_device(); 247 if (!gf2k || !input_dev) { 248 err = -ENOMEM; 249 goto fail1; 250 } 251 252 gf2k->gameport = gameport; 253 gf2k->dev = input_dev; 254 255 gameport_set_drvdata(gameport, gf2k); 256 257 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); 258 if (err) 259 goto fail1; 260 261 gf2k_trigger_seq(gameport, gf2k_seq_reset); 262 263 msleep(GF2K_TIMEOUT); 264 265 gf2k_trigger_seq(gameport, gf2k_seq_digital); 266 267 msleep(GF2K_TIMEOUT); 268 269 if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) { 270 err = -ENODEV; 271 goto fail2; 272 } 273 274 if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) { 275 err = -ENODEV; 276 goto fail2; 277 } 278 279 #ifdef RESET_WORKS 280 if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) && 281 (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { 282 err = -ENODEV; 283 goto fail2; 284 } 285 #else 286 gf2k->id = 6; 287 #endif 288 289 if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) { 290 printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n", 291 gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]); 292 err = -ENODEV; 293 goto fail2; 294 } 295 296 gameport_set_poll_handler(gameport, gf2k_poll); 297 gameport_set_poll_interval(gameport, 20); 298 299 snprintf(gf2k->phys, sizeof(gf2k->phys), "%s/input0", gameport->phys); 300 301 gf2k->length = gf2k_lens[gf2k->id]; 302 303 input_dev->name = gf2k_names[gf2k->id]; 304 input_dev->phys = gf2k->phys; 305 input_dev->id.bustype = BUS_GAMEPORT; 306 input_dev->id.vendor = GAMEPORT_ID_VENDOR_GENIUS; 307 input_dev->id.product = gf2k->id; 308 input_dev->id.version = 0x0100; 309 input_dev->dev.parent = &gameport->dev; 310 311 input_set_drvdata(input_dev, gf2k); 312 313 input_dev->open = gf2k_open; 314 input_dev->close = gf2k_close; 315 316 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 317 318 for (i = 0; i < gf2k_axes[gf2k->id]; i++) 319 set_bit(gf2k_abs[i], input_dev->absbit); 320 321 for (i = 0; i < gf2k_hats[gf2k->id]; i++) 322 input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); 323 324 for (i = 0; i < gf2k_joys[gf2k->id]; i++) 325 set_bit(gf2k_btn_joy[i], input_dev->keybit); 326 327 for (i = 0; i < gf2k_pads[gf2k->id]; i++) 328 set_bit(gf2k_btn_pad[i], input_dev->keybit); 329 330 gf2k_read_packet(gameport, gf2k->length, data); 331 gf2k_read(gf2k, data); 332 333 for (i = 0; i < gf2k_axes[gf2k->id]; i++) { 334 int max = i < 2 ? 335 input_abs_get_val(input_dev, gf2k_abs[i]) * 2 : 336 input_abs_get_val(input_dev, gf2k_abs[0]) + 337 input_abs_get_val(input_dev, gf2k_abs[1]); 338 int flat = i < 2 ? 24 : 0; 339 340 input_set_abs_params(input_dev, gf2k_abs[i], 341 32, max - 32, 8, flat); 342 } 343 344 err = input_register_device(gf2k->dev); 345 if (err) 346 goto fail2; 347 348 return 0; 349 350 fail2: gameport_close(gameport); 351 fail1: gameport_set_drvdata(gameport, NULL); 352 input_free_device(input_dev); 353 kfree(gf2k); 354 return err; 355 } 356 357 static void gf2k_disconnect(struct gameport *gameport) 358 { 359 struct gf2k *gf2k = gameport_get_drvdata(gameport); 360 361 input_unregister_device(gf2k->dev); 362 gameport_close(gameport); 363 gameport_set_drvdata(gameport, NULL); 364 kfree(gf2k); 365 } 366 367 static struct gameport_driver gf2k_drv = { 368 .driver = { 369 .name = "gf2k", 370 }, 371 .description = DRIVER_DESC, 372 .connect = gf2k_connect, 373 .disconnect = gf2k_disconnect, 374 }; 375 376 module_gameport_driver(gf2k_drv); 377