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);
209 return SDL_SYS_numjoysticks;
219 if (joydevnames[device_index] !=
NULL) {
220 return (joydevnames[device_index]);
222 return (joynames[device_index]);
232 usage_to_joyaxe(
unsigned usage)
246 joyaxe = JOYAXE_SLIDER;
249 joyaxe = JOYAXE_WHEEL;
267 hatval_to_sdl(
Sint32 hatval)
269 static const unsigned hat_dir_map[8] = {
274 if ((hatval & 7) == hatval)
275 result = hat_dir_map[hatval];
285 char *
path = joynames[device_index];
287 struct hid_item hitem;
288 struct hid_data *hdata;
289 struct report *rep =
NULL;
293 fd = open(path, O_RDONLY);
298 joy->instance_id = device_index;
309 hw->type = BSDJOY_JOY;
314 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
317 hw->type = BSDJOY_UHID;
322 for (ax = 0; ax < JOYAXE_count; ax++)
323 hw->axis_map[ax] = -1;
325 hw->repdesc = hid_get_report_desc(fd);
326 if (hw->repdesc ==
NULL) {
332 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) 333 rep->rid = hid_get_report_id(fd);
336 if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
340 #if defined(__NetBSD__) 341 usb_device_descriptor_t udd;
342 struct usb_string_desc usd;
343 if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
347 usd.usd_string_index = USB_LANGUAGE_TABLE;
348 usd.usd_language_id = 0;
349 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
350 usd.usd_language_id = 0;
352 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
355 usd.usd_string_index = udd.iProduct;
356 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
358 char *new_name =
NULL;
360 for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i <
sizeof(str) - 1; i++) {
361 str[
i] = UGETW(usd.usd_desc.bString[i]);
364 asprintf(&new_name,
"%s @ %s", str, path);
365 if (new_name !=
NULL) {
366 SDL_free(joydevnames[SDL_SYS_numjoysticks]);
367 joydevnames[SDL_SYS_numjoysticks] = new_name;
372 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
375 if (rep->size <= 0) {
376 SDL_SetError(
"%s: Input report descriptor has invalid length",
380 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 381 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
383 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
393 for (i = 0; i < JOYAXE_count; i++)
394 hw->axis_map[i] = -1;
396 while (hid_get_item(hdata, &hitem) > 0) {
400 switch (hitem.kind) {
402 switch (HID_PAGE(hitem.usage)) {
403 case HUP_GENERIC_DESKTOP:
404 switch (HID_USAGE(hitem.usage)) {
407 s = hid_usage_in_page(hitem.usage);
411 joydevnames[device_index] = sp;
416 switch (HID_PAGE(hitem.usage)) {
417 case HUP_GENERIC_DESKTOP:
419 unsigned usage = HID_USAGE(hitem.usage);
420 int joyaxe = usage_to_joyaxe(usage);
422 hw->axis_map[joyaxe] = 1;
423 }
else if (usage == HUG_HAT_SWITCH) {
439 hid_end_parse(hdata);
440 for (i = 0; i < JOYAXE_count; i++)
441 if (hw->axis_map[i] > 0)
442 hw->axis_map[
i] = joy->
naxes++;
444 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
451 fcntl(fd, F_SETFL, O_NONBLOCK);
455 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
477 struct hid_item hitem;
478 struct hid_data *hdata;
480 int nbutton, naxe = -1;
483 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) 484 struct joystick gameport;
485 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
487 if (joy->hwdata->type == BSDJOY_JOY) {
488 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
489 if (abs(x - gameport.x) > 8) {
502 v -= (xmax + xmin + 1) / 2;
503 v *= 32768 / ((xmax - xmin + 1) / 2);
506 if (abs(y - gameport.y) > 8) {
519 v -= (ymax + ymin + 1) / 2;
520 v *= 32768 / ((ymax - ymin + 1) / 2);
523 if (gameport.b1 != joy->buttons[0]) {
526 if (gameport.b2 != joy->buttons[1]) {
534 rep = &joy->hwdata->inreport;
536 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
537 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 538 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
540 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
547 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
548 switch (hitem.kind) {
550 switch (HID_PAGE(hitem.usage)) {
551 case HUP_GENERIC_DESKTOP:
553 unsigned usage = HID_USAGE(hitem.usage);
554 int joyaxe = usage_to_joyaxe(usage);
556 naxe = joy->hwdata->axis_map[joyaxe];
558 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
559 v -= (hitem.logical_maximum +
560 hitem.logical_minimum + 1) / 2;
562 ((hitem.logical_maximum -
563 hitem.logical_minimum + 1) / 2);
564 if (v != joy->axes[naxe]) {
567 }
else if (usage == HUG_HAT_SWITCH) {
568 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
571 hitem.logical_minimum);
576 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
577 if (joy->buttons[nbutton] != v) {
590 hid_end_parse(hdata);
598 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
599 report_free(&joy->hwdata->inreport);
600 hid_dispose_report_desc(joy->hwdata->repdesc);
602 close(joy->hwdata->fd);
612 for (i = 0; i < MAX_JOYS; i++) {
634 const char *name = joystick->name;
641 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
646 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
648 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) 649 # if (__FreeBSD_kernel_version <= 500111) 650 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
652 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
655 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
659 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
661 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
671 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 674 r->buf =
SDL_malloc(
sizeof(*r->buf) -
sizeof(REP_BUF_DATA(r)) +
677 if (r->buf ==
NULL) {
684 r->status = SREPORT_CLEAN;
689 report_free(
struct report *r)
692 r->status = SREPORT_UNINIT;
GLdouble GLdouble GLdouble r
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
int SDL_SYS_NumJoysticks()
GLint GLint GLint GLint GLint x
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
GLuint const GLchar * name
void SDL_SYS_JoystickQuit(void)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint GLuint GLsizei GLenum type
GLsizeiptr const void GLenum usage
#define SDL_HAT_RIGHTDOWN
GLint GLint GLint GLint GLint GLint y
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
void SDL_SYS_JoystickDetect()
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
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()
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
#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)