SDL  2.0
SDL_sysjoystick.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #ifdef SDL_JOYSTICK_USBHID
24 
25 /*
26  * Joystick driver for the uhid(4) interface found in OpenBSD,
27  * NetBSD and FreeBSD.
28  *
29  * Maintainer: <vedge at csoft.org>
30  */
31 
32 #include <sys/param.h>
33 
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <errno.h>
37 
38 #ifndef __FreeBSD_kernel_version
39 #define __FreeBSD_kernel_version __FreeBSD_version
40 #endif
41 
42 #if defined(HAVE_USB_H)
43 #include <usb.h>
44 #endif
45 #ifdef __DragonFly__
46 #include <bus/usb/usb.h>
47 #include <bus/usb/usbhid.h>
48 #else
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbhid.h>
51 #endif
52 
53 #if defined(HAVE_USBHID_H)
54 #include <usbhid.h>
55 #elif defined(HAVE_LIBUSB_H)
56 #include <libusb.h>
57 #elif defined(HAVE_LIBUSBHID_H)
58 #include <libusbhid.h>
59 #endif
60 
61 #if defined(__FREEBSD__) || defined(__FreeBSD_kernel__)
62 #ifndef __DragonFly__
63 #include <osreldate.h>
64 #endif
65 #if __FreeBSD_kernel_version > 800063
66 #include <dev/usb/usb_ioctl.h>
67 #endif
68 #include <sys/joystick.h>
69 #endif
70 
71 #if SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
72 #include <machine/joystick.h>
73 #endif
74 
75 #include "SDL_joystick.h"
76 #include "../SDL_sysjoystick.h"
77 #include "../SDL_joystick_c.h"
78 
79 #define MAX_UHID_JOYS 64
80 #define MAX_JOY_JOYS 2
81 #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS)
82 
83 #ifdef __OpenBSD__
84 
85 #define HUG_DPAD_UP 0x90
86 #define HUG_DPAD_DOWN 0x91
87 #define HUG_DPAD_RIGHT 0x92
88 #define HUG_DPAD_LEFT 0x93
89 
90 #define HAT_CENTERED 0x00
91 #define HAT_UP 0x01
92 #define HAT_RIGHT 0x02
93 #define HAT_DOWN 0x04
94 #define HAT_LEFT 0x08
95 #define HAT_RIGHTUP (HAT_RIGHT|HAT_UP)
96 #define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN)
97 #define HAT_LEFTUP (HAT_LEFT|HAT_UP)
98 #define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN)
99 
100 /* calculate the value from the state of the dpad */
101 int
102 dpad_to_sdl(Sint32 *dpad)
103 {
104  if (dpad[2]) {
105  if (dpad[0])
106  return HAT_RIGHTUP;
107  else if (dpad[1])
108  return HAT_RIGHTDOWN;
109  else
110  return HAT_RIGHT;
111  } else if (dpad[3]) {
112  if (dpad[0])
113  return HAT_LEFTUP;
114  else if (dpad[1])
115  return HAT_LEFTDOWN;
116  else
117  return HAT_LEFT;
118  } else if (dpad[0]) {
119  return HAT_UP;
120  } else if (dpad[1]) {
121  return HAT_DOWN;
122  }
123  return HAT_CENTERED;
124 }
125 #endif
126 
127 struct report
128 {
129 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
130  void *buf; /* Buffer */
131 #elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)
132  struct usb_gen_descriptor *buf; /* Buffer */
133 #else
134  struct usb_ctl_report *buf; /* Buffer */
135 #endif
136  size_t size; /* Buffer size */
137  int rid; /* Report ID */
138  enum
139  {
140  SREPORT_UNINIT,
141  SREPORT_CLEAN,
142  SREPORT_DIRTY
143  } status;
144 };
145 
146 static struct
147 {
148  int uhid_report;
149  hid_kind_t kind;
150  const char *name;
151 } const repinfo[] = {
152  {UHID_INPUT_REPORT, hid_input, "input"},
153  {UHID_OUTPUT_REPORT, hid_output, "output"},
154  {UHID_FEATURE_REPORT, hid_feature, "feature"}
155 };
156 
157 enum
158 {
159  REPORT_INPUT = 0,
160  REPORT_OUTPUT = 1,
161  REPORT_FEATURE = 2
162 };
163 
164 enum
165 {
166  JOYAXE_X,
167  JOYAXE_Y,
168  JOYAXE_Z,
169  JOYAXE_SLIDER,
170  JOYAXE_WHEEL,
171  JOYAXE_RX,
172  JOYAXE_RY,
173  JOYAXE_RZ,
174  JOYAXE_count
175 };
176 
177 struct joystick_hwdata
178 {
179  int fd;
180  char *path;
181  enum
182  {
183  BSDJOY_UHID, /* uhid(4) */
184  BSDJOY_JOY /* joy(4) */
185  } type;
186  struct report_desc *repdesc;
187  struct report inreport;
188  int axis_map[JOYAXE_count]; /* map present JOYAXE_* to 0,1,.. */
189 };
190 
191 static char *joynames[MAX_JOYS];
192 static char *joydevnames[MAX_JOYS];
193 
194 static int report_alloc(struct report *, struct report_desc *, int);
195 static void report_free(struct report *);
196 
197 #if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063)
198 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
199 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000))
200 #define REP_BUF_DATA(rep) ((rep)->buf)
201 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063))
202 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data)
203 #else
204 #define REP_BUF_DATA(rep) ((rep)->buf->data)
205 #endif
206 
207 static int numjoysticks = 0;
208 
209 static int BSD_JoystickOpen(SDL_Joystick * joy, int device_index);
210 static void BSD_JoystickClose(SDL_Joystick * joy);
211 
212 static int
213 BSD_JoystickInit(void)
214 {
215  char s[16];
216  int i, fd;
217 
218  numjoysticks = 0;
219 
220  SDL_memset(joynames, 0, sizeof(joynames));
221  SDL_memset(joydevnames, 0, sizeof(joydevnames));
222 
223  for (i = 0; i < MAX_UHID_JOYS; i++) {
224  SDL_Joystick nj;
225 
226  SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
227 
228  joynames[numjoysticks] = SDL_strdup(s);
229 
230  if (BSD_JoystickOpen(&nj, numjoysticks) == 0) {
231  BSD_JoystickClose(&nj);
232  numjoysticks++;
233  } else {
234  SDL_free(joynames[numjoysticks]);
235  joynames[numjoysticks] = NULL;
236  }
237  }
238  for (i = 0; i < MAX_JOY_JOYS; i++) {
239  SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
240  fd = open(s, O_RDONLY);
241  if (fd != -1) {
242  joynames[numjoysticks++] = SDL_strdup(s);
243  close(fd);
244  }
245  }
246 
247  /* Read the default USB HID usage table. */
248  hid_init(NULL);
249 
250  return (numjoysticks);
251 }
252 
253 static int
254 BSD_JoystickGetCount(void)
255 {
256  return numjoysticks;
257 }
258 
259 static void
260 BSD_JoystickDetect(void)
261 {
262 }
263 
264 static const char *
265 BSD_JoystickGetDeviceName(int device_index)
266 {
267  if (joydevnames[device_index] != NULL) {
268  return (joydevnames[device_index]);
269  }
270  return (joynames[device_index]);
271 }
272 
273 static int
274 BSD_JoystickGetDevicePlayerIndex(int device_index)
275 {
276  return -1;
277 }
278 
279 /* Function to perform the mapping from device index to the instance id for this index */
280 static SDL_JoystickID
281 BSD_JoystickGetDeviceInstanceID(int device_index)
282 {
283  return device_index;
284 }
285 
286 static int
287 usage_to_joyaxe(unsigned usage)
288 {
289  int joyaxe;
290  switch (usage) {
291  case HUG_X:
292  joyaxe = JOYAXE_X;
293  break;
294  case HUG_Y:
295  joyaxe = JOYAXE_Y;
296  break;
297  case HUG_Z:
298  joyaxe = JOYAXE_Z;
299  break;
300  case HUG_SLIDER:
301  joyaxe = JOYAXE_SLIDER;
302  break;
303  case HUG_WHEEL:
304  joyaxe = JOYAXE_WHEEL;
305  break;
306  case HUG_RX:
307  joyaxe = JOYAXE_RX;
308  break;
309  case HUG_RY:
310  joyaxe = JOYAXE_RY;
311  break;
312  case HUG_RZ:
313  joyaxe = JOYAXE_RZ;
314  break;
315  default:
316  joyaxe = -1;
317  }
318  return joyaxe;
319 }
320 
321 static unsigned
322 hatval_to_sdl(Sint32 hatval)
323 {
324  static const unsigned hat_dir_map[8] = {
327  };
328  unsigned result;
329  if ((hatval & 7) == hatval)
330  result = hat_dir_map[hatval];
331  else
333  return result;
334 }
335 
336 
337 static int
338 BSD_JoystickOpen(SDL_Joystick * joy, int device_index)
339 {
340  char *path = joynames[device_index];
341  struct joystick_hwdata *hw;
342  struct hid_item hitem;
343  struct hid_data *hdata;
344  struct report *rep = NULL;
345 #if defined(__NetBSD__)
346  usb_device_descriptor_t udd;
347  struct usb_string_desc usd;
348 #endif
349  int fd;
350  int i;
351 
352  fd = open(path, O_RDONLY);
353  if (fd == -1) {
354  return SDL_SetError("%s: %s", path, strerror(errno));
355  }
356 
357  joy->instance_id = device_index;
358  hw = (struct joystick_hwdata *)
359  SDL_malloc(sizeof(struct joystick_hwdata));
360  if (hw == NULL) {
361  close(fd);
362  return SDL_OutOfMemory();
363  }
364  joy->hwdata = hw;
365  hw->fd = fd;
366  hw->path = SDL_strdup(path);
367  if (!SDL_strncmp(path, "/dev/joy", 8)) {
368  hw->type = BSDJOY_JOY;
369  joy->naxes = 2;
370  joy->nbuttons = 2;
371  joy->nhats = 0;
372  joy->nballs = 0;
373  joydevnames[device_index] = SDL_strdup("Gameport joystick");
374  goto usbend;
375  } else {
376  hw->type = BSDJOY_UHID;
377  }
378 
379  {
380  int ax;
381  for (ax = 0; ax < JOYAXE_count; ax++)
382  hw->axis_map[ax] = -1;
383  }
384  hw->repdesc = hid_get_report_desc(fd);
385  if (hw->repdesc == NULL) {
386  SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path,
387  strerror(errno));
388  goto usberr;
389  }
390  rep = &hw->inreport;
391 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__)
392  rep->rid = hid_get_report_id(fd);
393  if (rep->rid < 0) {
394 #else
395  if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
396 #endif
397  rep->rid = -1; /* XXX */
398  }
399 #if defined(__NetBSD__)
400  if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1)
401  goto desc_failed;
402 
403  /* Get default language */
404  usd.usd_string_index = USB_LANGUAGE_TABLE;
405  usd.usd_language_id = 0;
406  if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) {
407  usd.usd_language_id = 0;
408  } else {
409  usd.usd_language_id = UGETW(usd.usd_desc.bString[0]);
410  }
411 
412  usd.usd_string_index = udd.iProduct;
413  if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) {
414  char str[128];
415  char *new_name = NULL;
416  int i;
417  for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) {
418  str[i] = UGETW(usd.usd_desc.bString[i]);
419  }
420  str[i] = '\0';
421  asprintf(&new_name, "%s @ %s", str, path);
422  if (new_name != NULL) {
423  SDL_free(joydevnames[numjoysticks]);
424  joydevnames[numjoysticks] = new_name;
425  }
426  }
427 desc_failed:
428 #endif
429  if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) {
430  goto usberr;
431  }
432  if (rep->size <= 0) {
433  SDL_SetError("%s: Input report descriptor has invalid length",
434  hw->path);
435  goto usberr;
436  }
437 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
438  hdata = hid_start_parse(hw->repdesc, 1 << hid_input, rep->rid);
439 #else
440  hdata = hid_start_parse(hw->repdesc, 1 << hid_input);
441 #endif
442  if (hdata == NULL) {
443  SDL_SetError("%s: Cannot start HID parser", hw->path);
444  goto usberr;
445  }
446  joy->naxes = 0;
447  joy->nbuttons = 0;
448  joy->nhats = 0;
449  joy->nballs = 0;
450  for (i = 0; i < JOYAXE_count; i++)
451  hw->axis_map[i] = -1;
452 
453  while (hid_get_item(hdata, &hitem) > 0) {
454  char *sp;
455  const char *s;
456 
457  switch (hitem.kind) {
458  case hid_collection:
459  switch (HID_PAGE(hitem.usage)) {
460  case HUP_GENERIC_DESKTOP:
461  switch (HID_USAGE(hitem.usage)) {
462  case HUG_JOYSTICK:
463  case HUG_GAME_PAD:
464  s = hid_usage_in_page(hitem.usage);
465  sp = SDL_malloc(SDL_strlen(s) + 5);
466  SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)",
467  s, device_index);
468  joydevnames[device_index] = sp;
469  }
470  }
471  break;
472  case hid_input:
473  switch (HID_PAGE(hitem.usage)) {
474  case HUP_GENERIC_DESKTOP:
475  {
476  unsigned usage = HID_USAGE(hitem.usage);
477  int joyaxe = usage_to_joyaxe(usage);
478  if (joyaxe >= 0) {
479  hw->axis_map[joyaxe] = 1;
480  } else if (usage == HUG_HAT_SWITCH
481 #ifdef __OpenBSD__
482  || usage == HUG_DPAD_UP
483 #endif
484  ) {
485  joy->nhats++;
486  }
487  break;
488  }
489  case HUP_BUTTON:
490  joy->nbuttons++;
491  break;
492  default:
493  break;
494  }
495  break;
496  default:
497  break;
498  }
499  }
500  hid_end_parse(hdata);
501  for (i = 0; i < JOYAXE_count; i++)
502  if (hw->axis_map[i] > 0)
503  hw->axis_map[i] = joy->naxes++;
504 
505  if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) {
506  SDL_SetError("%s: Not a joystick, ignoring", hw->path);
507  goto usberr;
508  }
509 
510  usbend:
511  /* The poll blocks the event thread. */
512  fcntl(fd, F_SETFL, O_NONBLOCK);
513 #ifdef __NetBSD__
514  /* Flush pending events */
515  if (rep) {
516  while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size)
517  ;
518  }
519 #endif
520 
521  return (0);
522  usberr:
523  close(hw->fd);
524  SDL_free(hw->path);
525  SDL_free(hw);
526  return (-1);
527 }
528 
529 static void
530 BSD_JoystickUpdate(SDL_Joystick * joy)
531 {
532  struct hid_item hitem;
533  struct hid_data *hdata;
534  struct report *rep;
535  int nbutton, naxe = -1;
536  Sint32 v;
537 #ifdef __OpenBSD__
538  Sint32 dpad[4] = {0, 0, 0, 0};
539 #endif
540 
541 #if defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H || defined(__FreeBSD_kernel__)
542  struct joystick gameport;
543  static int x, y, xmin = 0xffff, ymin = 0xffff, xmax = 0, ymax = 0;
544 
545  if (joy->hwdata->type == BSDJOY_JOY) {
546  while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) {
547  if (abs(x - gameport.x) > 8) {
548  x = gameport.x;
549  if (x < xmin) {
550  xmin = x;
551  }
552  if (x > xmax) {
553  xmax = x;
554  }
555  if (xmin == xmax) {
556  xmin--;
557  xmax++;
558  }
559  v = (Sint32) x;
560  v -= (xmax + xmin + 1) / 2;
561  v *= 32768 / ((xmax - xmin + 1) / 2);
562  SDL_PrivateJoystickAxis(joy, 0, v);
563  }
564  if (abs(y - gameport.y) > 8) {
565  y = gameport.y;
566  if (y < ymin) {
567  ymin = y;
568  }
569  if (y > ymax) {
570  ymax = y;
571  }
572  if (ymin == ymax) {
573  ymin--;
574  ymax++;
575  }
576  v = (Sint32) y;
577  v -= (ymax + ymin + 1) / 2;
578  v *= 32768 / ((ymax - ymin + 1) / 2);
579  SDL_PrivateJoystickAxis(joy, 1, v);
580  }
581  SDL_PrivateJoystickButton(joy, 0, gameport.b1);
582  SDL_PrivateJoystickButton(joy, 1, gameport.b2);
583  }
584  return;
585  }
586 #endif /* defined(__FREEBSD__) || SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H */
587 
588  rep = &joy->hwdata->inreport;
589 
590  while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) {
591 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__)
592  hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid);
593 #else
594  hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input);
595 #endif
596  if (hdata == NULL) {
597  /*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/
598  continue;
599  }
600 
601  for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
602  switch (hitem.kind) {
603  case hid_input:
604  switch (HID_PAGE(hitem.usage)) {
605  case HUP_GENERIC_DESKTOP:
606  {
607  unsigned usage = HID_USAGE(hitem.usage);
608  int joyaxe = usage_to_joyaxe(usage);
609  if (joyaxe >= 0) {
610  naxe = joy->hwdata->axis_map[joyaxe];
611  /* scaleaxe */
612  v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
613  v -= (hitem.logical_maximum +
614  hitem.logical_minimum + 1) / 2;
615  v *= 32768 /
616  ((hitem.logical_maximum -
617  hitem.logical_minimum + 1) / 2);
618  SDL_PrivateJoystickAxis(joy, naxe, v);
619  } else if (usage == HUG_HAT_SWITCH) {
620  v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
621  SDL_PrivateJoystickHat(joy, 0,
622  hatval_to_sdl(v) -
623  hitem.logical_minimum);
624  }
625 #ifdef __OpenBSD__
626  else if (usage == HUG_DPAD_UP) {
627  dpad[0] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
628  SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
629  }
630  else if (usage == HUG_DPAD_DOWN) {
631  dpad[1] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
632  SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
633  }
634  else if (usage == HUG_DPAD_RIGHT) {
635  dpad[2] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
636  SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
637  }
638  else if (usage == HUG_DPAD_LEFT) {
639  dpad[3] = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
640  SDL_PrivateJoystickHat(joy, 0, dpad_to_sdl(dpad));
641  }
642 #endif
643  break;
644  }
645  case HUP_BUTTON:
646  v = (Sint32) hid_get_data(REP_BUF_DATA(rep), &hitem);
647  SDL_PrivateJoystickButton(joy, nbutton, v);
648  nbutton++;
649  break;
650  default:
651  continue;
652  }
653  break;
654  default:
655  break;
656  }
657  }
658  hid_end_parse(hdata);
659  }
660 }
661 
662 /* Function to close a joystick after use */
663 static void
664 BSD_JoystickClose(SDL_Joystick * joy)
665 {
666  if (SDL_strncmp(joy->hwdata->path, "/dev/joy", 8)) {
667  report_free(&joy->hwdata->inreport);
668  hid_dispose_report_desc(joy->hwdata->repdesc);
669  }
670  close(joy->hwdata->fd);
671  SDL_free(joy->hwdata->path);
672  SDL_free(joy->hwdata);
673 }
674 
675 static void
676 BSD_JoystickQuit(void)
677 {
678  int i;
679 
680  for (i = 0; i < MAX_JOYS; i++) {
681  SDL_free(joynames[i]);
682  SDL_free(joydevnames[i]);
683  }
684 
685  return;
686 }
687 
688 static SDL_JoystickGUID
689 BSD_JoystickGetDeviceGUID( int device_index )
690 {
691  SDL_JoystickGUID guid;
692  /* the GUID is just the first 16 chars of the name for now */
693  const char *name = BSD_JoystickGetDeviceName( device_index );
694  SDL_zero( guid );
695  SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) );
696  return guid;
697 }
698 
699 static int
700 report_alloc(struct report *r, struct report_desc *rd, int repind)
701 {
702  int len;
703 
704 #ifdef __DragonFly__
705  len = hid_report_size(rd, r->rid, repinfo[repind].kind);
706 #elif __FREEBSD__
707 # if (__FreeBSD_kernel_version >= 460000) || defined(__FreeBSD_kernel__)
708 # if (__FreeBSD_kernel_version <= 500111)
709  len = hid_report_size(rd, r->rid, repinfo[repind].kind);
710 # else
711  len = hid_report_size(rd, repinfo[repind].kind, r->rid);
712 # endif
713 # else
714  len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
715 # endif
716 #else
717 # ifdef USBHID_NEW
718  len = hid_report_size(rd, repinfo[repind].kind, r->rid);
719 # else
720  len = hid_report_size(rd, repinfo[repind].kind, &r->rid);
721 # endif
722 #endif
723 
724  if (len < 0) {
725  return SDL_SetError("Negative HID report size");
726  }
727  r->size = len;
728 
729  if (r->size > 0) {
730 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)
731  r->buf = SDL_malloc(r->size);
732 #else
733  r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) +
734  r->size);
735 #endif
736  if (r->buf == NULL) {
737  return SDL_OutOfMemory();
738  }
739  } else {
740  r->buf = NULL;
741  }
742 
743  r->status = SREPORT_CLEAN;
744  return 0;
745 }
746 
747 static void
748 report_free(struct report *r)
749 {
750  SDL_free(r->buf);
751  r->status = SREPORT_UNINIT;
752 }
753 
754 static int
755 BSD_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
756 {
757  return SDL_Unsupported();
758 }
759 
761 {
762  BSD_JoystickInit,
763  BSD_JoystickGetCount,
764  BSD_JoystickDetect,
765  BSD_JoystickGetDeviceName,
766  BSD_JoystickGetDevicePlayerIndex,
767  BSD_JoystickGetDeviceGUID,
768  BSD_JoystickGetDeviceInstanceID,
769  BSD_JoystickOpen,
770  BSD_JoystickRumble,
771  BSD_JoystickUpdate,
772  BSD_JoystickClose,
773  BSD_JoystickQuit,
774 };
775 
776 #endif /* SDL_JOYSTICK_USBHID */
777 
778 /* vi: set ts=4 sw=4 expandtab: */
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
joystick_hwdata::nhats
int nhats
Definition: SDL_sysjoystick_c.h:48
Sint32
int32_t Sint32
Definition: SDL_stdinc.h:197
numjoysticks
static int numjoysticks
Definition: SDL_sysjoystick.m:83
SDL_HAT_CENTERED
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:329
NULL
#define NULL
Definition: begin_code.h:167
SDL_HAT_DOWN
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:332
SDL_joystick.h
SDL_BSD_JoystickDriver
SDL_JoystickDriver SDL_BSD_JoystickDriver
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2078
hid_init
int HID_API_EXPORT HID_API_CALL hid_init(void)
Initialize the HIDAPI library.
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3730
SDL_strncmp
#define SDL_strncmp
Definition: SDL_dynapi_overrides.h:418
v
const GLdouble * v
Definition: SDL_opengl.h:2063
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
SDL_HAT_LEFTDOWN
#define SDL_HAT_LEFTDOWN
Definition: SDL_joystick.h:337
SDL_PrivateJoystickAxis
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:833
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: SDL_opengl_glext.h:2480
joystick_hwdata::fd
int fd
Definition: SDL_sysjoystick_c.h:32
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
usage
GLsizeiptr const void GLenum usage
Definition: SDL_opengl_glext.h:537
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1573
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
joystick_hwdata::naxes
int naxes
Definition: SDL_sysjoystick_c.h:46
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_PrivateJoystickButton
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:966
SDL_HAT_LEFT
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:333
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_HAT_LEFTUP
#define SDL_HAT_LEFTUP
Definition: SDL_joystick.h:336
SDL_JoystickDriver
Definition: SDL_sysjoystick.h:92
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:537
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1573
SDL_PrivateJoystickHat
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:890
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_HAT_RIGHT
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:331
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
s
GLdouble s
Definition: SDL_opengl.h:2062
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:397
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_HAT_UP
#define SDL_HAT_UP
Definition: SDL_joystick.h:330
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
fd
GLuint64 GLenum GLint fd
Definition: gl2ext.h:1508
SDL_JoystickGUID
Definition: SDL_joystick.h:70
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1570
SDL_HAT_RIGHTDOWN
#define SDL_HAT_RIGHTDOWN
Definition: SDL_joystick.h:335
i
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)
Definition: SDL_x11sym.h:50
SDL_HAT_RIGHTUP
#define SDL_HAT_RIGHTUP
Definition: SDL_joystick.h:334
Uint16
uint16_t Uint16
Definition: SDL_stdinc.h:191
joystick_hwdata
Definition: SDL_sysjoystick_c.h:46
SDL_JoystickID
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:81