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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [joystick/] [turbografx.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
3
 *
4
 *  Copyright (c) 1998-2001 Vojtech Pavlik
5
 *
6
 *  Based on the work of:
7
 *      Steffen Schwenke
8
 */
9
 
10
/*
11
 * TurboGraFX parallel port interface driver for Linux.
12
 */
13
 
14
/*
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
 *
29
 * Should you need to contact me, the author, you can do so either by
30
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32
 */
33
 
34
#include <linux/kernel.h>
35
#include <linux/parport.h>
36
#include <linux/input.h>
37
#include <linux/module.h>
38
#include <linux/moduleparam.h>
39
#include <linux/init.h>
40
#include <linux/mutex.h>
41
 
42
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43
MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
44
MODULE_LICENSE("GPL");
45
 
46
#define TGFX_MAX_PORTS          3
47
#define TGFX_MAX_DEVICES        7
48
 
49
struct tgfx_config {
50
        int args[TGFX_MAX_DEVICES + 1];
51
        unsigned int nargs;
52
};
53
 
54
static struct tgfx_config tgfx_cfg[TGFX_MAX_PORTS] __initdata;
55
 
56
module_param_array_named(map, tgfx_cfg[0].args, int, &tgfx_cfg[0].nargs, 0);
57
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
58
module_param_array_named(map2, tgfx_cfg[1].args, int, &tgfx_cfg[1].nargs, 0);
59
MODULE_PARM_DESC(map2, "Describes second set of devices");
60
module_param_array_named(map3, tgfx_cfg[2].args, int, &tgfx_cfg[2].nargs, 0);
61
MODULE_PARM_DESC(map3, "Describes third set of devices");
62
 
63
#define TGFX_REFRESH_TIME       HZ/100  /* 10 ms */
64
 
65
#define TGFX_TRIGGER            0x08
66
#define TGFX_UP                 0x10
67
#define TGFX_DOWN               0x20
68
#define TGFX_LEFT               0x40
69
#define TGFX_RIGHT              0x80
70
 
71
#define TGFX_THUMB              0x02
72
#define TGFX_THUMB2             0x04
73
#define TGFX_TOP                0x01
74
#define TGFX_TOP2               0x08
75
 
76
static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
77
 
78
static struct tgfx {
79
        struct pardevice *pd;
80
        struct timer_list timer;
81
        struct input_dev *dev[TGFX_MAX_DEVICES];
82
        char name[TGFX_MAX_DEVICES][64];
83
        char phys[TGFX_MAX_DEVICES][32];
84
        int sticks;
85
        int used;
86
        struct mutex sem;
87
} *tgfx_base[TGFX_MAX_PORTS];
88
 
89
/*
90
 * tgfx_timer() reads and analyzes TurboGraFX joystick data.
91
 */
92
 
93
static void tgfx_timer(unsigned long private)
94
{
95
        struct tgfx *tgfx = (void *) private;
96
        struct input_dev *dev;
97
        int data1, data2, i;
98
 
99
        for (i = 0; i < 7; i++)
100
                if (tgfx->sticks & (1 << i)) {
101
 
102
                        dev = tgfx->dev[i];
103
 
104
                        parport_write_data(tgfx->pd->port, ~(1 << i));
105
                        data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
106
                        data2 = parport_read_control(tgfx->pd->port) ^ 0x04;    /* CAVEAT parport */
107
 
108
                        input_report_abs(dev, ABS_X, !!(data1 & TGFX_RIGHT) - !!(data1 & TGFX_LEFT));
109
                        input_report_abs(dev, ABS_Y, !!(data1 & TGFX_DOWN ) - !!(data1 & TGFX_UP  ));
110
 
111
                        input_report_key(dev, BTN_TRIGGER, (data1 & TGFX_TRIGGER));
112
                        input_report_key(dev, BTN_THUMB,   (data2 & TGFX_THUMB  ));
113
                        input_report_key(dev, BTN_THUMB2,  (data2 & TGFX_THUMB2 ));
114
                        input_report_key(dev, BTN_TOP,     (data2 & TGFX_TOP    ));
115
                        input_report_key(dev, BTN_TOP2,    (data2 & TGFX_TOP2   ));
116
 
117
                        input_sync(dev);
118
                }
119
 
120
        mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
121
}
122
 
123
static int tgfx_open(struct input_dev *dev)
124
{
125
        struct tgfx *tgfx = input_get_drvdata(dev);
126
        int err;
127
 
128
        err = mutex_lock_interruptible(&tgfx->sem);
129
        if (err)
130
                return err;
131
 
132
        if (!tgfx->used++) {
133
                parport_claim(tgfx->pd);
134
                parport_write_control(tgfx->pd->port, 0x04);
135
                mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
136
        }
137
 
138
        mutex_unlock(&tgfx->sem);
139
        return 0;
140
}
141
 
142
static void tgfx_close(struct input_dev *dev)
143
{
144
        struct tgfx *tgfx = input_get_drvdata(dev);
145
 
146
        mutex_lock(&tgfx->sem);
147
        if (!--tgfx->used) {
148
                del_timer_sync(&tgfx->timer);
149
                parport_write_control(tgfx->pd->port, 0x00);
150
                parport_release(tgfx->pd);
151
        }
152
        mutex_unlock(&tgfx->sem);
153
}
154
 
155
 
156
 
157
/*
158
 * tgfx_probe() probes for tg gamepads.
159
 */
160
 
161
static struct tgfx __init *tgfx_probe(int parport, int *n_buttons, int n_devs)
162
{
163
        struct tgfx *tgfx;
164
        struct input_dev *input_dev;
165
        struct parport *pp;
166
        struct pardevice *pd;
167
        int i, j;
168
        int err;
169
 
170
        pp = parport_find_number(parport);
171
        if (!pp) {
172
                printk(KERN_ERR "turbografx.c: no such parport\n");
173
                err = -EINVAL;
174
                goto err_out;
175
        }
176
 
177
        pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
178
        if (!pd) {
179
                printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
180
                err = -EBUSY;
181
                goto err_put_pp;
182
        }
183
 
184
        tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL);
185
        if (!tgfx) {
186
                printk(KERN_ERR "turbografx.c: Not enough memory\n");
187
                err = -ENOMEM;
188
                goto err_unreg_pardev;
189
        }
190
 
191
        mutex_init(&tgfx->sem);
192
        tgfx->pd = pd;
193
        init_timer(&tgfx->timer);
194
        tgfx->timer.data = (long) tgfx;
195
        tgfx->timer.function = tgfx_timer;
196
 
197
        for (i = 0; i < n_devs; i++) {
198
                if (n_buttons[i] < 1)
199
                        continue;
200
 
201
                if (n_buttons[i] > 6) {
202
                        printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
203
                        err = -EINVAL;
204
                        goto err_unreg_devs;
205
                }
206
 
207
                tgfx->dev[i] = input_dev = input_allocate_device();
208
                if (!input_dev) {
209
                        printk(KERN_ERR "turbografx.c: Not enough memory for input device\n");
210
                        err = -ENOMEM;
211
                        goto err_unreg_devs;
212
                }
213
 
214
                tgfx->sticks |= (1 << i);
215
                snprintf(tgfx->name[i], sizeof(tgfx->name[i]),
216
                         "TurboGraFX %d-button Multisystem joystick", n_buttons[i]);
217
                snprintf(tgfx->phys[i], sizeof(tgfx->phys[i]),
218
                         "%s/input%d", tgfx->pd->port->name, i);
219
 
220
                input_dev->name = tgfx->name[i];
221
                input_dev->phys = tgfx->phys[i];
222
                input_dev->id.bustype = BUS_PARPORT;
223
                input_dev->id.vendor = 0x0003;
224
                input_dev->id.product = n_buttons[i];
225
                input_dev->id.version = 0x0100;
226
 
227
                input_set_drvdata(input_dev, tgfx);
228
 
229
                input_dev->open = tgfx_open;
230
                input_dev->close = tgfx_close;
231
 
232
                input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
233
                input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
234
                input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
235
 
236
                for (j = 0; j < n_buttons[i]; j++)
237
                        set_bit(tgfx_buttons[j], input_dev->keybit);
238
 
239
                err = input_register_device(tgfx->dev[i]);
240
                if (err)
241
                        goto err_free_dev;
242
        }
243
 
244
        if (!tgfx->sticks) {
245
                printk(KERN_ERR "turbografx.c: No valid devices specified\n");
246
                err = -EINVAL;
247
                goto err_free_tgfx;
248
        }
249
 
250
        return tgfx;
251
 
252
 err_free_dev:
253
        input_free_device(tgfx->dev[i]);
254
 err_unreg_devs:
255
        while (--i >= 0)
256
                if (tgfx->dev[i])
257
                        input_unregister_device(tgfx->dev[i]);
258
 err_free_tgfx:
259
        kfree(tgfx);
260
 err_unreg_pardev:
261
        parport_unregister_device(pd);
262
 err_put_pp:
263
        parport_put_port(pp);
264
 err_out:
265
        return ERR_PTR(err);
266
}
267
 
268
static void tgfx_remove(struct tgfx *tgfx)
269
{
270
        int i;
271
 
272
        for (i = 0; i < TGFX_MAX_DEVICES; i++)
273
                if (tgfx->dev[i])
274
                        input_unregister_device(tgfx->dev[i]);
275
        parport_unregister_device(tgfx->pd);
276
        kfree(tgfx);
277
}
278
 
279
static int __init tgfx_init(void)
280
{
281
        int i;
282
        int have_dev = 0;
283
        int err = 0;
284
 
285
        for (i = 0; i < TGFX_MAX_PORTS; i++) {
286
                if (tgfx_cfg[i].nargs == 0 || tgfx_cfg[i].args[0] < 0)
287
                        continue;
288
 
289
                if (tgfx_cfg[i].nargs < 2) {
290
                        printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
291
                        err = -EINVAL;
292
                        break;
293
                }
294
 
295
                tgfx_base[i] = tgfx_probe(tgfx_cfg[i].args[0],
296
                                          tgfx_cfg[i].args + 1,
297
                                          tgfx_cfg[i].nargs - 1);
298
                if (IS_ERR(tgfx_base[i])) {
299
                        err = PTR_ERR(tgfx_base[i]);
300
                        break;
301
                }
302
 
303
                have_dev = 1;
304
        }
305
 
306
        if (err) {
307
                while (--i >= 0)
308
                        if (tgfx_base[i])
309
                                tgfx_remove(tgfx_base[i]);
310
                return err;
311
        }
312
 
313
        return have_dev ? 0 : -ENODEV;
314
}
315
 
316
static void __exit tgfx_exit(void)
317
{
318
        int i;
319
 
320
        for (i = 0; i < TGFX_MAX_PORTS; i++)
321
                if (tgfx_base[i])
322
                        tgfx_remove(tgfx_base[i]);
323
}
324
 
325
module_init(tgfx_init);
326
module_exit(tgfx_exit);

powered by: WebSVN 2.1.0

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