Subversion Repositories shark

Rev

Rev 538 | 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
int mouse_get(int *dx, int *dy, int *dz, unsigned long *buttons)
81
{
82
        if ( ((mtail+1) & MOUSE_BUFFERMASK) == ((mhead) & MOUSE_BUFFERMASK) )
83
                return -1;
84
 
85
        mtail = (mtail+1) & MOUSE_BUFFERMASK;
86
 
87
        *dx      = mbuffer[mtail].dx;
88
        *dy      = mbuffer[mtail].dy;
523 mauro 89
        *dz      = mbuffer[mtail].dz;
519 mauro 90
        *buttons = mbuffer[mtail].buttons;
91
 
523 mauro 92
#ifdef DEBUG_MOUSE
93
        printk(KERN_DEBUG "mouse.c: ( %3d %3d %3d - %6x)\n", *dx, *dy, *dz, *(int *)buttons);
94
#endif
519 mauro 95
        return 0;
96
}
97
 
98
static void mouse_abs_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
99
{
100
        int size;
101
 
102
        /* Ignore joysticks */
103
        if (test_bit(BTN_TRIGGER, handle->dev->keybit))
104
                return;
105
 
106
        /* Handle touchpad data */
107
        if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
108
 
109
                if (list->finger && list->finger < 3)
110
                        list->finger++;
111
 
112
                switch (code) {
113
                        case ABS_X:
114
                                if (list->finger == 3)
115
                                        list->dx += (value - list->oldx) / 8;
116
                                list->oldx = value;
117
                                return;
118
                        case ABS_Y:
119
                                if (list->finger == 3)
120
                                        list->dy -= (value - list->oldy) / 8;
121
                                list->oldy = value;
122
                                return;
123
                }
124
                return;
125
        }
126
 
127
        /* Handle tablet data */
128
        switch (code) {
129
                case ABS_X:
130
                        size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
131
                        if (size == 0) size = xres;
132
                        list->dx += (value * xres - list->oldx) / size;
133
                        list->oldx += list->dx * size;
134
                        return;
135
                case ABS_Y:
136
                        size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
137
                        if (size == 0) size = yres;
138
                        list->dy -= (value * yres - list->oldy) / size;
139
                        list->oldy -= list->dy * size;
140
                        return;
141
        }
142
}
143
 
144
static void mouse_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
145
{
146
        int index;
147
 
148
#ifdef DEBUG_MOUSE
149
        printk(KERN_DEBUG "mouse.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d\n", handle->dev->phys, type, code, value);
150
#endif
151
 
152
        switch (type) {
153
                case EV_ABS:
154
                        mouse_abs_event(handle, type, code, value);
155
                        break;
156
 
157
                case EV_REL:
158
                        switch (code) {
159
                                case REL_X:     list->dx += value; break;
160
                                case REL_Y:     list->dy -= value; break;
161
                                case REL_WHEEL: list->dz -= value; break;
162
                        }
163
                        break;
164
 
165
                case EV_KEY:
166
                        switch (code) {
167
                                case BTN_TOUCH: /* Handle touchpad data */
168
                                        if (test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
169
                                                list->finger = value;
170
                                                return;
171
                                        }
172
                                case BTN_0:
173
                                case BTN_FORWARD:
174
                                case BTN_LEFT:   index = 0; break;
175
                                case BTN_4:
176
                                case BTN_EXTRA:  index = 4; break;
177
                                case BTN_STYLUS:
178
                                case BTN_1:
179
                                case BTN_RIGHT:  index = 1; break;
180
                                case BTN_3:
181
                                case BTN_BACK:
182
                                case BTN_SIDE:   index = 3; break;
183
                                case BTN_2:
184
                                case BTN_STYLUS2:
185
                                case BTN_MIDDLE: index = 2; break;     
186
                                default: return;
187
                        }
188
                        switch (value) {
189
                                case 0: clear_bit(index, &list->buttons); break;
190
                                case 1: set_bit(index, &list->buttons); break;
191
                                case 2: return;
192
                        }
193
                        break;
194
 
195
                case EV_SYN:
196
                        switch (code) {
197
                                case SYN_REPORT:
198
                                        if (mtail != mhead) {
199
                                                mbuffer[mhead].buttons = list->buttons;
200
                                                mbuffer[mhead].dx = list->dx;
201
                                                mbuffer[mhead].dy = list->dy;
202
                                                mbuffer[mhead].dz = list->dz;
203
                                                mhead = (mhead+1) & MOUSE_BUFFERMASK;
523 mauro 204
                                                list->dx = list->dy = list->dz = 0;
519 mauro 205
                                        }
523 mauro 206
                                        shark_mouse_exec();
519 mauro 207
                                        break;
208
                        }
209
        }
210
}
211
 
212
static struct input_handle *mouse_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
213
{
214
        struct input_handle *handle;
215
 
216
        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
217
                return NULL;
218
        memset(handle, 0, sizeof(struct input_handle));
219
 
220
        handle->dev = dev;
221
        handle->handler = handler;
222
        handle->name = mouse_name;
223
 
224
        input_open_device(handle);
225
 
226
#ifdef DEBUG_MOUSE
227
        printk(KERN_DEBUG "mouse.c: Connected device: \"%s\", %s\n", dev->name, dev->phys);
228
#endif
229
 
230
        return handle;
231
}
232
 
233
static void mouse_disconnect(struct input_handle *handle)
234
{
235
#ifdef DEBUG_MOUSE
236
        printk(KERN_DEBUG "mouse.c: Disconnected device: %s\n", handle->dev->phys);
237
#endif
238
 
239
        input_close_device(handle);
240
 
241
        kfree(handle);
242
}
243
 
244
static struct input_device_id mouse_ids[] = {
245
        {
246
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
247
                .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
248
                .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
249
                .relbit = { BIT(REL_X) | BIT(REL_Y) },
250
        },      // A mouse like device, at least one button, two relative axes
251
        {
252
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
253
                .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
254
                .relbit = { BIT(REL_WHEEL) },
255
        },      // A separate scrollwheel
256
        {
257
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
258
                .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
259
                .keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
260
                .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
261
        },      // A tablet like device, at least touch detection, two absolute axes
262
        {
263
                .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
264
                .evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
265
                .keybit = { [LONG(BTN_TOOL_FINGER)] = BIT(BTN_TOOL_FINGER) },
266
                .absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_TOOL_WIDTH) },
267
        },      // A touchpad
268
 
269
        { },    // Terminating entry
270
};
271
 
272
MODULE_DEVICE_TABLE(input, mouse_ids);
273
 
274
static struct input_handler mouse_handler = {
275
        .event =        mouse_event,
276
        .connect =      mouse_connect,
277
        .disconnect =   mouse_disconnect,
278
        .name =         "mouse",
279
        .id_table =     mouse_ids,
280
};
281
 
282
int __init mouse_init(void)
283
{
523 mauro 284
        /* Initialize Buffer Variables */
285
        mhead=1;
286
        mtail=0;
287
 
519 mauro 288
        input_register_handler(&mouse_handler);
289
        return 0;
290
}
291
 
292
void __exit mouse_exit(void)
293
{
294
        input_unregister_handler(&mouse_handler);
295
}
296
 
297
module_init(mouse_init);
298
module_exit(mouse_exit);