File: /usr/src/linux/drivers/char/joystick/stinger.c

1     /*
2      * $Id: stinger.c,v 1.4 2001/05/23 09:25:02 vojtech Exp $
3      *
4      *  Copyright (c) 2000-2001 Vojtech Pavlik
5      *  Copyright (c) 2000 Mark Fletcher
6      *
7      *  Sponsored by SuSE
8      */
9     
10     /*
11      * Gravis Stinger gamepad driver for Linux
12      */
13     
14     /*
15      * This program is free warftware; you can redistribute it and/or modify
16      * it under the terms of the GNU General Public License as published by
17      * the Free Software Foundation; either version 2 of the License, or
18      * (at your option) any later version.
19      *
20      * This program is distributed in the hope that it will be useful,
21      * but WITHOUT ANY WARRANTY; without even the implied warranty of
22      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23      * GNU General Public License for more details.
24      *
25      * You should have received a copy of the GNU General Public License
26      * along with this program; if not, write to the Free Software
27      * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28      *
29      *  Should you need to contact me, the author, you can do so either by
30      * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31      * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
32      */
33     
34     #include <linux/kernel.h>
35     #include <linux/module.h>
36     #include <linux/slab.h>
37     #include <linux/input.h>
38     #include <linux/serio.h>
39     #include <linux/init.h>
40     
41     /*
42      * Constants.
43      */
44     
45     #define STINGER_MAX_LENGTH 8
46     
47     static char *stinger_name = "Gravis Stinger";
48     
49     /*
50      * Per-Stinger data.
51      */
52     
53     struct stinger {
54     	struct input_dev dev;
55     	int idx;
56     	unsigned char data[STINGER_MAX_LENGTH];
57     };
58     
59     /*
60      * stinger_process_packet() decodes packets the driver receives from the
61      * Stinger. It updates the data accordingly.
62      */
63     
64     static void stinger_process_packet(struct stinger *stinger)
65     {
66     	struct input_dev *dev = &stinger->dev;
67     	unsigned char *data = stinger->data;
68     
69     	if (!stinger->idx) return;
70     
71     	input_report_key(dev, BTN_A,	  ((data[0] & 0x20) >> 5));
72     	input_report_key(dev, BTN_B,	  ((data[0] & 0x10) >> 4));
73     	input_report_key(dev, BTN_C,	  ((data[0] & 0x08) >> 3));
74     	input_report_key(dev, BTN_X,	  ((data[0] & 0x04) >> 2));
75     	input_report_key(dev, BTN_Y,	  ((data[3] & 0x20) >> 5));
76     	input_report_key(dev, BTN_Z,	  ((data[3] & 0x10) >> 4));
77     	input_report_key(dev, BTN_TL,     ((data[3] & 0x08) >> 3));
78     	input_report_key(dev, BTN_TR,     ((data[3] & 0x04) >> 2));
79     	input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1));
80     	input_report_key(dev, BTN_START,   (data[3] & 0x01));
81     
82     	input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6));
83     	input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F));
84     
85     	return;
86     }
87     
88     /*
89      * stinger_interrupt() is called by the low level driver when characters
90      * are ready for us. We then buffer them for further processing, or call the
91      * packet processing routine.
92      */
93     
94     static void stinger_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
95     {
96     	struct stinger* stinger = serio->private;
97     
98     	/* All Stinger packets are 4 bytes */
99     
100     	if (stinger->idx < STINGER_MAX_LENGTH)
101     		stinger->data[stinger->idx++] = data;
102     
103     	if (stinger->idx == 4) {
104     		stinger_process_packet(stinger);
105     		stinger->idx = 0;
106     	}
107     
108     	return;
109     }
110     
111     /*
112      * stinger_disconnect() is the opposite of stinger_connect()
113      */
114     
115     static void stinger_disconnect(struct serio *serio)
116     {
117     	struct stinger* stinger = serio->private;
118     	input_unregister_device(&stinger->dev);
119     	serio_close(serio);
120     	kfree(stinger);
121     }
122     
123     /*
124      * stinger_connect() is the routine that is called when someone adds a
125      * new serio device. It looks for the Stinger, and if found, registers
126      * it as an input device.
127      */
128     
129     static void stinger_connect(struct serio *serio, struct serio_dev *dev)
130     {
131     	struct stinger *stinger;
132     	int i;
133     
134     	if (serio->type != (SERIO_RS232 | SERIO_STINGER))
135     		return;
136     
137     	if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
138     		return;
139     
140     	memset(stinger, 0, sizeof(struct stinger));
141     
142     	stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);	
143     	stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | 
144     					   BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | 
145     					   BIT(BTN_START) | BIT(BTN_SELECT);
146     	stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
147     
148     	stinger->dev.name = stinger_name;
149     	stinger->dev.idbus = BUS_RS232;
150     	stinger->dev.idvendor = SERIO_STINGER;
151     	stinger->dev.idproduct = 0x0001;
152     	stinger->dev.idversion = 0x0100;
153     
154     	for (i = 0; i < 2; i++) {
155     		stinger->dev.absmax[ABS_X+i] =  64;	
156     		stinger->dev.absmin[ABS_X+i] = -64;	
157     		stinger->dev.absflat[ABS_X+i] = 4;
158     	}
159     
160     	stinger->dev.private = stinger;
161     	
162     	serio->private = stinger;
163     
164     	if (serio_open(serio, dev)) {
165     		kfree(stinger);
166     		return;
167     	}
168     
169     	input_register_device(&stinger->dev);
170     
171     	printk(KERN_INFO "input%d: %s on serio%d\n", stinger->dev.number, stinger_name, serio->number);
172     }
173     
174     /*
175      * The serio device structure.
176      */
177     
178     static struct serio_dev stinger_dev = {
179     	interrupt:	stinger_interrupt,
180     	connect:	stinger_connect,
181     	disconnect:	stinger_disconnect,
182     };
183     
184     /*
185      * The functions for inserting/removing us as a module.
186      */
187     
188     int __init stinger_init(void)
189     {
190     	serio_register_device(&stinger_dev);
191     	return 0;
192     }
193     
194     void __exit stinger_exit(void)
195     {
196     	serio_unregister_device(&stinger_dev);
197     }
198     
199     module_init(stinger_init);
200     module_exit(stinger_exit);
201     
202     MODULE_LICENSE("GPL");
203