0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/delay.h>
0017 #include <linux/kernel.h>
0018 #include <linux/slab.h>
0019 #include <linux/module.h>
0020 #include <linux/gameport.h>
0021 #include <linux/input.h>
0022 #include <linux/jiffies.h>
0023
0024 #define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
0025
0026 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0027 MODULE_DESCRIPTION(DRIVER_DESC);
0028 MODULE_LICENSE("GPL");
0029
0030 #define TMDC_MAX_START 600
0031 #define TMDC_MAX_STROBE 60
0032 #define TMDC_MAX_LENGTH 13
0033
0034 #define TMDC_MODE_M3DI 1
0035 #define TMDC_MODE_3DRP 3
0036 #define TMDC_MODE_AT 4
0037 #define TMDC_MODE_FM 8
0038 #define TMDC_MODE_FGP 163
0039
0040 #define TMDC_BYTE_ID 10
0041 #define TMDC_BYTE_REV 11
0042 #define TMDC_BYTE_DEF 12
0043
0044 #define TMDC_ABS 7
0045 #define TMDC_ABS_HAT 4
0046 #define TMDC_BTN 16
0047
0048 static const unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
0049 static const unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
0050
0051 static const signed char tmdc_abs[TMDC_ABS] =
0052 { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
0053 static const signed char tmdc_abs_hat[TMDC_ABS_HAT] =
0054 { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
0055 static const signed char tmdc_abs_at[TMDC_ABS] =
0056 { ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
0057 static const signed char tmdc_abs_fm[TMDC_ABS] =
0058 { ABS_RX, ABS_RY, ABS_X, ABS_Y };
0059
0060 static const short tmdc_btn_pad[TMDC_BTN] =
0061 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
0062 static const short tmdc_btn_joy[TMDC_BTN] =
0063 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
0064 BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
0065 static const short tmdc_btn_fm[TMDC_BTN] =
0066 { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
0067 static const short tmdc_btn_at[TMDC_BTN] =
0068 { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
0069 BTN_BASE3, BTN_BASE2, BTN_BASE };
0070
0071 static const struct {
0072 int x;
0073 int y;
0074 } tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
0075
0076 static const struct tmdc_model {
0077 unsigned char id;
0078 const char *name;
0079 char abs;
0080 char hats;
0081 char btnc[4];
0082 char btno[4];
0083 const signed char *axes;
0084 const short *buttons;
0085 } tmdc_models[] = {
0086 { 1, "ThrustMaster Millennium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
0087 { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
0088 { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
0089 { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
0090 { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
0091 { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }
0092 };
0093
0094
0095 struct tmdc_port {
0096 struct input_dev *dev;
0097 char name[64];
0098 char phys[32];
0099 int mode;
0100 const signed char *abs;
0101 const short *btn;
0102 unsigned char absc;
0103 unsigned char btnc[4];
0104 unsigned char btno[4];
0105 };
0106
0107 struct tmdc {
0108 struct gameport *gameport;
0109 struct tmdc_port *port[2];
0110 #if 0
0111 struct input_dev *dev[2];
0112 char name[2][64];
0113 char phys[2][32];
0114 int mode[2];
0115 signed char *abs[2];
0116 short *btn[2];
0117 unsigned char absc[2];
0118 unsigned char btnc[2][4];
0119 unsigned char btno[2][4];
0120 #endif
0121 int reads;
0122 int bads;
0123 unsigned char exists;
0124 };
0125
0126
0127
0128
0129
0130 static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
0131 {
0132 unsigned char u, v, w, x;
0133 unsigned long flags;
0134 int i[2], j[2], t[2], p, k;
0135
0136 p = gameport_time(gameport, TMDC_MAX_STROBE);
0137
0138 for (k = 0; k < 2; k++) {
0139 t[k] = gameport_time(gameport, TMDC_MAX_START);
0140 i[k] = j[k] = 0;
0141 }
0142
0143 local_irq_save(flags);
0144 gameport_trigger(gameport);
0145
0146 w = gameport_read(gameport) >> 4;
0147
0148 do {
0149 x = w;
0150 w = gameport_read(gameport) >> 4;
0151
0152 for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
0153 if (~v & u & 2) {
0154 if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
0155 t[k] = p;
0156 if (j[k] == 0) {
0157 if (~v & 1) t[k] = 0;
0158 data[k][i[k]] = 0; j[k]++; continue;
0159 }
0160 if (j[k] == 9) {
0161 if (v & 1) t[k] = 0;
0162 j[k] = 0; i[k]++; continue;
0163 }
0164 data[k][i[k]] |= (~v & 1) << (j[k]++ - 1);
0165 }
0166 t[k]--;
0167 }
0168 } while (t[0] > 0 || t[1] > 0);
0169
0170 local_irq_restore(flags);
0171
0172 return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
0173 }
0174
0175 static int tmdc_parse_packet(struct tmdc_port *port, unsigned char *data)
0176 {
0177 int i, k, l;
0178
0179 if (data[TMDC_BYTE_ID] != port->mode)
0180 return -1;
0181
0182 for (i = 0; i < port->absc; i++) {
0183 if (port->abs[i] < 0)
0184 return 0;
0185
0186 input_report_abs(port->dev, port->abs[i], data[tmdc_byte_a[i]]);
0187 }
0188
0189 switch (port->mode) {
0190
0191 case TMDC_MODE_M3DI:
0192
0193 i = tmdc_byte_d[0];
0194 input_report_abs(port->dev, ABS_HAT0X, ((data[i] >> 3) & 1) - ((data[i] >> 1) & 1));
0195 input_report_abs(port->dev, ABS_HAT0Y, ((data[i] >> 2) & 1) - ( data[i] & 1));
0196 break;
0197
0198 case TMDC_MODE_AT:
0199
0200 i = tmdc_byte_a[3];
0201 input_report_abs(port->dev, ABS_HAT0X, tmdc_hat_to_axis[(data[i] - 141) / 25].x);
0202 input_report_abs(port->dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[i] - 141) / 25].y);
0203 break;
0204
0205 }
0206
0207 for (k = l = 0; k < 4; k++) {
0208 for (i = 0; i < port->btnc[k]; i++)
0209 input_report_key(port->dev, port->btn[i + l],
0210 ((data[tmdc_byte_d[k]] >> (i + port->btno[k])) & 1));
0211 l += port->btnc[k];
0212 }
0213
0214 input_sync(port->dev);
0215
0216 return 0;
0217 }
0218
0219
0220
0221
0222
0223 static void tmdc_poll(struct gameport *gameport)
0224 {
0225 unsigned char data[2][TMDC_MAX_LENGTH];
0226 struct tmdc *tmdc = gameport_get_drvdata(gameport);
0227 unsigned char r, bad = 0;
0228 int i;
0229
0230 tmdc->reads++;
0231
0232 if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
0233 bad = 1;
0234 else {
0235 for (i = 0; i < 2; i++) {
0236 if (r & (1 << i) & tmdc->exists) {
0237
0238 if (tmdc_parse_packet(tmdc->port[i], data[i]))
0239 bad = 1;
0240 }
0241 }
0242 }
0243
0244 tmdc->bads += bad;
0245 }
0246
0247 static int tmdc_open(struct input_dev *dev)
0248 {
0249 struct tmdc *tmdc = input_get_drvdata(dev);
0250
0251 gameport_start_polling(tmdc->gameport);
0252 return 0;
0253 }
0254
0255 static void tmdc_close(struct input_dev *dev)
0256 {
0257 struct tmdc *tmdc = input_get_drvdata(dev);
0258
0259 gameport_stop_polling(tmdc->gameport);
0260 }
0261
0262 static int tmdc_setup_port(struct tmdc *tmdc, int idx, unsigned char *data)
0263 {
0264 const struct tmdc_model *model;
0265 struct tmdc_port *port;
0266 struct input_dev *input_dev;
0267 int i, j, b = 0;
0268 int err;
0269
0270 tmdc->port[idx] = port = kzalloc(sizeof (struct tmdc_port), GFP_KERNEL);
0271 input_dev = input_allocate_device();
0272 if (!port || !input_dev) {
0273 err = -ENOMEM;
0274 goto fail;
0275 }
0276
0277 port->mode = data[TMDC_BYTE_ID];
0278
0279 for (model = tmdc_models; model->id && model->id != port->mode; model++)
0280 ;
0281
0282 port->abs = model->axes;
0283 port->btn = model->buttons;
0284
0285 if (!model->id) {
0286 port->absc = data[TMDC_BYTE_DEF] >> 4;
0287 for (i = 0; i < 4; i++)
0288 port->btnc[i] = i < (data[TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
0289 } else {
0290 port->absc = model->abs;
0291 for (i = 0; i < 4; i++)
0292 port->btnc[i] = model->btnc[i];
0293 }
0294
0295 for (i = 0; i < 4; i++)
0296 port->btno[i] = model->btno[i];
0297
0298 snprintf(port->name, sizeof(port->name), model->name,
0299 port->absc, (data[TMDC_BYTE_DEF] & 0xf) << 3, port->mode);
0300 snprintf(port->phys, sizeof(port->phys), "%s/input%d", tmdc->gameport->phys, i);
0301
0302 port->dev = input_dev;
0303
0304 input_dev->name = port->name;
0305 input_dev->phys = port->phys;
0306 input_dev->id.bustype = BUS_GAMEPORT;
0307 input_dev->id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
0308 input_dev->id.product = model->id;
0309 input_dev->id.version = 0x0100;
0310 input_dev->dev.parent = &tmdc->gameport->dev;
0311
0312 input_set_drvdata(input_dev, tmdc);
0313
0314 input_dev->open = tmdc_open;
0315 input_dev->close = tmdc_close;
0316
0317 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0318
0319 for (i = 0; i < port->absc && i < TMDC_ABS; i++)
0320 if (port->abs[i] >= 0)
0321 input_set_abs_params(input_dev, port->abs[i], 8, 248, 2, 4);
0322
0323 for (i = 0; i < model->hats && i < TMDC_ABS_HAT; i++)
0324 input_set_abs_params(input_dev, tmdc_abs_hat[i], -1, 1, 0, 0);
0325
0326 for (i = 0; i < 4; i++) {
0327 for (j = 0; j < port->btnc[i] && j < TMDC_BTN; j++)
0328 set_bit(port->btn[j + b], input_dev->keybit);
0329 b += port->btnc[i];
0330 }
0331
0332 err = input_register_device(port->dev);
0333 if (err)
0334 goto fail;
0335
0336 return 0;
0337
0338 fail: input_free_device(input_dev);
0339 kfree(port);
0340 return err;
0341 }
0342
0343
0344
0345
0346
0347 static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
0348 {
0349 unsigned char data[2][TMDC_MAX_LENGTH];
0350 struct tmdc *tmdc;
0351 int i;
0352 int err;
0353
0354 if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL)))
0355 return -ENOMEM;
0356
0357 tmdc->gameport = gameport;
0358
0359 gameport_set_drvdata(gameport, tmdc);
0360
0361 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
0362 if (err)
0363 goto fail1;
0364
0365 if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
0366 err = -ENODEV;
0367 goto fail2;
0368 }
0369
0370 gameport_set_poll_handler(gameport, tmdc_poll);
0371 gameport_set_poll_interval(gameport, 20);
0372
0373 for (i = 0; i < 2; i++) {
0374 if (tmdc->exists & (1 << i)) {
0375
0376 err = tmdc_setup_port(tmdc, i, data[i]);
0377 if (err)
0378 goto fail3;
0379 }
0380 }
0381
0382 return 0;
0383
0384 fail3: while (--i >= 0) {
0385 if (tmdc->port[i]) {
0386 input_unregister_device(tmdc->port[i]->dev);
0387 kfree(tmdc->port[i]);
0388 }
0389 }
0390 fail2: gameport_close(gameport);
0391 fail1: gameport_set_drvdata(gameport, NULL);
0392 kfree(tmdc);
0393 return err;
0394 }
0395
0396 static void tmdc_disconnect(struct gameport *gameport)
0397 {
0398 struct tmdc *tmdc = gameport_get_drvdata(gameport);
0399 int i;
0400
0401 for (i = 0; i < 2; i++) {
0402 if (tmdc->port[i]) {
0403 input_unregister_device(tmdc->port[i]->dev);
0404 kfree(tmdc->port[i]);
0405 }
0406 }
0407 gameport_close(gameport);
0408 gameport_set_drvdata(gameport, NULL);
0409 kfree(tmdc);
0410 }
0411
0412 static struct gameport_driver tmdc_drv = {
0413 .driver = {
0414 .name = "tmdc",
0415 .owner = THIS_MODULE,
0416 },
0417 .description = DRIVER_DESC,
0418 .connect = tmdc_connect,
0419 .disconnect = tmdc_disconnect,
0420 };
0421
0422 module_gameport_driver(tmdc_drv);