This source file includes following definitions.
- push_event
- queue_empty
- get_from_queue
- push_char
- sun_mouse_inbyte
- sun_mouse_open
- sun_mouse_fasync
- sun_mouse_close
- sun_mouse_write
- sun_mouse_read
- sun_mouse_select
- sun_mouse_ioctl
- sun_mouse_init
- sun_mouse_zsinit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/fcntl.h>
40 #include <linux/signal.h>
41 #include <linux/timer.h>
42 #include <linux/errno.h>
43 #include <linux/miscdevice.h>
44 #include <linux/mm.h>
45 #include <asm/segment.h>
46 #include <asm/system.h>
47 #include <asm/vuid_event.h>
48 #include <linux/random.h>
49
50
51
52 #define STREAM_SIZE 2048
53 #define EV_SIZE (STREAM_SIZE/sizeof (Firm_event))
54 #define BUTTON_LEFT 4
55 #define BUTTON_MIDDLE 2
56 #define BUTTON_RIGHT 1
57
58 struct sun_mouse {
59 unsigned char transaction[5];
60 unsigned char byte;
61 unsigned char button_state;
62 unsigned char prev_state;
63 int delta_x;
64 int delta_y;
65 int present;
66 int ready;
67 int active;
68 int vuid_mode;
69 struct wait_queue *proc_list;
70 struct fasync_struct *fasync;
71
72
73 unsigned int head;
74 unsigned int tail;
75 union {
76 char stream [STREAM_SIZE];
77 Firm_event ev [0];
78 } queue;
79 };
80
81 static struct sun_mouse sunmouse;
82 #define gen_events (sunmouse.vuid_mode != VUID_NATIVE)
83 #define bstate sunmouse.button_state
84 #define pstate sunmouse.prev_state
85
86 extern void mouse_put_char(char ch);
87
88
89
90 static void
91 push_event (Firm_event *ev)
92 {
93 int next = (sunmouse.head + 1) % EV_SIZE;
94
95 if (next != sunmouse.tail){
96 sunmouse.queue.ev [sunmouse.head] = *ev;
97 sunmouse.head = next;
98 }
99 }
100
101 static int
102 queue_empty (void)
103 {
104 return sunmouse.head == sunmouse.tail;
105 }
106
107 static Firm_event *
108 get_from_queue (void)
109 {
110 Firm_event *result;
111
112 result = &sunmouse.queue.ev [sunmouse.tail];
113 sunmouse.tail = (sunmouse.tail + 1) % EV_SIZE;
114 return result;
115 }
116
117 static void
118 push_char (char c)
119 {
120 int next = (sunmouse.head + 1) % STREAM_SIZE;
121
122 if (next != sunmouse.tail){
123 sunmouse.queue.stream [sunmouse.head] = c;
124 sunmouse.head = next;
125 }
126 sunmouse.ready = 1;
127 if (sunmouse.fasync)
128 kill_fasync (sunmouse.fasync, SIGIO);
129 wake_up_interruptible (&sunmouse.proc_list);
130 }
131
132
133
134
135 void
136 sun_mouse_inbyte(unsigned char byte, unsigned char status)
137 {
138 signed char mvalue;
139 int d;
140 Firm_event ev;
141
142 add_mouse_randomness (byte);
143 if(!sunmouse.active)
144 return;
145
146 if (!gen_events){
147 push_char (byte);
148 return;
149 }
150
151
152
153
154
155
156
157 if(byte >= 0x80 && byte <= 0x87)
158 sunmouse.byte = 0;
159
160 mvalue = (signed char) byte;
161 switch(sunmouse.byte) {
162 case 0:
163
164 sunmouse.button_state = (~byte) & 0x7;
165 #ifdef SMOUSE_DEBUG
166 printk("B<Left %s, Middle %s, Right %s>",
167 ((sunmouse.button_state & 0x4) ? "DOWN" : "UP"),
168 ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"),
169 ((sunmouse.button_state & 0x1) ? "DOWN" : "UP"));
170 #endif
171 sunmouse.byte++;
172 return;
173 case 1:
174
175 #ifdef SMOUSE_DEBUG
176 printk("DX1<%d>", mvalue);
177 #endif
178 sunmouse.delta_x = mvalue;
179 sunmouse.byte++;
180 return;
181 case 2:
182
183 #ifdef SMOUSE_DEBUG
184 printk("DY1<%d>", mvalue);
185 #endif
186 sunmouse.delta_y = mvalue;
187 sunmouse.byte++;
188 return;
189 case 3:
190
191 #ifdef SMOUSE_DEBUG
192 printk("DX2<%d>", mvalue);
193 #endif
194 sunmouse.delta_x += mvalue;
195 sunmouse.byte++;
196 return;
197 case 4:
198
199 #ifdef SMOUSE_DEBUG
200 printk("DY2<%d>", mvalue);
201 #endif
202 sunmouse.delta_y += mvalue;
203 sunmouse.byte = 69;
204 break;
205 case 69:
206
207
208
209
210 return;
211 default:
212 printk("sunmouse: bogon transaction state\n");
213 sunmouse.byte = 69;
214 return;
215 };
216 d = bstate ^ pstate;
217 pstate = bstate;
218 if (d){
219 if (d & BUTTON_LEFT){
220 ev.id = MS_LEFT;
221 ev.value = bstate & BUTTON_LEFT;
222 }
223 if (d & BUTTON_RIGHT){
224 ev.id = MS_RIGHT;
225 ev.value = bstate & BUTTON_RIGHT;
226 }
227 if (d & BUTTON_MIDDLE){
228 ev.id = MS_MIDDLE;
229 ev.value = bstate & BUTTON_MIDDLE;
230 }
231 ev.time = xtime;
232 ev.value = ev.value ? VKEY_DOWN : VKEY_UP;
233 push_event (&ev);
234 }
235 if (sunmouse.delta_x){
236 ev.id = LOC_X_DELTA;
237 ev.time = xtime;
238 ev.value = sunmouse.delta_x;
239 push_event (&ev);
240 sunmouse.delta_x = 0;
241 }
242 if (sunmouse.delta_y){
243 ev.id = LOC_Y_DELTA;
244 ev.time = xtime;
245 ev.value = sunmouse.delta_y;
246 push_event (&ev);
247 }
248
249
250
251
252 sunmouse.ready = 1;
253 if (sunmouse.fasync)
254 kill_fasync (sunmouse.fasync, SIGIO);
255 wake_up_interruptible(&sunmouse.proc_list);
256 return;
257 }
258
259 static int
260 sun_mouse_open(struct inode * inode, struct file * file)
261 {
262 if(!sunmouse.present)
263 return -EINVAL;
264 if(sunmouse.active)
265 return -EBUSY;
266 sunmouse.active = 1;
267 sunmouse.ready = sunmouse.delta_x = sunmouse.delta_y = 0;
268 sunmouse.button_state = 0x80;
269 sunmouse.vuid_mode = VUID_NATIVE;
270 return 0;
271 }
272
273 static int
274 sun_mouse_fasync (struct inode *inode, struct file *filp, int on)
275 {
276 int retval;
277
278 retval = fasync_helper (inode, filp, on, &sunmouse.fasync);
279 if (retval < 0)
280 return retval;
281 return 0;
282 }
283
284 static void
285 sun_mouse_close(struct inode *inode, struct file *file)
286 {
287 sunmouse.active = sunmouse.ready = 0;
288 sun_mouse_fasync (inode, file, 0);
289 }
290
291 static int
292 sun_mouse_write(struct inode *inode, struct file *file, const char *buffer,
293 int count)
294 {
295 return -EINVAL;
296 }
297
298 static int
299 sun_mouse_read(struct inode *inode, struct file *file, char *buffer,
300 int count)
301 {
302 struct wait_queue wait = { current, NULL };
303
304 if (queue_empty ()){
305 if (file->f_flags & O_NONBLOCK)
306 return -EWOULDBLOCK;
307 add_wait_queue (&sunmouse.proc_list, &wait);
308 while (queue_empty () && !(current->signal & ~current->blocked)){
309 current->state = TASK_INTERRUPTIBLE;
310 schedule ();
311 }
312 current->state = TASK_RUNNING;
313 remove_wait_queue (&sunmouse.proc_list, &wait);
314 }
315 if (gen_events){
316 char *p = buffer, *end = buffer+count;
317
318 while (p < end && !queue_empty ()){
319 *(Firm_event *)p = *get_from_queue ();
320 p += sizeof (Firm_event);
321 }
322 sunmouse.ready = !queue_empty ();
323 inode->i_atime = CURRENT_TIME;
324 return p-buffer;
325 } else {
326 int c;
327
328 for (c = count; !queue_empty () && c; c--){
329 *buffer++ = sunmouse.queue.stream [sunmouse.tail];
330 sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
331 }
332 sunmouse.ready = !queue_empty ();
333 inode->i_atime = CURRENT_TIME;
334 return count-c;
335 }
336
337 if (current->signal & ~current->blocked)
338 return -ERESTARTSYS;
339 return 0;
340 }
341
342 static int
343 sun_mouse_select(struct inode *inode, struct file *file, int sel_type,
344 select_table *wait)
345 {
346 if(sel_type != SEL_IN)
347 return 0;
348 if(sunmouse.ready)
349 return 1;
350 select_wait(&sunmouse.proc_list, wait);
351 return 0;
352 }
353 int
354 sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
355 {
356 int i;
357
358 switch (cmd){
359
360 case _IOR('v', 2, int):
361 i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (int));
362 if (i) return i;
363 *(int *)arg = sunmouse.vuid_mode;
364 break;
365
366
367 case _IOW('v', 1, int):
368 i = verify_area (VERIFY_READ, (void *)arg, sizeof (int));
369 if (i) return i;
370 i = *(int *) arg;
371 if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){
372 sunmouse.vuid_mode = *(int *)arg;
373 sunmouse.head = sunmouse.tail = 0;
374 } else
375 return -EINVAL;
376 break;
377
378 default:
379 printk ("[MOUSE-ioctl: %8.8x]\n", cmd);
380 return -1;
381 }
382 return 0;
383 }
384
385 struct file_operations sun_mouse_fops = {
386 NULL,
387 sun_mouse_read,
388 sun_mouse_write,
389 NULL,
390 sun_mouse_select,
391 sun_mouse_ioctl,
392 NULL,
393 sun_mouse_open,
394 sun_mouse_close,
395 NULL,
396 sun_mouse_fasync,
397 };
398
399 static struct miscdevice sun_mouse_mouse = {
400 SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops
401 };
402
403 int
404 sun_mouse_init(void)
405 {
406 printk("Sun Mouse-Systems mouse driver version 1.00\n");
407 sunmouse.present = 1;
408 sunmouse.ready = sunmouse.active = 0;
409 misc_register (&sun_mouse_mouse);
410 sunmouse.delta_x = sunmouse.delta_y = 0;
411 sunmouse.button_state = 0x80;
412 sunmouse.proc_list = NULL;
413 return 0;
414 }
415
416 void
417 sun_mouse_zsinit(void)
418 {
419 sunmouse.ready = 1;
420 }