Path: blob/master/drivers/input/joystick/sidewinder.c
15111 views
/*1* Copyright (c) 1998-2005 Vojtech Pavlik2*/34/*5* Microsoft SideWinder joystick family driver for Linux6*/78/*9* This program is free software; you can redistribute it and/or modify10* it under the terms of the GNU General Public License as published by11* the Free Software Foundation; either version 2 of the License, or12* (at your option) any later version.13*14* This program is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with this program; if not, write to the Free Software21* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA22*23* Should you need to contact me, the author, you can do so either by24* e-mail - mail your message to <[email protected]>, or by paper mail:25* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic26*/2728#include <linux/delay.h>29#include <linux/kernel.h>30#include <linux/module.h>31#include <linux/slab.h>32#include <linux/init.h>33#include <linux/input.h>34#include <linux/gameport.h>35#include <linux/jiffies.h>3637#define DRIVER_DESC "Microsoft SideWinder joystick family driver"3839MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");40MODULE_DESCRIPTION(DRIVER_DESC);41MODULE_LICENSE("GPL");4243/*44* These are really magic values. Changing them can make a problem go away,45* as well as break everything.46*/4748#undef SW_DEBUG49#undef SW_DEBUG_DATA5051#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 */6061#ifdef SW_DEBUG62#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)63#else64#define dbg(format, arg...) do {} while (0)65#endif6667/*68* SideWinder joystick types ...69*/7071#define SW_ID_3DP 072#define SW_ID_GP 173#define SW_ID_PP 274#define SW_ID_FFP 375#define SW_ID_FSP 476#define SW_ID_FFW 57778/*79* Names, buttons, axes ...80*/8182static char *sw_name[] = { "3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",83"Force Feedback Wheel" };8485static 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 }};9293static 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 }};100101static 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 }};108109static struct {110int x;111int y;112} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};113114struct sw {115struct gameport *gameport;116struct input_dev *dev[4];117char name[64];118char phys[4][32];119int length;120int type;121int bits;122int number;123int fail;124int ok;125int reads;126int bads;127};128129/*130* sw_read_packet() is a function which reads either a data packet, or an131* identification packet from a SideWinder joystick. The protocol is very,132* very, very braindamaged. Microsoft patented it in US patent #5628686.133*/134135static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)136{137unsigned long flags;138int timeout, bitout, sched, i, kick, start, strobe;139unsigned char pending, u, v;140141i = -id; /* Don't care about data, only want ID */142timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */143kick = id ? gameport_time(gameport, SW_KICK) : 0; /* Set up kick timeout for ID packet */144start = gameport_time(gameport, SW_START);145strobe = gameport_time(gameport, SW_STROBE);146bitout = start;147pending = 0;148sched = 0;149150local_irq_save(flags); /* Quiet, please */151152gameport_trigger(gameport); /* Trigger */153v = gameport_read(gameport);154155do {156bitout--;157u = v;158v = gameport_read(gameport);159} while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */160161if (bitout > 0)162bitout = strobe; /* Extend time if not timed out */163164while ((timeout > 0 || bitout > 0) && (i < length)) {165166timeout--;167bitout--; /* Decrement timers */168sched--;169170u = v;171v = gameport_read(gameport);172173if ((~u & v & 0x10) && (bitout > 0)) { /* Rising edge on clock - data bit */174if (i >= 0) /* Want this data */175buf[i] = v >> 5; /* Store it */176i++; /* Advance index */177bitout = strobe; /* Extend timeout for next bit */178}179180if (kick && (~v & u & 0x01)) { /* Falling edge on axis 0 */181sched = kick; /* Schedule second trigger */182kick = 0; /* Don't schedule next time on falling edge */183pending = 1; /* Mark schedule */184}185186if (pending && sched < 0 && (i > -SW_END)) { /* Second trigger time */187gameport_trigger(gameport); /* Trigger */188bitout = start; /* Long bit timeout */189pending = 0; /* Unmark schedule */190timeout = 0; /* Switch from global to bit timeouts */191}192}193194local_irq_restore(flags); /* Done - relax */195196#ifdef SW_DEBUG_DATA197{198int j;199printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);200for (j = 0; j < i; j++) printk("%d", buf[j]);201printk("]\n");202}203#endif204205return i;206}207208/*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 number211* of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits212* is number of bits per triplet.213*/214215#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)216217static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)218{219__u64 data = 0;220int tri = pos % bits; /* Start position */221int i = pos / bits;222int bit = 0;223224while (num--) {225data |= (__u64)((buf[i] >> tri++) & 1) << bit++; /* Transfer bit */226if (tri == bits) {227i++; /* Next triplet */228tri = 0;229}230}231232return data;233}234235/*236* sw_init_digital() initializes a SideWinder 3D Pro joystick237* into digital mode.238*/239240static void sw_init_digital(struct gameport *gameport)241{242int seq[] = { 140, 140+725, 140+300, 0 };243unsigned long flags;244int i, t;245246local_irq_save(flags);247248i = 0;249do {250gameport_trigger(gameport); /* Trigger */251t = gameport_time(gameport, SW_TIMEOUT * 1000);252while ((gameport_read(gameport) & 1) && t) t--; /* Wait for axis to fall back to 0 */253udelay(seq[i]); /* Delay magic time */254} while (seq[++i]);255256gameport_trigger(gameport); /* Last trigger */257258local_irq_restore(flags);259}260261/*262* sw_parity() computes parity of __u64263*/264265static int sw_parity(__u64 t)266{267int x = t ^ (t >> 32);268269x ^= x >> 16;270x ^= x >> 8;271x ^= x >> 4;272x ^= x >> 2;273x ^= x >> 1;274return x & 1;275}276277/*278* sw_ccheck() checks synchronization bits and computes checksum of nibbles.279*/280281static int sw_check(__u64 t)282{283unsigned char sum = 0;284285if ((t & 0x8080808080808080ULL) ^ 0x80) /* Sync */286return -1;287288while (t) { /* Sum */289sum += t & 0xf;290t >>= 4;291}292293return sum & 0xf;294}295296/*297* sw_parse() analyzes SideWinder joystick data, and writes the results into298* the axes and buttons arrays.299*/300301static int sw_parse(unsigned char *buf, struct sw *sw)302{303int hat, i, j;304struct input_dev *dev;305306switch (sw->type) {307308case SW_ID_3DP:309310if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)311return -1;312313dev = sw->dev[0];314315input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));316input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));317input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));318input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));319320input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);321input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);322323for (j = 0; j < 7; j++)324input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));325326input_report_key(dev, BTN_BASE4, !GB(38,1));327input_report_key(dev, BTN_BASE5, !GB(37,1));328329input_sync(dev);330331return 0;332333case SW_ID_GP:334335for (i = 0; i < sw->number; i ++) {336337if (sw_parity(GB(i*15,15)))338return -1;339340input_report_abs(sw->dev[i], ABS_X, GB(i*15+3,1) - GB(i*15+2,1));341input_report_abs(sw->dev[i], ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));342343for (j = 0; j < 10; j++)344input_report_key(sw->dev[i], sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));345346input_sync(sw->dev[i]);347}348349return 0;350351case SW_ID_PP:352case SW_ID_FFP:353354if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)355return -1;356357dev = sw->dev[0];358input_report_abs(dev, ABS_X, GB( 9,10));359input_report_abs(dev, ABS_Y, GB(19,10));360input_report_abs(dev, ABS_RZ, GB(36, 6));361input_report_abs(dev, ABS_THROTTLE, GB(29, 7));362363input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);364input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);365366for (j = 0; j < 9; j++)367input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));368369input_sync(dev);370371return 0;372373case SW_ID_FSP:374375if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)376return -1;377378dev = sw->dev[0];379input_report_abs(dev, ABS_X, GB( 0,10));380input_report_abs(dev, ABS_Y, GB(16,10));381input_report_abs(dev, ABS_THROTTLE, GB(32, 6));382383input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);384input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);385386for (j = 0; j < 6; j++)387input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));388389input_report_key(dev, BTN_TR, !GB(26,1));390input_report_key(dev, BTN_START, !GB(27,1));391input_report_key(dev, BTN_MODE, !GB(38,1));392input_report_key(dev, BTN_SELECT, !GB(39,1));393394input_sync(dev);395396return 0;397398case SW_ID_FFW:399400if (!sw_parity(GB(0,33)))401return -1;402403dev = sw->dev[0];404input_report_abs(dev, ABS_RX, GB( 0,10));405input_report_abs(dev, ABS_RUDDER, GB(10, 6));406input_report_abs(dev, ABS_THROTTLE, GB(16, 6));407408for (j = 0; j < 8; j++)409input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));410411input_sync(dev);412413return 0;414}415416return -1;417}418419/*420* sw_read() reads SideWinder joystick data, and reinitializes421* the joystick in case of persistent problems. This is the function that is422* called from the generic code to poll the joystick.423*/424425static int sw_read(struct sw *sw)426{427unsigned char buf[SW_LENGTH];428int i;429430i = sw_read_packet(sw->gameport, buf, sw->length, 0);431432if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */433434if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) { /* Last init failed, 1 bit mode */435printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"436" - going to reinitialize.\n", sw->gameport->phys);437sw->fail = SW_FAIL; /* Reinitialize */438i = 128; /* Bogus value */439}440441if (i < 66 && GB(0,64) == GB(i*3-66,64)) /* 1 == 3 */442i = 66; /* Everything is fine */443444if (i < 66 && GB(0,64) == GB(66,64)) /* 1 == 2 */445i = 66; /* Everything is fine */446447if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) { /* 2 == 3 */448memmove(buf, buf + i - 22, 22); /* Move data */449i = 66; /* Carry on */450}451}452453if (i == sw->length && !sw_parse(buf, sw)) { /* Parse data */454455sw->fail = 0;456sw->ok++;457458if (sw->type == SW_ID_3DP && sw->length == 66 /* Many packets OK */459&& sw->ok > SW_OK) {460461printk(KERN_INFO "sidewinder.c: No more trouble on %s"462" - enabling optimization again.\n", sw->gameport->phys);463sw->length = 22;464}465466return 0;467}468469sw->ok = 0;470sw->fail++;471472if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) { /* Consecutive bad packets */473474printk(KERN_INFO "sidewinder.c: Many bit errors on %s"475" - disabling optimization.\n", sw->gameport->phys);476sw->length = 66;477}478479if (sw->fail < SW_FAIL)480return -1; /* Not enough, don't reinitialize yet */481482printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"483" - reinitializing joystick.\n", sw->gameport->phys);484485if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */486mdelay(3 * SW_TIMEOUT);487sw_init_digital(sw->gameport);488}489490mdelay(SW_TIMEOUT);491i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0); /* Read normal data packet */492mdelay(SW_TIMEOUT);493sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */494495sw->fail = SW_FAIL;496497return -1;498}499500static void sw_poll(struct gameport *gameport)501{502struct sw *sw = gameport_get_drvdata(gameport);503504sw->reads++;505if (sw_read(sw))506sw->bads++;507}508509static int sw_open(struct input_dev *dev)510{511struct sw *sw = input_get_drvdata(dev);512513gameport_start_polling(sw->gameport);514return 0;515}516517static void sw_close(struct input_dev *dev)518{519struct sw *sw = input_get_drvdata(dev);520521gameport_stop_polling(sw->gameport);522}523524/*525* sw_print_packet() prints the contents of a SideWinder packet.526*/527528static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)529{530int i;531532printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);533for (i = (((length + 3) >> 2) - 1); i >= 0; i--)534printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));535printk("]\n");536}537538/*539* sw_3dp_id() translates the 3DP id into a human legible string.540* Unfortunately I don't know how to do this for the other SW types.541*/542543static void sw_3dp_id(unsigned char *buf, char *comment, size_t size)544{545int i;546char pnp[8], rev[9];547548for (i = 0; i < 7; i++) /* ASCII PnP ID */549pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);550551for (i = 0; i < 8; i++) /* ASCII firmware revision */552rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);553554pnp[7] = rev[8] = 0;555556snprintf(comment, size, " [PnP %d.%02d id %s rev %s]",557(int) ((sw_get_bits(buf, 8, 6, 1) << 6) | /* Two 6-bit values */558sw_get_bits(buf, 16, 6, 1)) / 100,559(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |560sw_get_bits(buf, 16, 6, 1)) % 100,561pnp, rev);562}563564/*565* sw_guess_mode() checks the upper two button bits for toggling -566* indication of that the joystick is in 3-bit mode. This is documented567* behavior for 3DP ID packet, and for example the FSP does this in568* normal packets instead. Fun ...569*/570571static int sw_guess_mode(unsigned char *buf, int len)572{573int i;574unsigned char xor = 0;575576for (i = 1; i < len; i++)577xor |= (buf[i - 1] ^ buf[i]) & 6;578579return !!xor * 2 + 1;580}581582/*583* sw_connect() probes for SideWinder type joysticks.584*/585586static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)587{588struct sw *sw;589struct input_dev *input_dev;590int i, j, k, l;591int err = 0;592unsigned char *buf = NULL; /* [SW_LENGTH] */593unsigned char *idbuf = NULL; /* [SW_LENGTH] */594unsigned char m = 1;595char comment[40];596597comment[0] = 0;598599sw = kzalloc(sizeof(struct sw), GFP_KERNEL);600buf = kmalloc(SW_LENGTH, GFP_KERNEL);601idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);602if (!sw || !buf || !idbuf) {603err = -ENOMEM;604goto fail1;605}606607sw->gameport = gameport;608609gameport_set_drvdata(gameport, sw);610611err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);612if (err)613goto fail1;614615dbg("Init 0: Opened %s, io %#x, speed %d",616gameport->phys, gameport->io, gameport->speed);617618i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */619msleep(SW_TIMEOUT);620dbg("Init 1: Mode %d. Length %d.", m , i);621622if (!i) { /* No data. 3d Pro analog mode? */623sw_init_digital(gameport); /* Switch to digital */624msleep(SW_TIMEOUT);625i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */626msleep(SW_TIMEOUT);627dbg("Init 1b: Length %d.", i);628if (!i) { /* No data -> FAIL */629err = -ENODEV;630goto fail2;631}632}633634j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */635m |= sw_guess_mode(idbuf, j); /* ID packet should carry mode info [3DP] */636dbg("Init 2: Mode %d. ID Length %d.", m, j);637638if (j <= 0) { /* Read ID failed. Happens in 1-bit mode on PP */639msleep(SW_TIMEOUT);640i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */641m |= sw_guess_mode(buf, i);642dbg("Init 2b: Mode %d. Length %d.", m, i);643if (!i) {644err = -ENODEV;645goto fail2;646}647msleep(SW_TIMEOUT);648j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */649dbg("Init 2c: ID Length %d.", j);650}651652sw->type = -1;653k = SW_FAIL; /* Try SW_FAIL times */654l = 0;655656do {657k--;658msleep(SW_TIMEOUT);659i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read data packet */660dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);661662if (i > l) { /* Longer? As we can only lose bits, it makes */663/* no sense to try detection for a packet shorter */664l = i; /* than the previous one */665666sw->number = 1;667sw->gameport = gameport;668sw->length = i;669sw->bits = m;670671dbg("Init 3a: Case %d.\n", i * m);672673switch (i * m) {674case 60:675sw->number++;676case 45: /* Ambiguous packet length */677if (j <= 40) { /* ID length less or eq 40 -> FSP */678case 43:679sw->type = SW_ID_FSP;680break;681}682sw->number++;683case 30:684sw->number++;685case 15:686sw->type = SW_ID_GP;687break;688case 33:689case 31:690sw->type = SW_ID_FFW;691break;692case 48: /* Ambiguous */693if (j == 14) { /* ID length 14*3 -> FFP */694sw->type = SW_ID_FFP;695sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");696} else697sw->type = SW_ID_PP;698break;699case 66:700sw->bits = 3;701case 198:702sw->length = 22;703case 64:704sw->type = SW_ID_3DP;705if (j == 160)706sw_3dp_id(idbuf, comment, sizeof(comment));707break;708}709}710711} while (k && sw->type == -1);712713if (sw->type == -1) {714printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "715"on %s, contact <[email protected]>\n", gameport->phys);716sw_print_packet("ID", j * 3, idbuf, 3);717sw_print_packet("Data", i * m, buf, m);718err = -ENODEV;719goto fail2;720}721722#ifdef SW_DEBUG723sw_print_packet("ID", j * 3, idbuf, 3);724sw_print_packet("Data", i * m, buf, m);725#endif726727gameport_set_poll_handler(gameport, sw_poll);728gameport_set_poll_interval(gameport, 20);729730k = i;731l = j;732733for (i = 0; i < sw->number; i++) {734int bits, code;735736snprintf(sw->name, sizeof(sw->name),737"Microsoft SideWinder %s", sw_name[sw->type]);738snprintf(sw->phys[i], sizeof(sw->phys[i]),739"%s/input%d", gameport->phys, i);740741sw->dev[i] = input_dev = input_allocate_device();742if (!input_dev) {743err = -ENOMEM;744goto fail3;745}746747input_dev->name = sw->name;748input_dev->phys = sw->phys[i];749input_dev->id.bustype = BUS_GAMEPORT;750input_dev->id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;751input_dev->id.product = sw->type;752input_dev->id.version = 0x0100;753input_dev->dev.parent = &gameport->dev;754755input_set_drvdata(input_dev, sw);756757input_dev->open = sw_open;758input_dev->close = sw_close;759760input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);761762for (j = 0; (bits = sw_bit[sw->type][j]); j++) {763int min, max, fuzz, flat;764765code = sw_abs[sw->type][j];766min = bits == 1 ? -1 : 0;767max = (1 << bits) - 1;768fuzz = (bits >> 1) >= 2 ? 1 << ((bits >> 1) - 2) : 0;769flat = code == ABS_THROTTLE || bits < 5 ?7700 : 1 << (bits - 5);771772input_set_abs_params(input_dev, code,773min, max, fuzz, flat);774}775776for (j = 0; (code = sw_btn[sw->type][j]); j++)777__set_bit(code, input_dev->keybit);778779dbg("%s%s [%d-bit id %d data %d]\n", sw->name, comment, m, l, k);780781err = input_register_device(sw->dev[i]);782if (err)783goto fail4;784}785786out: kfree(buf);787kfree(idbuf);788789return err;790791fail4: input_free_device(sw->dev[i]);792fail3: while (--i >= 0)793input_unregister_device(sw->dev[i]);794fail2: gameport_close(gameport);795fail1: gameport_set_drvdata(gameport, NULL);796kfree(sw);797goto out;798}799800static void sw_disconnect(struct gameport *gameport)801{802struct sw *sw = gameport_get_drvdata(gameport);803int i;804805for (i = 0; i < sw->number; i++)806input_unregister_device(sw->dev[i]);807gameport_close(gameport);808gameport_set_drvdata(gameport, NULL);809kfree(sw);810}811812static struct gameport_driver sw_drv = {813.driver = {814.name = "sidewinder",815.owner = THIS_MODULE,816},817.description = DRIVER_DESC,818.connect = sw_connect,819.disconnect = sw_disconnect,820};821822static int __init sw_init(void)823{824return gameport_register_driver(&sw_drv);825}826827static void __exit sw_exit(void)828{829gameport_unregister_driver(&sw_drv);830}831832module_init(sw_init);833module_exit(sw_exit);834835836