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) 166 static int BSD_JoystickOpen(SDL_Joystick * joy,
int device_index);
167 static void BSD_JoystickClose(SDL_Joystick * joy);
170 BSD_JoystickInit(
void)
178 SDL_memset(joydevnames, 0,
sizeof(joydevnames));
180 for (i = 0; i < MAX_UHID_JOYS; i++) {
188 BSD_JoystickClose(&nj);
195 for (i = 0; i < MAX_JOY_JOYS; i++) {
197 fd = open(s, O_RDONLY);
211 BSD_JoystickGetCount(
void)
217 BSD_JoystickDetect(
void)
222 BSD_JoystickGetDeviceName(
int device_index)
224 if (joydevnames[device_index] !=
NULL) {
225 return (joydevnames[device_index]);
227 return (joynames[device_index]);
231 BSD_JoystickGetDevicePlayerIndex(
int device_index)
238 BSD_JoystickGetDeviceInstanceID(
int device_index)
244 usage_to_joyaxe(
unsigned usage)
258 joyaxe = JOYAXE_SLIDER;
261 joyaxe = JOYAXE_WHEEL;
279 hatval_to_sdl(
Sint32 hatval)
281 static const unsigned hat_dir_map[8] = {
286 if ((hatval & 7) == hatval)
287 result = hat_dir_map[hatval];
295 BSD_JoystickOpen(SDL_Joystick * joy,
int device_index)
297 char *
path = joynames[device_index];
299 struct hid_item hitem;
300 struct hid_data *hdata;
301 struct report *rep =
NULL;
305 fd = open(path, O_RDONLY);
310 joy->instance_id = device_index;
321 hw->type = BSDJOY_JOY;
326 joydevnames[device_index] =
SDL_strdup(
"Gameport joystick");
329 hw->type = BSDJOY_UHID;
334 for (ax = 0; ax < JOYAXE_count; ax++)
335 hw->axis_map[ax] = -1;
337 hw->repdesc = hid_get_report_desc(fd);
338 if (hw->repdesc ==
NULL) {
344 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) 345 rep->rid = hid_get_report_id(fd);
348 if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
352 #if defined(__NetBSD__) 353 usb_device_descriptor_t udd;
354 struct usb_string_desc usd;
355 if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
359 usd.usd_string_index = USB_LANGUAGE_TABLE;
360 usd.usd_language_id = 0;
361 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
362 usd.usd_language_id = 0;
364 usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
367 usd.usd_string_index = udd.iProduct;
368 if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
370 char *new_name =
NULL;
372 for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i <
sizeof(str) - 1; i++) {
373 str[
i] = UGETW(usd.usd_desc.bString[i]);
376 asprintf(&new_name,
"%s @ %s", str, path);
377 if (new_name !=
NULL) {
384 if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
387 if (rep->size <= 0) {
388 SDL_SetError(
"%s: Input report descriptor has invalid length",
392 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 393 hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
395 hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
405 for (i = 0; i < JOYAXE_count; i++)
406 hw->axis_map[i] = -1;
408 while (hid_get_item(hdata, &hitem) > 0) {
412 switch (hitem.kind) {
414 switch (HID_PAGE(hitem.usage)) {
415 case HUP_GENERIC_DESKTOP:
416 switch (HID_USAGE(hitem.usage)) {
419 s = hid_usage_in_page(hitem.usage);
423 joydevnames[device_index] = sp;
428 switch (HID_PAGE(hitem.usage)) {
429 case HUP_GENERIC_DESKTOP:
431 unsigned usage = HID_USAGE(hitem.usage);
432 int joyaxe = usage_to_joyaxe(usage);
434 hw->axis_map[joyaxe] = 1;
435 }
else if (usage == HUG_HAT_SWITCH) {
451 hid_end_parse(hdata);
452 for (i = 0; i < JOYAXE_count; i++)
453 if (hw->axis_map[i] > 0)
454 hw->axis_map[
i] = joy->
naxes++;
456 if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
463 fcntl(fd, F_SETFL, O_NONBLOCK);
467 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
481 BSD_JoystickUpdate(SDL_Joystick * joy)
483 struct hid_item hitem;
484 struct hid_data *hdata;
486 int nbutton, naxe = -1;
489 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__) 490 struct joystick gameport;
491 static int x,
y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
493 if (joy->hwdata->type == BSDJOY_JOY) {
494 while (read(joy->hwdata->fd, &gameport,
sizeof gameport) ==
sizeof gameport) {
495 if (abs(x - gameport.x) > 8) {
508 v -= (xmax + xmin + 1) / 2;
509 v *= 32768 / ((xmax - xmin + 1) / 2);
512 if (abs(y - gameport.y) > 8) {
525 v -= (ymax + ymin + 1) / 2;
526 v *= 32768 / ((ymax - ymin + 1) / 2);
536 rep = &joy->hwdata->inreport;
538 while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
539 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 540 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
542 hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
549 for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
550 switch (hitem.kind) {
552 switch (HID_PAGE(hitem.usage)) {
553 case HUP_GENERIC_DESKTOP:
555 unsigned usage = HID_USAGE(hitem.usage);
556 int joyaxe = usage_to_joyaxe(usage);
558 naxe = joy->hwdata->axis_map[joyaxe];
560 v = (
Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
561 v -= (hitem.logical_maximum +
562 hitem.logical_minimum + 1) / 2;
564 ((hitem.logical_maximum -
565 hitem.logical_minimum + 1) / 2);
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);
588 hid_end_parse(hdata);
594 BSD_JoystickClose(SDL_Joystick * joy)
596 if (
SDL_strncmp(joy->hwdata->path,
"/dev/joy", 8)) {
597 report_free(&joy->hwdata->inreport);
598 hid_dispose_report_desc(joy->hwdata->repdesc);
600 close(joy->hwdata->fd);
606 BSD_JoystickQuit(
void)
610 for (i = 0; i < MAX_JOYS; i++) {
619 BSD_JoystickGetDeviceGUID(
int device_index )
623 const char *
name = BSD_JoystickGetDeviceName( device_index );
630 report_alloc(
struct report *
r,
struct report_desc *rd,
int repind)
635 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
637 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__) 638 # if (__FreeBSD_kernel_version <= 500111) 639 len = hid_report_size(rd, r->rid, repinfo[repind].kind);
641 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
644 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
648 len = hid_report_size(rd, repinfo[repind].kind, r->rid);
650 len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
660 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 663 r->buf =
SDL_malloc(
sizeof(*r->buf) -
sizeof(REP_BUF_DATA(r)) +
666 if (r->buf ==
NULL) {
673 r->status = SREPORT_CLEAN;
678 report_free(
struct report *r)
681 r->status = SREPORT_UNINIT;
685 BSD_JoystickRumble(SDL_Joystick * joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble,
Uint32 duration_ms)
693 BSD_JoystickGetCount,
695 BSD_JoystickGetDeviceName,
696 BSD_JoystickGetDevicePlayerIndex,
697 BSD_JoystickGetDeviceGUID,
698 BSD_JoystickGetDeviceInstanceID,
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)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
GLuint const GLchar * name
GLsizeiptr const void GLenum usage
#define SDL_HAT_RIGHTDOWN
GLint GLint GLint GLint GLint GLint y
GLenum GLuint GLenum GLsizei const GLchar * buf
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)
#define SDL_OutOfMemory()
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
GLuint GLuint GLsizei GLenum type
#define SDL_arraysize(array)
GLsizei const GLchar *const * path
SDL_JoystickDriver SDL_BSD_JoystickDriver
#define SDL_Unsupported()