Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1998-2001 Vojtech Pavlik
0004  */
0005 
0006 /*
0007  * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
0008  */
0009 
0010 /*
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016 #include <linux/gameport.h>
0017 #include <linux/input.h>
0018 #include <linux/jiffies.h>
0019 
0020 #define DRIVER_DESC "Gravis GrIP protocol joystick driver"
0021 
0022 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0023 MODULE_DESCRIPTION(DRIVER_DESC);
0024 MODULE_LICENSE("GPL");
0025 
0026 #define GRIP_MODE_GPP       1
0027 #define GRIP_MODE_BD        2
0028 #define GRIP_MODE_XT        3
0029 #define GRIP_MODE_DC        4
0030 
0031 #define GRIP_LENGTH_GPP     24
0032 #define GRIP_STROBE_GPP     200 /* 200 us */
0033 #define GRIP_LENGTH_XT      4
0034 #define GRIP_STROBE_XT      64  /* 64 us */
0035 #define GRIP_MAX_CHUNKS_XT  10
0036 #define GRIP_MAX_BITS_XT    30
0037 
0038 struct grip {
0039     struct gameport *gameport;
0040     struct input_dev *dev[2];
0041     unsigned char mode[2];
0042     int reads;
0043     int bads;
0044     char phys[2][32];
0045 };
0046 
0047 static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
0048 static int grip_btn_bd[] = { BTN_THUMB, BTN_THUMB2, BTN_TRIGGER, BTN_TOP, BTN_BASE, -1 };
0049 static int grip_btn_xt[] = { BTN_TRIGGER, BTN_THUMB, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_SELECT, BTN_START, BTN_MODE, -1 };
0050 static int grip_btn_dc[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, -1 };
0051 
0052 static int grip_abs_gpp[] = { ABS_X, ABS_Y, -1 };
0053 static int grip_abs_bd[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
0054 static int grip_abs_xt[] = { ABS_X, ABS_Y, ABS_BRAKE, ABS_GAS, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 };
0055 static int grip_abs_dc[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
0056 
0057 static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
0058                 "Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
0059 static int *grip_abs[] = { NULL, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
0060 static int *grip_btn[] = { NULL, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
0061 static char grip_anx[] = { 0, 0, 3, 5, 5 };
0062 static char grip_cen[] = { 0, 0, 2, 2, 4 };
0063 
0064 /*
0065  * grip_gpp_read_packet() reads a Gravis GamePad Pro packet.
0066  */
0067 
0068 static int grip_gpp_read_packet(struct gameport *gameport, int shift, unsigned int *data)
0069 {
0070     unsigned long flags;
0071     unsigned char u, v;
0072     unsigned int t;
0073     int i;
0074 
0075     int strobe = gameport_time(gameport, GRIP_STROBE_GPP);
0076 
0077     data[0] = 0;
0078     t = strobe;
0079     i = 0;
0080 
0081     local_irq_save(flags);
0082 
0083     v = gameport_read(gameport) >> shift;
0084 
0085     do {
0086         t--;
0087         u = v; v = (gameport_read(gameport) >> shift) & 3;
0088         if (~v & u & 1) {
0089             data[0] |= (v >> 1) << i++;
0090             t = strobe;
0091         }
0092     } while (i < GRIP_LENGTH_GPP && t > 0);
0093 
0094     local_irq_restore(flags);
0095 
0096     if (i < GRIP_LENGTH_GPP) return -1;
0097 
0098     for (i = 0; i < GRIP_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
0099         data[0] = data[0] >> 1 | (data[0] & 1) << (GRIP_LENGTH_GPP - 1);
0100 
0101     return -(i == GRIP_LENGTH_GPP);
0102 }
0103 
0104 /*
0105  * grip_xt_read_packet() reads a Gravis Xterminator packet.
0106  */
0107 
0108 static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned int *data)
0109 {
0110     unsigned int i, j, buf, crc;
0111     unsigned char u, v, w;
0112     unsigned long flags;
0113     unsigned int t;
0114     char status;
0115 
0116     int strobe = gameport_time(gameport, GRIP_STROBE_XT);
0117 
0118     data[0] = data[1] = data[2] = data[3] = 0;
0119     status = buf = i = j = 0;
0120     t = strobe;
0121 
0122     local_irq_save(flags);
0123 
0124     v = w = (gameport_read(gameport) >> shift) & 3;
0125 
0126     do {
0127         t--;
0128         u = (gameport_read(gameport) >> shift) & 3;
0129 
0130         if (u ^ v) {
0131 
0132             if ((u ^ v) & 1) {
0133                 buf = (buf << 1) | (u >> 1);
0134                 t = strobe;
0135                 i++;
0136             } else
0137 
0138             if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
0139                 if (i == 20) {
0140                     crc = buf ^ (buf >> 7) ^ (buf >> 14);
0141                     if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
0142                         data[buf >> 18] = buf >> 4;
0143                         status |= 1 << (buf >> 18);
0144                     }
0145                     j++;
0146                 }
0147                 t = strobe;
0148                 buf = 0;
0149                 i = 0;
0150             }
0151             w = v;
0152             v = u;
0153         }
0154 
0155     } while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0);
0156 
0157     local_irq_restore(flags);
0158 
0159     return -(status != 0xf);
0160 }
0161 
0162 /*
0163  * grip_timer() repeatedly polls the joysticks and generates events.
0164  */
0165 
0166 static void grip_poll(struct gameport *gameport)
0167 {
0168     struct grip *grip = gameport_get_drvdata(gameport);
0169     unsigned int data[GRIP_LENGTH_XT];
0170     struct input_dev *dev;
0171     int i, j;
0172 
0173     for (i = 0; i < 2; i++) {
0174 
0175         dev = grip->dev[i];
0176         if (!dev)
0177             continue;
0178 
0179         grip->reads++;
0180 
0181         switch (grip->mode[i]) {
0182 
0183             case GRIP_MODE_GPP:
0184 
0185                 if (grip_gpp_read_packet(grip->gameport, (i << 1) + 4, data)) {
0186                     grip->bads++;
0187                     break;
0188                 }
0189 
0190                 input_report_abs(dev, ABS_X, ((*data >> 15) & 1) - ((*data >> 16) & 1));
0191                 input_report_abs(dev, ABS_Y, ((*data >> 13) & 1) - ((*data >> 12) & 1));
0192 
0193                 for (j = 0; j < 12; j++)
0194                     if (grip_btn_gpp[j])
0195                         input_report_key(dev, grip_btn_gpp[j], (*data >> j) & 1);
0196 
0197                 break;
0198 
0199             case GRIP_MODE_BD:
0200 
0201                 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
0202                     grip->bads++;
0203                     break;
0204                 }
0205 
0206                 input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
0207                 input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
0208                 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
0209 
0210                 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
0211                 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
0212 
0213                 for (j = 0; j < 5; j++)
0214                     input_report_key(dev, grip_btn_bd[j], (data[3] >> (j + 4)) & 1);
0215 
0216                 break;
0217 
0218             case GRIP_MODE_XT:
0219 
0220                 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
0221                     grip->bads++;
0222                     break;
0223                 }
0224 
0225                 input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
0226                 input_report_abs(dev, ABS_Y,  63 - ((data[0] >> 8) & 0x3f));
0227                 input_report_abs(dev, ABS_BRAKE,    (data[1] >> 2) & 0x3f);
0228                 input_report_abs(dev, ABS_GAS,      (data[1] >> 8) & 0x3f);
0229                 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
0230 
0231                 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
0232                 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
0233                 input_report_abs(dev, ABS_HAT1X, ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1));
0234                 input_report_abs(dev, ABS_HAT1Y, ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1));
0235 
0236                 for (j = 0; j < 11; j++)
0237                     input_report_key(dev, grip_btn_xt[j], (data[3] >> (j + 3)) & 1);
0238                 break;
0239 
0240             case GRIP_MODE_DC:
0241 
0242                 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
0243                     grip->bads++;
0244                     break;
0245                 }
0246 
0247                 input_report_abs(dev, ABS_X,        (data[0] >> 2) & 0x3f);
0248                 input_report_abs(dev, ABS_Y,        (data[0] >> 8) & 0x3f);
0249                 input_report_abs(dev, ABS_RX,       (data[1] >> 2) & 0x3f);
0250                 input_report_abs(dev, ABS_RY,       (data[1] >> 8) & 0x3f);
0251                 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
0252 
0253                 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2]       & 1));
0254                 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
0255 
0256                 for (j = 0; j < 9; j++)
0257                     input_report_key(dev, grip_btn_dc[j], (data[3] >> (j + 3)) & 1);
0258                 break;
0259 
0260 
0261         }
0262 
0263         input_sync(dev);
0264     }
0265 }
0266 
0267 static int grip_open(struct input_dev *dev)
0268 {
0269     struct grip *grip = input_get_drvdata(dev);
0270 
0271     gameport_start_polling(grip->gameport);
0272     return 0;
0273 }
0274 
0275 static void grip_close(struct input_dev *dev)
0276 {
0277     struct grip *grip = input_get_drvdata(dev);
0278 
0279     gameport_stop_polling(grip->gameport);
0280 }
0281 
0282 static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
0283 {
0284     struct grip *grip;
0285     struct input_dev *input_dev;
0286     unsigned int data[GRIP_LENGTH_XT];
0287     int i, j, t;
0288     int err;
0289 
0290     if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL)))
0291         return -ENOMEM;
0292 
0293     grip->gameport = gameport;
0294 
0295     gameport_set_drvdata(gameport, grip);
0296 
0297     err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
0298     if (err)
0299         goto fail1;
0300 
0301     for (i = 0; i < 2; i++) {
0302         if (!grip_gpp_read_packet(gameport, (i << 1) + 4, data)) {
0303             grip->mode[i] = GRIP_MODE_GPP;
0304             continue;
0305         }
0306         if (!grip_xt_read_packet(gameport, (i << 1) + 4, data)) {
0307             if (!(data[3] & 7)) {
0308                 grip->mode[i] = GRIP_MODE_BD;
0309                 continue;
0310             }
0311             if (!(data[2] & 0xf0)) {
0312                 grip->mode[i] = GRIP_MODE_XT;
0313                 continue;
0314             }
0315             grip->mode[i] = GRIP_MODE_DC;
0316             continue;
0317         }
0318     }
0319 
0320     if (!grip->mode[0] && !grip->mode[1]) {
0321         err = -ENODEV;
0322         goto fail2;
0323     }
0324 
0325     gameport_set_poll_handler(gameport, grip_poll);
0326     gameport_set_poll_interval(gameport, 20);
0327 
0328     for (i = 0; i < 2; i++) {
0329         if (!grip->mode[i])
0330             continue;
0331 
0332         grip->dev[i] = input_dev = input_allocate_device();
0333         if (!input_dev) {
0334             err = -ENOMEM;
0335             goto fail3;
0336         }
0337 
0338         snprintf(grip->phys[i], sizeof(grip->phys[i]),
0339              "%s/input%d", gameport->phys, i);
0340 
0341         input_dev->name = grip_name[grip->mode[i]];
0342         input_dev->phys = grip->phys[i];
0343         input_dev->id.bustype = BUS_GAMEPORT;
0344         input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
0345         input_dev->id.product = grip->mode[i];
0346         input_dev->id.version = 0x0100;
0347         input_dev->dev.parent = &gameport->dev;
0348 
0349         input_set_drvdata(input_dev, grip);
0350 
0351         input_dev->open = grip_open;
0352         input_dev->close = grip_close;
0353 
0354         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0355 
0356         for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
0357 
0358             if (j < grip_cen[grip->mode[i]])
0359                 input_set_abs_params(input_dev, t, 14, 52, 1, 2);
0360             else if (j < grip_anx[grip->mode[i]])
0361                 input_set_abs_params(input_dev, t, 3, 57, 1, 0);
0362             else
0363                 input_set_abs_params(input_dev, t, -1, 1, 0, 0);
0364         }
0365 
0366         for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
0367             if (t > 0)
0368                 set_bit(t, input_dev->keybit);
0369 
0370         err = input_register_device(grip->dev[i]);
0371         if (err)
0372             goto fail4;
0373     }
0374 
0375     return 0;
0376 
0377  fail4: input_free_device(grip->dev[i]);
0378  fail3: while (--i >= 0)
0379         if (grip->dev[i])
0380             input_unregister_device(grip->dev[i]);
0381  fail2: gameport_close(gameport);
0382  fail1: gameport_set_drvdata(gameport, NULL);
0383     kfree(grip);
0384     return err;
0385 }
0386 
0387 static void grip_disconnect(struct gameport *gameport)
0388 {
0389     struct grip *grip = gameport_get_drvdata(gameport);
0390     int i;
0391 
0392     for (i = 0; i < 2; i++)
0393         if (grip->dev[i])
0394             input_unregister_device(grip->dev[i]);
0395     gameport_close(gameport);
0396     gameport_set_drvdata(gameport, NULL);
0397     kfree(grip);
0398 }
0399 
0400 static struct gameport_driver grip_drv = {
0401     .driver     = {
0402         .name   = "grip",
0403         .owner  = THIS_MODULE,
0404     },
0405     .description    = DRIVER_DESC,
0406     .connect    = grip_connect,
0407     .disconnect = grip_disconnect,
0408 };
0409 
0410 module_gameport_driver(grip_drv);