Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 1999-2001 Vojtech Pavlik
0004  *
0005  *  Based on the work of:
0006  *  David Thompson
0007  *  Joseph Krahn
0008  */
0009 
0010 /*
0011  * SpaceTec SpaceBall 2003/3003/4000 FLX driver for Linux
0012  */
0013 
0014 /*
0015  */
0016 
0017 #include <linux/kernel.h>
0018 #include <linux/slab.h>
0019 #include <linux/module.h>
0020 #include <linux/input.h>
0021 #include <linux/serio.h>
0022 #include <asm/unaligned.h>
0023 
0024 #define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
0025 
0026 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0027 MODULE_DESCRIPTION(DRIVER_DESC);
0028 MODULE_LICENSE("GPL");
0029 
0030 /*
0031  * Constants.
0032  */
0033 
0034 #define SPACEBALL_MAX_LENGTH    128
0035 #define SPACEBALL_MAX_ID    9
0036 
0037 #define SPACEBALL_1003      1
0038 #define SPACEBALL_2003B     3
0039 #define SPACEBALL_2003C     4
0040 #define SPACEBALL_3003C     7
0041 #define SPACEBALL_4000FLX   8
0042 #define SPACEBALL_4000FLX_L 9
0043 
0044 static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
0045 static char *spaceball_names[] = {
0046     "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B",
0047     "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController",
0048     "SpaceTec SpaceBall 3003C", "SpaceTec SpaceBall 4000FLX", "SpaceTec SpaceBall 4000FLX Lefty" };
0049 
0050 /*
0051  * Per-Ball data.
0052  */
0053 
0054 struct spaceball {
0055     struct input_dev *dev;
0056     int idx;
0057     int escape;
0058     unsigned char data[SPACEBALL_MAX_LENGTH];
0059     char phys[32];
0060 };
0061 
0062 /*
0063  * spaceball_process_packet() decodes packets the driver receives from the
0064  * SpaceBall.
0065  */
0066 
0067 static void spaceball_process_packet(struct spaceball* spaceball)
0068 {
0069     struct input_dev *dev = spaceball->dev;
0070     unsigned char *data = spaceball->data;
0071     int i;
0072 
0073     if (spaceball->idx < 2) return;
0074 
0075     switch (spaceball->data[0]) {
0076 
0077         case 'D':                   /* Ball data */
0078             if (spaceball->idx != 15) return;
0079             /*
0080              * Skip first three bytes; read six axes worth of data.
0081              * Axis values are signed 16-bit big-endian.
0082              */
0083             data += 3;
0084             for (i = 0; i < ARRAY_SIZE(spaceball_axes); i++) {
0085                 input_report_abs(dev, spaceball_axes[i],
0086                     (__s16)get_unaligned_be16(&data[i * 2]));
0087             }
0088             break;
0089 
0090         case 'K':                   /* Button data */
0091             if (spaceball->idx != 3) return;
0092             input_report_key(dev, BTN_1, (data[2] & 0x01) || (data[2] & 0x20));
0093             input_report_key(dev, BTN_2, data[2] & 0x02);
0094             input_report_key(dev, BTN_3, data[2] & 0x04);
0095             input_report_key(dev, BTN_4, data[2] & 0x08);
0096             input_report_key(dev, BTN_5, data[1] & 0x01);
0097             input_report_key(dev, BTN_6, data[1] & 0x02);
0098             input_report_key(dev, BTN_7, data[1] & 0x04);
0099             input_report_key(dev, BTN_8, data[1] & 0x10);
0100             break;
0101 
0102         case '.':                   /* Advanced button data */
0103             if (spaceball->idx != 3) return;
0104             input_report_key(dev, BTN_1, data[2] & 0x01);
0105             input_report_key(dev, BTN_2, data[2] & 0x02);
0106             input_report_key(dev, BTN_3, data[2] & 0x04);
0107             input_report_key(dev, BTN_4, data[2] & 0x08);
0108             input_report_key(dev, BTN_5, data[2] & 0x10);
0109             input_report_key(dev, BTN_6, data[2] & 0x20);
0110             input_report_key(dev, BTN_7, data[2] & 0x80);
0111             input_report_key(dev, BTN_8, data[1] & 0x01);
0112             input_report_key(dev, BTN_9, data[1] & 0x02);
0113             input_report_key(dev, BTN_A, data[1] & 0x04);
0114             input_report_key(dev, BTN_B, data[1] & 0x08);
0115             input_report_key(dev, BTN_C, data[1] & 0x10);
0116             input_report_key(dev, BTN_MODE, data[1] & 0x20);
0117             break;
0118 
0119         case 'E':                   /* Device error */
0120             spaceball->data[spaceball->idx - 1] = 0;
0121             printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
0122             break;
0123 
0124         case '?':                   /* Bad command packet */
0125             spaceball->data[spaceball->idx - 1] = 0;
0126             printk(KERN_ERR "spaceball: Bad command. [%s]\n", spaceball->data + 1);
0127             break;
0128     }
0129 
0130     input_sync(dev);
0131 }
0132 
0133 /*
0134  * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
0135  * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
0136  * can occur in the axis values.
0137  */
0138 
0139 static irqreturn_t spaceball_interrupt(struct serio *serio,
0140         unsigned char data, unsigned int flags)
0141 {
0142     struct spaceball *spaceball = serio_get_drvdata(serio);
0143 
0144     switch (data) {
0145         case 0xd:
0146             spaceball_process_packet(spaceball);
0147             spaceball->idx = 0;
0148             spaceball->escape = 0;
0149             break;
0150         case '^':
0151             if (!spaceball->escape) {
0152                 spaceball->escape = 1;
0153                 break;
0154             }
0155             spaceball->escape = 0;
0156             fallthrough;
0157         case 'M':
0158         case 'Q':
0159         case 'S':
0160             if (spaceball->escape) {
0161                 spaceball->escape = 0;
0162                 data &= 0x1f;
0163             }
0164             fallthrough;
0165         default:
0166             if (spaceball->escape)
0167                 spaceball->escape = 0;
0168             if (spaceball->idx < SPACEBALL_MAX_LENGTH)
0169                 spaceball->data[spaceball->idx++] = data;
0170             break;
0171     }
0172     return IRQ_HANDLED;
0173 }
0174 
0175 /*
0176  * spaceball_disconnect() is the opposite of spaceball_connect()
0177  */
0178 
0179 static void spaceball_disconnect(struct serio *serio)
0180 {
0181     struct spaceball* spaceball = serio_get_drvdata(serio);
0182 
0183     serio_close(serio);
0184     serio_set_drvdata(serio, NULL);
0185     input_unregister_device(spaceball->dev);
0186     kfree(spaceball);
0187 }
0188 
0189 /*
0190  * spaceball_connect() is the routine that is called when someone adds a
0191  * new serio device that supports Spaceball protocol and registers it as
0192  * an input device.
0193  */
0194 
0195 static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
0196 {
0197     struct spaceball *spaceball;
0198     struct input_dev *input_dev;
0199     int err = -ENOMEM;
0200     int i, id;
0201 
0202     if ((id = serio->id.id) > SPACEBALL_MAX_ID)
0203         return -ENODEV;
0204 
0205     spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL);
0206     input_dev = input_allocate_device();
0207     if (!spaceball || !input_dev)
0208         goto fail1;
0209 
0210     spaceball->dev = input_dev;
0211     snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys);
0212 
0213     input_dev->name = spaceball_names[id];
0214     input_dev->phys = spaceball->phys;
0215     input_dev->id.bustype = BUS_RS232;
0216     input_dev->id.vendor = SERIO_SPACEBALL;
0217     input_dev->id.product = id;
0218     input_dev->id.version = 0x0100;
0219     input_dev->dev.parent = &serio->dev;
0220 
0221     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0222 
0223     switch (id) {
0224         case SPACEBALL_4000FLX:
0225         case SPACEBALL_4000FLX_L:
0226             input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_9);
0227             input_dev->keybit[BIT_WORD(BTN_A)] |= BIT_MASK(BTN_A) |
0228                 BIT_MASK(BTN_B) | BIT_MASK(BTN_C) |
0229                 BIT_MASK(BTN_MODE);
0230             fallthrough;
0231         default:
0232             input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_2) |
0233                 BIT_MASK(BTN_3) | BIT_MASK(BTN_4) |
0234                 BIT_MASK(BTN_5) | BIT_MASK(BTN_6) |
0235                 BIT_MASK(BTN_7) | BIT_MASK(BTN_8);
0236             fallthrough;
0237         case SPACEBALL_3003C:
0238             input_dev->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_1) |
0239                 BIT_MASK(BTN_8);
0240     }
0241 
0242     for (i = 0; i < 3; i++) {
0243         input_set_abs_params(input_dev, ABS_X + i, -8000, 8000, 8, 40);
0244         input_set_abs_params(input_dev, ABS_RX + i, -1600, 1600, 2, 8);
0245     }
0246 
0247     serio_set_drvdata(serio, spaceball);
0248 
0249     err = serio_open(serio, drv);
0250     if (err)
0251         goto fail2;
0252 
0253     err = input_register_device(spaceball->dev);
0254     if (err)
0255         goto fail3;
0256 
0257     return 0;
0258 
0259  fail3: serio_close(serio);
0260  fail2: serio_set_drvdata(serio, NULL);
0261  fail1: input_free_device(input_dev);
0262     kfree(spaceball);
0263     return err;
0264 }
0265 
0266 /*
0267  * The serio driver structure.
0268  */
0269 
0270 static const struct serio_device_id spaceball_serio_ids[] = {
0271     {
0272         .type   = SERIO_RS232,
0273         .proto  = SERIO_SPACEBALL,
0274         .id = SERIO_ANY,
0275         .extra  = SERIO_ANY,
0276     },
0277     { 0 }
0278 };
0279 
0280 MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
0281 
0282 static struct serio_driver spaceball_drv = {
0283     .driver     = {
0284         .name   = "spaceball",
0285     },
0286     .description    = DRIVER_DESC,
0287     .id_table   = spaceball_serio_ids,
0288     .interrupt  = spaceball_interrupt,
0289     .connect    = spaceball_connect,
0290     .disconnect = spaceball_disconnect,
0291 };
0292 
0293 module_serio_driver(spaceball_drv);