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) 86 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 88 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) 89 struct usb_gen_descriptor *
buf;
91 struct usb_ctl_report *
buf;
108 }
const repinfo[] = {
109 {UHID_INPUT_REPORT, hid_input,
"input"},
110 {UHID_OUTPUT_REPORT, hid_output,
"output"},
111 {UHID_FEATURE_REPORT, hid_feature,
"feature"}
143 struct report_desc *repdesc;
144 struct report inreport;
145 int axis_map[JOYAXE_count];
148 static char *joynames[MAX_JOYS];
149 static char *joydevnames[MAX_JOYS];
151 static int report_alloc(
struct report *,
struct report_desc *,
int);
152 static void report_free(
struct report *);
154 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063) 155 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) 156 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)) 157 #define REP_BUF_DATA(rep) ((rep)->buf) 158 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) 159 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) 161 #define REP_BUF_DATA(rep) ((rep)->buf->data) 164 static int SDL_SYS_numjoysticks = 0;
172 SDL_SYS_numjoysticks = 0;
175 SDL_memset(joydevnames, 0,
sizeof(joydevnames));
177 for (i = 0; i < MAX_UHID_JOYS; i++) {
182 joynames[SDL_SYS_numjoysticks] =
SDL_strdup(s);
186 SDL_SYS_numjoysticks++;
188 SDL_free(joynames[SDL_SYS_numjoysticks]);
189 joynames[SDL_SYS_numjoysticks] =
NULL;
192 for (i = 0; i < MAX_JOY_JOYS; i++) {
194 fd = open(s, O_RDONLY);
196 joynames[SDL_SYS_numjoysticks++] =
SDL_strdup(s);
204 return (SDL_SYS_numjoysticks);
210 return SDL_SYS_numjoysticks;
221 if (joydevnames[device_index] !=
NULL) {
222 return (joydevnames[device_index]);
224 return (joynames[device_index]);
234 usage_to_joyaxe(
unsigned usage)
248 joyaxe = JOYAXE_SLIDER;
251 joyaxe = JOYAXE_WHEEL;
269 hatval_to_sdl(
Sint32 hatval)
271 static const unsigned hat_dir_map[8] = {
276 if ((hatval & 7) == hatval)
277 result = hat_dir_map[hatval];
287 char *
path = joynames[device_index];
289 struct hid_item hitem;
290 struct hid_data *hdata;
291 struct report *rep =
NULL;
295 fd = open(path, O_RDONLY);
300 joy->instance_id = device_index;
311 hw->type = BSDJOY_JOY;
316 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
319 hw->type = BSDJOY_UHID;
324 for (ax = 0; ax < JOYAXE_count; ax++)
325 hw->axis_map[ax] = -1;
327 hw->repdesc = hid_get_report_desc(fd);
328 if (hw->repdesc ==
NULL) {
334 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) 335 rep->rid = hid_get_report_id(fd);
338 if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
342 #if defined(__NetBSD__) 343 usb_device_descriptor_t udd;
344 struct usb_string_desc usd;
345 if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
349 usd.usd_string_index = USB_LANGUAGE_TABLE;
350 usd.usd_language_id = 0;
351 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
352 usd.usd_language_id = 0;
354 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
357 usd.usd_string_index = udd.iProduct;
358 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
360 char *new_name =
NULL;
362 for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i <
sizeof(str) - 1; i++) {
363 str[
i] = UGETW(usd.usd_desc.bString[i]);
366 asprintf(&new_name,
"%s @ %s", str, path);
367 if (new_name !=
NULL) {
368 SDL_free(joydevnames[SDL_SYS_numjoysticks]);
369 joydevnames[SDL_SYS_numjoysticks] = new_name;
374 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
377 if (rep->size <= 0) {
378 SDL_SetError(
"%s: Input report descriptor has invalid length",
382 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 383 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
385 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
395 for (i = 0; i < JOYAXE_count; i++)
396 hw->axis_map[i] = -1;
398 while (hid_get_item(hdata, &hitem) > 0) {
402 switch (hitem.kind) {
404 switch (HID_PAGE(hitem.usage)) {
405 case HUP_GENERIC_DESKTOP:
406 switch (HID_USAGE(hitem.usage)) {
409 s = hid_usage_in_page(hitem.usage);
413 joydevnames[device_index] = sp;
418 switch (HID_PAGE(hitem.usage)) {
419 case HUP_GENERIC_DESKTOP:
421 unsigned usage = HID_USAGE(hitem.usage);
422 int joyaxe = usage_to_joyaxe(usage);
424 hw->axis_map[joyaxe] = 1;
425 }
else if (usage == HUG_HAT_SWITCH) {
441 hid_end_parse(hdata);
442 for (i = 0; i < JOYAXE_count; i++)
443 if (hw->axis_map[i] > 0)
444 hw->axis_map[
i] = joy->
naxes++;
446 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
453 fcntl(fd, F_SETFL, O_NONBLOCK);
457 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
479 struct hid_item hitem;
480 struct hid_data *hdata;
482 int nbutton, naxe = -1;
485 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) 486 struct joystick gameport;
487 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
489 if (joy->hwdata->type == BSDJOY_JOY) {
490 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
491 if (abs(x - gameport.x) > 8) {
504 v -= (xmax + xmin + 1) / 2;
505 v *= 32768 / ((xmax - xmin + 1) / 2);
508 if (abs(y - gameport.y) > 8) {
521 v -= (ymax + ymin + 1) / 2;
522 v *= 32768 / ((ymax - ymin + 1) / 2);
532 rep = &joy->hwdata->inreport;
534 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
535 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 536 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
538 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
545 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
546 switch (hitem.kind) {
548 switch (HID_PAGE(hitem.usage)) {
549 case HUP_GENERIC_DESKTOP:
551 unsigned usage = HID_USAGE(hitem.usage);
552 int joyaxe = usage_to_joyaxe(usage);
554 naxe = joy->hwdata->axis_map[joyaxe];
556 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
557 v -= (hitem.logical_maximum +
558 hitem.logical_minimum + 1) / 2;
560 ((hitem.logical_maximum -
561 hitem.logical_minimum + 1) / 2);
563 }
else if (usage == HUG_HAT_SWITCH) {
564 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
567 hitem.logical_minimum);
572 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
584 hid_end_parse(hdata);
592 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
593 report_free(&joy->hwdata->inreport);
594 hid_dispose_report_desc(joy->hwdata->repdesc);
596 close(joy->hwdata->fd);
606 for (i = 0; i < MAX_JOYS; i++) {
628 const char *name = joystick->name;
635 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
640 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
642 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) 643 # if (__FreeBSD_kernel_version <= 500111) 644 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
646 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
649 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
653 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
655 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
665 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 668 r->buf =
SDL_malloc(
sizeof(*r->buf) -
sizeof(REP_BUF_DATA(r)) +
671 if (r->buf ==
NULL) {
678 r->status = SREPORT_CLEAN;
683 report_free(
struct report *r)
686 r->status = SREPORT_UNINIT;
GLdouble GLdouble GLdouble r
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
GLint GLint GLint GLint GLint x
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
void SDL_SYS_JoystickQuit(void)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint const GLchar * name
GLsizeiptr const void GLenum usage
#define SDL_HAT_RIGHTDOWN
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
GLint GLint GLint GLint GLint GLint y
GLenum GLuint GLenum GLsizei const GLchar * buf
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
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 SDL_SYS_JoystickInit(void)
#define SDL_OutOfMemory()
int SDL_SYS_NumJoysticks(void)
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
GLuint GLuint GLsizei GLenum type
#define SDL_arraysize(array)
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
GLsizei const GLchar *const * path
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
void SDL_SYS_JoystickDetect(void)