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)
281 BSD_JoystickGetDeviceInstanceID(
int device_index)
287 usage_to_joyaxe(
unsigned usage)
301 joyaxe = JOYAXE_SLIDER;
304 joyaxe = JOYAXE_WHEEL;
322 hatval_to_sdl(
Sint32 hatval)
324 static const unsigned hat_dir_map[8] = {
329 if ((hatval & 7) == hatval)
330 result = hat_dir_map[hatval];
338 BSD_JoystickOpen(SDL_Joystick * joy,
int device_index)
340 char *
path = joynames[device_index];
342 struct hid_item hitem;
343 struct hid_data *hdata;
344 struct report *rep =
NULL;
345 #if defined(__NetBSD__)
346 usb_device_descriptor_t udd;
347 struct usb_string_desc usd;
352 fd = open(
path, O_RDONLY);
357 joy->instance_id = device_index;
368 hw->type = BSDJOY_JOY;
373 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
376 hw->type = BSDJOY_UHID;
381 for (ax = 0; ax < JOYAXE_count; ax++)
382 hw->axis_map[ax] = -1;
384 hw->repdesc = hid_get_report_desc(
fd);
385 if (hw->repdesc ==
NULL) {
391 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
392 rep->rid = hid_get_report_id(
fd);
395 if (ioctl(
fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
399 #if defined(__NetBSD__)
400 if (ioctl(
fd, USB_GET_DEVICE_DESC, &udd) == -1)
404 usd.usd_string_index = USB_LANGUAGE_TABLE;
405 usd.usd_language_id = 0;
406 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
407 usd.usd_language_id = 0;
409 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
412 usd.usd_string_index = udd.iProduct;
413 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == 0) {
415 char *new_name =
NULL;
417 for (
i = 0;
i < (usd.usd_desc.bLength >> 1) - 1 &&
i <
sizeof(str) - 1;
i++) {
418 str[
i] = UGETW(usd.usd_desc.bString[
i]);
421 asprintf(&new_name,
"%s @ %s", str,
path);
422 if (new_name !=
NULL) {
429 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
432 if (rep->size <= 0) {
433 SDL_SetError(
"%s: Input report descriptor has invalid length",
437 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
438 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
440 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
450 for (
i = 0;
i < JOYAXE_count;
i++)
451 hw->axis_map[
i] = -1;
453 while (hid_get_item(hdata, &hitem) > 0) {
457 switch (hitem.kind) {
459 switch (HID_PAGE(hitem.usage)) {
460 case HUP_GENERIC_DESKTOP:
461 switch (HID_USAGE(hitem.usage)) {
464 s = hid_usage_in_page(hitem.usage);
468 joydevnames[device_index] = sp;
473 switch (HID_PAGE(hitem.usage)) {
474 case HUP_GENERIC_DESKTOP:
476 unsigned usage = HID_USAGE(hitem.usage);
477 int joyaxe = usage_to_joyaxe(
usage);
479 hw->axis_map[joyaxe] = 1;
480 }
else if (
usage == HUG_HAT_SWITCH
482 ||
usage == HUG_DPAD_UP
500 hid_end_parse(hdata);
501 for (
i = 0;
i < JOYAXE_count;
i++)
502 if (hw->axis_map[
i] > 0)
503 hw->axis_map[
i] = joy->
naxes++;
505 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
512 fcntl(
fd, F_SETFL, O_NONBLOCK);
516 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
530 BSD_JoystickUpdate(SDL_Joystick * joy)
532 struct hid_item hitem;
533 struct hid_data *hdata;
535 int nbutton, naxe = -1;
538 Sint32 dpad[4] = {0, 0, 0, 0};
541 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
542 struct joystick gameport;
543 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
545 if (joy->hwdata->type == BSDJOY_JOY) {
546 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
547 if (abs(
x - gameport.x) > 8) {
560 v -= (xmax + xmin + 1) / 2;
561 v *= 32768 / ((xmax - xmin + 1) / 2);
564 if (abs(
y - gameport.y) > 8) {
577 v -= (ymax + ymin + 1) / 2;
578 v *= 32768 / ((ymax - ymin + 1) / 2);
588 rep = &joy->hwdata->inreport;
590 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
591 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
592 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
594 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
601 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
602 switch (hitem.kind) {
604 switch (HID_PAGE(hitem.usage)) {
605 case HUP_GENERIC_DESKTOP:
607 unsigned usage = HID_USAGE(hitem.usage);
608 int joyaxe = usage_to_joyaxe(
usage);
610 naxe = joy->hwdata->axis_map[joyaxe];
612 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
613 v -= (hitem.logical_maximum +
614 hitem.logical_minimum + 1) / 2;
616 ((hitem.logical_maximum -
617 hitem.logical_minimum + 1) / 2);
619 }
else if (
usage == HUG_HAT_SWITCH) {
620 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
623 hitem.logical_minimum);
626 else if (
usage == HUG_DPAD_UP) {
627 dpad[0] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
630 else if (
usage == HUG_DPAD_DOWN) {
631 dpad[1] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
634 else if (
usage == HUG_DPAD_RIGHT) {
635 dpad[2] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
638 else if (
usage == HUG_DPAD_LEFT) {
639 dpad[3] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
646 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
658 hid_end_parse(hdata);
664 BSD_JoystickClose(SDL_Joystick * joy)
666 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
667 report_free(&joy->hwdata->inreport);
668 hid_dispose_report_desc(joy->hwdata->repdesc);
670 close(joy->hwdata->fd);
676 BSD_JoystickQuit(
void)
680 for (
i = 0;
i < MAX_JOYS;
i++) {
689 BSD_JoystickGetDeviceGUID(
int device_index )
693 const char *
name = BSD_JoystickGetDeviceName( device_index );
700 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
705 len = hid_report_size(rd,
r->rid, repinfo[repind].kind);
707 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
708 # if (__FreeBSD_kernel_version <= 500111)
709 len = hid_report_size(rd,
r->rid, repinfo[repind].kind);
711 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
714 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
718 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
720 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
730 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
733 r->buf =
SDL_malloc(
sizeof(*
r->buf) -
sizeof(REP_BUF_DATA(
r)) +
736 if (
r->buf ==
NULL) {
743 r->status = SREPORT_CLEAN;
748 report_free(
struct report *
r)
751 r->status = SREPORT_UNINIT;
755 BSD_JoystickRumble(SDL_Joystick * joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble,
Uint32 duration_ms)
763 BSD_JoystickGetCount,
765 BSD_JoystickGetDeviceName,
766 BSD_JoystickGetDevicePlayerIndex,
767 BSD_JoystickGetDeviceGUID,
768 BSD_JoystickGetDeviceInstanceID,