Mercurial > sdl-ios-xcode
comparison src/joystick/bsd/SDL_sysjoystick.c @ 632:85e104fe14c2
Date: Sun, 1 Jun 2003 15:38:45 -0700 (PDT)
From: Jeff Brown <jabrown@caida.org>
Subject: [patch] SDL-1.2.5 + FreeBSD joystick axes, hat fixes
Hello again! When I sent in some SDL fixes last December, I found out
they'd already been fixed in the CVS version. This time, I checked the
repository before bugging you. =)
I'm using SDL-1.2.5 on a FreeBSD 4.6.2-RELEASE system, and in the course
of getting my multi-analog-axis USB controller (with a hat switch!)
working with d2x-sdl -- the SDL port of the Descent 2 engine -- I came
across a few problems:
1) The second analog stick is reported as a slider in one direction, and
"Rz" in the other. SDL was ignoring the Rz axis, so I added Rx/Ry/Rz to
the set of things SDL considers to be axes.
2) After the above change, the set of JOYAXE_* axes for my gamepad was
{0,1,3,7}; however, d2x-sdl expects the axes to be contiguously numbered
from 0, which seems like a pretty reasonable expectation, rather than
having to scan the entire space of axes that SDL may or may not have.
So, I added a table lookup which maps the JOYAXE_* axis numbers to 0,1,...
in the order they're detected by SDL_SYS_JoystickOpen(), when reporting
them to the application. I also added a function "usage_to_joyaxe()"
which maps the USB HUG_* usage values to JOYAXE_values, since the repeated
case statements testing for HUG_* were getting out of hand.
3) The BSD joystick driver had no hat support, so I added it. It looks
like our USB library can only support one hat switch per device, which
makes life easy.
The patch against SDL-1.2.5 which implements these changes is at:
http://www.caida.org/~jabrown/patches/sdl-1.2.5-bsdhat.diff
After applying, SDL's "testjoystick" reports all activity from my gamepad
correctly, and d2x works too (though it needed some other fixes).
Moving on...
There is also a problem with slightly different USBHID library interfaces
on different versions of FreeBSD. I wasn't going to mention this since the
FreeBSD port for SDL-1.2.5 (and not SDL itself) was doing the FreeBSD
version-specific patching, so I e-mailed the port maintainer with this
change. However, I see that you've incorporated the FreeBSD
version-checking stuff into the CVS version of SDL, so now it's relevant
for you too.
The problem is, the FreeBSD #if tests don't work right for FreeBSD
4.6.2-RELEASE. There may be other versions with this problem, but I've
only tested 4.6.2-R. The following patch against your latest CVS version
fixes this:
--- SDL_sysjoystick.c-1.16 Tue Apr 15 09:02:08 2003
+++ SDL_sysjoystick.c Sun Jun 1 15:10:28 2003
@@ -420,6 +420,8 @@
# else
len = hid_report_size(rd, repinfo[repind].kind, r->rid);
# endif
+# elif (__FreeBSD_version == 460002)
+ len = hid_report_size(rd, r->rid, repinfo[repind].kind);
# else
len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
#endif
I hope this is all useful to you. I've been getting myself dizzy playing
Descent 2 with it, all morning!
-Jeff Brown
P.S. My USB controller is a Thrustmaster Firestorm Dual Analog 2. That's
probably irrelevant, but I threw it in for completeness.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 02 Jun 2003 14:50:22 +0000 |
parents | 0a2ef9e8ca41 |
children | de0351c47596 |
comparison
equal
deleted
inserted
replaced
631:52864d66d168 | 632:85e104fe14c2 |
---|---|
98 enum { | 98 enum { |
99 JOYAXE_X, | 99 JOYAXE_X, |
100 JOYAXE_Y, | 100 JOYAXE_Y, |
101 JOYAXE_Z, | 101 JOYAXE_Z, |
102 JOYAXE_SLIDER, | 102 JOYAXE_SLIDER, |
103 JOYAXE_WHEEL | 103 JOYAXE_WHEEL, |
104 JOYAXE_RX, | |
105 JOYAXE_RY, | |
106 JOYAXE_RZ, | |
107 JOYAXE_count | |
104 }; | 108 }; |
105 | 109 |
106 struct joystick_hwdata { | 110 struct joystick_hwdata { |
107 int fd; | 111 int fd; |
108 char *path; | 112 char *path; |
110 BSDJOY_UHID, /* uhid(4) */ | 114 BSDJOY_UHID, /* uhid(4) */ |
111 BSDJOY_JOY /* joy(4) */ | 115 BSDJOY_JOY /* joy(4) */ |
112 } type; | 116 } type; |
113 struct report_desc *repdesc; | 117 struct report_desc *repdesc; |
114 struct report inreport; | 118 struct report inreport; |
115 #if 0 | 119 int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,..*/ |
116 int axismin[]; | |
117 int axismax[]; | |
118 #endif | |
119 }; | 120 }; |
120 | 121 |
121 static char *joynames[MAX_JOYS]; | 122 static char *joynames[MAX_JOYS]; |
122 static char *joydevnames[MAX_JOYS]; | 123 static char *joydevnames[MAX_JOYS]; |
123 | 124 |
178 return (joydevnames[index]); | 179 return (joydevnames[index]); |
179 } | 180 } |
180 return (joynames[index]); | 181 return (joynames[index]); |
181 } | 182 } |
182 | 183 |
184 static int | |
185 usage_to_joyaxe(unsigned usage) | |
186 { | |
187 int joyaxe; | |
188 switch (usage) { | |
189 case HUG_X: | |
190 joyaxe = JOYAXE_X; break; | |
191 case HUG_Y: | |
192 joyaxe = JOYAXE_Y; break; | |
193 case HUG_Z: | |
194 joyaxe = JOYAXE_Z; break; | |
195 case HUG_SLIDER: | |
196 joyaxe = JOYAXE_SLIDER; break; | |
197 case HUG_WHEEL: | |
198 joyaxe = JOYAXE_WHEEL; break; | |
199 case HUG_RX: | |
200 joyaxe = JOYAXE_RX; break; | |
201 case HUG_RY: | |
202 joyaxe = JOYAXE_RY; break; | |
203 case HUG_RZ: | |
204 joyaxe = JOYAXE_RZ; break; | |
205 default: | |
206 joyaxe = -1; | |
207 } | |
208 return joyaxe; | |
209 } | |
210 | |
211 static unsigned | |
212 hatval_to_sdl(Sint32 hatval) | |
213 { | |
214 static const unsigned hat_dir_map[8] = { | |
215 SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN, | |
216 SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP | |
217 }; | |
218 unsigned result; | |
219 if ((hatval & 7) == hatval) | |
220 result = hat_dir_map[hatval]; | |
221 else | |
222 result = SDL_HAT_CENTERED; | |
223 return result; | |
224 } | |
225 | |
226 | |
183 int | 227 int |
184 SDL_SYS_JoystickOpen(SDL_Joystick *joy) | 228 SDL_SYS_JoystickOpen(SDL_Joystick *joy) |
185 { | 229 { |
186 char *path = joynames[joy->index]; | 230 char *path = joynames[joy->index]; |
187 struct joystick_hwdata *hw; | 231 struct joystick_hwdata *hw; |
204 } | 248 } |
205 joy->hwdata = hw; | 249 joy->hwdata = hw; |
206 hw->fd = fd; | 250 hw->fd = fd; |
207 hw->path = strdup(path); | 251 hw->path = strdup(path); |
208 hw->type = BSDJOY_UHID; | 252 hw->type = BSDJOY_UHID; |
253 { | |
254 int ax; | |
255 for (ax = 0; ax < JOYAXE_count; ax++) | |
256 hw->axis_map[ax] = -1; | |
257 } | |
209 hw->repdesc = hid_get_report_desc(fd); | 258 hw->repdesc = hid_get_report_desc(fd); |
210 if (hw->repdesc == NULL) { | 259 if (hw->repdesc == NULL) { |
211 SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path, | 260 SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path, |
212 strerror(errno)); | 261 strerror(errno)); |
213 goto usberr; | 262 goto usberr; |
257 } | 306 } |
258 } | 307 } |
259 break; | 308 break; |
260 case hid_input: | 309 case hid_input: |
261 switch (HID_PAGE(hitem.usage)) { | 310 switch (HID_PAGE(hitem.usage)) { |
262 case HUP_GENERIC_DESKTOP: | 311 case HUP_GENERIC_DESKTOP: { |
263 switch (HID_USAGE(hitem.usage)) { | 312 unsigned usage = HID_USAGE(hitem.usage); |
264 case HUG_X: | 313 int joyaxe = usage_to_joyaxe(usage); |
265 case HUG_Y: | 314 if (joyaxe >= 0) { |
266 case HUG_Z: | 315 hw->axis_map[joyaxe] = joy->naxes; |
267 case HUG_SLIDER: | 316 joy->naxes++; |
268 case HUG_WHEEL: | 317 } else if (usage == HUG_HAT_SWITCH) { |
269 #if 0 | 318 joy->nhats++; |
270 hw->axismin[joy->naxes] = | 319 } |
271 hitem.logical_minimum; | 320 break; |
272 hw->axismax[joy->naxes] = | 321 } |
273 hitem.logical_maximum; | |
274 #endif | |
275 joy->naxes++; | |
276 break; | |
277 } | |
278 break; | |
279 case HUP_BUTTON: | 322 case HUP_BUTTON: |
280 joy->nbuttons++; | 323 joy->nbuttons++; |
281 break; | 324 break; |
282 default: | 325 default: |
283 break; | 326 break; |
327 | 370 |
328 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { | 371 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { |
329 switch (hitem.kind) { | 372 switch (hitem.kind) { |
330 case hid_input: | 373 case hid_input: |
331 switch (HID_PAGE(hitem.usage)) { | 374 switch (HID_PAGE(hitem.usage)) { |
332 case HUP_GENERIC_DESKTOP: | 375 case HUP_GENERIC_DESKTOP: { |
333 switch (HID_USAGE(hitem.usage)) { | 376 unsigned usage = HID_USAGE(hitem.usage); |
334 case HUG_X: | 377 int joyaxe = usage_to_joyaxe(usage); |
335 naxe = JOYAXE_X; | 378 if (joyaxe >= 0) { |
336 goto scaleaxe; | 379 naxe = joy->hwdata->axis_map[joyaxe]; |
337 case HUG_Y: | 380 /* scaleaxe */ |
338 naxe = JOYAXE_Y; | |
339 goto scaleaxe; | |
340 case HUG_Z: | |
341 naxe = JOYAXE_Z; | |
342 goto scaleaxe; | |
343 case HUG_SLIDER: | |
344 naxe = JOYAXE_SLIDER; | |
345 goto scaleaxe; | |
346 case HUG_WHEEL: | |
347 naxe = JOYAXE_WHEEL; | |
348 goto scaleaxe; | |
349 default: | |
350 continue; | |
351 } | |
352 scaleaxe: | |
353 v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | 381 v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
354 &hitem); | 382 &hitem); |
355 v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; | 383 v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; |
356 v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); | 384 v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); |
357 if (v != joy->axes[naxe]) { | 385 if (v != joy->axes[naxe]) { |
358 SDL_PrivateJoystickAxis(joy, naxe, v); | 386 SDL_PrivateJoystickAxis(joy, naxe, v); |
359 } | 387 } |
360 break; | 388 } else if (usage == HUG_HAT_SWITCH) { |
389 v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | |
390 &hitem); | |
391 SDL_PrivateJoystickHat(joy, 0, hatval_to_sdl(v)); | |
392 } | |
393 break; | |
394 } | |
361 case HUP_BUTTON: | 395 case HUP_BUTTON: |
362 v = (Sint32)hid_get_data(REP_BUF_DATA(rep), | 396 v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
363 &hitem); | 397 &hitem); |
364 if (joy->buttons[nbutton] != v) { | 398 if (joy->buttons[nbutton] != v) { |
365 SDL_PrivateJoystickButton(joy, | 399 SDL_PrivateJoystickButton(joy, |
418 # if (__FreeBSD_version <= 500111) | 452 # if (__FreeBSD_version <= 500111) |
419 len = hid_report_size(rd, r->rid, repinfo[repind].kind); | 453 len = hid_report_size(rd, r->rid, repinfo[repind].kind); |
420 # else | 454 # else |
421 len = hid_report_size(rd, repinfo[repind].kind, r->rid); | 455 len = hid_report_size(rd, repinfo[repind].kind, r->rid); |
422 # endif | 456 # endif |
457 # elif (__FreeBSD_version == 460002) | |
458 len = hid_report_size(rd, r->rid, repinfo[repind].kind); | |
423 # else | 459 # else |
424 len = hid_report_size(rd, repinfo[repind].kind, &r->rid); | 460 len = hid_report_size(rd, repinfo[repind].kind, &r->rid); |
425 #endif | 461 #endif |
426 #else | 462 #else |
427 # ifdef USBHID_NEW | 463 # ifdef USBHID_NEW |