0001
0002
0003
0004
0005
0006
0007
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
0033 #define GRIP_LENGTH_XT 4
0034 #define GRIP_STROBE_XT 64
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
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
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
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);