joy.c revision 7430
1193323Sed/*- 2193323Sed * Copyright (c) 1995 Jean-Marc Zucconi 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer 10193323Sed * in this position and unchanged. 11193323Sed * 2. Redistributions in binary form must reproduce the above copyright 12193323Sed * notice, this list of conditions and the following disclaimer in the 13193323Sed * documentation and/or other materials provided with the distribution. 14193323Sed * 3. The name of the author may not be used to endorse or promote products 15193323Sed * derived from this software withough specific prior written permission 16193323Sed * 17193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20193323Sed * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21193323Sed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22193323Sed * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23193323Sed * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24193323Sed * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25193323Sed * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26193323Sed * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27193323Sed * 28193323Sed */ 29193323Sed#include "joy.h" 30193323Sed 31193323Sed#if NJOY > 0 32193323Sed 33193323Sed#include <errno.h> 34193323Sed 35193323Sed#include <sys/param.h> 36193323Sed#include <sys/systm.h> 37193323Sed 38193323Sed#include <machine/joystick.h> 39193323Sed 40193323Sed#include <i386/isa/isa.h> 41193323Sed#include <i386/isa/isa_device.h> 42193323Sed#include <i386/isa/timerreg.h> 43193323Sed 44193323Sed/* The game port can manage 4 buttons and 4 variable resistors (usually 2 45193323Sed * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201. 46193323Sed * Getting the state of the buttons is done by reading the game port: 47193323Sed * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2) 48193323Sed * to bits 0-3. 49193323Sed * if button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5, 6, 7) is set to 0 50193323Sed * to get the value of a resistor, write the value 0xff at port and 51193323Sed * wait until the corresponding bit returns to 0. 52193323Sed */ 53193323Sed 54193323Sed 55193323Sed/* the formulae below only work if u is ``not too large''. See also 56193323Sed * the discussion in microtime.s */ 57193323Sed#define usec2ticks(u) (((u) * 19549)>>14) 58193323Sed#define ticks2usec(u) (((u) * 3433)>>12) 59193323Sed 60193323Sed 61193323Sed#define joypart(d) minor(d)&1 62193323Sed#define UNIT(d) minor(d)>>1&3 63193323Sed#ifndef JOY_TIMEOUT 64193323Sed#define JOY_TIMEOUT 2000 /* 2 milliseconds */ 65193323Sed#endif 66193323Sed 67193323Sedstatic struct { 68193323Sed int port; 69193323Sed int x_off[2], y_off[2]; 70193323Sed int timeout[2]; 71193323Sed} joy[NJOY]; 72193323Sed 73193323Sed 74193323Sedextern int timer0_max_count; 75193323Sed 76193323Sedint joyprobe (struct isa_device *), joyattach (struct isa_device *); 77193323Sed 78193323Sedstruct isa_driver joydriver = {joyprobe, joyattach, "joy"}; 79193323Sed 80193323Sedstatic int get_tick (); 81193323Sed 82193323Sed 83193323Sedint 84193323Sedjoyprobe (struct isa_device *dev) 85193323Sed{ 86193323Sed#ifdef WANT_JOYSTICK_CONNECTED 87193323Sed outb (dev->id_iobase, 0xff); 88193323Sed DELAY (10000); /* 10 ms delay */ 89193323Sed return (inb (dev->id_iobase) & 0x0f) != 0x0f; 90193323Sed#else 91193323Sed return 1; 92193323Sed#endif 93193323Sed} 94193323Sed 95193323Sedint 96193323Sedjoyattach (struct isa_device *dev) 97193323Sed{ 98193323Sed joy[dev->id_unit].port = dev->id_iobase; 99193323Sed joy[dev->id_unit].timeout[0] = joy[dev->id_unit].timeout[1] = 0; 100193323Sed printf("joy%d: joystick\n", dev->id_unit); 101193323Sed 102193323Sed return 1; 103193323Sed} 104193323Sed 105193323Sedint 106193323Sedjoyopen (dev_t dev, int flag) 107193323Sed{ 108193323Sed int unit = UNIT (dev); 109193323Sed int i = joypart (dev); 110193323Sed 111193323Sed if (joy[unit].timeout[i]) 112193323Sed return EBUSY; 113193323Sed joy[unit].x_off[i] = joy[unit].y_off[i] = 0; 114193323Sed joy[unit].timeout[i] = JOY_TIMEOUT; 115193323Sed return 0; 116193323Sed} 117193323Sedint 118193323Sedjoyclose (dev_t dev, int flag) 119193323Sed{ 120193323Sed int unit = UNIT (dev); 121193323Sed int i = joypart (dev); 122193323Sed 123193323Sed joy[unit].timeout[i] = 0; 124193323Sed return 0; 125193323Sed} 126193323Sed 127193323Sedint 128193323Sedjoyread (dev_t dev, struct uio *uio, int flag) 129193323Sed{ 130193323Sed int unit = UNIT(dev); 131193323Sed int port = joy[unit].port; 132193323Sed int i, t0, t1; 133193323Sed int state = 0, x = 0, y = 0; 134193323Sed struct joystick c; 135193323Sed 136193323Sed disable_intr (); 137193323Sed outb (port, 0xff); 138193323Sed t0 = get_tick (); 139193323Sed t1 = t0; 140193323Sed i = usec2ticks(joy[unit].timeout[joypart(dev)]); 141193323Sed while (t0-t1 < i) { 142193323Sed state = inb (port); 143193323Sed if (joypart(dev) == 1) 144193323Sed state >>= 2; 145193323Sed t1 = get_tick (); 146193323Sed if (t1 > t0) 147193323Sed t1 -= timer0_max_count; 148193323Sed if (!x && !(state & 0x01)) 149193323Sed x = t1; 150193323Sed if (!y && !(state & 0x02)) 151193323Sed y = t1; 152193323Sed if (x && y) 153193323Sed break; 154193323Sed } 155193323Sed enable_intr (); 156193323Sed c.x = x ? joy[unit].x_off[joypart(dev)] + ticks2usec(t0-x) : 0x80000000; 157193323Sed c.y = y ? joy[unit].y_off[joypart(dev)] + ticks2usec(t0-y) : 0x80000000; 158193323Sed state >>= 4; 159193323Sed c.b1 = ~state & 1; 160193323Sed c.b2 = ~(state >> 1) & 1; 161193323Sed return uiomove ((caddr_t)&c, sizeof(struct joystick), uio); 162193323Sed} 163193323Sedint joyioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 164193323Sed{ 165193323Sed int unit = UNIT (dev); 166193323Sed int i = joypart (dev); 167193323Sed int x; 168193323Sed 169193323Sed switch (cmd) { 170193323Sed case JOY_SETTIMEOUT: 171193323Sed x = *(int *) data; 172193323Sed if (x < 1 || x > 10000) /* 10ms maximum! */ 173193323Sed return EINVAL; 174193323Sed joy[unit].timeout[i] = x; 175193323Sed break; 176193323Sed case JOY_GETTIMEOUT: 177193323Sed *(int *) data = joy[unit].timeout[i]; 178193323Sed break; 179193323Sed case JOY_SET_X_OFFSET: 180193323Sed joy[unit].x_off[i] = *(int *) data; 181193323Sed break; 182193323Sed case JOY_SET_Y_OFFSET: 183193323Sed joy[unit].y_off[i] = *(int *) data; 184193323Sed break; 185193323Sed case JOY_GET_X_OFFSET: 186193323Sed *(int *) data = joy[unit].x_off[i]; 187193323Sed break; 188193323Sed case JOY_GET_Y_OFFSET: 189193323Sed *(int *) data = joy[unit].y_off[i]; 190193323Sed break; 191193323Sed default: 192193323Sed return ENXIO; 193193323Sed } 194193323Sed return 0; 195193323Sed} 196193323Sedstatic int 197193323Sedget_tick () 198193323Sed{ 199193323Sed int low, high; 200193323Sed 201193323Sed outb (TIMER_MODE, TIMER_SEL0); 202193323Sed low = inb (TIMER_CNTR0); 203193323Sed high = inb (TIMER_CNTR0); 204193323Sed 205193323Sed return (high << 8) | low; 206193323Sed} 207193323Sed 208193323Sed#endif /* NJOY > 0 */ 209193323Sed