0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/module.h>
0016 #include <linux/delay.h>
0017 #include <linux/gameport.h>
0018 #include <linux/input.h>
0019 #include <linux/jiffies.h>
0020
0021 #define DRIVER_DESC "Guillemot Digital joystick driver"
0022
0023 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0024 MODULE_DESCRIPTION(DRIVER_DESC);
0025 MODULE_LICENSE("GPL");
0026
0027 #define GUILLEMOT_MAX_START 600
0028 #define GUILLEMOT_MAX_STROBE 60
0029 #define GUILLEMOT_MAX_LENGTH 17
0030
0031 static short guillemot_abs_pad[] =
0032 { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
0033
0034 static short guillemot_btn_pad[] =
0035 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_MODE, BTN_SELECT, -1 };
0036
0037 static struct {
0038 int x;
0039 int y;
0040 } guillemot_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
0041
0042 struct guillemot_type {
0043 unsigned char id;
0044 short *abs;
0045 short *btn;
0046 int hat;
0047 char *name;
0048 };
0049
0050 struct guillemot {
0051 struct gameport *gameport;
0052 struct input_dev *dev;
0053 int bads;
0054 int reads;
0055 struct guillemot_type *type;
0056 unsigned char length;
0057 char phys[32];
0058 };
0059
0060 static struct guillemot_type guillemot_type[] = {
0061 { 0x00, guillemot_abs_pad, guillemot_btn_pad, 1, "Guillemot Pad" },
0062 { 0 }};
0063
0064
0065
0066
0067
0068 static int guillemot_read_packet(struct gameport *gameport, u8 *data)
0069 {
0070 unsigned long flags;
0071 unsigned char u, v;
0072 unsigned int t, s;
0073 int i;
0074
0075 for (i = 0; i < GUILLEMOT_MAX_LENGTH; i++)
0076 data[i] = 0;
0077
0078 i = 0;
0079 t = gameport_time(gameport, GUILLEMOT_MAX_START);
0080 s = gameport_time(gameport, GUILLEMOT_MAX_STROBE);
0081
0082 local_irq_save(flags);
0083 gameport_trigger(gameport);
0084 v = gameport_read(gameport);
0085
0086 while (t > 0 && i < GUILLEMOT_MAX_LENGTH * 8) {
0087 t--;
0088 u = v; v = gameport_read(gameport);
0089 if (v & ~u & 0x10) {
0090 data[i >> 3] |= ((v >> 5) & 1) << (i & 7);
0091 i++;
0092 t = s;
0093 }
0094 }
0095
0096 local_irq_restore(flags);
0097
0098 return i;
0099 }
0100
0101
0102
0103
0104
0105 static void guillemot_poll(struct gameport *gameport)
0106 {
0107 struct guillemot *guillemot = gameport_get_drvdata(gameport);
0108 struct input_dev *dev = guillemot->dev;
0109 u8 data[GUILLEMOT_MAX_LENGTH];
0110 int i;
0111
0112 guillemot->reads++;
0113
0114 if (guillemot_read_packet(guillemot->gameport, data) != GUILLEMOT_MAX_LENGTH * 8 ||
0115 data[0] != 0x55 || data[16] != 0xaa) {
0116 guillemot->bads++;
0117 } else {
0118
0119 for (i = 0; i < 6 && guillemot->type->abs[i] >= 0; i++)
0120 input_report_abs(dev, guillemot->type->abs[i], data[i + 5]);
0121
0122 if (guillemot->type->hat) {
0123 input_report_abs(dev, ABS_HAT0X, guillemot_hat_to_axis[data[4] >> 4].x);
0124 input_report_abs(dev, ABS_HAT0Y, guillemot_hat_to_axis[data[4] >> 4].y);
0125 }
0126
0127 for (i = 0; i < 16 && guillemot->type->btn[i] >= 0; i++)
0128 input_report_key(dev, guillemot->type->btn[i], (data[2 + (i >> 3)] >> (i & 7)) & 1);
0129 }
0130
0131 input_sync(dev);
0132 }
0133
0134
0135
0136
0137
0138 static int guillemot_open(struct input_dev *dev)
0139 {
0140 struct guillemot *guillemot = input_get_drvdata(dev);
0141
0142 gameport_start_polling(guillemot->gameport);
0143 return 0;
0144 }
0145
0146
0147
0148
0149
0150 static void guillemot_close(struct input_dev *dev)
0151 {
0152 struct guillemot *guillemot = input_get_drvdata(dev);
0153
0154 gameport_stop_polling(guillemot->gameport);
0155 }
0156
0157
0158
0159
0160
0161 static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
0162 {
0163 struct guillemot *guillemot;
0164 struct input_dev *input_dev;
0165 u8 data[GUILLEMOT_MAX_LENGTH];
0166 int i, t;
0167 int err;
0168
0169 guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL);
0170 input_dev = input_allocate_device();
0171 if (!guillemot || !input_dev) {
0172 err = -ENOMEM;
0173 goto fail1;
0174 }
0175
0176 guillemot->gameport = gameport;
0177 guillemot->dev = input_dev;
0178
0179 gameport_set_drvdata(gameport, guillemot);
0180
0181 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
0182 if (err)
0183 goto fail1;
0184
0185 i = guillemot_read_packet(gameport, data);
0186
0187 if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
0188 err = -ENODEV;
0189 goto fail2;
0190 }
0191
0192 for (i = 0; guillemot_type[i].name; i++)
0193 if (guillemot_type[i].id == data[11])
0194 break;
0195
0196 if (!guillemot_type[i].name) {
0197 printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
0198 gameport->phys, data[12], data[13], data[11], data[14], data[15]);
0199 err = -ENODEV;
0200 goto fail2;
0201 }
0202
0203 gameport_set_poll_handler(gameport, guillemot_poll);
0204 gameport_set_poll_interval(gameport, 20);
0205
0206 snprintf(guillemot->phys, sizeof(guillemot->phys), "%s/input0", gameport->phys);
0207 guillemot->type = guillemot_type + i;
0208
0209 input_dev->name = guillemot_type[i].name;
0210 input_dev->phys = guillemot->phys;
0211 input_dev->id.bustype = BUS_GAMEPORT;
0212 input_dev->id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
0213 input_dev->id.product = guillemot_type[i].id;
0214 input_dev->id.version = (int)data[14] << 8 | data[15];
0215 input_dev->dev.parent = &gameport->dev;
0216
0217 input_set_drvdata(input_dev, guillemot);
0218
0219 input_dev->open = guillemot_open;
0220 input_dev->close = guillemot_close;
0221
0222 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0223
0224 for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
0225 input_set_abs_params(input_dev, t, 0, 255, 0, 0);
0226
0227 if (guillemot->type->hat) {
0228 input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
0229 input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
0230 }
0231
0232 for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
0233 set_bit(t, input_dev->keybit);
0234
0235 err = input_register_device(guillemot->dev);
0236 if (err)
0237 goto fail2;
0238
0239 return 0;
0240
0241 fail2: gameport_close(gameport);
0242 fail1: gameport_set_drvdata(gameport, NULL);
0243 input_free_device(input_dev);
0244 kfree(guillemot);
0245 return err;
0246 }
0247
0248 static void guillemot_disconnect(struct gameport *gameport)
0249 {
0250 struct guillemot *guillemot = gameport_get_drvdata(gameport);
0251
0252 printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
0253 input_unregister_device(guillemot->dev);
0254 gameport_close(gameport);
0255 kfree(guillemot);
0256 }
0257
0258 static struct gameport_driver guillemot_drv = {
0259 .driver = {
0260 .name = "guillemot",
0261 },
0262 .description = DRIVER_DESC,
0263 .connect = guillemot_connect,
0264 .disconnect = guillemot_disconnect,
0265 };
0266
0267 module_gameport_driver(guillemot_drv);