Subversion Repositories shark

Rev

Rev 523 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
519 mauro 1
/*
538 mauro 2
 *  Input driver mouse module
519 mauro 3
 */
4
 
5
/*
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 */
16
 
17
#include <linuxcomp.h>
18
 
19
#include <linux/slab.h>
20
#include <linux/module.h>
21
#include <linux/input.h>
22
#include <linux/init.h>
23
#include <linux/device.h>
24
 
523 mauro 25
//#define DEBUG_MOUSE
519 mauro 26
 
27
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
538 mauro 28
MODULE_DESCRIPTION("Input driver mouse module");
519 mauro 29
MODULE_LICENSE("GPL");
30
 
523 mauro 31
extern void shark_mouse_exec(void);
519 mauro 32
 
33
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
34
#define CONFIG_INPUT_MOUSEDEV_SCREEN_X  1024
35
#endif
36
#ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_Y
37
#define CONFIG_INPUT_MOUSEDEV_SCREEN_Y  768
38
#endif
39
 
40
static int xres = CONFIG_INPUT_MOUSEDEV_SCREEN_X;
41
static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
42
 
43
/* Buffer Ssize */
44
#define MOUSE_BUFFERSIZE 256
45
 
46
/* Buffer Mask ( i=(i+1)&MASK is better than i=(i+1)%SIZE ) */
47
#define MOUSE_BUFFERMASK 0xff
48
 
49
/* Circular Buffer */
50
static struct mouse_event {
51
        unsigned long buttons;
52
        int dx, dy, dz;
53
} mbuffer[MOUSE_BUFFERSIZE];
54
 
55
/*
56
 * Buffer Pointers
57
 * data is inserted to mhead
58
 * data is kept from mtail+1
59
 * (mhead point to mtail+1 when buffer is empty)
60
 */
61
static unsigned mtail, mhead;
62
 
63
static char mouse_name[] = "mouse";
64
 
65
struct mouse_list {
66
        int dx, dy, dz, oldx, oldy;
67
        signed char ps2[6];
68
        unsigned long buttons;
69
        /*unsigned char ready, buffer, bufsiz;
70
        unsigned char mode, imexseq, impsseq;*/
71
        int finger;
72
};
73
 
74
static struct mouse_list m_list;
75
static struct mouse_list *list = &m_list;
76
 
77
/*
78
 * Get data from the mouse
79
 *
80
 * it's follow the port_receive() semantic
81
 */
82
int mouse_get(int *dx, int *dy, int *dz, unsigned long *buttons)
83
{
84
        if ( ((mtail+1) & MOUSE_BUFFERMASK) == ((mhead) & MOUSE_BUFFERMASK) )
85
                return -1;
86
 
87
        mtail = (mtail+1) & MOUSE_BUFFERMASK;
88
 
89
        *dx      = mbuffer[mtail].dx;
90
        *dy      = mbuffer[mtail].dy;
523 mauro 91
        *dz      = mbuffer[mtail].dz;
519 mauro 92
        *buttons = mbuffer[mtail].buttons;
93
 
523 mauro 94
#ifdef DEBUG_MOUSE
95
        printk(KERN_DEBUG "mouse.c: ( %3d %3d %3d - %6x)\n", mbuffer[mtail].dx, mbuffer[mtail].dy, mbuffer[mtail].dz, (int)mbuffer[mtail].buttons);
96
        printk(KERN_DEBUG "mouse.c: ( %3d %3d %3d - %6x)\n", *dx, *dy, *dz, *(int *)buttons);
97
#endif
519 mauro 98
        return 0;
99
}
100
 
101
static void mouse_abs_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
102
{
103
        int size;
104
 
105
        /* Ignore joysticks */
106
        if (test_bit(BTN_TRIGGER, handle->dev->keybit))
107
                return;
108
 
109
        /* Handle touchpad data */
110
        if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
111
 
112
                if (list->finger && list->finger < 3)
113
                        list->finger++;
114
 
115
                switch (code) {
116
                        case ABS_X:
117
                                if (list->finger == 3)
118
                                        list->dx += (value - list->oldx) / 8;
119
                                list->oldx = value;
120
                                return;
121
                        case ABS_Y:
122
                                if (list->finger == 3)
123
                                        list->dy -= (value - list->oldy) / 8;
124
                                list->oldy = value;
125
                                return;
126
                }
127
                return;
128
        }
129
 
130
        /* Handle tablet data */
131
        switch (code) {
132
                case ABS_X:
133
                        size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
134
                        if (size == 0) size = xres;
135
                        list->dx += (value * xres - list->oldx) / size;
136
                        list->oldx += list->dx * size;
137
                        return;
138
                case ABS_Y:
139
                        size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
140
                        if (size == 0) size = yres;
141
                        list->dy -= (value * yres - list->oldy) / size;
142
                        list->oldy -= list->dy * size;
143
                        return;
144
        }
145
}
146
 
147
static void mouse_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
148
{
149
        int index;
150
 
151
#ifdef DEBUG_MOUSE
152
        printk(KERN_DEBUG "mouse.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value);
153
#endif
154
 
155
        switch (type) {
156
                case EV_ABS:
157
                        mouse_abs_event(handle, type, code, value);
158
                        break;
159
 
160
                case EV_REL:
161
                        switch (code) {
162
                                case REL_X:     list->dx += value; break;
163
                                case REL_Y:     list->dy -= value; break;
164
                                case REL_WHEEL: list->dz -= value; break;
165
                        }
166
                        break;
167
 
168
                case EV_KEY:
169
                        switch (code) {
170
                                case BTN_TOUCH: /* Handle touchpad data */
171
                                        if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
172
                                                list->finger = value;
173
                                                return;
174
                                        }
175
                                case BTN_0:
176
                                case BTN_FORWARD:
177
                                case BTN_LEFT:   index = 0; break;
178
                                case BTN_4:
179
                                case BTN_EXTRA:  index = 4; break;
180
                                case BTN_STYLUS:
181
                                case BTN_1:
182
                                case BTN_RIGHT:  index = 1; break;
183
                                case BTN_3:
184
                                case BTN_BACK:
185
                                case BTN_SIDE:   index = 3; break;
186
                                case BTN_2:
187
                                case BTN_STYLUS2:
188
                                case BTN_MIDDLE: index = 2; break;     
189
                                default: return;
190
                        }
191
                        switch (value) {
192
                                case 0: clear_bit(index, &list->buttons); break;
193
                                case 1: set_bit(index, &list->buttons); break;
194
                                case 2: return;
195
                        }
196
                        break;
197
 
198
                case EV_SYN:
199
                        switch (code) {
200
                                case SYN_REPORT:
201
                                        if (mtail != mhead) {
202
                                                mbuffer[mhead].buttons = list->buttons;
203
                                                mbuffer[mhead].dx = list->dx;
204
                                                mbuffer[mhead].dy = list->dy;
205
                                                mbuffer[mhead].dz = list->dz;
206
                                                mhead = (mhead+1) & MOUSE_BUFFERMASK;
523 mauro 207
                                                list->dx = list->dy = list->dz = 0;
519 mauro 208
                                        }
523 mauro 209
                                        shark_mouse_exec();
519 mauro 210
                                        break;
211
                        }
212
        }
213
}
214
 
215
static struct input_handle *mouse_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
216
{
217
        struct input_handle *handle;
218
 
219
        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
220
                return NULL;
221
        memset(handle, 0, sizeof(struct input_handle));
222
 
223
        handle->dev = dev;
224
        handle->handler = handler;
225
        handle->name = mouse_name;
226
 
227
        input_open_device(handle);
228
 
229
#ifdef DEBUG_MOUSE
230
        printk(KERN_DEBUG "mouse.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
231
#endif
232
 
233
        return handle;
234
}
235
 
236
static void mouse_disconnect(struct input_handle *handle)
237
{
238
#ifdef DEBUG_MOUSE
239
        printk(KERN_DEBUG "mouse.c: Disconnected device: %s\n", handle->dev->phys);
240
#endif
241
 
242
        input_close_device(handle);
243
 
244
        kfree(handle);
245
}
246
 
247
static struct input_device_id mouse_ids[] = {
248
        {
249
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
250
                .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
251
                .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
252
                .relbit = { BIT(REL_X) | BIT(REL_Y) },
253
        },      // A mouse like device, at least one button, two relative axes
254
        {
255
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
256
                .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
257
                .relbit = { BIT(REL_WHEEL) },
258
        },      // A separate scrollwheel
259
        {
260
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
261
                .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
262
                .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
263
                .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
264
        },      // A tablet like device, at least touch detection, two absolute axes
265
        {
266
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
267
                .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
268
                .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
269
                .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
270
        },      // A touchpad
271
 
272
        { },    // Terminating entry
273
};
274
 
275
MODULE_DEVICE_TABLE(input, mouse_ids);
276
 
277
static struct input_handler mouse_handler = {
278
        .event =        mouse_event,
279
        .connect =      mouse_connect,
280
        .disconnect =   mouse_disconnect,
281
        .name =         "mouse",
282
        .id_table =     mouse_ids,
283
};
284
 
285
int __init mouse_init(void)
286
{
523 mauro 287
        /* Initialize Buffer Variables */
288
        mhead=1;
289
        mtail=0;
290
 
519 mauro 291
        input_register_handler(&mouse_handler);
292
        return 0;
293
}
294
 
295
void __exit mouse_exit(void)
296
{
297
        input_unregister_handler(&mouse_handler);
298
}
299
 
300
module_init(mouse_init);
301
module_exit(mouse_exit);