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