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/input.h>
0017 #include <linux/serio.h>
0018
0019 #define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
0020
0021 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0022 MODULE_DESCRIPTION(DRIVER_DESC);
0023 MODULE_LICENSE("GPL");
0024
0025
0026
0027
0028
0029 #define WARRIOR_MAX_LENGTH 16
0030 static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
0031
0032
0033
0034
0035
0036 struct warrior {
0037 struct input_dev *dev;
0038 int idx, len;
0039 unsigned char data[WARRIOR_MAX_LENGTH];
0040 char phys[32];
0041 };
0042
0043
0044
0045
0046
0047
0048 static void warrior_process_packet(struct warrior *warrior)
0049 {
0050 struct input_dev *dev = warrior->dev;
0051 unsigned char *data = warrior->data;
0052
0053 if (!warrior->idx) return;
0054
0055 switch ((data[0] >> 4) & 7) {
0056 case 1:
0057 input_report_key(dev, BTN_TRIGGER, data[3] & 1);
0058 input_report_key(dev, BTN_THUMB, (data[3] >> 1) & 1);
0059 input_report_key(dev, BTN_TOP, (data[3] >> 2) & 1);
0060 input_report_key(dev, BTN_TOP2, (data[3] >> 3) & 1);
0061 break;
0062 case 3:
0063 input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)));
0064 input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
0065 break;
0066 case 5:
0067 input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
0068 input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0));
0069 input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0));
0070 input_report_rel(dev, REL_DIAL, (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5));
0071 break;
0072 }
0073 input_sync(dev);
0074 }
0075
0076
0077
0078
0079
0080
0081
0082 static irqreturn_t warrior_interrupt(struct serio *serio,
0083 unsigned char data, unsigned int flags)
0084 {
0085 struct warrior *warrior = serio_get_drvdata(serio);
0086
0087 if (data & 0x80) {
0088 if (warrior->idx) warrior_process_packet(warrior);
0089 warrior->idx = 0;
0090 warrior->len = warrior_lengths[(data >> 4) & 7];
0091 }
0092
0093 if (warrior->idx < warrior->len)
0094 warrior->data[warrior->idx++] = data;
0095
0096 if (warrior->idx == warrior->len) {
0097 if (warrior->idx) warrior_process_packet(warrior);
0098 warrior->idx = 0;
0099 warrior->len = 0;
0100 }
0101 return IRQ_HANDLED;
0102 }
0103
0104
0105
0106
0107
0108 static void warrior_disconnect(struct serio *serio)
0109 {
0110 struct warrior *warrior = serio_get_drvdata(serio);
0111
0112 serio_close(serio);
0113 serio_set_drvdata(serio, NULL);
0114 input_unregister_device(warrior->dev);
0115 kfree(warrior);
0116 }
0117
0118
0119
0120
0121
0122
0123
0124 static int warrior_connect(struct serio *serio, struct serio_driver *drv)
0125 {
0126 struct warrior *warrior;
0127 struct input_dev *input_dev;
0128 int err = -ENOMEM;
0129
0130 warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL);
0131 input_dev = input_allocate_device();
0132 if (!warrior || !input_dev)
0133 goto fail1;
0134
0135 warrior->dev = input_dev;
0136 snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys);
0137
0138 input_dev->name = "Logitech WingMan Warrior";
0139 input_dev->phys = warrior->phys;
0140 input_dev->id.bustype = BUS_RS232;
0141 input_dev->id.vendor = SERIO_WARRIOR;
0142 input_dev->id.product = 0x0001;
0143 input_dev->id.version = 0x0100;
0144 input_dev->dev.parent = &serio->dev;
0145
0146 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) |
0147 BIT_MASK(EV_ABS);
0148 input_dev->keybit[BIT_WORD(BTN_TRIGGER)] = BIT_MASK(BTN_TRIGGER) |
0149 BIT_MASK(BTN_THUMB) | BIT_MASK(BTN_TOP) | BIT_MASK(BTN_TOP2);
0150 input_dev->relbit[0] = BIT_MASK(REL_DIAL);
0151 input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8);
0152 input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8);
0153 input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0);
0154 input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0);
0155 input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0);
0156
0157 serio_set_drvdata(serio, warrior);
0158
0159 err = serio_open(serio, drv);
0160 if (err)
0161 goto fail2;
0162
0163 err = input_register_device(warrior->dev);
0164 if (err)
0165 goto fail3;
0166
0167 return 0;
0168
0169 fail3: serio_close(serio);
0170 fail2: serio_set_drvdata(serio, NULL);
0171 fail1: input_free_device(input_dev);
0172 kfree(warrior);
0173 return err;
0174 }
0175
0176
0177
0178
0179
0180 static const struct serio_device_id warrior_serio_ids[] = {
0181 {
0182 .type = SERIO_RS232,
0183 .proto = SERIO_WARRIOR,
0184 .id = SERIO_ANY,
0185 .extra = SERIO_ANY,
0186 },
0187 { 0 }
0188 };
0189
0190 MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
0191
0192 static struct serio_driver warrior_drv = {
0193 .driver = {
0194 .name = "warrior",
0195 },
0196 .description = DRIVER_DESC,
0197 .id_table = warrior_serio_ids,
0198 .interrupt = warrior_interrupt,
0199 .connect = warrior_connect,
0200 .disconnect = warrior_disconnect,
0201 };
0202
0203 module_serio_driver(warrior_drv);