1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 1999-2001 Vojtech Pavlik 4 */ 5 6 /* 7 * Logitech WingMan Warrior joystick driver for Linux 8 */ 9 10 /* 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 #include <linux/input.h> 17 #include <linux/serio.h> 18 19 #define DRIVER_DESC "Logitech WingMan Warrior joystick driver" 20 21 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 22 MODULE_DESCRIPTION(DRIVER_DESC); 23 MODULE_LICENSE("GPL"); 24 25 /* 26 * Constants. 27 */ 28 29 #define WARRIOR_MAX_LENGTH 16 30 static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 }; 31 32 /* 33 * Per-Warrior data. 34 */ 35 36 struct warrior { 37 struct input_dev *dev; 38 int idx, len; 39 unsigned char data[WARRIOR_MAX_LENGTH]; 40 char phys[32]; 41 }; 42 43 /* 44 * warrior_process_packet() decodes packets the driver receives from the 45 * Warrior. It updates the data accordingly. 46 */ 47 48 static void warrior_process_packet(struct warrior *warrior) 49 { 50 struct input_dev *dev = warrior->dev; 51 unsigned char *data = warrior->data; 52 53 if (!warrior->idx) return; 54 55 switch ((data[0] >> 4) & 7) { 56 case 1: /* Button data */ 57 input_report_key(dev, BTN_TRIGGER, data[3] & 1); 58 input_report_key(dev, BTN_THUMB, (data[3] >> 1) & 1); 59 input_report_key(dev, BTN_TOP, (data[3] >> 2) & 1); 60 input_report_key(dev, BTN_TOP2, (data[3] >> 3) & 1); 61 break; 62 case 3: /* XY-axis info->data */ 63 input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5))); 64 input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7)); 65 break; 66 case 5: /* Throttle, spinner, hat info->data */ 67 input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7)); 68 input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0)); 69 input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0)); 70 input_report_rel(dev, REL_DIAL, (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5)); 71 break; 72 } 73 input_sync(dev); 74 } 75 76 /* 77 * warrior_interrupt() is called by the low level driver when characters 78 * are ready for us. We then buffer them for further processing, or call the 79 * packet processing routine. 80 */ 81 82 static irqreturn_t warrior_interrupt(struct serio *serio, 83 unsigned char data, unsigned int flags) 84 { 85 struct warrior *warrior = serio_get_drvdata(serio); 86 87 if (data & 0x80) { 88 if (warrior->idx) warrior_process_packet(warrior); 89 warrior->idx = 0; 90 warrior->len = warrior_lengths[(data >> 4) & 7]; 91 } 92 93 if (warrior->idx < warrior->len) 94 warrior->data[warrior->idx++] = data; 95 96 if (warrior->idx == warrior->len) { 97 if (warrior->idx) warrior_process_packet(warrior); 98 warrior->idx = 0; 99 warrior->len = 0; 100 } 101 return IRQ_HANDLED; 102 } 103 104 /* 105 * warrior_disconnect() is the opposite of warrior_connect() 106 */ 107 108 static void warrior_disconnect(struct serio *serio) 109 { 110 struct warrior *warrior = serio_get_drvdata(serio); 111 112 serio_close(serio); 113 serio_set_drvdata(serio, NULL); 114 input_unregister_device(warrior->dev); 115 kfree(warrior); 116 } 117 118 /* 119 * warrior_connect() is the routine that is called when someone adds a 120 * new serio device. It looks for the Warrior, and if found, registers 121 * it as an input device. 122 */ 123 124 static int warrior_connect(struct serio *serio, struct serio_driver *drv) 125 { 126 struct warrior *warrior; 127 struct input_dev *input_dev; 128 int err = -ENOMEM; 129 130 warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL); 131 input_dev = input_allocate_device(); 132 if (!warrior || !input_dev) 133 goto fail1; 134 135 warrior->dev = input_dev; 136 snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys); 137 138 input_dev->name = "Logitech WingMan Warrior"; 139 input_dev->phys = warrior->phys; 140 input_dev->id.bustype = BUS_RS232; 141 input_dev->id.vendor = SERIO_WARRIOR; 142 input_dev->id.product = 0x0001; 143 input_dev->id.version = 0x0100; 144 input_dev->dev.parent = &serio->dev; 145 146 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) | 147 BIT_MASK(EV_ABS); 148 input_dev->keybit[BIT_WORD(BTN_TRIGGER)] = BIT_MASK(BTN_TRIGGER) | 149 BIT_MASK(BTN_THUMB) | BIT_MASK(BTN_TOP) | BIT_MASK(BTN_TOP2); 150 input_dev->relbit[0] = BIT_MASK(REL_DIAL); 151 input_set_abs_params(input_dev, ABS_X, -64, 64, 0, 8); 152 input_set_abs_params(input_dev, ABS_Y, -64, 64, 0, 8); 153 input_set_abs_params(input_dev, ABS_THROTTLE, -112, 112, 0, 0); 154 input_set_abs_params(input_dev, ABS_HAT0X, -1, 1, 0, 0); 155 input_set_abs_params(input_dev, ABS_HAT0Y, -1, 1, 0, 0); 156 157 serio_set_drvdata(serio, warrior); 158 159 err = serio_open(serio, drv); 160 if (err) 161 goto fail2; 162 163 err = input_register_device(warrior->dev); 164 if (err) 165 goto fail3; 166 167 return 0; 168 169 fail3: serio_close(serio); 170 fail2: serio_set_drvdata(serio, NULL); 171 fail1: input_free_device(input_dev); 172 kfree(warrior); 173 return err; 174 } 175 176 /* 177 * The serio driver structure. 178 */ 179 180 static const struct serio_device_id warrior_serio_ids[] = { 181 { 182 .type = SERIO_RS232, 183 .proto = SERIO_WARRIOR, 184 .id = SERIO_ANY, 185 .extra = SERIO_ANY, 186 }, 187 { 0 } 188 }; 189 190 MODULE_DEVICE_TABLE(serio, warrior_serio_ids); 191 192 static struct serio_driver warrior_drv = { 193 .driver = { 194 .name = "warrior", 195 }, 196 .description = DRIVER_DESC, 197 .id_table = warrior_serio_ids, 198 .interrupt = warrior_interrupt, 199 .connect = warrior_connect, 200 .disconnect = warrior_disconnect, 201 }; 202 203 module_serio_driver(warrior_drv); 204