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/u4b/usb.h>
47 #include <bus/u4b/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__)
62 #include <osreldate.h>
63 #if __FreeBSD_kernel_version > 800063
64 #include <dev/usb/usb_ioctl.h>
66 #include <sys/joystick.h>
67 #elif defined(__DragonFly__)
68 #include <bus/u4b/usb_ioctl.h>
69 #include <sys/joystick.h>
72 #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
73 #include <machine/joystick.h>
77 #include "../SDL_sysjoystick.h"
78 #include "../SDL_joystick_c.h"
80 #define MAX_UHID_JOYS 64
81 #define MAX_JOY_JOYS 2
82 #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
86 #define HUG_DPAD_UP 0x90
87 #define HUG_DPAD_DOWN 0x91
88 #define HUG_DPAD_RIGHT 0x92
89 #define HUG_DPAD_LEFT 0x93
91 #define HAT_CENTERED 0x00
93 #define HAT_RIGHT 0x02
96 #define HAT_RIGHTUP (HAT_RIGHT|HAT_UP)
97 #define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN)
98 #define HAT_LEFTUP (HAT_LEFT|HAT_UP)
99 #define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN)
109 return HAT_RIGHTDOWN;
112 }
else if (dpad[3]) {
119 }
else if (dpad[0]) {
121 }
else if (dpad[1]) {
130 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || \
131 defined(__DragonFly__)
133 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
134 struct usb_gen_descriptor *
buf;
136 struct usb_ctl_report *
buf;
153 }
const repinfo[] = {
154 {UHID_INPUT_REPORT, hid_input,
"input"},
155 {UHID_OUTPUT_REPORT, hid_output,
"output"},
156 {UHID_FEATURE_REPORT, hid_feature,
"feature"}
188 struct report_desc *repdesc;
189 struct report inreport;
190 int axis_map[JOYAXE_count];
193 static char *joynames[MAX_JOYS];
194 static char *joydevnames[MAX_JOYS];
196 static int report_alloc(
struct report *,
struct report_desc *,
int);
197 static void report_free(
struct report *);
199 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
200 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
201 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)) || \
202 defined(__DragonFly__)
203 #define REP_BUF_DATA(rep) ((rep)->buf)
204 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
205 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
207 #define REP_BUF_DATA(rep) ((rep)->buf->data)
212 static int BSD_JoystickOpen(SDL_Joystick *joy,
int device_index);
213 static void BSD_JoystickClose(SDL_Joystick *joy);
216 BSD_JoystickInit(
void)
224 SDL_memset(joydevnames, 0,
sizeof(joydevnames));
226 for (
i = 0;
i < MAX_UHID_JOYS;
i++) {
234 BSD_JoystickClose(&nj);
241 for (
i = 0;
i < MAX_JOY_JOYS;
i++) {
243 fd = open(
s, O_RDONLY);
257 BSD_JoystickGetCount(
void)
263 BSD_JoystickDetect(
void)
268 BSD_JoystickGetDeviceName(
int device_index)
270 if (joydevnames[device_index] !=
NULL) {
271 return (joydevnames[device_index]);
273 return (joynames[device_index]);
277 BSD_JoystickGetDevicePlayerIndex(
int device_index)
283 BSD_JoystickSetDevicePlayerIndex(
int device_index,
int player_index)
289 BSD_JoystickGetDeviceInstanceID(
int device_index)
295 usage_to_joyaxe(
unsigned usage)
309 joyaxe = JOYAXE_SLIDER;
312 joyaxe = JOYAXE_WHEEL;
330 hatval_to_sdl(
Sint32 hatval)
332 static const unsigned hat_dir_map[8] = {
337 if ((hatval & 7) == hatval)
338 result = hat_dir_map[hatval];
346 BSD_JoystickOpen(SDL_Joystick *joy,
int device_index)
348 char *
path = joynames[device_index];
350 struct hid_item hitem;
351 struct hid_data *hdata;
352 struct report *rep =
NULL;
353 #if defined(__NetBSD__)
354 usb_device_descriptor_t udd;
355 struct usb_string_desc usd;
360 fd = open(
path, O_RDONLY);
365 joy->instance_id = device_index;
376 hw->type = BSDJOY_JOY;
381 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
384 hw->type = BSDJOY_UHID;
389 for (ax = 0; ax < JOYAXE_count; ax++)
390 hw->axis_map[ax] = -1;
392 hw->repdesc = hid_get_report_desc(
fd);
393 if (hw->repdesc ==
NULL) {
399 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
400 rep->rid = hid_get_report_id(
fd);
403 if (ioctl(
fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
407 #if defined(__NetBSD__)
408 if (ioctl(
fd, USB_GET_DEVICE_DESC, &udd) == -1)
412 usd.usd_string_index = USB_LANGUAGE_TABLE;
413 usd.usd_language_id = 0;
414 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
415 usd.usd_language_id = 0;
417 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
420 usd.usd_string_index = udd.iProduct;
421 if (ioctl(
fd, USB_GET_STRING_DESC, &usd) == 0) {
423 char *new_name =
NULL;
425 for (
i = 0;
i < (usd.usd_desc.bLength >> 1) - 1 &&
i <
sizeof(str) - 1;
i++) {
426 str[
i] = UGETW(usd.usd_desc.bString[
i]);
429 asprintf(&new_name,
"%s @ %s", str,
path);
430 if (new_name !=
NULL) {
437 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
440 if (rep->size <= 0) {
441 SDL_SetError(
"%s: Input report descriptor has invalid length",
445 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
446 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
448 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
458 for (
i = 0;
i < JOYAXE_count;
i++)
459 hw->axis_map[
i] = -1;
461 while (hid_get_item(hdata, &hitem) > 0) {
465 switch (hitem.kind) {
467 switch (HID_PAGE(hitem.usage)) {
468 case HUP_GENERIC_DESKTOP:
469 switch (HID_USAGE(hitem.usage)) {
472 s = hid_usage_in_page(hitem.usage);
476 joydevnames[device_index] = sp;
481 switch (HID_PAGE(hitem.usage)) {
482 case HUP_GENERIC_DESKTOP:
484 unsigned usage = HID_USAGE(hitem.usage);
485 int joyaxe = usage_to_joyaxe(
usage);
487 hw->axis_map[joyaxe] = 1;
488 }
else if (
usage == HUG_HAT_SWITCH
490 ||
usage == HUG_DPAD_UP
508 hid_end_parse(hdata);
509 for (
i = 0;
i < JOYAXE_count;
i++)
510 if (hw->axis_map[
i] > 0)
511 hw->axis_map[
i] = joy->
naxes++;
513 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
520 fcntl(
fd, F_SETFL, O_NONBLOCK);
524 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
538 BSD_JoystickUpdate(SDL_Joystick *joy)
540 struct hid_item hitem;
541 struct hid_data *hdata;
543 int nbutton, naxe = -1;
546 Sint32 dpad[4] = {0, 0, 0, 0};
549 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) || defined(__DragonFly_)
551 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
553 if (joy->hwdata->type == BSDJOY_JOY) {
554 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
555 if (abs(
x - gameport.x) > 8) {
568 v -= (xmax + xmin + 1) / 2;
569 v *= 32768 / ((xmax - xmin + 1) / 2);
572 if (abs(
y - gameport.y) > 8) {
585 v -= (ymax + ymin + 1) / 2;
586 v *= 32768 / ((ymax - ymin + 1) / 2);
596 rep = &joy->hwdata->inreport;
598 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
599 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
600 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
602 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
609 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
610 switch (hitem.kind) {
612 switch (HID_PAGE(hitem.usage)) {
613 case HUP_GENERIC_DESKTOP:
615 unsigned usage = HID_USAGE(hitem.usage);
616 int joyaxe = usage_to_joyaxe(
usage);
618 naxe = joy->hwdata->axis_map[joyaxe];
620 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
621 v -= (hitem.logical_maximum +
622 hitem.logical_minimum + 1) / 2;
624 ((hitem.logical_maximum -
625 hitem.logical_minimum + 1) / 2);
627 }
else if (
usage == HUG_HAT_SWITCH) {
628 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
631 hitem.logical_minimum);
634 else if (
usage == HUG_DPAD_UP) {
635 dpad[0] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
638 else if (
usage == HUG_DPAD_DOWN) {
639 dpad[1] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
642 else if (
usage == HUG_DPAD_RIGHT) {
643 dpad[2] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
646 else if (
usage == HUG_DPAD_LEFT) {
647 dpad[3] = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
654 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
666 hid_end_parse(hdata);
672 BSD_JoystickClose(SDL_Joystick *joy)
674 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
675 report_free(&joy->hwdata->inreport);
676 hid_dispose_report_desc(joy->hwdata->repdesc);
678 close(joy->hwdata->fd);
684 BSD_JoystickQuit(
void)
688 for (
i = 0;
i < MAX_JOYS;
i++) {
697 BSD_JoystickGetDeviceGUID(
int device_index )
701 const char *
name = BSD_JoystickGetDeviceName( device_index );
708 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
713 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
715 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
716 # if (__FreeBSD_kernel_version <= 500111)
717 len = hid_report_size(rd,
r->rid, repinfo[repind].kind);
719 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
722 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
726 len = hid_report_size(rd, repinfo[repind].kind,
r->rid);
728 len = hid_report_size(rd, repinfo[repind].kind, &
r->rid);
738 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) || defined(__DragonFly__)
741 r->buf =
SDL_malloc(
sizeof(*
r->buf) -
sizeof(REP_BUF_DATA(
r)) +
744 if (
r->buf ==
NULL) {
751 r->status = SREPORT_CLEAN;
756 report_free(
struct report *
r)
759 r->status = SREPORT_UNINIT;
763 BSD_JoystickRumble(SDL_Joystick *
joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble)
781 BSD_JoystickHasLED(SDL_Joystick *
joystick)
801 BSD_JoystickGetCount,
803 BSD_JoystickGetDeviceName,
804 BSD_JoystickGetDevicePlayerIndex,
805 BSD_JoystickSetDevicePlayerIndex,
806 BSD_JoystickGetDeviceGUID,
807 BSD_JoystickGetDeviceInstanceID,
810 BSD_JoystickRumbleTriggers,
813 BSD_JoystickSetSensorsEnabled,
817 BSD_JoystickGetGamepadMapping
#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
GLenum GLenum GLsizei const GLuint GLboolean enabled
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.
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if
static SDL_Joystick * joystick