21#include "../../SDL_internal.h"
23#ifdef SDL_JOYSTICK_USBHID
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)
61#if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
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
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
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;
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];
191static char *joynames[MAX_JOYS];
192static char *joydevnames[MAX_JOYS];
194static int report_alloc(
struct report *,
struct report_desc *,
int);
195static 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)
209static int BSD_JoystickOpen(SDL_Joystick * joy,
int device_index);
210static void BSD_JoystickClose(SDL_Joystick * joy);
213BSD_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);
254BSD_JoystickGetCount(
void)
260BSD_JoystickDetect(
void)
265BSD_JoystickGetDeviceName(
int device_index)
267 if (joydevnames[device_index] !=
NULL) {
268 return (joydevnames[device_index]);
270 return (joynames[device_index]);
274BSD_JoystickGetDevicePlayerIndex(
int device_index)
281BSD_JoystickGetDeviceInstanceID(
int device_index)
287usage_to_joyaxe(
unsigned usage)
301 joyaxe = JOYAXE_SLIDER;
304 joyaxe = JOYAXE_WHEEL;
322hatval_to_sdl(
Sint32 hatval)
324 static const unsigned hat_dir_map[8] = {
329 if ((hatval & 7) == hatval)
330 result = hat_dir_map[hatval];
338BSD_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)
530BSD_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);
664BSD_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);
676BSD_JoystickQuit(
void)
680 for (
i = 0;
i < MAX_JOYS;
i++) {
689BSD_JoystickGetDeviceGUID(
int device_index )
693 const char *
name = BSD_JoystickGetDeviceName( device_index );
700report_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;
748report_free(
struct report *
r)
751 r->status = SREPORT_UNINIT;
755BSD_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,
#define SDL_OutOfMemory()
#define SDL_Unsupported()
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
#define SDL_HAT_RIGHTDOWN
GLint GLint GLint GLint GLint GLint y
GLdouble GLdouble GLdouble r
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei GLenum type
GLuint const GLchar * name
GLenum GLuint GLenum GLsizei const GLchar * buf
GLsizei const GLchar *const * path
GLsizeiptr const void GLenum usage
#define SDL_arraysize(array)
SDL_JoystickDriver SDL_BSD_JoystickDriver
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.