50
50
#define JOYSTICK_USAGE_NUMBER 0x04
51
51
#define GAMEPAD_USAGE_NUMBER 0x05
52
52
53
+ #define JOYSTICK_NAME_MAX 256
54
+
53
55
typedef struct {
54
56
ALLEGRO_JOYSTICK parent;
57
+ char name[JOYSTICK_NAME_MAX];
55
58
IOHIDElementRef buttons[_AL_MAX_JOYSTICK_BUTTONS];
56
59
IOHIDElementRef axes[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
57
60
IOHIDElementRef dpad;
@@ -130,12 +133,37 @@ static CFMutableDictionaryRef CreateDeviceMatchingDictionary(
130
133
return result;
131
134
}
132
135
133
- static ALLEGRO_JOYSTICK_OSX *find_joystick (IOHIDDeviceRef ident)
136
+ static bool joystick_uses_element (ALLEGRO_JOYSTICK_OSX *joy, IOHIDElementRef elem)
137
+ {
138
+ int i, j;
139
+
140
+ if (elem) {
141
+ for (i = 0 ; i < joy->parent .info .num_buttons ; i++) {
142
+ if (joy->buttons [i] == elem)
143
+ return true ;
144
+ }
145
+ for (i = 0 ; i < joy->parent .info .num_sticks ; i++) {
146
+ for (j = 0 ; j < joy->parent .info .stick [i].num_axes ; j++) {
147
+ if (joy->axes [i][j] == elem)
148
+ return true ;
149
+ }
150
+ }
151
+ if (joy->dpad == elem)
152
+ return true ;
153
+ }
154
+ else {
155
+ return true ;
156
+ }
157
+
158
+ return false ;
159
+ }
160
+
161
+ static ALLEGRO_JOYSTICK_OSX *find_joystick (IOHIDDeviceRef ident, IOHIDElementRef elem)
134
162
{
135
163
int i;
136
164
for (i = 0 ; i < (int )_al_vector_size (&joysticks); i++) {
137
165
ALLEGRO_JOYSTICK_OSX *joy = *(ALLEGRO_JOYSTICK_OSX **)_al_vector_ref (&joysticks, i);
138
- if (ident == joy->ident ) {
166
+ if (ident == joy->ident && joystick_uses_element (joy, elem) ) {
139
167
return joy;
140
168
}
141
169
}
@@ -145,10 +173,12 @@ static CFMutableDictionaryRef CreateDeviceMatchingDictionary(
145
173
146
174
static const char *get_element_name (IOHIDElementRef elem, const char *default_name)
147
175
{
176
+ const char *name_cstr = NULL ;
148
177
CFStringRef name = IOHIDElementGetName (elem);
149
- if (name) {
150
- return CFStringGetCStringPtr (name, kCFStringEncodingUTF8 );
151
- }
178
+ if (name)
179
+ name_cstr = CFStringGetCStringPtr (name, kCFStringEncodingUTF8 );
180
+ if (name_cstr)
181
+ return name_cstr;
152
182
else
153
183
return default_name;
154
184
}
@@ -182,31 +212,58 @@ static void add_axis(ALLEGRO_JOYSTICK_OSX *joy, int stick_index, int axis_index,
182
212
joy->axes [stick_index][axis_index] = elem;
183
213
}
184
214
185
- static void add_elements (CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
215
+ static void add_elements (CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy, int device_joystick )
186
216
{
187
- int i;
217
+ int i, start_i = 0 ;
188
218
char default_name[100 ];
189
219
int stick_class = -1 ;
190
220
int axis_index = 0 ;
221
+ bool collection_started = false ;
222
+ int current_joystick = -1 ;
191
223
192
224
joy_null (joy);
193
225
226
+ /* look for device_joystick */
194
227
for (i = 0 ; i < CFArrayGetCount (elements); i++) {
195
228
IOHIDElementRef elem = (IOHIDElementRef)CFArrayGetValueAtIndex (
196
229
elements,
197
230
i
198
231
);
232
+ int etype = IOHIDElementGetType (elem);
233
+ if (etype == kIOHIDElementTypeCollection ) {
234
+ collection_started = true ;
235
+ }
236
+ else if (etype == kIOHIDElementTypeInput_Button || etype == kIOHIDElementTypeInput_Misc ) {
237
+ if (collection_started) {
238
+ current_joystick++;
239
+ collection_started = false ;
240
+ if (current_joystick == device_joystick) {
241
+ start_i = i;
242
+ break ;
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ for (i = start_i; i < CFArrayGetCount (elements); i++) {
249
+ IOHIDElementRef elem = (IOHIDElementRef)CFArrayGetValueAtIndex (
250
+ elements,
251
+ i
252
+ );
199
253
200
254
int usage = IOHIDElementGetUsage (elem);
255
+ if (IOHIDElementGetType (elem) == kIOHIDElementTypeCollection ) {
256
+ break ;
257
+ }
201
258
if (IOHIDElementGetType (elem) == kIOHIDElementTypeInput_Button ) {
202
- if (usage >= 0 && usage < _AL_MAX_JOYSTICK_BUTTONS &&
203
- !joy->buttons [usage- 1 ]) {
204
- joy->buttons [usage- 1 ] = elem;
205
- sprintf (default_name, " Button %d " , usage- 1 );
259
+ if (usage >= 0 && joy-> parent . info . num_buttons < _AL_MAX_JOYSTICK_BUTTONS &&
260
+ !joy->buttons [joy->parent.info.num_buttons ]) {
261
+ joy->buttons [joy->parent.info.num_buttons ] = elem;
262
+ sprintf (default_name, " Button %d " , joy-> parent . info . num_buttons );
206
263
const char *name = get_element_name (elem, default_name);
207
264
char *str = al_malloc (strlen (name)+1 );
208
265
strcpy (str, name);
209
- joy->parent .info .button [usage- 1 ].name = str;
266
+ joy->parent .info .button [joy->parent.info.num_buttons ].name = str;
210
267
joy->parent .info .num_buttons ++;
211
268
}
212
269
}
@@ -216,18 +273,33 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
216
273
long max = IOHIDElementGetLogicalMax (elem);
217
274
int new_stick_class = -1 ;
218
275
int stick_index = joy->parent .info .num_sticks - 1 ;
276
+ int axis_type = -1 ;
219
277
220
278
switch (usage) {
221
279
case kHIDUsage_GD_X :
280
+ new_stick_class = 1 ;
281
+ axis_type = 0 ;
282
+ break ;
222
283
case kHIDUsage_GD_Y :
284
+ new_stick_class = 1 ;
285
+ axis_type = 1 ;
286
+ break ;
223
287
case kHIDUsage_GD_Z :
224
288
new_stick_class = 1 ;
289
+ axis_type = 2 ;
225
290
break ;
226
291
227
292
case kHIDUsage_GD_Rx :
293
+ new_stick_class = 2 ;
294
+ axis_type = 0 ;
295
+ break ;
228
296
case kHIDUsage_GD_Ry :
297
+ new_stick_class = 2 ;
298
+ axis_type = 1 ;
299
+ break ;
229
300
case kHIDUsage_GD_Rz :
230
301
new_stick_class = 2 ;
302
+ axis_type = 2 ;
231
303
break ;
232
304
233
305
case kHIDUsage_GD_Hatswitch :
@@ -250,7 +322,19 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
250
322
stick_class = new_stick_class;
251
323
252
324
char *buf = al_malloc (20 );
253
- sprintf (buf, " Stick %d " , stick_index);
325
+ switch (stick_class) {
326
+ case 1 :
327
+ sprintf (buf, " Primary Stick" );
328
+ break ;
329
+ case 2 :
330
+ sprintf (buf, " Secondary Stick" );
331
+ break ;
332
+ case 3 :
333
+ sprintf (buf, " Hat Switch" );
334
+ break ;
335
+ default :
336
+ sprintf (buf, " Stick %d " , stick_index);
337
+ }
254
338
joy->parent .info .stick [stick_index].name = buf;
255
339
}
256
340
else
@@ -261,14 +345,14 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
261
345
joy->dpad = elem;
262
346
263
347
joy->dpad_axis_horiz = axis_index;
264
- sprintf (default_name, " Axis %i " , axis_index );
348
+ sprintf (default_name, " X- Axis" );
265
349
char *str = al_malloc (strlen (default_name)+1 );
266
350
strcpy (str, default_name);
267
351
joy->parent .info .stick [stick_index].axis [axis_index].name = str;
268
352
269
353
++axis_index;
270
354
joy->dpad_axis_vert = axis_index;
271
- sprintf (default_name, " Axis %i " , axis_index );
355
+ sprintf (default_name, " Y- Axis" );
272
356
str = al_malloc (strlen (default_name)+1 );
273
357
strcpy (str, default_name);
274
358
add_axis (joy, stick_index, axis_index, min, max, str, elem);
@@ -277,7 +361,19 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
277
361
joy->parent .info .stick [stick_index].num_axes = 2 ;
278
362
}
279
363
else {
280
- sprintf (default_name, " Axis %i " , axis_index);
364
+ switch (axis_type) {
365
+ case 0 :
366
+ sprintf (default_name, " X-Axis" );
367
+ break ;
368
+ case 1 :
369
+ sprintf (default_name, " Y-Axis" );
370
+ break ;
371
+ case 2 :
372
+ sprintf (default_name, " Z-Axis" );
373
+ break ;
374
+ default :
375
+ sprintf (default_name, " Axis %i " , axis_index);
376
+ }
281
377
const char *name = get_element_name (elem, default_name);
282
378
char *str = al_malloc (strlen (name)+1 );
283
379
strcpy (str, name);
@@ -298,44 +394,92 @@ static void osx_joy_generate_configure_event(void)
298
394
_al_generate_joystick_event (&event);
299
395
}
300
396
397
+ static int device_count_joysticks (IOHIDDeviceRef ref)
398
+ {
399
+ int i;
400
+ int count = 0 ;
401
+ bool collection_started = false ;
402
+
403
+ CFArrayRef elements = IOHIDDeviceCopyMatchingElements (
404
+ ref,
405
+ NULL ,
406
+ kIOHIDOptionsTypeNone
407
+ );
408
+ for (i = 0 ; i < CFArrayGetCount (elements); i++) {
409
+ IOHIDElementRef elem = (IOHIDElementRef)CFArrayGetValueAtIndex (
410
+ elements,
411
+ i
412
+ );
413
+
414
+ int etype = IOHIDElementGetType (elem);
415
+ if (etype == kIOHIDElementTypeCollection ) {
416
+ collection_started = true ;
417
+ }
418
+ else if (etype == kIOHIDElementTypeInput_Button || etype == kIOHIDElementTypeInput_Misc ) {
419
+ if (collection_started) {
420
+ count++;
421
+ collection_started = false ;
422
+ }
423
+ }
424
+ }
425
+ CFRelease (elements);
426
+ return count;
427
+ }
428
+
429
+ static void device_setup_joystick (IOHIDDeviceRef ref, ALLEGRO_JOYSTICK_OSX *joy, int device_joystick)
430
+ {
431
+ CFStringRef product_name;
432
+ joy->cfg_state = new_joystick_state;
433
+
434
+ CFArrayRef elements = IOHIDDeviceCopyMatchingElements (
435
+ ref,
436
+ NULL ,
437
+ kIOHIDOptionsTypeNone
438
+ );
439
+
440
+ add_elements (elements, joy, device_joystick);
441
+ product_name = IOHIDDeviceGetProperty (ref, CFSTR (kIOHIDProductKey ));
442
+ if (product_name)
443
+ {
444
+ CFStringGetCString (product_name, joy->name , JOYSTICK_NAME_MAX, kCFStringEncodingUTF8 );
445
+ }
446
+ CFRelease (elements);
447
+ }
448
+
301
449
static void device_add_callback (
302
450
void *context,
303
451
IOReturn result,
304
452
void *sender,
305
453
IOHIDDeviceRef ref
306
454
) {
455
+ int i;
456
+ int device_joysticks;
307
457
(void )context;
308
458
(void )result;
309
459
(void )sender;
310
460
311
461
al_lock_mutex (add_mutex);
312
462
313
- ALLEGRO_JOYSTICK_OSX *joy = find_joystick (ref);
463
+ ALLEGRO_JOYSTICK_OSX *joy = find_joystick (ref, NULL );
314
464
if (joy == NULL ) {
315
- joy = al_calloc (1 , sizeof (ALLEGRO_JOYSTICK_OSX));
316
- joy->ident = ref;
317
- ALLEGRO_JOYSTICK_OSX **back = _al_vector_alloc_back (&joysticks);
318
- *back = joy;
465
+ device_joysticks = device_count_joysticks (ref);
466
+ for (i = 0 ; i < device_joysticks; i++) {
467
+ joy = al_calloc (1 , sizeof (ALLEGRO_JOYSTICK_OSX));
468
+ joy->ident = ref;
469
+ ALLEGRO_JOYSTICK_OSX **back = _al_vector_alloc_back (&joysticks);
470
+ *back = joy;
471
+ device_setup_joystick (ref, joy, i);
472
+ ALLEGRO_INFO (" Found joystick (%d buttons, %d sticks)\n " ,
473
+ joy->parent .info .num_buttons , joy->parent .info .num_sticks );
474
+ }
475
+ }
476
+ else {
477
+ device_setup_joystick (ref, joy, 0 );
319
478
}
320
- joy->cfg_state = new_joystick_state;
321
-
322
- CFArrayRef elements = IOHIDDeviceCopyMatchingElements (
323
- ref,
324
- NULL ,
325
- kIOHIDOptionsTypeNone
326
- );
327
-
328
- add_elements (elements, joy);
329
-
330
- CFRelease (elements);
331
-
332
479
333
480
al_unlock_mutex (add_mutex);
334
481
335
482
osx_joy_generate_configure_event ();
336
-
337
- ALLEGRO_INFO (" Found joystick (%d buttons, %d sticks)\n " ,
338
- joy->parent .info .num_buttons , joy->parent .info .num_sticks );
339
483
}
340
484
341
485
static void device_remove_callback (
@@ -432,7 +576,7 @@ static void value_callback(
432
576
433
577
IOHIDElementRef elem = IOHIDValueGetElement (value);
434
578
IOHIDDeviceRef ref = IOHIDElementGetDevice (elem);
435
- ALLEGRO_JOYSTICK_OSX *joy = find_joystick (ref);
579
+ ALLEGRO_JOYSTICK_OSX *joy = find_joystick (ref, elem );
436
580
437
581
if (!joy) return ;
438
582
@@ -733,8 +877,8 @@ static bool reconfigure_joysticks(void)
733
877
// FIXME!
734
878
static const char *get_joystick_name (ALLEGRO_JOYSTICK *joy_)
735
879
{
736
- ( void )joy_;
737
- return " Joystick " ;
880
+ ALLEGRO_JOYSTICK_OSX *joy = (ALLEGRO_JOYSTICK_OSX * )joy_;
881
+ return joy-> name ;
738
882
}
739
883
740
884
static bool get_joystick_active (ALLEGRO_JOYSTICK *joy_)
0 commit comments