SDL_joystick.c (21148B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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/* This is the joystick API for Simple DirectMedia Layer */ 24 25#include "SDL.h" 26#include "SDL_events.h" 27#include "SDL_sysjoystick.h" 28#include "SDL_assert.h" 29#include "SDL_hints.h" 30 31#if !SDL_EVENTS_DISABLED 32#include "../events/SDL_events_c.h" 33#endif 34 35static SDL_bool SDL_joystick_allows_background_events = SDL_FALSE; 36static SDL_Joystick *SDL_joysticks = NULL; 37static SDL_Joystick *SDL_updating_joystick = NULL; 38 39static void 40SDL_JoystickAllowBackgroundEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) 41{ 42 if (hint && *hint == '1') { 43 SDL_joystick_allows_background_events = SDL_TRUE; 44 } else { 45 SDL_joystick_allows_background_events = SDL_FALSE; 46 } 47} 48 49int 50SDL_JoystickInit(void) 51{ 52 int status; 53 54 /* See if we should allow joystick events while in the background */ 55 SDL_AddHintCallback(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, 56 SDL_JoystickAllowBackgroundEventsChanged, NULL); 57 58#if !SDL_EVENTS_DISABLED 59 if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) { 60 return -1; 61 } 62#endif /* !SDL_EVENTS_DISABLED */ 63 64 status = SDL_SYS_JoystickInit(); 65 if (status >= 0) { 66 status = 0; 67 } 68 return (status); 69} 70 71/* 72 * Count the number of joysticks attached to the system 73 */ 74int 75SDL_NumJoysticks(void) 76{ 77 return SDL_SYS_NumJoysticks(); 78} 79 80/* 81 * Get the implementation dependent name of a joystick 82 */ 83const char * 84SDL_JoystickNameForIndex(int device_index) 85{ 86 if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { 87 SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); 88 return (NULL); 89 } 90 return (SDL_SYS_JoystickNameForDeviceIndex(device_index)); 91} 92 93/* 94 * Open a joystick for use - the index passed as an argument refers to 95 * the N'th joystick on the system. This index is the value which will 96 * identify this joystick in future joystick events. 97 * 98 * This function returns a joystick identifier, or NULL if an error occurred. 99 */ 100SDL_Joystick * 101SDL_JoystickOpen(int device_index) 102{ 103 SDL_Joystick *joystick; 104 SDL_Joystick *joysticklist; 105 const char *joystickname = NULL; 106 107 if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { 108 SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); 109 return (NULL); 110 } 111 112 joysticklist = SDL_joysticks; 113 /* If the joystick is already open, return it 114 * it is important that we have a single joystick * for each instance id 115 */ 116 while (joysticklist) { 117 if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == joysticklist->instance_id) { 118 joystick = joysticklist; 119 ++joystick->ref_count; 120 return (joystick); 121 } 122 joysticklist = joysticklist->next; 123 } 124 125 /* Create and initialize the joystick */ 126 joystick = (SDL_Joystick *) SDL_malloc((sizeof *joystick)); 127 if (joystick == NULL) { 128 SDL_OutOfMemory(); 129 return NULL; 130 } 131 132 SDL_memset(joystick, 0, (sizeof *joystick)); 133 if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) { 134 SDL_free(joystick); 135 return NULL; 136 } 137 138 joystickname = SDL_SYS_JoystickNameForDeviceIndex(device_index); 139 if (joystickname) 140 joystick->name = SDL_strdup(joystickname); 141 else 142 joystick->name = NULL; 143 144 if (joystick->naxes > 0) { 145 joystick->axes = (Sint16 *) SDL_malloc 146 (joystick->naxes * sizeof(Sint16)); 147 } 148 if (joystick->nhats > 0) { 149 joystick->hats = (Uint8 *) SDL_malloc 150 (joystick->nhats * sizeof(Uint8)); 151 } 152 if (joystick->nballs > 0) { 153 joystick->balls = (struct balldelta *) SDL_malloc 154 (joystick->nballs * sizeof(*joystick->balls)); 155 } 156 if (joystick->nbuttons > 0) { 157 joystick->buttons = (Uint8 *) SDL_malloc 158 (joystick->nbuttons * sizeof(Uint8)); 159 } 160 if (((joystick->naxes > 0) && !joystick->axes) 161 || ((joystick->nhats > 0) && !joystick->hats) 162 || ((joystick->nballs > 0) && !joystick->balls) 163 || ((joystick->nbuttons > 0) && !joystick->buttons)) { 164 SDL_OutOfMemory(); 165 SDL_JoystickClose(joystick); 166 return NULL; 167 } 168 if (joystick->axes) { 169 SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16)); 170 } 171 if (joystick->hats) { 172 SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8)); 173 } 174 if (joystick->balls) { 175 SDL_memset(joystick->balls, 0, 176 joystick->nballs * sizeof(*joystick->balls)); 177 } 178 if (joystick->buttons) { 179 SDL_memset(joystick->buttons, 0, joystick->nbuttons * sizeof(Uint8)); 180 } 181 182 /* Add joystick to list */ 183 ++joystick->ref_count; 184 /* Link the joystick in the list */ 185 joystick->next = SDL_joysticks; 186 SDL_joysticks = joystick; 187 188 SDL_SYS_JoystickUpdate(joystick); 189 190 return (joystick); 191} 192 193 194/* 195 * Checks to make sure the joystick is valid. 196 */ 197int 198SDL_PrivateJoystickValid(SDL_Joystick * joystick) 199{ 200 int valid; 201 202 if (joystick == NULL) { 203 SDL_SetError("Joystick hasn't been opened yet"); 204 valid = 0; 205 } else { 206 valid = 1; 207 } 208 209 if (joystick && joystick->closed) { 210 valid = 0; 211 } 212 213 return valid; 214} 215 216/* 217 * Get the number of multi-dimensional axis controls on a joystick 218 */ 219int 220SDL_JoystickNumAxes(SDL_Joystick * joystick) 221{ 222 if (!SDL_PrivateJoystickValid(joystick)) { 223 return (-1); 224 } 225 return (joystick->naxes); 226} 227 228/* 229 * Get the number of hats on a joystick 230 */ 231int 232SDL_JoystickNumHats(SDL_Joystick * joystick) 233{ 234 if (!SDL_PrivateJoystickValid(joystick)) { 235 return (-1); 236 } 237 return (joystick->nhats); 238} 239 240/* 241 * Get the number of trackballs on a joystick 242 */ 243int 244SDL_JoystickNumBalls(SDL_Joystick * joystick) 245{ 246 if (!SDL_PrivateJoystickValid(joystick)) { 247 return (-1); 248 } 249 return (joystick->nballs); 250} 251 252/* 253 * Get the number of buttons on a joystick 254 */ 255int 256SDL_JoystickNumButtons(SDL_Joystick * joystick) 257{ 258 if (!SDL_PrivateJoystickValid(joystick)) { 259 return (-1); 260 } 261 return (joystick->nbuttons); 262} 263 264/* 265 * Get the current state of an axis control on a joystick 266 */ 267Sint16 268SDL_JoystickGetAxis(SDL_Joystick * joystick, int axis) 269{ 270 Sint16 state; 271 272 if (!SDL_PrivateJoystickValid(joystick)) { 273 return (0); 274 } 275 if (axis < joystick->naxes) { 276 state = joystick->axes[axis]; 277 } else { 278 SDL_SetError("Joystick only has %d axes", joystick->naxes); 279 state = 0; 280 } 281 return (state); 282} 283 284/* 285 * Get the current state of a hat on a joystick 286 */ 287Uint8 288SDL_JoystickGetHat(SDL_Joystick * joystick, int hat) 289{ 290 Uint8 state; 291 292 if (!SDL_PrivateJoystickValid(joystick)) { 293 return (0); 294 } 295 if (hat < joystick->nhats) { 296 state = joystick->hats[hat]; 297 } else { 298 SDL_SetError("Joystick only has %d hats", joystick->nhats); 299 state = 0; 300 } 301 return (state); 302} 303 304/* 305 * Get the ball axis change since the last poll 306 */ 307int 308SDL_JoystickGetBall(SDL_Joystick * joystick, int ball, int *dx, int *dy) 309{ 310 int retval; 311 312 if (!SDL_PrivateJoystickValid(joystick)) { 313 return (-1); 314 } 315 316 retval = 0; 317 if (ball < joystick->nballs) { 318 if (dx) { 319 *dx = joystick->balls[ball].dx; 320 } 321 if (dy) { 322 *dy = joystick->balls[ball].dy; 323 } 324 joystick->balls[ball].dx = 0; 325 joystick->balls[ball].dy = 0; 326 } else { 327 return SDL_SetError("Joystick only has %d balls", joystick->nballs); 328 } 329 return (retval); 330} 331 332/* 333 * Get the current state of a button on a joystick 334 */ 335Uint8 336SDL_JoystickGetButton(SDL_Joystick * joystick, int button) 337{ 338 Uint8 state; 339 340 if (!SDL_PrivateJoystickValid(joystick)) { 341 return (0); 342 } 343 if (button < joystick->nbuttons) { 344 state = joystick->buttons[button]; 345 } else { 346 SDL_SetError("Joystick only has %d buttons", joystick->nbuttons); 347 state = 0; 348 } 349 return (state); 350} 351 352/* 353 * Return if the joystick in question is currently attached to the system, 354 * \return SDL_FALSE if not plugged in, SDL_TRUE if still present. 355 */ 356SDL_bool 357SDL_JoystickGetAttached(SDL_Joystick * joystick) 358{ 359 if (!SDL_PrivateJoystickValid(joystick)) { 360 return SDL_FALSE; 361 } 362 363 return SDL_SYS_JoystickAttached(joystick); 364} 365 366/* 367 * Get the instance id for this opened joystick 368 */ 369SDL_JoystickID 370SDL_JoystickInstanceID(SDL_Joystick * joystick) 371{ 372 if (!SDL_PrivateJoystickValid(joystick)) { 373 return (-1); 374 } 375 376 return (joystick->instance_id); 377} 378 379/* 380 * Get the friendly name of this joystick 381 */ 382const char * 383SDL_JoystickName(SDL_Joystick * joystick) 384{ 385 if (!SDL_PrivateJoystickValid(joystick)) { 386 return (NULL); 387 } 388 389 return (joystick->name); 390} 391 392/* 393 * Close a joystick previously opened with SDL_JoystickOpen() 394 */ 395void 396SDL_JoystickClose(SDL_Joystick * joystick) 397{ 398 SDL_Joystick *joysticklist; 399 SDL_Joystick *joysticklistprev; 400 401 if (!joystick) { 402 return; 403 } 404 405 /* First decrement ref count */ 406 if (--joystick->ref_count > 0) { 407 return; 408 } 409 410 if (joystick == SDL_updating_joystick) { 411 return; 412 } 413 414 SDL_SYS_JoystickClose(joystick); 415 416 joysticklist = SDL_joysticks; 417 joysticklistprev = NULL; 418 while (joysticklist) { 419 if (joystick == joysticklist) { 420 if (joysticklistprev) { 421 /* unlink this entry */ 422 joysticklistprev->next = joysticklist->next; 423 } else { 424 SDL_joysticks = joystick->next; 425 } 426 break; 427 } 428 joysticklistprev = joysticklist; 429 joysticklist = joysticklist->next; 430 } 431 432 SDL_free(joystick->name); 433 434 /* Free the data associated with this joystick */ 435 SDL_free(joystick->axes); 436 SDL_free(joystick->hats); 437 SDL_free(joystick->balls); 438 SDL_free(joystick->buttons); 439 SDL_free(joystick); 440} 441 442void 443SDL_JoystickQuit(void) 444{ 445 /* Make sure we're not getting called in the middle of updating joysticks */ 446 SDL_assert(!SDL_updating_joystick); 447 448 /* Stop the event polling */ 449 while (SDL_joysticks) { 450 SDL_joysticks->ref_count = 1; 451 SDL_JoystickClose(SDL_joysticks); 452 } 453 454 /* Quit the joystick setup */ 455 SDL_SYS_JoystickQuit(); 456 457#if !SDL_EVENTS_DISABLED 458 SDL_QuitSubSystem(SDL_INIT_EVENTS); 459#endif 460} 461 462 463static SDL_bool 464SDL_PrivateJoystickShouldIgnoreEvent() 465{ 466 if (SDL_joystick_allows_background_events) { 467 return SDL_FALSE; 468 } 469 470 if (SDL_WasInit(SDL_INIT_VIDEO)) { 471 if (SDL_GetKeyboardFocus() == NULL) { 472 /* Video is initialized and we don't have focus, ignore the event. */ 473 return SDL_TRUE; 474 } else { 475 return SDL_FALSE; 476 } 477 } 478 479 /* Video subsystem wasn't initialized, always allow the event */ 480 return SDL_FALSE; 481} 482 483/* These are global for SDL_sysjoystick.c and SDL_events.c */ 484 485int 486SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value) 487{ 488 int posted; 489 490 /* Make sure we're not getting garbage or duplicate events */ 491 if (axis >= joystick->naxes) { 492 return 0; 493 } 494 if (value == joystick->axes[axis]) { 495 return 0; 496 } 497 498 /* We ignore events if we don't have keyboard focus, except for centering 499 * events. 500 */ 501 if (SDL_PrivateJoystickShouldIgnoreEvent()) { 502 if ((value > 0 && value >= joystick->axes[axis]) || 503 (value < 0 && value <= joystick->axes[axis])) { 504 return 0; 505 } 506 } 507 508 /* Update internal joystick state */ 509 joystick->axes[axis] = value; 510 511 /* Post the event, if desired */ 512 posted = 0; 513#if !SDL_EVENTS_DISABLED 514 if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) { 515 SDL_Event event; 516 event.type = SDL_JOYAXISMOTION; 517 event.jaxis.which = joystick->instance_id; 518 event.jaxis.axis = axis; 519 event.jaxis.value = value; 520 posted = SDL_PushEvent(&event) == 1; 521 } 522#endif /* !SDL_EVENTS_DISABLED */ 523 return (posted); 524} 525 526int 527SDL_PrivateJoystickHat(SDL_Joystick * joystick, Uint8 hat, Uint8 value) 528{ 529 int posted; 530 531 /* Make sure we're not getting garbage or duplicate events */ 532 if (hat >= joystick->nhats) { 533 return 0; 534 } 535 if (value == joystick->hats[hat]) { 536 return 0; 537 } 538 539 /* We ignore events if we don't have keyboard focus, except for centering 540 * events. 541 */ 542 if (SDL_PrivateJoystickShouldIgnoreEvent()) { 543 if (value != SDL_HAT_CENTERED) { 544 return 0; 545 } 546 } 547 548 /* Update internal joystick state */ 549 joystick->hats[hat] = value; 550 551 /* Post the event, if desired */ 552 posted = 0; 553#if !SDL_EVENTS_DISABLED 554 if (SDL_GetEventState(SDL_JOYHATMOTION) == SDL_ENABLE) { 555 SDL_Event event; 556 event.jhat.type = SDL_JOYHATMOTION; 557 event.jhat.which = joystick->instance_id; 558 event.jhat.hat = hat; 559 event.jhat.value = value; 560 posted = SDL_PushEvent(&event) == 1; 561 } 562#endif /* !SDL_EVENTS_DISABLED */ 563 return (posted); 564} 565 566int 567SDL_PrivateJoystickBall(SDL_Joystick * joystick, Uint8 ball, 568 Sint16 xrel, Sint16 yrel) 569{ 570 int posted; 571 572 /* Make sure we're not getting garbage events */ 573 if (ball >= joystick->nballs) { 574 return 0; 575 } 576 577 /* We ignore events if we don't have keyboard focus. */ 578 if (SDL_PrivateJoystickShouldIgnoreEvent()) { 579 return 0; 580 } 581 582 /* Update internal mouse state */ 583 joystick->balls[ball].dx += xrel; 584 joystick->balls[ball].dy += yrel; 585 586 /* Post the event, if desired */ 587 posted = 0; 588#if !SDL_EVENTS_DISABLED 589 if (SDL_GetEventState(SDL_JOYBALLMOTION) == SDL_ENABLE) { 590 SDL_Event event; 591 event.jball.type = SDL_JOYBALLMOTION; 592 event.jball.which = joystick->instance_id; 593 event.jball.ball = ball; 594 event.jball.xrel = xrel; 595 event.jball.yrel = yrel; 596 posted = SDL_PushEvent(&event) == 1; 597 } 598#endif /* !SDL_EVENTS_DISABLED */ 599 return (posted); 600} 601 602int 603SDL_PrivateJoystickButton(SDL_Joystick * joystick, Uint8 button, Uint8 state) 604{ 605 int posted; 606#if !SDL_EVENTS_DISABLED 607 SDL_Event event; 608 609 switch (state) { 610 case SDL_PRESSED: 611 event.type = SDL_JOYBUTTONDOWN; 612 break; 613 case SDL_RELEASED: 614 event.type = SDL_JOYBUTTONUP; 615 break; 616 default: 617 /* Invalid state -- bail */ 618 return (0); 619 } 620#endif /* !SDL_EVENTS_DISABLED */ 621 622 /* Make sure we're not getting garbage or duplicate events */ 623 if (button >= joystick->nbuttons) { 624 return 0; 625 } 626 if (state == joystick->buttons[button]) { 627 return 0; 628 } 629 630 /* We ignore events if we don't have keyboard focus, except for button 631 * release. */ 632 if (SDL_PrivateJoystickShouldIgnoreEvent()) { 633 if (state == SDL_PRESSED) { 634 return 0; 635 } 636 } 637 638 /* Update internal joystick state */ 639 joystick->buttons[button] = state; 640 641 /* Post the event, if desired */ 642 posted = 0; 643#if !SDL_EVENTS_DISABLED 644 if (SDL_GetEventState(event.type) == SDL_ENABLE) { 645 event.jbutton.which = joystick->instance_id; 646 event.jbutton.button = button; 647 event.jbutton.state = state; 648 posted = SDL_PushEvent(&event) == 1; 649 } 650#endif /* !SDL_EVENTS_DISABLED */ 651 return (posted); 652} 653 654void 655SDL_JoystickUpdate(void) 656{ 657 SDL_Joystick *joystick; 658 659 joystick = SDL_joysticks; 660 while (joystick) { 661 SDL_Joystick *joysticknext; 662 /* save off the next pointer, the Update call may cause a joystick removed event 663 * and cause our joystick pointer to be freed 664 */ 665 joysticknext = joystick->next; 666 667 SDL_updating_joystick = joystick; 668 669 SDL_SYS_JoystickUpdate(joystick); 670 671 if (joystick->closed && joystick->uncentered) { 672 int i; 673 674 /* Tell the app that everything is centered/unpressed... */ 675 for (i = 0; i < joystick->naxes; i++) 676 SDL_PrivateJoystickAxis(joystick, i, 0); 677 678 for (i = 0; i < joystick->nbuttons; i++) 679 SDL_PrivateJoystickButton(joystick, i, 0); 680 681 for (i = 0; i < joystick->nhats; i++) 682 SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); 683 684 joystick->uncentered = SDL_FALSE; 685 } 686 687 SDL_updating_joystick = NULL; 688 689 /* If the joystick was closed while updating, free it here */ 690 if (joystick->ref_count <= 0) { 691 SDL_JoystickClose(joystick); 692 } 693 694 joystick = joysticknext; 695 } 696 697 /* this needs to happen AFTER walking the joystick list above, so that any 698 dangling hardware data from removed devices can be free'd 699 */ 700 SDL_SYS_JoystickDetect(); 701} 702 703int 704SDL_JoystickEventState(int state) 705{ 706#if SDL_EVENTS_DISABLED 707 return SDL_DISABLE; 708#else 709 const Uint32 event_list[] = { 710 SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION, 711 SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED 712 }; 713 unsigned int i; 714 715 switch (state) { 716 case SDL_QUERY: 717 state = SDL_DISABLE; 718 for (i = 0; i < SDL_arraysize(event_list); ++i) { 719 state = SDL_EventState(event_list[i], SDL_QUERY); 720 if (state == SDL_ENABLE) { 721 break; 722 } 723 } 724 break; 725 default: 726 for (i = 0; i < SDL_arraysize(event_list); ++i) { 727 SDL_EventState(event_list[i], state); 728 } 729 break; 730 } 731 return (state); 732#endif /* SDL_EVENTS_DISABLED */ 733} 734 735/* return the guid for this index */ 736SDL_JoystickGUID SDL_JoystickGetDeviceGUID(int device_index) 737{ 738 if ((device_index < 0) || (device_index >= SDL_NumJoysticks())) { 739 SDL_JoystickGUID emptyGUID; 740 SDL_SetError("There are %d joysticks available", SDL_NumJoysticks()); 741 SDL_zero(emptyGUID); 742 return emptyGUID; 743 } 744 return SDL_SYS_JoystickGetDeviceGUID(device_index); 745} 746 747/* return the guid for this opened device */ 748SDL_JoystickGUID SDL_JoystickGetGUID(SDL_Joystick * joystick) 749{ 750 if (!SDL_PrivateJoystickValid(joystick)) { 751 SDL_JoystickGUID emptyGUID; 752 SDL_zero(emptyGUID); 753 return emptyGUID; 754 } 755 return SDL_SYS_JoystickGetGUID(joystick); 756} 757 758/* convert the guid to a printable string */ 759void SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID) 760{ 761 static const char k_rgchHexToASCII[] = "0123456789abcdef"; 762 int i; 763 764 if ((pszGUID == NULL) || (cbGUID <= 0)) { 765 return; 766 } 767 768 for (i = 0; i < sizeof(guid.data) && i < (cbGUID-1)/2; i++) { 769 /* each input byte writes 2 ascii chars, and might write a null byte. */ 770 /* If we don't have room for next input byte, stop */ 771 unsigned char c = guid.data[i]; 772 773 *pszGUID++ = k_rgchHexToASCII[c >> 4]; 774 *pszGUID++ = k_rgchHexToASCII[c & 0x0F]; 775 } 776 *pszGUID = '\0'; 777} 778 779 780/*----------------------------------------------------------------------------- 781 * Purpose: Returns the 4 bit nibble for a hex character 782 * Input : c - 783 * Output : unsigned char 784 *-----------------------------------------------------------------------------*/ 785static unsigned char nibble(char c) 786{ 787 if ((c >= '0') && (c <= '9')) { 788 return (unsigned char)(c - '0'); 789 } 790 791 if ((c >= 'A') && (c <= 'F')) { 792 return (unsigned char)(c - 'A' + 0x0a); 793 } 794 795 if ((c >= 'a') && (c <= 'f')) { 796 return (unsigned char)(c - 'a' + 0x0a); 797 } 798 799 /* received an invalid character, and no real way to return an error */ 800 /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */ 801 return 0; 802} 803 804 805/* convert the string version of a joystick guid to the struct */ 806SDL_JoystickGUID SDL_JoystickGetGUIDFromString(const char *pchGUID) 807{ 808 SDL_JoystickGUID guid; 809 int maxoutputbytes= sizeof(guid); 810 size_t len = SDL_strlen(pchGUID); 811 Uint8 *p; 812 size_t i; 813 814 /* Make sure it's even */ 815 len = (len) & ~0x1; 816 817 SDL_memset(&guid, 0x00, sizeof(guid)); 818 819 p = (Uint8 *)&guid; 820 for (i = 0; (i < len) && ((p - (Uint8 *)&guid) < maxoutputbytes); i+=2, p++) { 821 *p = (nibble(pchGUID[i]) << 4) | nibble(pchGUID[i+1]); 822 } 823 824 return guid; 825} 826 827 828/* vi: set ts=4 sw=4 expandtab: */