|
@@ -30,6 +30,7 @@
|
|
|
*/
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
+#include <sys/stat.h>
|
|
|
|
|
|
#include <unistd.h>
|
|
|
#include <fcntl.h>
|
|
@@ -87,9 +88,6 @@
|
|
|
|
|
|
#ifdef __OpenBSD__
|
|
|
|
|
|
-#define DEV_USB 3 /* needed to get GUID from USB_GET_DEVICEINFO */
|
|
|
-#define GUID_LEN 32 /* GUID string has length 32 */
|
|
|
-
|
|
|
#define HUG_DPAD_UP 0x90
|
|
|
#define HUG_DPAD_DOWN 0x91
|
|
|
#define HUG_DPAD_RIGHT 0x92
|
|
@@ -191,16 +189,29 @@ struct joystick_hwdata
|
|
|
BSDJOY_UHID, /* uhid(4) */
|
|
|
BSDJOY_JOY /* joy(4) */
|
|
|
} type;
|
|
|
+
|
|
|
+ int naxes;
|
|
|
+ int nbuttons;
|
|
|
+ int nhats;
|
|
|
struct report_desc *repdesc;
|
|
|
struct report inreport;
|
|
|
int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,.. */
|
|
|
};
|
|
|
|
|
|
-static char *joynames[MAX_JOYS];
|
|
|
-static char *joydevnames[MAX_JOYS];
|
|
|
-#ifdef __OpenBSD__
|
|
|
-static char joyguids[MAX_JOYS][GUID_LEN];
|
|
|
-#endif
|
|
|
+/* A linked list of available joysticks */
|
|
|
+typedef struct SDL_joylist_item
|
|
|
+{
|
|
|
+ SDL_JoystickID device_instance;
|
|
|
+ char *path; /* "/dev/uhid0" or whatever */
|
|
|
+ char *name; /* "SideWinder 3D Pro" or whatever */
|
|
|
+ SDL_JoystickGUID guid;
|
|
|
+ dev_t devnum;
|
|
|
+ struct SDL_joylist_item *next;
|
|
|
+} SDL_joylist_item;
|
|
|
+
|
|
|
+static SDL_joylist_item *SDL_joylist = NULL;
|
|
|
+static SDL_joylist_item *SDL_joylist_tail = NULL;
|
|
|
+static int numjoysticks = 0;
|
|
|
|
|
|
static int report_alloc(struct report *, struct report_desc *, int);
|
|
|
static void report_free(struct report *);
|
|
@@ -216,104 +227,6 @@ static void report_free(struct report *);
|
|
|
#define REP_BUF_DATA(rep) ((rep)->buf->data)
|
|
|
#endif
|
|
|
|
|
|
-static int numjoysticks = 0;
|
|
|
-
|
|
|
-static int BSD_JoystickOpen(SDL_Joystick *joy, int device_index);
|
|
|
-static void BSD_JoystickClose(SDL_Joystick *joy);
|
|
|
-
|
|
|
-static int
|
|
|
-BSD_JoystickInit(void)
|
|
|
-{
|
|
|
- char s[16];
|
|
|
- int i, fd;
|
|
|
-
|
|
|
- numjoysticks = 0;
|
|
|
-
|
|
|
- SDL_memset(joynames, 0, sizeof(joynames));
|
|
|
- SDL_memset(joydevnames, 0, sizeof(joydevnames));
|
|
|
-#ifdef __OpenBSD__
|
|
|
- SDL_memset(joyguids, 0, sizeof(char) * MAX_JOYS * GUID_LEN);
|
|
|
-#endif
|
|
|
-
|
|
|
- for (i = 0; i < MAX_UHID_JOYS; i++) {
|
|
|
- SDL_Joystick nj;
|
|
|
-
|
|
|
-#if defined(__OpenBSD__) && (OpenBSD >= 202105)
|
|
|
- SDL_snprintf(s, SDL_arraysize(s), "/dev/ujoy/%d", i);
|
|
|
-#else
|
|
|
- SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
|
|
|
-#endif
|
|
|
-
|
|
|
- joynames[numjoysticks] = SDL_strdup(s);
|
|
|
-
|
|
|
- if (BSD_JoystickOpen(&nj, numjoysticks) == 0) {
|
|
|
- BSD_JoystickClose(&nj);
|
|
|
- numjoysticks++;
|
|
|
- } else {
|
|
|
- SDL_free(joynames[numjoysticks]);
|
|
|
- joynames[numjoysticks] = NULL;
|
|
|
- }
|
|
|
- }
|
|
|
-#ifdef SUPPORT_JOY_GAMEPORT
|
|
|
- for (i = 0; i < MAX_JOY_JOYS; i++) {
|
|
|
- SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
|
|
|
- fd = open(s, O_RDONLY | O_CLOEXEC);
|
|
|
- if (fd != -1) {
|
|
|
- joynames[numjoysticks++] = SDL_strdup(s);
|
|
|
- close(fd);
|
|
|
- }
|
|
|
- }
|
|
|
-#endif /* SUPPORT_JOY_GAMEPORT */
|
|
|
-
|
|
|
- /* Read the default USB HID usage table. */
|
|
|
- hid_init(NULL);
|
|
|
-
|
|
|
- return (numjoysticks);
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-BSD_JoystickGetCount(void)
|
|
|
-{
|
|
|
- return numjoysticks;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-BSD_JoystickDetect(void)
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-static const char *
|
|
|
-BSD_JoystickGetDeviceName(int device_index)
|
|
|
-{
|
|
|
- if (joydevnames[device_index] != NULL) {
|
|
|
- return joydevnames[device_index];
|
|
|
- }
|
|
|
- return joynames[device_index];
|
|
|
-}
|
|
|
-
|
|
|
-static const char *
|
|
|
-BSD_JoystickGetDevicePath(int device_index)
|
|
|
-{
|
|
|
- return joynames[device_index];
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-BSD_JoystickGetDevicePlayerIndex(int device_index)
|
|
|
-{
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-BSD_JoystickSetDevicePlayerIndex(int device_index, int player_index)
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-/* Function to perform the mapping from device index to the instance id for this index */
|
|
|
-static SDL_JoystickID
|
|
|
-BSD_JoystickGetDeviceInstanceID(int device_index)
|
|
|
-{
|
|
|
- return device_index;
|
|
|
-}
|
|
|
|
|
|
static int
|
|
|
usage_to_joyaxe(unsigned usage)
|
|
@@ -350,227 +263,383 @@ usage_to_joyaxe(unsigned usage)
|
|
|
return joyaxe;
|
|
|
}
|
|
|
|
|
|
-static unsigned
|
|
|
-hatval_to_sdl(Sint32 hatval)
|
|
|
+static void
|
|
|
+FreeJoylistItem(SDL_joylist_item *item)
|
|
|
{
|
|
|
- static const unsigned hat_dir_map[8] = {
|
|
|
- SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
|
|
|
- SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
|
|
|
- };
|
|
|
- unsigned result;
|
|
|
- if ((hatval & 7) == hatval)
|
|
|
- result = hat_dir_map[hatval];
|
|
|
- else
|
|
|
- result = SDL_HAT_CENTERED;
|
|
|
- return result;
|
|
|
+ SDL_free(item->path);
|
|
|
+ SDL_free(item->name);
|
|
|
+ SDL_free(item);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+FreeHwData(struct joystick_hwdata *hw)
|
|
|
+{
|
|
|
+ if (hw->type == BSDJOY_UHID) {
|
|
|
+ report_free(&hw->inreport);
|
|
|
+
|
|
|
+ if (hw->repdesc) {
|
|
|
+ hid_dispose_report_desc(hw->repdesc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ close(hw->fd);
|
|
|
+ SDL_free(hw);
|
|
|
+}
|
|
|
|
|
|
-static int
|
|
|
-BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
|
|
|
+static struct joystick_hwdata *
|
|
|
+CreateHwData(const char *path)
|
|
|
{
|
|
|
- char *path = joynames[device_index];
|
|
|
struct joystick_hwdata *hw;
|
|
|
struct hid_item hitem;
|
|
|
struct hid_data *hdata;
|
|
|
struct report *rep = NULL;
|
|
|
-#if defined(__NetBSD__)
|
|
|
- usb_device_descriptor_t udd;
|
|
|
- struct usb_string_desc usd;
|
|
|
-#endif
|
|
|
int fd;
|
|
|
int i;
|
|
|
-#ifdef __OpenBSD__
|
|
|
- struct usb_device_info di;
|
|
|
-#endif
|
|
|
|
|
|
fd = open(path, O_RDONLY | O_CLOEXEC);
|
|
|
if (fd == -1) {
|
|
|
- return SDL_SetError("%s: %s", path, strerror(errno));
|
|
|
+ SDL_SetError("%s: %s", path, strerror(errno));
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
- joy->instance_id = device_index;
|
|
|
hw = (struct joystick_hwdata *)
|
|
|
- SDL_malloc(sizeof(struct joystick_hwdata));
|
|
|
+ SDL_calloc(1, sizeof(struct joystick_hwdata));
|
|
|
if (hw == NULL) {
|
|
|
close(fd);
|
|
|
- return SDL_OutOfMemory();
|
|
|
+ SDL_OutOfMemory();
|
|
|
+ return NULL;
|
|
|
}
|
|
|
- joy->hwdata = hw;
|
|
|
hw->fd = fd;
|
|
|
+
|
|
|
#ifdef SUPPORT_JOY_GAMEPORT
|
|
|
if (SDL_strncmp(path, "/dev/joy", 8) == 0) {
|
|
|
hw->type = BSDJOY_JOY;
|
|
|
- joy->naxes = 2;
|
|
|
- joy->nbuttons = 2;
|
|
|
- joy->nhats = 0;
|
|
|
- joy->nballs = 0;
|
|
|
- joydevnames[device_index] = SDL_strdup("Gameport joystick");
|
|
|
- goto usbend;
|
|
|
+ hw->naxes = 2;
|
|
|
+ hw->nbuttons = 2;
|
|
|
} else
|
|
|
#endif
|
|
|
{
|
|
|
hw->type = BSDJOY_UHID;
|
|
|
- }
|
|
|
-
|
|
|
- {
|
|
|
- int ax;
|
|
|
- for (ax = 0; ax < JOYAXE_count; ax++)
|
|
|
- hw->axis_map[ax] = -1;
|
|
|
- }
|
|
|
- hw->repdesc = hid_get_report_desc(fd);
|
|
|
- if (hw->repdesc == NULL) {
|
|
|
- SDL_SetError("%s: USB_GET_REPORT_DESC: %s", path,
|
|
|
- strerror(errno));
|
|
|
- goto usberr;
|
|
|
- }
|
|
|
- rep = &hw->inreport;
|
|
|
+ {
|
|
|
+ int ax;
|
|
|
+ for (ax = 0; ax < JOYAXE_count; ax++)
|
|
|
+ hw->axis_map[ax] = -1;
|
|
|
+ }
|
|
|
+ hw->repdesc = hid_get_report_desc(fd);
|
|
|
+ if (hw->repdesc == NULL) {
|
|
|
+ SDL_SetError("%s: USB_GET_REPORT_DESC: %s", path,
|
|
|
+ strerror(errno));
|
|
|
+ goto usberr;
|
|
|
+ }
|
|
|
+ rep = &hw->inreport;
|
|
|
#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
|
|
- rep->rid = hid_get_report_id(fd);
|
|
|
- if (rep->rid < 0) {
|
|
|
+ rep->rid = hid_get_report_id(fd);
|
|
|
+ if (rep->rid < 0) {
|
|
|
#else
|
|
|
- if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
|
|
|
+ if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
|
|
|
#endif
|
|
|
- rep->rid = -1; /* XXX */
|
|
|
- }
|
|
|
-#if defined(__NetBSD__)
|
|
|
- if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
|
|
|
- goto desc_failed;
|
|
|
-
|
|
|
- /* Get default language */
|
|
|
- usd.usd_string_index = USB_LANGUAGE_TABLE;
|
|
|
- usd.usd_language_id = 0;
|
|
|
- if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
|
|
|
- usd.usd_language_id = 0;
|
|
|
- } else {
|
|
|
- usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
|
|
|
- }
|
|
|
-
|
|
|
- usd.usd_string_index = udd.iProduct;
|
|
|
- if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
|
|
|
- char str[128];
|
|
|
- char *new_name = NULL;
|
|
|
- int i;
|
|
|
- for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) {
|
|
|
- str[i] = UGETW(usd.usd_desc.bString[i]);
|
|
|
+ rep->rid = -1; /* XXX */
|
|
|
}
|
|
|
- str[i] = '\0';
|
|
|
- SDL_asprintf(&new_name, "%s @ %s", str, path);
|
|
|
- if (new_name != NULL) {
|
|
|
- SDL_free(joydevnames[numjoysticks]);
|
|
|
- joydevnames[numjoysticks] = new_name;
|
|
|
+ if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
|
|
|
+ goto usberr;
|
|
|
+ }
|
|
|
+ if (rep->size <= 0) {
|
|
|
+ SDL_SetError("%s: Input report descriptor has invalid length",
|
|
|
+ path);
|
|
|
+ goto usberr;
|
|
|
}
|
|
|
- }
|
|
|
-desc_failed:
|
|
|
-#endif
|
|
|
-#if defined(__OpenBSD__)
|
|
|
- if (ioctl(fd, USB_GET_DEVICEINFO, &di) != -1) {
|
|
|
- SDL_snprintf(joyguids[numjoysticks],
|
|
|
- SDL_arraysize(joyguids[device_index]),
|
|
|
- "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
|
|
|
- DEV_USB & 0xFF, DEV_USB >> 8,
|
|
|
- di.udi_vendorNo & 0xFF, di.udi_vendorNo >> 8,
|
|
|
- di.udi_productNo & 0xFF, di.udi_productNo >> 8,
|
|
|
- di.udi_releaseNo & 0xFF, di.udi_releaseNo >> 8);
|
|
|
- }
|
|
|
-#endif
|
|
|
- if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
|
|
|
- goto usberr;
|
|
|
- }
|
|
|
- if (rep->size <= 0) {
|
|
|
- SDL_SetError("%s: Input report descriptor has invalid length",
|
|
|
- path);
|
|
|
- goto usberr;
|
|
|
- }
|
|
|
#if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
|
|
- hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
|
|
|
+ hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
|
|
|
#else
|
|
|
- hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
|
|
|
+ hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
|
|
|
#endif
|
|
|
- if (hdata == NULL) {
|
|
|
- SDL_SetError("%s: Cannot start HID parser", path);
|
|
|
- goto usberr;
|
|
|
- }
|
|
|
- joy->naxes = 0;
|
|
|
- joy->nbuttons = 0;
|
|
|
- joy->nhats = 0;
|
|
|
- joy->nballs = 0;
|
|
|
- for (i = 0; i < JOYAXE_count; i++)
|
|
|
- hw->axis_map[i] = -1;
|
|
|
-
|
|
|
- while (hid_get_item(hdata, &hitem) > 0) {
|
|
|
- char *sp;
|
|
|
- const char *s;
|
|
|
-
|
|
|
- switch (hitem.kind) {
|
|
|
- case hid_collection:
|
|
|
- switch (HID_PAGE(hitem.usage)) {
|
|
|
- case HUP_GENERIC_DESKTOP:
|
|
|
- switch (HID_USAGE(hitem.usage)) {
|
|
|
- case HUG_JOYSTICK:
|
|
|
- case HUG_GAME_PAD:
|
|
|
- s = hid_usage_in_page(hitem.usage);
|
|
|
- sp = SDL_malloc(SDL_strlen(s) + 5);
|
|
|
- SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
|
|
|
- s, device_index);
|
|
|
- joydevnames[device_index] = sp;
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case hid_input:
|
|
|
- switch (HID_PAGE(hitem.usage)) {
|
|
|
- case HUP_GENERIC_DESKTOP:
|
|
|
- {
|
|
|
- unsigned usage = HID_USAGE(hitem.usage);
|
|
|
- int joyaxe = usage_to_joyaxe(usage);
|
|
|
- if (joyaxe >= 0) {
|
|
|
- hw->axis_map[joyaxe] = 1;
|
|
|
- } else if (usage == HUG_HAT_SWITCH
|
|
|
+ if (hdata == NULL) {
|
|
|
+ SDL_SetError("%s: Cannot start HID parser", path);
|
|
|
+ goto usberr;
|
|
|
+ }
|
|
|
+ for (i = 0; i < JOYAXE_count; i++)
|
|
|
+ hw->axis_map[i] = -1;
|
|
|
+
|
|
|
+ while (hid_get_item(hdata, &hitem) > 0) {
|
|
|
+ switch (hitem.kind) {
|
|
|
+ case hid_input:
|
|
|
+ switch (HID_PAGE(hitem.usage)) {
|
|
|
+ case HUP_GENERIC_DESKTOP:
|
|
|
+ {
|
|
|
+ unsigned usage = HID_USAGE(hitem.usage);
|
|
|
+ int joyaxe = usage_to_joyaxe(usage);
|
|
|
+ if (joyaxe >= 0) {
|
|
|
+ hw->axis_map[joyaxe] = 1;
|
|
|
+ } else if (usage == HUG_HAT_SWITCH
|
|
|
#ifdef __OpenBSD__
|
|
|
- || usage == HUG_DPAD_UP
|
|
|
+ || usage == HUG_DPAD_UP
|
|
|
#endif
|
|
|
- ) {
|
|
|
- joy->nhats++;
|
|
|
+ ) {
|
|
|
+ hw->nhats++;
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
+ case HUP_BUTTON:
|
|
|
+ hw->nbuttons++;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
break;
|
|
|
}
|
|
|
- case HUP_BUTTON:
|
|
|
- joy->nbuttons++;
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
}
|
|
|
- }
|
|
|
- hid_end_parse(hdata);
|
|
|
- for (i = 0; i < JOYAXE_count; i++)
|
|
|
- if (hw->axis_map[i] > 0)
|
|
|
- hw->axis_map[i] = joy->naxes++;
|
|
|
-
|
|
|
- if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
|
|
|
- SDL_SetError("%s: Not a joystick, ignoring", path);
|
|
|
- goto usberr;
|
|
|
+ hid_end_parse(hdata);
|
|
|
+ for (i = 0; i < JOYAXE_count; i++)
|
|
|
+ if (hw->axis_map[i] > 0)
|
|
|
+ hw->axis_map[i] = hw->naxes++;
|
|
|
+
|
|
|
+ if (hw->naxes == 0 && hw->nbuttons == 0 && hw->nhats == 0) {
|
|
|
+ SDL_SetError("%s: Not a joystick, ignoring", path);
|
|
|
+ goto usberr;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- usbend:
|
|
|
/* The poll blocks the event thread. */
|
|
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
|
#ifdef __NetBSD__
|
|
|
/* Flush pending events */
|
|
|
if (rep) {
|
|
|
- while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
|
|
|
+ while (read(fd, REP_BUF_DATA(rep), rep->size) == rep->size)
|
|
|
;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- return (0);
|
|
|
- usberr:
|
|
|
- close(hw->fd);
|
|
|
- SDL_free(hw);
|
|
|
- return (-1);
|
|
|
+ return hw;
|
|
|
+
|
|
|
+usberr:
|
|
|
+ FreeHwData(hw);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+MaybeAddDevice(const char *path)
|
|
|
+{
|
|
|
+ struct stat sb;
|
|
|
+ char *name = NULL;
|
|
|
+ SDL_JoystickGUID guid;
|
|
|
+ SDL_joylist_item *item;
|
|
|
+ struct joystick_hwdata *hw;
|
|
|
+
|
|
|
+ if (path == NULL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stat(path, &sb) == -1) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Check to make sure it's not already in list. */
|
|
|
+ for (item = SDL_joylist; item != NULL; item = item->next) {
|
|
|
+ if (sb.st_rdev == item->devnum) {
|
|
|
+ return -1; /* already have this one */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ hw = CreateHwData(path);
|
|
|
+ if (!hw) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hw->type == BSDJOY_JOY) {
|
|
|
+ name = SDL_strdup("Gameport joystick");
|
|
|
+ guid = SDL_CreateJoystickGUIDForName(name);
|
|
|
+ } else {
|
|
|
+#ifdef USB_GET_DEVICEINFO
|
|
|
+ struct usb_device_info di;
|
|
|
+ if (ioctl(hw->fd, USB_GET_DEVICEINFO, &di) != -1) {
|
|
|
+ name = SDL_CreateJoystickName(di.udi_vendorNo, di.udi_productNo, di.udi_vendor, di.udi_product);
|
|
|
+ guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name, 0, 0);
|
|
|
+
|
|
|
+#ifdef SDL_JOYSTICK_HIDAPI
|
|
|
+ if (HIDAPI_IsDevicePresent(di.udi_vendorNo, di.udi_productNo, di.udi_releaseNo, name)) {
|
|
|
+ /* The HIDAPI driver is taking care of this device */
|
|
|
+ SDL_free(name);
|
|
|
+ FreeHwData(hw);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ if (SDL_ShouldIgnoreJoystick(name, guid)) {
|
|
|
+ SDL_free(name);
|
|
|
+ FreeHwData(hw);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif /* USB_GET_DEVICEINFO */
|
|
|
+ }
|
|
|
+ if (!name) {
|
|
|
+ name = SDL_strdup(path);
|
|
|
+ guid = SDL_CreateJoystickGUIDForName(name);
|
|
|
+ }
|
|
|
+ FreeHwData(hw);
|
|
|
+
|
|
|
+ item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
|
|
|
+ if (item == NULL) {
|
|
|
+ SDL_free(name);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ item->devnum = sb.st_rdev;
|
|
|
+ item->path = SDL_strdup(path);
|
|
|
+ item->name = name;
|
|
|
+ item->guid = guid;
|
|
|
+
|
|
|
+ if ((item->path == NULL) || (item->name == NULL)) {
|
|
|
+ FreeJoylistItem(item);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ item->device_instance = SDL_GetNextJoystickInstanceID();
|
|
|
+ if (SDL_joylist_tail == NULL) {
|
|
|
+ SDL_joylist = SDL_joylist_tail = item;
|
|
|
+ } else {
|
|
|
+ SDL_joylist_tail->next = item;
|
|
|
+ SDL_joylist_tail = item;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Need to increment the joystick count before we post the event */
|
|
|
+ ++numjoysticks;
|
|
|
+
|
|
|
+ SDL_PrivateJoystickAdded(item->device_instance);
|
|
|
+
|
|
|
+ return numjoysticks;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+BSD_JoystickInit(void)
|
|
|
+{
|
|
|
+ char s[16];
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < MAX_UHID_JOYS; i++) {
|
|
|
+#if defined(__OpenBSD__) && (OpenBSD >= 202105)
|
|
|
+ SDL_snprintf(s, SDL_arraysize(s), "/dev/ujoy/%d", i);
|
|
|
+#else
|
|
|
+ SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
|
|
|
+#endif
|
|
|
+ MaybeAddDevice(s);
|
|
|
+ }
|
|
|
+#ifdef SUPPORT_JOY_GAMEPORT
|
|
|
+ for (i = 0; i < MAX_JOY_JOYS; i++) {
|
|
|
+ SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
|
|
|
+ MaybeAddDevice(s);
|
|
|
+ }
|
|
|
+#endif /* SUPPORT_JOY_GAMEPORT */
|
|
|
+
|
|
|
+ /* Read the default USB HID usage table. */
|
|
|
+ hid_init(NULL);
|
|
|
+
|
|
|
+ return numjoysticks;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+BSD_JoystickGetCount(void)
|
|
|
+{
|
|
|
+ return numjoysticks;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+BSD_JoystickDetect(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static SDL_joylist_item *
|
|
|
+JoystickByDevIndex(int device_index)
|
|
|
+{
|
|
|
+ SDL_joylist_item *item = SDL_joylist;
|
|
|
+
|
|
|
+ if ((device_index < 0) || (device_index >= numjoysticks)) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ while (device_index > 0) {
|
|
|
+ SDL_assert(item != NULL);
|
|
|
+ device_index--;
|
|
|
+ item = item->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ return item;
|
|
|
+}
|
|
|
+
|
|
|
+static const char *
|
|
|
+BSD_JoystickGetDeviceName(int device_index)
|
|
|
+{
|
|
|
+ return JoystickByDevIndex(device_index)->name;
|
|
|
+}
|
|
|
+
|
|
|
+static const char *
|
|
|
+BSD_JoystickGetDevicePath(int device_index)
|
|
|
+{
|
|
|
+ return JoystickByDevIndex(device_index)->path;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+BSD_JoystickGetDevicePlayerIndex(int device_index)
|
|
|
+{
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+BSD_JoystickSetDevicePlayerIndex(int device_index, int player_index)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static SDL_JoystickGUID
|
|
|
+BSD_JoystickGetDeviceGUID(int device_index)
|
|
|
+{
|
|
|
+ return JoystickByDevIndex(device_index)->guid;
|
|
|
+}
|
|
|
+
|
|
|
+/* Function to perform the mapping from device index to the instance id for this index */
|
|
|
+static SDL_JoystickID
|
|
|
+BSD_JoystickGetDeviceInstanceID(int device_index)
|
|
|
+{
|
|
|
+ return JoystickByDevIndex(device_index)->device_instance;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned
|
|
|
+hatval_to_sdl(Sint32 hatval)
|
|
|
+{
|
|
|
+ static const unsigned hat_dir_map[8] = {
|
|
|
+ SDL_HAT_UP, SDL_HAT_RIGHTUP, SDL_HAT_RIGHT, SDL_HAT_RIGHTDOWN,
|
|
|
+ SDL_HAT_DOWN, SDL_HAT_LEFTDOWN, SDL_HAT_LEFT, SDL_HAT_LEFTUP
|
|
|
+ };
|
|
|
+ unsigned result;
|
|
|
+ if ((hatval & 7) == hatval)
|
|
|
+ result = hat_dir_map[hatval];
|
|
|
+ else
|
|
|
+ result = SDL_HAT_CENTERED;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
|
|
|
+{
|
|
|
+ SDL_joylist_item *item = JoystickByDevIndex(device_index);
|
|
|
+ struct joystick_hwdata *hw;
|
|
|
+
|
|
|
+ if (item == NULL) {
|
|
|
+ return SDL_SetError("No such device");
|
|
|
+ }
|
|
|
+
|
|
|
+ hw = CreateHwData(item->path);
|
|
|
+ if (!hw) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ joy->instance_id = item->device_instance;
|
|
|
+ joy->hwdata = hw;
|
|
|
+ joy->naxes = hw->naxes;
|
|
|
+ joy->nbuttons = hw->nbuttons;
|
|
|
+ joy->nhats = hw->nhats;
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -728,39 +797,26 @@ BSD_JoystickUpdate(SDL_Joystick *joy)
|
|
|
static void
|
|
|
BSD_JoystickClose(SDL_Joystick *joy)
|
|
|
{
|
|
|
- if (joy->hwdata->type == BSDJOY_UHID) {
|
|
|
- report_free(&joy->hwdata->inreport);
|
|
|
- hid_dispose_report_desc(joy->hwdata->repdesc);
|
|
|
+ if (joy->hwdata) {
|
|
|
+ FreeHwData(joy->hwdata);
|
|
|
+ joy->hwdata = NULL;
|
|
|
}
|
|
|
- close(joy->hwdata->fd);
|
|
|
- SDL_free(joy->hwdata);
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
BSD_JoystickQuit(void)
|
|
|
{
|
|
|
- int i;
|
|
|
+ SDL_joylist_item *item = NULL;
|
|
|
+ SDL_joylist_item *next = NULL;
|
|
|
|
|
|
- for (i = 0; i < MAX_JOYS; i++) {
|
|
|
- SDL_free(joynames[i]);
|
|
|
- SDL_free(joydevnames[i]);
|
|
|
+ for (item = SDL_joylist; item; item = next) {
|
|
|
+ next = item->next;
|
|
|
+ FreeJoylistItem(item);
|
|
|
}
|
|
|
|
|
|
- return;
|
|
|
-}
|
|
|
+ SDL_joylist = SDL_joylist_tail = NULL;
|
|
|
|
|
|
-static SDL_JoystickGUID
|
|
|
-BSD_JoystickGetDeviceGUID(int device_index)
|
|
|
-{
|
|
|
-#ifdef __OpenBSD__
|
|
|
- SDL_JoystickGUID guid;
|
|
|
- guid = SDL_JoystickGetGUIDFromString(joyguids[device_index]);
|
|
|
- return guid;
|
|
|
-#else
|
|
|
- /* the GUID is just the name for now */
|
|
|
- const char *name = BSD_JoystickGetDeviceName(device_index);
|
|
|
- return SDL_CreateJoystickGUIDForName(name);
|
|
|
-#endif
|
|
|
+ numjoysticks = 0;
|
|
|
}
|
|
|
|
|
|
static int
|