Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1998-2005 Vojtech Pavlik |
| 3 | */ |
| 4 | |
| 5 | /* |
| 6 | * Microsoft SideWinder joystick family 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/module.h> |
| 32 | #include <linux/slab.h> |
| 33 | #include <linux/init.h> |
| 34 | #include <linux/input.h> |
| 35 | #include <linux/gameport.h> |
| 36 | |
| 37 | #define DRIVER_DESC "Microsoft SideWinder joystick family driver" |
| 38 | |
| 39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 40 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 41 | MODULE_LICENSE("GPL"); |
| 42 | |
| 43 | /* |
| 44 | * These are really magic values. Changing them can make a problem go away, |
| 45 | * as well as break everything. |
| 46 | */ |
| 47 | |
| 48 | #undef SW_DEBUG |
| 49 | #undef SW_DEBUG_DATA |
| 50 | |
| 51 | #define SW_START 600 /* The time we wait for the first bit [600 us] */ |
| 52 | #define SW_STROBE 60 /* Max time per bit [60 us] */ |
| 53 | #define SW_TIMEOUT 6 /* Wait for everything to settle [6 ms] */ |
| 54 | #define SW_KICK 45 /* Wait after A0 fall till kick [45 us] */ |
| 55 | #define SW_END 8 /* Number of bits before end of packet to kick */ |
| 56 | #define SW_FAIL 16 /* Number of packet read errors to fail and reinitialize */ |
| 57 | #define SW_BAD 2 /* Number of packet read errors to switch off 3d Pro optimization */ |
| 58 | #define SW_OK 64 /* Number of packet read successes to switch optimization back on */ |
| 59 | #define SW_LENGTH 512 /* Max number of bits in a packet */ |
| 60 | |
| 61 | #ifdef SW_DEBUG |
| 62 | #define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg) |
| 63 | #else |
| 64 | #define dbg(format, arg...) do {} while (0) |
| 65 | #endif |
| 66 | |
| 67 | /* |
| 68 | * SideWinder joystick types ... |
| 69 | */ |
| 70 | |
| 71 | #define SW_ID_3DP 0 |
| 72 | #define SW_ID_GP 1 |
| 73 | #define SW_ID_PP 2 |
| 74 | #define SW_ID_FFP 3 |
| 75 | #define SW_ID_FSP 4 |
| 76 | #define SW_ID_FFW 5 |
| 77 | |
| 78 | /* |
| 79 | * Names, buttons, axes ... |
| 80 | */ |
| 81 | |
| 82 | static char *sw_name[] = { "3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro", |
| 83 | "Force Feedback Wheel" }; |
| 84 | |
| 85 | static char sw_abs[][7] = { |
| 86 | { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y }, |
| 87 | { ABS_X, ABS_Y }, |
| 88 | { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y }, |
| 89 | { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y }, |
| 90 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y }, |
| 91 | { ABS_RX, ABS_RUDDER, ABS_THROTTLE }}; |
| 92 | |
| 93 | static char sw_bit[][7] = { |
| 94 | { 10, 10, 9, 10, 1, 1 }, |
| 95 | { 1, 1 }, |
| 96 | { 10, 10, 6, 7, 1, 1 }, |
| 97 | { 10, 10, 6, 7, 1, 1 }, |
| 98 | { 10, 10, 6, 1, 1 }, |
| 99 | { 10, 7, 7, 1, 1 }}; |
| 100 | |
| 101 | static short sw_btn[][12] = { |
| 102 | { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE }, |
| 103 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE }, |
| 104 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, |
| 105 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, |
| 106 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }, |
| 107 | { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }}; |
| 108 | |
| 109 | static struct { |
| 110 | int x; |
| 111 | int y; |
| 112 | } sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; |
| 113 | |
| 114 | struct sw { |
| 115 | struct gameport *gameport; |
| 116 | struct input_dev dev[4]; |
| 117 | char name[64]; |
| 118 | char phys[4][32]; |
| 119 | int length; |
| 120 | int type; |
| 121 | int bits; |
| 122 | int number; |
| 123 | int fail; |
| 124 | int ok; |
| 125 | int reads; |
| 126 | int bads; |
| 127 | }; |
| 128 | |
| 129 | /* |
| 130 | * sw_read_packet() is a function which reads either a data packet, or an |
| 131 | * identification packet from a SideWinder joystick. The protocol is very, |
| 132 | * very, very braindamaged. Microsoft patented it in US patent #5628686. |
| 133 | */ |
| 134 | |
| 135 | static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id) |
| 136 | { |
| 137 | unsigned long flags; |
| 138 | int timeout, bitout, sched, i, kick, start, strobe; |
| 139 | unsigned char pending, u, v; |
| 140 | |
| 141 | i = -id; /* Don't care about data, only want ID */ |
| 142 | timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */ |
| 143 | kick = id ? gameport_time(gameport, SW_KICK) : 0; /* Set up kick timeout for ID packet */ |
| 144 | start = gameport_time(gameport, SW_START); |
| 145 | strobe = gameport_time(gameport, SW_STROBE); |
| 146 | bitout = start; |
| 147 | pending = 0; |
| 148 | sched = 0; |
| 149 | |
| 150 | local_irq_save(flags); /* Quiet, please */ |
| 151 | |
| 152 | gameport_trigger(gameport); /* Trigger */ |
| 153 | v = gameport_read(gameport); |
| 154 | |
| 155 | do { |
| 156 | bitout--; |
| 157 | u = v; |
| 158 | v = gameport_read(gameport); |
| 159 | } while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */ |
| 160 | |
| 161 | if (bitout > 0) |
| 162 | bitout = strobe; /* Extend time if not timed out */ |
| 163 | |
| 164 | while ((timeout > 0 || bitout > 0) && (i < length)) { |
| 165 | |
| 166 | timeout--; |
| 167 | bitout--; /* Decrement timers */ |
| 168 | sched--; |
| 169 | |
| 170 | u = v; |
| 171 | v = gameport_read(gameport); |
| 172 | |
| 173 | if ((~u & v & 0x10) && (bitout > 0)) { /* Rising edge on clock - data bit */ |
| 174 | if (i >= 0) /* Want this data */ |
| 175 | buf[i] = v >> 5; /* Store it */ |
| 176 | i++; /* Advance index */ |
| 177 | bitout = strobe; /* Extend timeout for next bit */ |
| 178 | } |
| 179 | |
| 180 | if (kick && (~v & u & 0x01)) { /* Falling edge on axis 0 */ |
| 181 | sched = kick; /* Schedule second trigger */ |
| 182 | kick = 0; /* Don't schedule next time on falling edge */ |
| 183 | pending = 1; /* Mark schedule */ |
| 184 | } |
| 185 | |
| 186 | if (pending && sched < 0 && (i > -SW_END)) { /* Second trigger time */ |
| 187 | gameport_trigger(gameport); /* Trigger */ |
| 188 | bitout = start; /* Long bit timeout */ |
| 189 | pending = 0; /* Unmark schedule */ |
| 190 | timeout = 0; /* Switch from global to bit timeouts */ |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | local_irq_restore(flags); /* Done - relax */ |
| 195 | |
| 196 | #ifdef SW_DEBUG_DATA |
| 197 | { |
| 198 | int j; |
| 199 | printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i); |
| 200 | for (j = 0; j < i; j++) printk("%d", buf[j]); |
| 201 | printk("]\n"); |
| 202 | } |
| 203 | #endif |
| 204 | |
| 205 | return i; |
| 206 | } |
| 207 | |
| 208 | /* |
| 209 | * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64. |
| 210 | * Parameter 'pos' is bit number inside packet where to start at, 'num' is number |
| 211 | * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits |
| 212 | * is number of bits per triplet. |
| 213 | */ |
| 214 | |
| 215 | #define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits) |
| 216 | |
| 217 | static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits) |
| 218 | { |
| 219 | __u64 data = 0; |
| 220 | int tri = pos % bits; /* Start position */ |
| 221 | int i = pos / bits; |
| 222 | int bit = 0; |
| 223 | |
| 224 | while (num--) { |
| 225 | data |= (__u64)((buf[i] >> tri++) & 1) << bit++; /* Transfer bit */ |
| 226 | if (tri == bits) { |
| 227 | i++; /* Next triplet */ |
| 228 | tri = 0; |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | return data; |
| 233 | } |
| 234 | |
| 235 | /* |
| 236 | * sw_init_digital() initializes a SideWinder 3D Pro joystick |
| 237 | * into digital mode. |
| 238 | */ |
| 239 | |
| 240 | static void sw_init_digital(struct gameport *gameport) |
| 241 | { |
| 242 | int seq[] = { 140, 140+725, 140+300, 0 }; |
| 243 | unsigned long flags; |
| 244 | int i, t; |
| 245 | |
| 246 | local_irq_save(flags); |
| 247 | |
| 248 | i = 0; |
| 249 | do { |
| 250 | gameport_trigger(gameport); /* Trigger */ |
| 251 | t = gameport_time(gameport, SW_TIMEOUT * 1000); |
| 252 | while ((gameport_read(gameport) & 1) && t) t--; /* Wait for axis to fall back to 0 */ |
| 253 | udelay(seq[i]); /* Delay magic time */ |
| 254 | } while (seq[++i]); |
| 255 | |
| 256 | gameport_trigger(gameport); /* Last trigger */ |
| 257 | |
| 258 | local_irq_restore(flags); |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | * sw_parity() computes parity of __u64 |
| 263 | */ |
| 264 | |
| 265 | static int sw_parity(__u64 t) |
| 266 | { |
| 267 | int x = t ^ (t >> 32); |
| 268 | |
| 269 | x ^= x >> 16; |
| 270 | x ^= x >> 8; |
| 271 | x ^= x >> 4; |
| 272 | x ^= x >> 2; |
| 273 | x ^= x >> 1; |
| 274 | return x & 1; |
| 275 | } |
| 276 | |
| 277 | /* |
| 278 | * sw_ccheck() checks synchronization bits and computes checksum of nibbles. |
| 279 | */ |
| 280 | |
| 281 | static int sw_check(__u64 t) |
| 282 | { |
| 283 | unsigned char sum = 0; |
| 284 | |
| 285 | if ((t & 0x8080808080808080ULL) ^ 0x80) /* Sync */ |
| 286 | return -1; |
| 287 | |
| 288 | while (t) { /* Sum */ |
| 289 | sum += t & 0xf; |
| 290 | t >>= 4; |
| 291 | } |
| 292 | |
| 293 | return sum & 0xf; |
| 294 | } |
| 295 | |
| 296 | /* |
| 297 | * sw_parse() analyzes SideWinder joystick data, and writes the results into |
| 298 | * the axes and buttons arrays. |
| 299 | */ |
| 300 | |
| 301 | static int sw_parse(unsigned char *buf, struct sw *sw) |
| 302 | { |
| 303 | int hat, i, j; |
| 304 | struct input_dev *dev = sw->dev; |
| 305 | |
| 306 | switch (sw->type) { |
| 307 | |
| 308 | case SW_ID_3DP: |
| 309 | |
| 310 | if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) |
| 311 | return -1; |
| 312 | |
| 313 | input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7)); |
| 314 | input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7)); |
| 315 | input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7)); |
| 316 | input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7)); |
| 317 | |
| 318 | input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x); |
| 319 | input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y); |
| 320 | |
| 321 | for (j = 0; j < 7; j++) |
| 322 | input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1)); |
| 323 | |
| 324 | input_report_key(dev, BTN_BASE4, !GB(38,1)); |
| 325 | input_report_key(dev, BTN_BASE5, !GB(37,1)); |
| 326 | |
| 327 | input_sync(dev); |
| 328 | |
| 329 | return 0; |
| 330 | |
| 331 | case SW_ID_GP: |
| 332 | |
| 333 | for (i = 0; i < sw->number; i ++) { |
| 334 | |
| 335 | if (sw_parity(GB(i*15,15))) |
| 336 | return -1; |
| 337 | |
| 338 | input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1)); |
| 339 | input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1)); |
| 340 | |
| 341 | for (j = 0; j < 10; j++) |
| 342 | input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1)); |
| 343 | |
| 344 | input_sync(dev + i); |
| 345 | } |
| 346 | |
| 347 | return 0; |
| 348 | |
| 349 | case SW_ID_PP: |
| 350 | case SW_ID_FFP: |
| 351 | |
| 352 | if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) |
| 353 | return -1; |
| 354 | |
| 355 | input_report_abs(dev, ABS_X, GB( 9,10)); |
| 356 | input_report_abs(dev, ABS_Y, GB(19,10)); |
| 357 | input_report_abs(dev, ABS_RZ, GB(36, 6)); |
| 358 | input_report_abs(dev, ABS_THROTTLE, GB(29, 7)); |
| 359 | |
| 360 | input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x); |
| 361 | input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y); |
| 362 | |
| 363 | for (j = 0; j < 9; j++) |
| 364 | input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1)); |
| 365 | |
| 366 | input_sync(dev); |
| 367 | |
| 368 | return 0; |
| 369 | |
| 370 | case SW_ID_FSP: |
| 371 | |
| 372 | if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) |
| 373 | return -1; |
| 374 | |
| 375 | input_report_abs(dev, ABS_X, GB( 0,10)); |
| 376 | input_report_abs(dev, ABS_Y, GB(16,10)); |
| 377 | input_report_abs(dev, ABS_THROTTLE, GB(32, 6)); |
| 378 | |
| 379 | input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x); |
| 380 | input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y); |
| 381 | |
| 382 | for (j = 0; j < 6; j++) |
| 383 | input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1)); |
| 384 | |
| 385 | input_report_key(dev, BTN_TR, !GB(26,1)); |
| 386 | input_report_key(dev, BTN_START, !GB(27,1)); |
| 387 | input_report_key(dev, BTN_MODE, !GB(38,1)); |
| 388 | input_report_key(dev, BTN_SELECT, !GB(39,1)); |
| 389 | |
| 390 | input_sync(dev); |
| 391 | |
| 392 | return 0; |
| 393 | |
| 394 | case SW_ID_FFW: |
| 395 | |
| 396 | if (!sw_parity(GB(0,33))) |
| 397 | return -1; |
| 398 | |
| 399 | input_report_abs(dev, ABS_RX, GB( 0,10)); |
| 400 | input_report_abs(dev, ABS_RUDDER, GB(10, 6)); |
| 401 | input_report_abs(dev, ABS_THROTTLE, GB(16, 6)); |
| 402 | |
| 403 | for (j = 0; j < 8; j++) |
| 404 | input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1)); |
| 405 | |
| 406 | input_sync(dev); |
| 407 | |
| 408 | return 0; |
| 409 | } |
| 410 | |
| 411 | return -1; |
| 412 | } |
| 413 | |
| 414 | /* |
| 415 | * sw_read() reads SideWinder joystick data, and reinitializes |
| 416 | * the joystick in case of persistent problems. This is the function that is |
| 417 | * called from the generic code to poll the joystick. |
| 418 | */ |
| 419 | |
| 420 | static int sw_read(struct sw *sw) |
| 421 | { |
| 422 | unsigned char buf[SW_LENGTH]; |
| 423 | int i; |
| 424 | |
| 425 | i = sw_read_packet(sw->gameport, buf, sw->length, 0); |
| 426 | |
| 427 | if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */ |
| 428 | |
| 429 | if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) { /* Last init failed, 1 bit mode */ |
| 430 | printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s" |
| 431 | " - going to reinitialize.\n", sw->gameport->phys); |
| 432 | sw->fail = SW_FAIL; /* Reinitialize */ |
| 433 | i = 128; /* Bogus value */ |
| 434 | } |
| 435 | |
| 436 | if (i < 66 && GB(0,64) == GB(i*3-66,64)) /* 1 == 3 */ |
| 437 | i = 66; /* Everything is fine */ |
| 438 | |
| 439 | if (i < 66 && GB(0,64) == GB(66,64)) /* 1 == 2 */ |
| 440 | i = 66; /* Everything is fine */ |
| 441 | |
| 442 | if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) { /* 2 == 3 */ |
| 443 | memmove(buf, buf + i - 22, 22); /* Move data */ |
| 444 | i = 66; /* Carry on */ |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | if (i == sw->length && !sw_parse(buf, sw)) { /* Parse data */ |
| 449 | |
| 450 | sw->fail = 0; |
| 451 | sw->ok++; |
| 452 | |
| 453 | if (sw->type == SW_ID_3DP && sw->length == 66 /* Many packets OK */ |
| 454 | && sw->ok > SW_OK) { |
| 455 | |
| 456 | printk(KERN_INFO "sidewinder.c: No more trouble on %s" |
| 457 | " - enabling optimization again.\n", sw->gameport->phys); |
| 458 | sw->length = 22; |
| 459 | } |
| 460 | |
| 461 | return 0; |
| 462 | } |
| 463 | |
| 464 | sw->ok = 0; |
| 465 | sw->fail++; |
| 466 | |
| 467 | if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) { /* Consecutive bad packets */ |
| 468 | |
| 469 | printk(KERN_INFO "sidewinder.c: Many bit errors on %s" |
| 470 | " - disabling optimization.\n", sw->gameport->phys); |
| 471 | sw->length = 66; |
| 472 | } |
| 473 | |
| 474 | if (sw->fail < SW_FAIL) |
| 475 | return -1; /* Not enough, don't reinitialize yet */ |
| 476 | |
| 477 | printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s" |
| 478 | " - reinitializing joystick.\n", sw->gameport->phys); |
| 479 | |
| 480 | if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */ |
| 481 | mdelay(3 * SW_TIMEOUT); |
| 482 | sw_init_digital(sw->gameport); |
| 483 | } |
| 484 | |
| 485 | mdelay(SW_TIMEOUT); |
| 486 | i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0); /* Read normal data packet */ |
| 487 | mdelay(SW_TIMEOUT); |
| 488 | sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */ |
| 489 | |
| 490 | sw->fail = SW_FAIL; |
| 491 | |
| 492 | return -1; |
| 493 | } |
| 494 | |
| 495 | static void sw_poll(struct gameport *gameport) |
| 496 | { |
| 497 | struct sw *sw = gameport_get_drvdata(gameport); |
| 498 | |
| 499 | sw->reads++; |
| 500 | if (sw_read(sw)) |
| 501 | sw->bads++; |
| 502 | } |
| 503 | |
| 504 | static int sw_open(struct input_dev *dev) |
| 505 | { |
| 506 | struct sw *sw = dev->private; |
| 507 | |
| 508 | gameport_start_polling(sw->gameport); |
| 509 | return 0; |
| 510 | } |
| 511 | |
| 512 | static void sw_close(struct input_dev *dev) |
| 513 | { |
| 514 | struct sw *sw = dev->private; |
| 515 | |
| 516 | gameport_stop_polling(sw->gameport); |
| 517 | } |
| 518 | |
| 519 | /* |
| 520 | * sw_print_packet() prints the contents of a SideWinder packet. |
| 521 | */ |
| 522 | |
| 523 | static void sw_print_packet(char *name, int length, unsigned char *buf, char bits) |
| 524 | { |
| 525 | int i; |
| 526 | |
| 527 | printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length); |
| 528 | for (i = (((length + 3) >> 2) - 1); i >= 0; i--) |
| 529 | printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits)); |
| 530 | printk("]\n"); |
| 531 | } |
| 532 | |
| 533 | /* |
| 534 | * sw_3dp_id() translates the 3DP id into a human legible string. |
| 535 | * Unfortunately I don't know how to do this for the other SW types. |
| 536 | */ |
| 537 | |
| 538 | static void sw_3dp_id(unsigned char *buf, char *comment) |
| 539 | { |
| 540 | int i; |
| 541 | char pnp[8], rev[9]; |
| 542 | |
| 543 | for (i = 0; i < 7; i++) /* ASCII PnP ID */ |
| 544 | pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1); |
| 545 | |
| 546 | for (i = 0; i < 8; i++) /* ASCII firmware revision */ |
| 547 | rev[i] = sw_get_bits(buf, 88+8*i, 8, 1); |
| 548 | |
| 549 | pnp[7] = rev[8] = 0; |
| 550 | |
| 551 | sprintf(comment, " [PnP %d.%02d id %s rev %s]", |
| 552 | (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | /* Two 6-bit values */ |
| 553 | sw_get_bits(buf, 16, 6, 1)) / 100, |
| 554 | (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | |
| 555 | sw_get_bits(buf, 16, 6, 1)) % 100, |
| 556 | pnp, rev); |
| 557 | } |
| 558 | |
| 559 | /* |
| 560 | * sw_guess_mode() checks the upper two button bits for toggling - |
| 561 | * indication of that the joystick is in 3-bit mode. This is documented |
| 562 | * behavior for 3DP ID packet, and for example the FSP does this in |
| 563 | * normal packets instead. Fun ... |
| 564 | */ |
| 565 | |
| 566 | static int sw_guess_mode(unsigned char *buf, int len) |
| 567 | { |
| 568 | int i; |
| 569 | unsigned char xor = 0; |
| 570 | |
| 571 | for (i = 1; i < len; i++) |
| 572 | xor |= (buf[i - 1] ^ buf[i]) & 6; |
| 573 | |
| 574 | return !!xor * 2 + 1; |
| 575 | } |
| 576 | |
| 577 | /* |
| 578 | * sw_connect() probes for SideWinder type joysticks. |
| 579 | */ |
| 580 | |
| 581 | static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) |
| 582 | { |
| 583 | struct sw *sw; |
| 584 | int i, j, k, l; |
| 585 | int err; |
| 586 | unsigned char *buf = NULL; /* [SW_LENGTH] */ |
| 587 | unsigned char *idbuf = NULL; /* [SW_LENGTH] */ |
| 588 | unsigned char m = 1; |
| 589 | char comment[40]; |
| 590 | |
| 591 | comment[0] = 0; |
| 592 | |
Pekka Enberg | a97e148 | 2005-09-06 15:18:33 -0700 | [diff] [blame] | 593 | sw = kzalloc(sizeof(struct sw), GFP_KERNEL); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 594 | buf = kmalloc(SW_LENGTH, GFP_KERNEL); |
| 595 | idbuf = kmalloc(SW_LENGTH, GFP_KERNEL); |
| 596 | if (!sw || !buf || !idbuf) { |
| 597 | err = -ENOMEM; |
| 598 | goto fail1; |
| 599 | } |
| 600 | |
| 601 | sw->gameport = gameport; |
| 602 | |
| 603 | gameport_set_drvdata(gameport, sw); |
| 604 | |
| 605 | err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); |
| 606 | if (err) |
| 607 | goto fail1; |
| 608 | |
| 609 | dbg("Init 0: Opened %s, io %#x, speed %d", |
| 610 | gameport->phys, gameport->io, gameport->speed); |
| 611 | |
| 612 | i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */ |
| 613 | msleep(SW_TIMEOUT); |
| 614 | dbg("Init 1: Mode %d. Length %d.", m , i); |
| 615 | |
| 616 | if (!i) { /* No data. 3d Pro analog mode? */ |
| 617 | sw_init_digital(gameport); /* Switch to digital */ |
| 618 | msleep(SW_TIMEOUT); |
| 619 | i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */ |
| 620 | msleep(SW_TIMEOUT); |
| 621 | dbg("Init 1b: Length %d.", i); |
| 622 | if (!i) { /* No data -> FAIL */ |
| 623 | err = -ENODEV; |
| 624 | goto fail2; |
| 625 | } |
| 626 | } |
| 627 | |
| 628 | j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */ |
| 629 | m |= sw_guess_mode(idbuf, j); /* ID packet should carry mode info [3DP] */ |
| 630 | dbg("Init 2: Mode %d. ID Length %d.", m, j); |
| 631 | |
| 632 | if (j <= 0) { /* Read ID failed. Happens in 1-bit mode on PP */ |
| 633 | msleep(SW_TIMEOUT); |
| 634 | i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */ |
| 635 | m |= sw_guess_mode(buf, i); |
| 636 | dbg("Init 2b: Mode %d. Length %d.", m, i); |
| 637 | if (!i) { |
| 638 | err = -ENODEV; |
| 639 | goto fail2; |
| 640 | } |
| 641 | msleep(SW_TIMEOUT); |
| 642 | j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */ |
| 643 | dbg("Init 2c: ID Length %d.", j); |
| 644 | } |
| 645 | |
| 646 | sw->type = -1; |
| 647 | k = SW_FAIL; /* Try SW_FAIL times */ |
| 648 | l = 0; |
| 649 | |
| 650 | do { |
| 651 | k--; |
| 652 | msleep(SW_TIMEOUT); |
| 653 | i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read data packet */ |
| 654 | dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k); |
| 655 | |
| 656 | if (i > l) { /* Longer? As we can only lose bits, it makes */ |
| 657 | /* no sense to try detection for a packet shorter */ |
| 658 | l = i; /* than the previous one */ |
| 659 | |
| 660 | sw->number = 1; |
| 661 | sw->gameport = gameport; |
| 662 | sw->length = i; |
| 663 | sw->bits = m; |
| 664 | |
| 665 | dbg("Init 3a: Case %d.\n", i * m); |
| 666 | |
| 667 | switch (i * m) { |
| 668 | case 60: |
| 669 | sw->number++; |
| 670 | case 45: /* Ambiguous packet length */ |
| 671 | if (j <= 40) { /* ID length less or eq 40 -> FSP */ |
| 672 | case 43: |
| 673 | sw->type = SW_ID_FSP; |
| 674 | break; |
| 675 | } |
| 676 | sw->number++; |
| 677 | case 30: |
| 678 | sw->number++; |
| 679 | case 15: |
| 680 | sw->type = SW_ID_GP; |
| 681 | break; |
| 682 | case 33: |
| 683 | case 31: |
| 684 | sw->type = SW_ID_FFW; |
| 685 | break; |
| 686 | case 48: /* Ambiguous */ |
| 687 | if (j == 14) { /* ID length 14*3 -> FFP */ |
| 688 | sw->type = SW_ID_FFP; |
| 689 | sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on"); |
| 690 | } else |
| 691 | sw->type = SW_ID_PP; |
| 692 | break; |
| 693 | case 66: |
| 694 | sw->bits = 3; |
| 695 | case 198: |
| 696 | sw->length = 22; |
| 697 | case 64: |
| 698 | sw->type = SW_ID_3DP; |
| 699 | if (j == 160) sw_3dp_id(idbuf, comment); |
| 700 | break; |
| 701 | } |
| 702 | } |
| 703 | |
| 704 | } while (k && sw->type == -1); |
| 705 | |
| 706 | if (sw->type == -1) { |
| 707 | printk(KERN_WARNING "sidewinder.c: unknown joystick device detected " |
| 708 | "on %s, contact <vojtech@ucw.cz>\n", gameport->phys); |
| 709 | sw_print_packet("ID", j * 3, idbuf, 3); |
| 710 | sw_print_packet("Data", i * m, buf, m); |
| 711 | err = -ENODEV; |
| 712 | goto fail2; |
| 713 | } |
| 714 | |
| 715 | #ifdef SW_DEBUG |
| 716 | sw_print_packet("ID", j * 3, idbuf, 3); |
| 717 | sw_print_packet("Data", i * m, buf, m); |
| 718 | #endif |
| 719 | |
| 720 | gameport_set_poll_handler(gameport, sw_poll); |
| 721 | gameport_set_poll_interval(gameport, 20); |
| 722 | |
| 723 | k = i; |
| 724 | l = j; |
| 725 | |
| 726 | for (i = 0; i < sw->number; i++) { |
| 727 | int bits, code; |
| 728 | |
| 729 | sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]); |
| 730 | sprintf(sw->phys[i], "%s/input%d", gameport->phys, i); |
| 731 | |
| 732 | sw->dev[i].private = sw; |
| 733 | |
| 734 | sw->dev[i].open = sw_open; |
| 735 | sw->dev[i].close = sw_close; |
| 736 | |
| 737 | sw->dev[i].name = sw->name; |
| 738 | sw->dev[i].phys = sw->phys[i]; |
| 739 | sw->dev[i].id.bustype = BUS_GAMEPORT; |
| 740 | sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT; |
| 741 | sw->dev[i].id.product = sw->type; |
| 742 | sw->dev[i].id.version = 0x0100; |
| 743 | |
| 744 | sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
| 745 | |
| 746 | for (j = 0; (bits = sw_bit[sw->type][j]); j++) { |
| 747 | code = sw_abs[sw->type][j]; |
| 748 | set_bit(code, sw->dev[i].absbit); |
| 749 | sw->dev[i].absmax[code] = (1 << bits) - 1; |
| 750 | sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0; |
| 751 | sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0; |
| 752 | if (code != ABS_THROTTLE) |
| 753 | sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0; |
| 754 | } |
| 755 | |
| 756 | for (j = 0; (code = sw_btn[sw->type][j]); j++) |
| 757 | set_bit(code, sw->dev[i].keybit); |
| 758 | |
| 759 | input_register_device(sw->dev + i); |
| 760 | printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n", |
| 761 | sw->name, comment, gameport->phys, m, l, k); |
| 762 | } |
| 763 | |
| 764 | return 0; |
| 765 | |
| 766 | fail2: gameport_close(gameport); |
| 767 | fail1: gameport_set_drvdata(gameport, NULL); |
| 768 | kfree(sw); |
| 769 | kfree(buf); |
| 770 | kfree(idbuf); |
| 771 | return err; |
| 772 | } |
| 773 | |
| 774 | static void sw_disconnect(struct gameport *gameport) |
| 775 | { |
| 776 | struct sw *sw = gameport_get_drvdata(gameport); |
| 777 | int i; |
| 778 | |
| 779 | for (i = 0; i < sw->number; i++) |
| 780 | input_unregister_device(sw->dev + i); |
| 781 | gameport_close(gameport); |
| 782 | gameport_set_drvdata(gameport, NULL); |
| 783 | kfree(sw); |
| 784 | } |
| 785 | |
| 786 | static struct gameport_driver sw_drv = { |
| 787 | .driver = { |
| 788 | .name = "sidewinder", |
| 789 | }, |
| 790 | .description = DRIVER_DESC, |
| 791 | .connect = sw_connect, |
| 792 | .disconnect = sw_disconnect, |
| 793 | }; |
| 794 | |
| 795 | static int __init sw_init(void) |
| 796 | { |
| 797 | gameport_register_driver(&sw_drv); |
| 798 | return 0; |
| 799 | } |
| 800 | |
| 801 | static void __exit sw_exit(void) |
| 802 | { |
| 803 | gameport_unregister_driver(&sw_drv); |
| 804 | } |
| 805 | |
| 806 | module_init(sw_init); |
| 807 | module_exit(sw_exit); |