OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [joystick/] [spaceball.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * $Id: spaceball.c,v 1.1.1.1 2004-04-15 02:03:29 phoenix Exp $
3
 *
4
 *  Copyright (c) 1999-2000 Vojtech Pavlik
5
 *
6
 *  Based on the work of:
7
 *      David Thompson
8
 *      Joseph Krahn
9
 *
10
 *  Sponsored by SuSE
11
 */
12
 
13
/*
14
 * SpaceTec SpaceBall 4000 FLX driver for Linux
15
 */
16
 
17
/*
18
 * This program is free software; you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation; either version 2 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program; if not, write to the Free Software
30
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31
 *
32
 *  Should you need to contact me, the author, you can do so either by
33
 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
34
 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
35
 */
36
 
37
#include <linux/kernel.h>
38
#include <linux/slab.h>
39
#include <linux/module.h>
40
#include <linux/init.h>
41
#include <linux/input.h>
42
#include <linux/serio.h>
43
 
44
/*
45
 * Constants.
46
 */
47
 
48
#define JS_SBALL_MAX_LENGTH     128
49
static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
50
static char *spaceball_name = "SpaceTec SpaceBall 4000 FLX";
51
 
52
/*
53
 * Per-Ball data.
54
 */
55
 
56
struct spaceball {
57
        struct input_dev dev;
58
        struct serio *serio;
59
        int idx;
60
        int escape;
61
        unsigned char data[JS_SBALL_MAX_LENGTH];
62
};
63
 
64
/*
65
 * spaceball_process_packet() decodes packets the driver receives from the
66
 * SpaceBall.
67
 */
68
 
69
static void spaceball_process_packet(struct spaceball* spaceball)
70
{
71
        struct input_dev *dev = &spaceball->dev;
72
        unsigned char *data = spaceball->data;
73
        int i;
74
 
75
        if (spaceball->idx < 2) return;
76
 
77
        printk("%c %d\n", spaceball->data[0], spaceball->idx);
78
 
79
        switch (spaceball->data[0]) {
80
 
81
                case '@':                                       /* Reset packet */
82
                        spaceball->data[spaceball->idx - 1] = 0;
83
                        for (i = 1; i < spaceball->idx && spaceball->data[i] == ' '; i++);
84
                        printk(KERN_INFO "input%d: %s [%s] on serio%d\n",
85
                                spaceball->dev.number, spaceball_name, spaceball->data + i, spaceball->serio->number);
86
                        break;
87
 
88
                case 'D':                                       /* Ball data */
89
                        if (spaceball->idx != 15) return;
90
                        for (i = 0; i < 6; i++) {
91
                                input_report_abs(dev, spaceball_axes[i],
92
                                        (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
93
                        }
94
                        break;
95
 
96
                case '.':                               /* Button data, part2 */
97
                        if (spaceball->idx != 3) return;
98
                        input_report_key(dev, BTN_0,  data[2] & 1);
99
                        input_report_key(dev, BTN_1, data[2] & 2);
100
                        break;
101
 
102
                case '?':                               /* Error packet */
103
                        spaceball->data[spaceball->idx - 1] = 0;
104
                        printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
105
                        break;
106
        }
107
}
108
 
109
/*
110
 * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
111
 * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
112
 * can occur in the axis values.
113
 */
114
 
115
static void spaceball_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
116
{
117
        struct spaceball *spaceball = serio->private;
118
 
119
        switch (data) {
120
                case 0xd:
121
                        spaceball_process_packet(spaceball);
122
                        spaceball->idx = 0;
123
                        spaceball->escape = 0;
124
                        return;
125
                case '^':
126
                        if (!spaceball->escape) {
127
                                spaceball->escape = 1;
128
                                return;
129
                        }
130
                        spaceball->escape = 0;
131
                case 'M':
132
                case 'Q':
133
                case 'S':
134
                        if (spaceball->escape) {
135
                                spaceball->escape = 0;
136
                                data &= 0x1f;
137
                        }
138
                default:
139
                        if (spaceball->escape) {
140
                                spaceball->escape = 0;
141
                                printk(KERN_WARNING "spaceball.c: Unknown escaped character: %#x (%c)\n", data, data);
142
                        }
143
                        if (spaceball->idx < JS_SBALL_MAX_LENGTH)
144
                                spaceball->data[spaceball->idx++] = data;
145
                        return;
146
        }
147
}
148
 
149
/*
150
 * spaceball_disconnect() is the opposite of spaceball_connect()
151
 */
152
 
153
static void spaceball_disconnect(struct serio *serio)
154
{
155
        struct spaceball* spaceball = serio->private;
156
        input_unregister_device(&spaceball->dev);
157
        serio_close(serio);
158
        kfree(spaceball);
159
}
160
 
161
/*
162
 * spaceball_connect() is the routine that is called when someone adds a
163
 * new serio device. It looks for the Magellan, and if found, registers
164
 * it as an input device.
165
 */
166
 
167
static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
168
{
169
        struct spaceball *spaceball;
170
        int i, t;
171
 
172
        if (serio->type != (SERIO_RS232 | SERIO_SPACEBALL))
173
                return;
174
 
175
        if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
176
                return;
177
        memset(spaceball, 0, sizeof(struct spaceball));
178
 
179
        spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
180
        spaceball->dev.keybit[LONG(BTN_0)] = BIT(BTN_0) | BIT(BTN_1);
181
 
182
        for (i = 0; i < 6; i++) {
183
                t = spaceball_axes[i];
184
                set_bit(t, spaceball->dev.absbit);
185
                spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
186
                spaceball->dev.absmax[t] = i < 3 ?  8000 :  1600;
187
                spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
188
                spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
189
        }
190
 
191
        spaceball->serio = serio;
192
        spaceball->dev.private = spaceball;
193
 
194
        spaceball->dev.name = spaceball_name;
195
        spaceball->dev.idbus = BUS_RS232;
196
        spaceball->dev.idvendor = SERIO_SPACEBALL;
197
        spaceball->dev.idproduct = 0x0001;
198
        spaceball->dev.idversion = 0x0100;
199
 
200
        serio->private = spaceball;
201
 
202
        if (serio_open(serio, dev)) {
203
                kfree(spaceball);
204
                return;
205
        }
206
 
207
        input_register_device(&spaceball->dev);
208
}
209
 
210
/*
211
 * The serio device structure.
212
 */
213
 
214
static struct serio_dev spaceball_dev = {
215
        interrupt:      spaceball_interrupt,
216
        connect:        spaceball_connect,
217
        disconnect:     spaceball_disconnect,
218
};
219
 
220
/*
221
 * The functions for inserting/removing us as a module.
222
 */
223
 
224
int __init spaceball_init(void)
225
{
226
        serio_register_device(&spaceball_dev);
227
        return 0;
228
}
229
 
230
void __exit spaceball_exit(void)
231
{
232
        serio_unregister_device(&spaceball_dev);
233
}
234
 
235
module_init(spaceball_init);
236
module_exit(spaceball_exit);
237
 
238
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.