root/drivers/input/joystick/gf2k.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gf2k_read_packet
  2. gf2k_trigger_seq
  3. gf2k_get_bits
  4. gf2k_read
  5. gf2k_poll
  6. gf2k_open
  7. gf2k_close
  8. gf2k_connect
  9. gf2k_disconnect

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

/* [<][>][^][v][top][bottom][index][help] */