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