1*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2*4882a593SmuzhiyunProgramming gameport drivers 3*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4*4882a593Smuzhiyun 5*4882a593SmuzhiyunA basic classic gameport 6*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~ 7*4882a593Smuzhiyun 8*4882a593SmuzhiyunIf the gameport doesn't provide more than the inb()/outb() functionality, 9*4882a593Smuzhiyunthe code needed to register it with the joystick drivers is simple:: 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun struct gameport gameport; 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun gameport.io = MY_IO_ADDRESS; 14*4882a593Smuzhiyun gameport_register_port(&gameport); 15*4882a593Smuzhiyun 16*4882a593SmuzhiyunMake sure struct gameport is initialized to 0 in all other fields. The 17*4882a593Smuzhiyungameport generic code will take care of the rest. 18*4882a593Smuzhiyun 19*4882a593SmuzhiyunIf your hardware supports more than one io address, and your driver can 20*4882a593Smuzhiyunchoose which one to program the hardware to, starting from the more exotic 21*4882a593Smuzhiyunaddresses is preferred, because the likelihood of clashing with the standard 22*4882a593Smuzhiyun0x201 address is smaller. 23*4882a593Smuzhiyun 24*4882a593SmuzhiyunEg. if your driver supports addresses 0x200, 0x208, 0x210 and 0x218, then 25*4882a593Smuzhiyun0x218 would be the address of first choice. 26*4882a593Smuzhiyun 27*4882a593SmuzhiyunIf your hardware supports a gameport address that is not mapped to ISA io 28*4882a593Smuzhiyunspace (is above 0x1000), use that one, and don't map the ISA mirror. 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunAlso, always request_region() on the whole io space occupied by the 31*4882a593Smuzhiyungameport. Although only one ioport is really used, the gameport usually 32*4882a593Smuzhiyunoccupies from one to sixteen addresses in the io space. 33*4882a593Smuzhiyun 34*4882a593SmuzhiyunPlease also consider enabling the gameport on the card in the ->open() 35*4882a593Smuzhiyuncallback if the io is mapped to ISA space - this way it'll occupy the io 36*4882a593Smuzhiyunspace only when something really is using it. Disable it again in the 37*4882a593Smuzhiyun->close() callback. You also can select the io address in the ->open() 38*4882a593Smuzhiyuncallback, so that it doesn't fail if some of the possible addresses are 39*4882a593Smuzhiyunalready occupied by other gameports. 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunMemory mapped gameport 42*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~ 43*4882a593Smuzhiyun 44*4882a593SmuzhiyunWhen a gameport can be accessed through MMIO, this way is preferred, because 45*4882a593Smuzhiyunit is faster, allowing more reads per second. Registering such a gameport 46*4882a593Smuzhiyunisn't as easy as a basic IO one, but not so much complex:: 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun struct gameport gameport; 49*4882a593Smuzhiyun 50*4882a593Smuzhiyun void my_trigger(struct gameport *gameport) 51*4882a593Smuzhiyun { 52*4882a593Smuzhiyun my_mmio = 0xff; 53*4882a593Smuzhiyun } 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun unsigned char my_read(struct gameport *gameport) 56*4882a593Smuzhiyun { 57*4882a593Smuzhiyun return my_mmio; 58*4882a593Smuzhiyun } 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun gameport.read = my_read; 61*4882a593Smuzhiyun gameport.trigger = my_trigger; 62*4882a593Smuzhiyun gameport_register_port(&gameport); 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun.. _gameport_pgm_cooked_mode: 65*4882a593Smuzhiyun 66*4882a593SmuzhiyunCooked mode gameport 67*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~ 68*4882a593Smuzhiyun 69*4882a593SmuzhiyunThere are gameports that can report the axis values as numbers, that means 70*4882a593Smuzhiyunthe driver doesn't have to measure them the old way - an ADC is built into 71*4882a593Smuzhiyunthe gameport. To register a cooked gameport:: 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun struct gameport gameport; 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun int my_cooked_read(struct gameport *gameport, int *axes, int *buttons) 76*4882a593Smuzhiyun { 77*4882a593Smuzhiyun int i; 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun for (i = 0; i < 4; i++) 80*4882a593Smuzhiyun axes[i] = my_mmio[i]; 81*4882a593Smuzhiyun buttons[i] = my_mmio[4]; 82*4882a593Smuzhiyun } 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun int my_open(struct gameport *gameport, int mode) 85*4882a593Smuzhiyun { 86*4882a593Smuzhiyun return -(mode != GAMEPORT_MODE_COOKED); 87*4882a593Smuzhiyun } 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun gameport.cooked_read = my_cooked_read; 90*4882a593Smuzhiyun gameport.open = my_open; 91*4882a593Smuzhiyun gameport.fuzz = 8; 92*4882a593Smuzhiyun gameport_register_port(&gameport); 93*4882a593Smuzhiyun 94*4882a593SmuzhiyunThe only confusing thing here is the fuzz value. Best determined by 95*4882a593Smuzhiyunexperimentation, it is the amount of noise in the ADC data. Perfect 96*4882a593Smuzhiyungameports can set this to zero, most common have fuzz between 8 and 32. 97*4882a593SmuzhiyunSee analog.c and input.c for handling of fuzz - the fuzz value determines 98*4882a593Smuzhiyunthe size of a gaussian filter window that is used to eliminate the noise 99*4882a593Smuzhiyunin the data. 100*4882a593Smuzhiyun 101*4882a593SmuzhiyunMore complex gameports 102*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~ 103*4882a593Smuzhiyun 104*4882a593SmuzhiyunGameports can support both raw and cooked modes. In that case combine either 105*4882a593Smuzhiyunexamples 1+2 or 1+3. Gameports can support internal calibration - see below, 106*4882a593Smuzhiyunand also lightning.c and analog.c on how that works. If your driver supports 107*4882a593Smuzhiyunmore than one gameport instance simultaneously, use the ->private member of 108*4882a593Smuzhiyunthe gameport struct to point to your data. 109*4882a593Smuzhiyun 110*4882a593SmuzhiyunUnregistering a gameport 111*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~ 112*4882a593Smuzhiyun 113*4882a593SmuzhiyunSimple:: 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun gameport_unregister_port(&gameport); 116*4882a593Smuzhiyun 117*4882a593SmuzhiyunThe gameport structure 118*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~ 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun.. note:: 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun This section is outdated. There are several fields here that don't 123*4882a593Smuzhiyun match what's there at include/linux/gameport.h. 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun:: 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun struct gameport { 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun void *private; 130*4882a593Smuzhiyun 131*4882a593SmuzhiyunA private pointer for free use in the gameport driver. (Not the joystick 132*4882a593Smuzhiyundriver!) 133*4882a593Smuzhiyun 134*4882a593Smuzhiyun:: 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun int number; 137*4882a593Smuzhiyun 138*4882a593SmuzhiyunNumber assigned to the gameport when registered. Informational purpose only. 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun:: 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun int io; 143*4882a593Smuzhiyun 144*4882a593SmuzhiyunI/O address for use with raw mode. You have to either set this, or ->read() 145*4882a593Smuzhiyunto some value if your gameport supports raw mode. 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun:: 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun int speed; 150*4882a593Smuzhiyun 151*4882a593SmuzhiyunRaw mode speed of the gameport reads in thousands of reads per second. 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun:: 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun int fuzz; 156*4882a593Smuzhiyun 157*4882a593SmuzhiyunIf the gameport supports cooked mode, this should be set to a value that 158*4882a593Smuzhiyunrepresents the amount of noise in the data. See 159*4882a593Smuzhiyun:ref:`gameport_pgm_cooked_mode`. 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun:: 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun void (*trigger)(struct gameport *); 164*4882a593Smuzhiyun 165*4882a593SmuzhiyunTrigger. This function should trigger the ns558 oneshots. If set to NULL, 166*4882a593Smuzhiyunoutb(0xff, io) will be used. 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun:: 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun unsigned char (*read)(struct gameport *); 171*4882a593Smuzhiyun 172*4882a593SmuzhiyunRead the buttons and ns558 oneshot bits. If set to NULL, inb(io) will be 173*4882a593Smuzhiyunused instead. 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun:: 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun int (*cooked_read)(struct gameport *, int *axes, int *buttons); 178*4882a593Smuzhiyun 179*4882a593SmuzhiyunIf the gameport supports cooked mode, it should point this to its cooked 180*4882a593Smuzhiyunread function. It should fill axes[0..3] with four values of the joystick axes 181*4882a593Smuzhiyunand buttons[0] with four bits representing the buttons. 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun:: 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun int (*calibrate)(struct gameport *, int *axes, int *max); 186*4882a593Smuzhiyun 187*4882a593SmuzhiyunFunction for calibrating the ADC hardware. When called, axes[0..3] should be 188*4882a593Smuzhiyunpre-filled by cooked data by the caller, max[0..3] should be pre-filled with 189*4882a593Smuzhiyunexpected maximums for each axis. The calibrate() function should set the 190*4882a593Smuzhiyunsensitivity of the ADC hardware so that the maximums fit in its range and 191*4882a593Smuzhiyunrecompute the axes[] values to match the new sensitivity or re-read them from 192*4882a593Smuzhiyunthe hardware so that they give valid values. 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun:: 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun int (*open)(struct gameport *, int mode); 197*4882a593Smuzhiyun 198*4882a593SmuzhiyunOpen() serves two purposes. First a driver either opens the port in raw or 199*4882a593Smuzhiyunin cooked mode, the open() callback can decide which modes are supported. 200*4882a593SmuzhiyunSecond, resource allocation can happen here. The port can also be enabled 201*4882a593Smuzhiyunhere. Prior to this call, other fields of the gameport struct (namely the io 202*4882a593Smuzhiyunmember) need not to be valid. 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun:: 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun void (*close)(struct gameport *); 207*4882a593Smuzhiyun 208*4882a593SmuzhiyunClose() should free the resources allocated by open, possibly disabling the 209*4882a593Smuzhiyungameport. 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun:: 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun struct gameport_dev *dev; 214*4882a593Smuzhiyun struct gameport *next; 215*4882a593Smuzhiyun 216*4882a593SmuzhiyunFor internal use by the gameport layer. 217*4882a593Smuzhiyun 218*4882a593Smuzhiyun:: 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun }; 221*4882a593Smuzhiyun 222*4882a593SmuzhiyunEnjoy! 223