1 --- src/joystick/bsd/SDL_sysjoystick.c.orig 2012-01-19 07:30:06.000000000 +0100 2 +++ src/joystick/bsd/SDL_sysjoystick.c 2015-05-06 22:52:50.648504057 +0900 3 @@ -77,12 +77,14 @@ 4 #include "../SDL_sysjoystick.h" 5 #include "../SDL_joystick_c.h" 6 7 -#define MAX_UHID_JOYS 4 8 -#define MAX_JOY_JOYS 2 9 +#define MAX_UHID_JOYS 16 10 +#define MAX_JOY_JOYS 8 11 #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) 12 13 struct report { 14 -#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) 15 +#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 16 + void *buf; /* Buffer */ 17 +#elif defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) 18 struct usb_gen_descriptor *buf; /* Buffer */ 19 #else 20 struct usb_ctl_report *buf; /* Buffer */ 21 @@ -148,8 +150,10 @@ 22 static int report_alloc(struct report *, struct report_desc *, int); 23 static void report_free(struct report *); 24 25 -#if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) 26 +#if defined(USBHID_UCR_DATA) || (defined(__FreeBSD_kernel__) && __FreeBSD_kernel_version <= 800063) 27 #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) 28 +#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000)) 29 +#define REP_BUF_DATA(rep) ((rep)->buf) 30 #elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) 31 #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) 32 #else 33 @@ -161,15 +165,40 @@ 34 { 35 char s[16]; 36 int i, fd; 37 + SDL_Joystick nj; 38 39 SDL_numjoysticks = 0; 40 41 SDL_memset(joynames, 0, sizeof(joynames)); 42 SDL_memset(joydevnames, 0, sizeof(joydevnames)); 43 44 - for (i = 0; i < MAX_UHID_JOYS; i++) { 45 - SDL_Joystick nj; 46 + /* First see if the user specified one or more joysticks to use */ 47 + if (NULL != SDL_getenv("SDL_JOYSTICK_DEVICE")) { 48 + char *envcopy, *envpath, *delim; 49 + envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE")); 50 + envpath = envcopy; 51 + while (NULL != envpath) { 52 + delim = SDL_strchr(envpath, ':'); 53 + if (NULL != delim) { 54 + *delim ++ = '\0'; 55 + } 56 + 57 + nj.index = SDL_numjoysticks; 58 + joynames[nj.index] = strdup(envpath); 59 + 60 + if (0 == SDL_SYS_JoystickOpen(&nj)) { 61 + SDL_SYS_JoystickClose(&nj); 62 + SDL_numjoysticks ++; 63 + } else { 64 + SDL_free(joynames[nj.index]); 65 + joynames[nj.index] = NULL; 66 + } 67 + envpath = delim; 68 + } 69 + SDL_free(envcopy); 70 + } 71 72 + for (i = 0; i < MAX_UHID_JOYS; i++) { 73 SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i); 74 75 nj.index = SDL_numjoysticks; 76 @@ -253,13 +282,12 @@ 77 int 78 SDL_SYS_JoystickOpen(SDL_Joystick *joy) 79 { 80 - char *path = joynames[joy->index]; 81 + char *path = joynames[joy->index], *sp, *s; 82 struct joystick_hwdata *hw; 83 struct hid_item hitem; 84 struct hid_data *hdata; 85 struct report *rep; 86 - int fd; 87 - int i; 88 + int i, fd; 89 90 fd = open(path, O_RDONLY); 91 if (fd == -1) { 92 @@ -282,6 +310,9 @@ 93 hw->ymin = 0xffff; 94 hw->xmax = 0; 95 hw->ymax = 0; 96 + for (i = 0; i < JOYAXE_count; i ++) { 97 + hw->axis_map[i] = -1; 98 + } 99 if (! SDL_strncmp(path, "/dev/joy", 8)) { 100 hw->type = BSDJOY_JOY; 101 joy->naxes = 2; 102 @@ -292,13 +323,12 @@ 103 goto usbend; 104 } else { 105 hw->type = BSDJOY_UHID; 106 + sp = SDL_malloc(32); 107 + SDL_snprintf(sp, 32, "Gamepad/Joystick (%d)", joy->index); 108 + SDL_free(joydevnames[joy->index]); 109 + joydevnames[joy->index] = sp; 110 } 111 112 - { 113 - int ax; 114 - for (ax = 0; ax < JOYAXE_count; ax++) 115 - hw->axis_map[ax] = -1; 116 - } 117 hw->repdesc = hid_get_report_desc(fd); 118 if (hw->repdesc == NULL) { 119 SDL_SetError("%s: USB_GET_REPORT_DESC: %s", hw->path, 120 @@ -307,8 +337,8 @@ 121 } 122 rep = &hw->inreport; 123 #if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063) || defined(__FreeBSD_kernel__) 124 - rep->rid = hid_get_report_id(fd); 125 - if (rep->rid < 0) { 126 + rep->rid = hid_get_report_id(fd); 127 + if (rep->rid < 0) { 128 #else 129 if (ioctl(fd, USB_GET_REPORT_ID, &rep->rid) < 0) { 130 #endif 131 @@ -336,13 +366,8 @@ 132 joy->nbuttons = 0; 133 joy->nhats = 0; 134 joy->nballs = 0; 135 - for (i=0; i<JOYAXE_count; i++) 136 - hw->axis_map[i] = -1; 137 138 while (hid_get_item(hdata, &hitem) > 0) { 139 - char *sp; 140 - const char *s; 141 - 142 switch (hitem.kind) { 143 case hid_collection: 144 switch (HID_PAGE(hitem.usage)) { 145 @@ -351,9 +376,10 @@ 146 case HUG_JOYSTICK: 147 case HUG_GAME_PAD: 148 s = hid_usage_in_page(hitem.usage); 149 - sp = SDL_malloc(SDL_strlen(s) + 5); 150 - SDL_snprintf(sp, SDL_strlen(s) + 5, "%s (%d)", s, 151 + sp = SDL_malloc(SDL_strlen(s) + 8); 152 + SDL_snprintf(sp, SDL_strlen(s) + 8, "%s (%d)", s, 153 joy->index); 154 + SDL_free(joydevnames[joy->index]); 155 joydevnames[joy->index] = sp; 156 } 157 } 158 @@ -361,24 +387,20 @@ 159 case hid_input: 160 switch (HID_PAGE(hitem.usage)) { 161 case HUP_GENERIC_DESKTOP: { 162 - unsigned usage = HID_USAGE(hitem.usage); 163 - int joyaxe = usage_to_joyaxe(usage); 164 - if (joyaxe >= 0) { 165 - hw->axis_map[joyaxe] = 1; 166 - } else if (usage == HUG_HAT_SWITCH) { 167 - joy->nhats++; 168 - } 169 - break; 170 + unsigned usage = HID_USAGE(hitem.usage); 171 + int joyaxe = usage_to_joyaxe(usage); 172 + if (joyaxe >= 0) { 173 + hw->axis_map[joyaxe] = 1; 174 + } else if (usage == HUG_HAT_SWITCH) { 175 + joy->nhats++; 176 + } 177 + break; 178 } 179 case HUP_BUTTON: 180 joy->nbuttons++; 181 break; 182 - default: 183 - break; 184 } 185 break; 186 - default: 187 - break; 188 } 189 } 190 hid_end_parse(hdata); 191 @@ -386,6 +408,12 @@ 192 if (hw->axis_map[i] > 0) 193 hw->axis_map[i] = joy->naxes++; 194 195 + if (0 == joy->naxes && 196 + 0 == joy->nbuttons && 197 + 0 == joy->nhats && 198 + 0 == joy->nballs) 199 + goto usberr; 200 + 201 usbend: 202 /* The poll blocks the event thread. */ 203 fcntl(fd, F_SETFL, O_NONBLOCK); 204 @@ -411,47 +439,47 @@ 205 struct joystick gameport; 206 207 if (joy->hwdata->type == BSDJOY_JOY) { 208 - if (read(joy->hwdata->fd, &gameport, sizeof gameport) != sizeof gameport) 209 - return; 210 - if (abs(joy->hwdata->x - gameport.x) > 8) { 211 - joy->hwdata->x = gameport.x; 212 - if (joy->hwdata->x < joy->hwdata->xmin) { 213 - joy->hwdata->xmin = joy->hwdata->x; 214 - } 215 - if (joy->hwdata->x > joy->hwdata->xmax) { 216 - joy->hwdata->xmax = joy->hwdata->x; 217 - } 218 - if (joy->hwdata->xmin == joy->hwdata->xmax) { 219 - joy->hwdata->xmin--; 220 - joy->hwdata->xmax++; 221 - } 222 - v = (Sint32)joy->hwdata->x; 223 - v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2; 224 - v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2); 225 - SDL_PrivateJoystickAxis(joy, 0, v); 226 - } 227 - if (abs(joy->hwdata->y - gameport.y) > 8) { 228 - joy->hwdata->y = gameport.y; 229 - if (joy->hwdata->y < joy->hwdata->ymin) { 230 - joy->hwdata->ymin = joy->hwdata->y; 231 + while (read(joy->hwdata->fd, &gameport, sizeof gameport) == sizeof gameport) { 232 + if (abs(joy->hwdata->x - gameport.x) > 8) { 233 + joy->hwdata->x = gameport.x; 234 + if (joy->hwdata->x < joy->hwdata->xmin) { 235 + joy->hwdata->xmin = joy->hwdata->x; 236 + } 237 + if (joy->hwdata->x > joy->hwdata->xmax) { 238 + joy->hwdata->xmax = joy->hwdata->x; 239 + } 240 + if (joy->hwdata->xmin == joy->hwdata->xmax) { 241 + joy->hwdata->xmin--; 242 + joy->hwdata->xmax++; 243 + } 244 + v = (Sint32)joy->hwdata->x; 245 + v -= (joy->hwdata->xmax + joy->hwdata->xmin + 1)/2; 246 + v *= 32768/((joy->hwdata->xmax - joy->hwdata->xmin + 1)/2); 247 + SDL_PrivateJoystickAxis(joy, 0, v); 248 + } 249 + if (abs(joy->hwdata->y - gameport.y) > 8) { 250 + joy->hwdata->y = gameport.y; 251 + if (joy->hwdata->y < joy->hwdata->ymin) { 252 + joy->hwdata->ymin = joy->hwdata->y; 253 + } 254 + if (joy->hwdata->y > joy->hwdata->ymax) { 255 + joy->hwdata->ymax = joy->hwdata->y; 256 + } 257 + if (joy->hwdata->ymin == joy->hwdata->ymax) { 258 + joy->hwdata->ymin--; 259 + joy->hwdata->ymax++; 260 + } 261 + v = (Sint32)joy->hwdata->y; 262 + v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2; 263 + v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2); 264 + SDL_PrivateJoystickAxis(joy, 1, v); 265 } 266 - if (joy->hwdata->y > joy->hwdata->ymax) { 267 - joy->hwdata->ymax = joy->hwdata->y; 268 + if (gameport.b1 != joy->buttons[0]) { 269 + SDL_PrivateJoystickButton(joy, 0, gameport.b1); 270 } 271 - if (joy->hwdata->ymin == joy->hwdata->ymax) { 272 - joy->hwdata->ymin--; 273 - joy->hwdata->ymax++; 274 + if (gameport.b2 != joy->buttons[1]) { 275 + SDL_PrivateJoystickButton(joy, 1, gameport.b2); 276 } 277 - v = (Sint32)joy->hwdata->y; 278 - v -= (joy->hwdata->ymax + joy->hwdata->ymin + 1)/2; 279 - v *= 32768/((joy->hwdata->ymax - joy->hwdata->ymin + 1)/2); 280 - SDL_PrivateJoystickAxis(joy, 1, v); 281 - } 282 - if (gameport.b1 != joy->buttons[0]) { 283 - SDL_PrivateJoystickButton(joy, 0, gameport.b1); 284 - } 285 - if (gameport.b2 != joy->buttons[1]) { 286 - SDL_PrivateJoystickButton(joy, 1, gameport.b2); 287 } 288 return; 289 } 290 @@ -459,65 +487,61 @@ 291 292 rep = &joy->hwdata->inreport; 293 294 - if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) { 295 - return; 296 - } 297 + while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) { 298 #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) 299 - hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); 300 + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); 301 #else 302 - hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); 303 + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); 304 #endif 305 - if (hdata == NULL) { 306 - fprintf(stderr, "%s: Cannot start HID parser\n", 307 - joy->hwdata->path); 308 - return; 309 - } 310 + if (hdata == NULL) { 311 + /*fprintf(stderr, "%s: Cannot start HID parser\n", joy->hwdata->path);*/ 312 + continue; 313 + } 314 315 - for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { 316 - switch (hitem.kind) { 317 - case hid_input: 318 - switch (HID_PAGE(hitem.usage)) { 319 - case HUP_GENERIC_DESKTOP: { 320 - unsigned usage = HID_USAGE(hitem.usage); 321 - int joyaxe = usage_to_joyaxe(usage); 322 - if (joyaxe >= 0) { 323 - naxe = joy->hwdata->axis_map[joyaxe]; 324 - /* scaleaxe */ 325 - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 326 - &hitem); 327 - v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; 328 - v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); 329 - if (v != joy->axes[naxe]) { 330 - SDL_PrivateJoystickAxis(joy, naxe, v); 331 + for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { 332 + switch (hitem.kind) { 333 + case hid_input: 334 + switch (HID_PAGE(hitem.usage)) { 335 + case HUP_GENERIC_DESKTOP: { 336 + unsigned usage = HID_USAGE(hitem.usage); 337 + int joyaxe = usage_to_joyaxe(usage); 338 + if (joyaxe >= 0) { 339 + naxe = joy->hwdata->axis_map[joyaxe]; 340 + /* scaleaxe */ 341 + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 342 + &hitem); 343 + v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; 344 + v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); 345 + if (v != joy->axes[naxe]) { 346 + SDL_PrivateJoystickAxis(joy, naxe, v); 347 + } 348 + } else if (usage == HUG_HAT_SWITCH) { 349 + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 350 + &hitem); 351 + SDL_PrivateJoystickHat(joy, 0, 352 + hatval_to_sdl(v)-hitem.logical_minimum); 353 + } 354 + break; 355 } 356 - } else if (usage == HUG_HAT_SWITCH) { 357 - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 358 - &hitem); 359 - SDL_PrivateJoystickHat(joy, 0, 360 - hatval_to_sdl(v)-hitem.logical_minimum); 361 - } 362 - break; 363 - } 364 - case HUP_BUTTON: 365 - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 366 - &hitem); 367 - if (joy->buttons[nbutton] != v) { 368 - SDL_PrivateJoystickButton(joy, 369 - nbutton, v); 370 + case HUP_BUTTON: 371 + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), 372 + &hitem); 373 + if (joy->buttons[nbutton] != v) { 374 + SDL_PrivateJoystickButton(joy, 375 + nbutton, v); 376 + } 377 + nbutton++; 378 + break; 379 + default: 380 + continue; 381 } 382 - nbutton++; 383 break; 384 default: 385 - continue; 386 + break; 387 } 388 - break; 389 - default: 390 - break; 391 } 392 + hid_end_parse(hdata); 393 } 394 - hid_end_parse(hdata); 395 - 396 - return; 397 } 398 399 /* Function to close a joystick after use */ 400 @@ -582,8 +606,12 @@ 401 r->size = len; 402 403 if (r->size > 0) { 404 +#if defined(__FREEBSD__) && (__FreeBSD_kernel_version > 900000) 405 + r->buf = SDL_malloc(r->size); 406 +#else 407 r->buf = SDL_malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + 408 r->size); 409 +#endif 410 if (r->buf == NULL) { 411 SDL_OutOfMemory(); 412 return (-1); 413