2 * joy-spaceorb.c Version 0.1
4 * Copyright (c) 1998 David Thompson
5 * Copyright (c) 1999 Vojtech Pavlik
11 * This is a module for the Linux joystick driver, supporting
12 * the SpaceTec SpaceOrb 360 and SpaceBall Avenger 6dof controllers.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * Should you need to contact me, the author, you can do so either by
31 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
32 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
36 #include <asm/system.h>
37 #include <linux/errno.h>
38 #include <linux/joystick.h>
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/tty.h>
42 #include <linux/init.h>
48 #define N_JOYSTICK_ORB 15
49 #define JS_ORB_MAX_LENGTH 64
55 static struct js_port
* js_orb_port
= NULL
;
62 struct tty_struct
* tty
;
65 unsigned char data
[JS_ORB_MAX_LENGTH
];
70 static unsigned char js_orb_xor
[] = "SpaceWare";
72 static unsigned char *js_orb_errors
[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
73 "Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" };
76 * js_orb_process_packet() decodes packets the driver receives from the
80 static void js_orb_process_packet(struct js_orb_info
* info
)
83 int **axes
= info
->port
->axes
;
84 int **buttons
= info
->port
->buttons
;
85 unsigned char *data
= info
->data
;
88 if (info
->idx
< 2) return;
89 for (i
= 0; i
< info
->idx
; i
++) c
^= data
[i
];
92 switch (info
->data
[0]) {
94 case 'R': /* Reset packet */
95 info
->data
[info
->idx
- 1] = 0;
96 for (i
= 1; i
< info
->idx
&& info
->data
[i
] == ' '; i
++);
97 printk(KERN_INFO
"js%d: SpaceOrb 360 [%s] on %s%d\n",
98 info
->js
, info
->data
+ i
, info
->tty
->driver
.name
,
99 MINOR(info
->tty
->device
) - info
->tty
->driver
.minor_start
);
102 case 'D': /* Ball + button data */
103 if (info
->idx
!= 12) return;
104 if (!info
->port
->devs
[0]) return;
105 for (i
= 0; i
< 9; i
++) info
->data
[i
+2] ^= js_orb_xor
[i
];
106 axes
[0][0] = ( data
[2] << 3) | (data
[ 3] >> 4);
107 axes
[0][1] = ((data
[3] & 0x0f) << 6) | (data
[ 4] >> 1);
108 axes
[0][2] = ((data
[4] & 0x01) << 9) | (data
[ 5] << 2) | (data
[4] >> 5);
109 axes
[0][3] = ((data
[6] & 0x1f) << 5) | (data
[ 7] >> 2);
110 axes
[0][4] = ((data
[7] & 0x03) << 8) | (data
[ 8] << 1) | (data
[7] >> 6);
111 axes
[0][5] = ((data
[9] & 0x3f) << 4) | (data
[10] >> 3);
112 for(i
= 0; i
< 6; i
++) if (axes
[0][i
] & 0x200) axes
[0][i
] -= 1024;
113 buttons
[0][0] = data
[1];
116 case 'K': /* Button data */
117 if (info
->idx
!= 5) return;
118 if (!info
->port
->devs
[0]) return;
119 buttons
[0][0] = data
[2];
122 case 'E': /* Error packet */
123 if (info
->idx
!= 4) return;
124 printk(KERN_ERR
"joy-spaceorb: Device error. [ ");
125 for (i
= 0; i
< 7; i
++)
126 if (data
[1] & (1 << i
))
127 printk("%s ", js_orb_errors
[i
]);
131 case 'N': /* Null region */
132 if (info
->idx
!= 3) return;
135 case 'P': /* Pulse (update) speed */
136 if (info
->idx
!= 4) return;
140 printk("joy-spaceorb: Unknown packet %d length %d:", data
[0], info
->idx
);
141 for (i
= 0; i
< info
->idx
; i
++) printk(" %02x", data
[i
]);
148 * js_orb_open() is a callback from the joystick device open routine.
151 static int js_orb_open(struct js_dev
*jd
)
153 struct js_orb_info
*info
= jd
->port
->info
;
159 * js_orb_close() is a callback from the joystick device release routine.
162 static int js_orb_close(struct js_dev
*jd
)
164 struct js_orb_info
*info
= jd
->port
->info
;
166 js_unregister_device(jd
->port
->devs
[0]);
167 js_orb_port
= js_unregister_port(jd
->port
);
173 * js_orb_init_corr() initializes the correction values for the SpaceOrb.
176 static void __init
js_orb_init_corr(struct js_corr
**corr
)
180 for (j
= 0; j
< 6; j
++) {
181 corr
[0][j
].type
= JS_CORR_BROKEN
;
183 corr
[0][j
].coef
[0] = 0 ;
184 corr
[0][j
].coef
[1] = 0 ;
185 corr
[0][j
].coef
[2] = (1 << 29) / 511;
186 corr
[0][j
].coef
[3] = (1 << 29) / 511;
191 * js_orb_ldisc_open() is the routine that is called upon setting our line
192 * discipline on a tty.
195 static int js_orb_ldisc_open(struct tty_struct
*tty
)
197 struct js_orb_info iniinfo
;
198 struct js_orb_info
*info
= &iniinfo
;
206 js_orb_port
= js_register_port(js_orb_port
, info
, 1, sizeof(struct js_orb_info
), NULL
);
208 info
= js_orb_port
->info
;
209 info
->port
= js_orb_port
;
210 tty
->disc_data
= info
;
212 info
->js
= js_register_device(js_orb_port
, 0, 6, 7, "SpaceOrb 360", THIS_MODULE
, js_orb_open
, js_orb_close
);
214 js_orb_init_corr(js_orb_port
->corr
);
220 * js_orb_ldisc_close() is the opposite of js_orb_ldisc_open()
223 static void js_orb_ldisc_close(struct tty_struct
*tty
)
225 struct js_orb_info
* info
= (struct js_orb_info
*) tty
->disc_data
;
227 js_unregister_device(info
->port
->devs
[0]);
228 js_orb_port
= js_unregister_port(info
->port
);
234 * js_orb_ldisc_receive() is called by the low level driver when characters
235 * are ready for us. We then buffer them for further processing, or call the
236 * packet processing routine.
239 static void js_orb_ldisc_receive(struct tty_struct
*tty
, const unsigned char *cp
, char *fp
, int count
)
241 struct js_orb_info
* info
= (struct js_orb_info
*) tty
->disc_data
;
244 for (i
= 0; i
< count
; i
++) {
246 if (info
->idx
) js_orb_process_packet(info
);
249 if (info
->idx
< JS_ORB_MAX_LENGTH
)
250 info
->data
[info
->idx
++] = cp
[i
] & 0x7f;
255 * js_orb_ldisc_room() reports how much room we do have for receiving data.
256 * Although we in fact have infinite room, we need to specify some value
257 * here, so why not the size of our packet buffer. It's big anyway.
260 static int js_orb_ldisc_room(struct tty_struct
*tty
)
262 return JS_ORB_MAX_LENGTH
;
266 * The line discipline structure.
269 static struct tty_ldisc js_orb_ldisc
= {
270 magic
: TTY_LDISC_MAGIC
,
272 open
: js_orb_ldisc_open
,
273 close
: js_orb_ldisc_close
,
274 receive_buf
: js_orb_ldisc_receive
,
275 receive_room
: js_orb_ldisc_room
,
279 * The functions for inserting/removing us as a module.
283 int init_module(void)
285 int __init
js_orb_init(void)
288 if (tty_register_ldisc(N_JOYSTICK_ORB
, &js_orb_ldisc
)) {
289 printk(KERN_ERR
"joy-spaceorb: Error registering line discipline.\n");
297 void cleanup_module(void)
299 tty_register_ldisc(N_JOYSTICK_ORB
, NULL
);