1 /* $NetBSD: joy.c,v 1.16 2007/12/01 23:40:28 jmcneill Exp $ */
4 * Copyright (c) 1995 Jean-Marc Zucconi
7 * Ported to NetBSD by Matthieu Herrb <matthieu@laas.fr>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer
14 * in this position and unchanged.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: joy.c,v 1.16 2007/12/01 23:40:28 jmcneill Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/errno.h>
43 #include <sys/event.h>
44 #include <sys/vnode.h>
47 #include <sys/joystick.h>
48 #include <dev/ic/joyvar.h>
51 * The game port can manage 4 buttons and 4 variable resistors (usually 2
52 * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201.
53 * Getting the state of the buttons is done by reading the game port;
54 * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2)
55 * to bits 0-3. If button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5,
56 * 6, 7) is set to 0 to get the value of a resistor, write the value 0xff
57 * at port and wait until the corresponding bit returns to 0.
61 #define JOYPART(d) (minor(d) & 1)
62 #define JOYUNIT(d) (minor(d) >> 1)
65 #define JOY_TIMEOUT 2000 /* 2 milliseconds */
68 extern struct cfdriver joy_cd
;
70 dev_type_open(joyopen
);
71 dev_type_close(joyclose
);
72 dev_type_read(joyread
);
73 dev_type_ioctl(joyioctl
);
75 const struct cdevsw joy_cdevsw
= {
76 joyopen
, joyclose
, joyread
, nowrite
, joyioctl
,
77 nostop
, notty
, nopoll
, nommap
, nokqfilter
, D_OTHER
,
81 joyattach(struct joy_softc
*sc
)
83 sc
->timeout
[0] = sc
->timeout
[1] = 0;
84 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, 0, 0xff);
85 DELAY(10000); /* 10 ms delay */
86 aprint_normal_dev(sc
->sc_dev
, "joystick %sconnected\n",
87 (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, 0) & 0x0f) == 0x0f ?
92 joydetach(struct joy_softc
*sc
, int flags
)
96 maj
= cdevsw_lookup_major(&joy_cdevsw
);
97 mn
= device_unit(sc
->sc_dev
) << 1;
98 vdevgone(maj
, mn
, mn
, VCHR
);
99 vdevgone(maj
, mn
+ 1, mn
+ 1, VCHR
);
105 joyopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
107 int unit
= JOYUNIT(dev
);
108 int i
= JOYPART(dev
);
109 struct joy_softc
*sc
;
111 sc
= device_lookup_private(&joy_cd
, unit
);
118 sc
->x_off
[i
] = sc
->y_off
[i
] = 0;
119 sc
->timeout
[i
] = JOY_TIMEOUT
;
124 joyclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
126 int unit
= JOYUNIT(dev
);
127 int i
= JOYPART(dev
);
128 struct joy_softc
*sc
= device_lookup_private(&joy_cd
, unit
);
135 joyread(dev_t dev
, struct uio
*uio
, int flag
)
137 int unit
= JOYUNIT(dev
);
138 struct joy_softc
*sc
= device_lookup_private(&joy_cd
, unit
);
139 bus_space_tag_t iot
= sc
->sc_iot
;
140 bus_space_handle_t ioh
= sc
->sc_ioh
;
143 struct timeval start
, now
, diff
;
144 int state
= 0, x
= 0, y
= 0;
146 s
= splhigh(); /* XXX */
147 bus_space_write_1(iot
, ioh
, 0, 0xff);
149 now
= start
; /* structure assignment */
150 i
= sc
->timeout
[JOYPART(dev
)];
152 timersub(&now
, &start
, &diff
);
153 if (diff
.tv_sec
> 0 || diff
.tv_usec
> i
)
155 state
= bus_space_read_1(iot
, ioh
, 0);
156 if (JOYPART(dev
) == 1)
158 if (!x
&& !(state
& 0x01))
160 if (!y
&& !(state
& 0x02))
168 c
.x
= x
? sc
->x_off
[JOYPART(dev
)] + x
: 0x80000000;
169 c
.y
= y
? sc
->y_off
[JOYPART(dev
)] + y
: 0x80000000;
172 c
.b2
= ~(state
>> 1) & 1;
173 return uiomove(&c
, sizeof(struct joystick
), uio
);
177 joyioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
179 int unit
= JOYUNIT(dev
);
180 struct joy_softc
*sc
= device_lookup_private(&joy_cd
, unit
);
181 int i
= JOYPART(dev
);
187 if (x
< 1 || x
> 10000) /* 10ms maximum! */
192 *(int *)data
= sc
->timeout
[i
];
194 case JOY_SET_X_OFFSET
:
195 sc
->x_off
[i
] = *(int *)data
;
197 case JOY_SET_Y_OFFSET
:
198 sc
->y_off
[i
] = *(int *)data
;
200 case JOY_GET_X_OFFSET
:
201 *(int *)data
= sc
->x_off
[i
];
203 case JOY_GET_Y_OFFSET
:
204 *(int *)data
= sc
->y_off
[i
];