21 #include "../../SDL_internal.h"
23 #ifdef SDL_JOYSTICK_USBHID
32 #include <sys/param.h>
38 #ifndef __FreeBSD_kernel_version
39 #define __FreeBSD_kernel_version __FreeBSD_version
42 #if defined(HAVE_USB_H)
46 #include <bus/usb/usb.h>
47 #include <bus/usb/usbhid.h>
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbhid.h>
53 #if defined(HAVE_USBHID_H)
55 #elif defined(HAVE_LIBUSB_H)
57 #elif defined(HAVE_LIBUSBHID_H)
58 #include <libusbhid.h>
61 #if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
63 #include <osreldate.h>
65 #if __FreeBSD_kernel_version > 800063
66 #include <dev/usb/usb_ioctl.h>
68 #include <sys/joystick.h>
71 #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
72 #include <machine/joystick.h>
76 #include "../SDL_sysjoystick.h"
77 #include "../SDL_joystick_c.h"
79 #define MAX_UHID_JOYS 64
80 #define MAX_JOY_JOYS 2
81 #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
85 #define HUG_DPAD_UP 0x90
86 #define HUG_DPAD_DOWN 0x91
87 #define HUG_DPAD_RIGHT 0x92
88 #define HUG_DPAD_LEFT 0x93
90 #define HAT_CENTERED 0x00
92 #define HAT_RIGHT 0x02
95 #define HAT_RIGHTUP (HAT_RIGHT|HAT_UP)
96 #define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN)
97 #define HAT_LEFTUP (HAT_LEFT|HAT_UP)
98 #define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN)
108 return HAT_RIGHTDOWN;
111 }
else if (dpad[3]) {
118 }
else if (dpad[0]) {
120 }
else if (dpad[1]) {
129 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
131 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
132 struct usb_gen_descriptor *
buf;
134 struct usb_ctl_report *
buf;
151 }
const repinfo[] = {
152 {UHID_INPUT_REPORT, hid_input,
"input"},
153 {UHID_OUTPUT_REPORT, hid_output,
"output"},
154 {UHID_FEATURE_REPORT, hid_feature,
"feature"}
186 struct report_desc *repdesc;
187 struct report inreport;
188 int axis_map[JOYAXE_count];
191 static char *joynames[MAX_JOYS];
192 static char *joydevnames[MAX_JOYS];
194 static int report_alloc(
struct report *,
struct report_desc *,
int);
195 static void report_free(
struct report *);
197 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
198 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
199 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000))
200 #define REP_BUF_DATA(rep) ((rep)->buf)
201 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
202 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
204 #define REP_BUF_DATA(rep) ((rep)->buf->data)
209 static int BSD_JoystickOpen(SDL_Joystick * joy,
int device_index);
210 static void BSD_JoystickClose(SDL_Joystick * joy);
213 BSD_JoystickInit(
void)
221 SDL_memset(joydevnames, 0,
sizeof(joydevnames));
223 for (
i = 0;
i < MAX_UHID_JOYS;
i++) {
231 BSD_JoystickClose(&nj);
238 for (
i = 0;
i < MAX_JOY_JOYS;
i++) {
240 fd = open(
s, O_RDONLY);
254 BSD_JoystickGetCount(
void)
260 BSD_JoystickDetect(
void)
265 BSD_JoystickGetDeviceName(
int device_index)
267 if (joydevnames[device_index] !=
NULL) {
268 return (joydevnames[device_index]);
270 return (joynames[device_index]);
274 BSD_JoystickGetDevicePlayerIndex(
int device_index)
280 BSD_JoystickSetDevicePlayerIndex(
int device_index,
int player_index)
286 BSD_JoystickGetDeviceInstanceID(
int device_index)
292 usage_to_joyaxe(
unsigned usage)
306 joyaxe = JOYAXE_SLIDER;
309 joyaxe = JOYAXE_WHEEL;
327 hatval_to_sdl(
Sint32 hatval)
329 static const unsigned hat_dir_map[8] = {
334 if ((hatval & 7) == hatval)
335 result = hat_dir_map[hatval];
343 BSD_JoystickOpen(SDL_Joystick * joy,
int device_index)
345 char *
path = joynames[device_index];
347 struct hid_item hitem;
348 struct hid_data *hdata;
349 struct report *rep =
NULL;
350 #if defined(__NetBSD__)
351 usb_device_descriptor_t udd;
352 struct usb_string_desc usd;
357 fd = open(
path, O_RDONLY);
362 joy->instance_id = device_index;
373 hw->type = BSDJOY_JOY;
378 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
381 hw->type = BSDJOY_UHID;
386 for (ax = 0; ax < JOYAXE_count; ax++)
387 hw->axis_map[ax] = -1;
389 hw->repdesc = hid_get_report_desc(
fd);
390 if (hw->repdesc ==
NULL) {
396 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
397 rep->rid = hid_get_report_id(
fd);
400 if (ioctl(
fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
404 #if defined(__NetBSD__)
405 if (ioctl(
fd, USB_GET_DEVICE_DESC, &udd) == -1)
409 usd.usd_string_index = USB_LANGUAGE_TABLE;
410 usd.usd_language_id = 0;
411 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
412 usd.usd_language_id = 0;
414 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
417 usd.usd_string_index = udd.iProduct;
418 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == 0) {
420 char *new_name =
NULL;
422 for (
i = 0;
i < (usd.usd_desc.bLength >> 1) - 1 &&
i <
sizeof(str) - 1;
i++) {
423 str[
i] = UGETW(usd.usd_desc.bString[
i]);
426 asprintf(&new_name,
"%s @ %s", str,
path);
427 if (new_name !=
NULL) {
434 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
437 if (rep->size <= 0) {
438 SDL_SetError(
"%s: Input report descriptor has invalid length",
442 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
443 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
445 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
455 for (
i = 0;
i < JOYAXE_count;
i++)
456 hw->axis_map[
i] = -1;
458 while (hid_get_item(hdata, &hitem) > 0) {
462 switch (hitem.kind) {
464 switch (HID_PAGE(hitem.usage)) {
465 case HUP_GENERIC_DESKTOP:
466 switch (HID_USAGE(hitem.usage)) {
469 s = hid_usage_in_page(hitem.usage);
473 joydevnames[device_index] = sp;
478 switch (HID_PAGE(hitem.usage)) {
479 case HUP_GENERIC_DESKTOP:
481 unsigned usage = HID_USAGE(hitem.usage);
482 int joyaxe = usage_to_joyaxe(
usage);
484 hw->axis_map[joyaxe] = 1;
485 }
else if (
usage == HUG_HAT_SWITCH
487 ||
usage == HUG_DPAD_UP
505 hid_end_parse(hdata);
506 for (
i = 0;
i < JOYAXE_count;
i++)
507 if (hw->axis_map[
i] > 0)
508 hw->axis_map[
i] = joy->
naxes++;
510 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
517 fcntl(
fd, F_SETFL, O_NONBLOCK);
521 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
535 BSD_JoystickUpdate(SDL_Joystick * joy)
537 struct hid_item hitem;
538 struct hid_data *hdata;
540 int nbutton, naxe = -1;
543 Sint32 dpad[4] = {0, 0, 0, 0};
546 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
547 struct joystick gameport;
548 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
550 if (joy->hwdata->type == BSDJOY_JOY) {
551 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
552 if (abs(
x - gameport.x) > 8) {
565 v -= (xmax + xmin + 1) / 2;
566 v *= 32768 / ((xmax - xmin + 1) / 2);
569 if (abs(
y - gameport.y) > 8) {
582 v -= (ymax + ymin + 1) / 2;
583 v *= 32768 / ((ymax - ymin + 1) / 2);
593 rep = &joy->hwdata->inreport;
595 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
596 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
597 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
599 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
606 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
607 switch (hitem.kind) {
609 switch (HID_PAGE(hitem.usage)) {
610 case HUP_GENERIC_DESKTOP:
612 unsigned usage = HID_USAGE(hitem.usage);
613 int joyaxe = usage_to_joyaxe(
usage);
615 naxe = joy->hwdata->axis_map[joyaxe];
617 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
618 v -= (hitem.logical_maximum +
619 hitem.logical_minimum + 1) / 2;
621 ((hitem.logical_maximum -
622 hitem.logical_minimum + 1) / 2);
624 }
else if (
usage == HUG_HAT_SWITCH) {
625 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
628 hitem.logical_minimum);
631 else if (
usage == HUG_DPAD_UP) {
632 dpad[0] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
635 else if (
usage == HUG_DPAD_DOWN) {
636 dpad[1] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
639 else if (
usage == HUG_DPAD_RIGHT) {
640 dpad[2] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
643 else if (
usage == HUG_DPAD_LEFT) {
644 dpad[3] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
651 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
663 hid_end_parse(hdata);
669 BSD_JoystickClose(SDL_Joystick * joy)
671 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
672 report_free(&joy->hwdata->inreport);
673 hid_dispose_report_desc(joy->hwdata->repdesc);
675 close(joy->hwdata->fd);
681 BSD_JoystickQuit(
void)
685 for (
i = 0;
i < MAX_JOYS;
i++) {
694 BSD_JoystickGetDeviceGUID(
int device_index )
698 const char *
name = BSD_JoystickGetDeviceName( device_index );
705 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
710 len = hid_report_size(rd,
r->rid, repinfo[repind].kind);
712 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
713 # if (__FreeBSD_kernel_version <= 500111)
714 len = hid_report_size(rd,
r->rid, repinfo[repind].kind);
716 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
719 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
723 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
725 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
735 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
738 r->buf =
SDL_malloc(
sizeof(*
r->buf) -
sizeof(REP_BUF_DATA(
r)) +
741 if (
r->buf ==
NULL) {
748 r->status = SREPORT_CLEAN;
753 report_free(
struct report *
r)
756 r->status = SREPORT_UNINIT;
760 BSD_JoystickRumble(SDL_Joystick * joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble)
768 BSD_JoystickGetCount,
770 BSD_JoystickGetDeviceName,
771 BSD_JoystickGetDevicePlayerIndex,
772 BSD_JoystickSetDevicePlayerIndex,
773 BSD_JoystickGetDeviceGUID,
774 BSD_JoystickGetDeviceInstanceID,