Re: [AD] Problems with gamepad on MacOS X and general thoughts |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
OK, here's the patch for hidjoy.m. I only patched the 10.5+ version.
It fixes my problem where there were more Z-axes than X-axes, and the
number of sticks was wrong, and also adds support for "Hatswitch", which
represents D-pad on my gamepad. I could find no documentation on the way
Hatswitch reports values, but from looking at other peoples' code, I
decided to just hard-code 8 directions (Apple documentation for working
with HID devices is lacking a lot of details).
src/macosx/hidjoy.m | 216 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 133 insertions(+), 83 deletions(-)
diff --git a/src/macosx/hidjoy.m b/src/macosx/hidjoy.m
index ee60a38..6f40d1d 100644
--- a/src/macosx/hidjoy.m
+++ b/src/macosx/hidjoy.m
@@ -52,12 +52,12 @@ typedef enum {
typedef struct {
ALLEGRO_JOYSTICK parent;
- int num_buttons;
- int num_x_axes;
- int num_y_axes;
- int num_z_axes;
IOHIDElementRef buttons[_AL_MAX_JOYSTICK_BUTTONS];
IOHIDElementRef axes[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
+ IOHIDElementRef dpad;
+ int dpad_stick;
+ int dpad_axis_vert;
+ int dpad_axis_horiz;
long min[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
long max[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
CONFIG_STATE cfg_state;
@@ -169,10 +169,27 @@ static void joy_null(ALLEGRO_JOYSTICK_OSX *joy)
}
}
+static void add_axis(ALLEGRO_JOYSTICK_OSX *joy, int stick_index, int axis_index, int min, int max, char *name, IOHIDElementRef elem)
+{
+ if ( axis_index >= _AL_MAX_JOYSTICK_AXES )
+ return;
+
+ joy->min[stick_index][axis_index] = min;
+ joy->max[stick_index][axis_index] = max;
+
+ joy->parent.info.stick[stick_index].axis[axis_index].name = name;
+ joy->parent.info.stick[stick_index].num_axes++;
+ joy->axes[stick_index][axis_index] = elem;
+}
+
static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
{
+
+
int i;
char default_name[100];
+ int stick_class = -1;
+ int axis_index = 0;
joy_null(joy);
@@ -181,58 +198,95 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
elements,
i
);
+
int usage = IOHIDElementGetUsage(elem);
if (IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Button) {
if (usage >= 0 && usage < _AL_MAX_JOYSTICK_BUTTONS &&
!joy->buttons[usage-1]) {
joy->buttons[usage-1] = elem;
sprintf(default_name, "Button %d", usage-1);
- const char *name = get_element_name(elem, default_name);
- char *str = al_malloc(strlen(name)+1);
- strcpy(str, name);
+ const char *name = get_element_name(elem, default_name);
+ char *str = al_malloc(strlen(name)+1);
+ strcpy(str, name);
joy->parent.info.button[usage-1].name = str;
- joy->num_buttons++;
+ joy->parent.info.num_buttons++;
}
}
else if (
IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Misc) {
long min = IOHIDElementGetLogicalMin(elem);
long max = IOHIDElementGetLogicalMax(elem);
- if ((usage == kHIDUsage_GD_X ||
- usage == kHIDUsage_GD_Rx) &&
- joy->num_x_axes < _AL_MAX_JOYSTICK_STICKS) {
- joy->min[joy->num_x_axes][0] = min;
- joy->max[joy->num_x_axes][0] = max;
- sprintf(default_name, "Axis 0");
- const char *name = get_element_name(elem, default_name);
- char *str = al_malloc(strlen(name)+1);
- strcpy(str, name);
- joy->parent.info.stick[joy->num_x_axes].axis[0].name = str;
- joy->axes[joy->num_x_axes++][0] = elem;
+ int new_stick_class = -1;
+ int stick_index = joy->parent.info.num_sticks - 1;
+
+ switch( usage )
+ {
+ case kHIDUsage_GD_X:
+ case kHIDUsage_GD_Y:
+ case kHIDUsage_GD_Z:
+ new_stick_class = 1;
+ break;
+
+ case kHIDUsage_GD_Rx:
+ case kHIDUsage_GD_Ry:
+ case kHIDUsage_GD_Rz:
+ new_stick_class = 2;
+ break;
+
+ case kHIDUsage_GD_Hatswitch:
+ new_stick_class = 3;
+ break;
}
- else if ((usage == kHIDUsage_GD_Y ||
- usage == kHIDUsage_GD_Ry) &&
- joy->num_x_axes < _AL_MAX_JOYSTICK_STICKS) {
- joy->min[joy->num_y_axes][1] = min;
- joy->max[joy->num_y_axes][1] = max;
- sprintf(default_name, "Axis 1");
- const char *name = get_element_name(elem, default_name);
- char *str = al_malloc(strlen(name)+1);
- strcpy(str, name);
- joy->parent.info.stick[joy->num_y_axes].axis[1].name = str;
- joy->axes[joy->num_y_axes++][1] = elem;
+
+ if ( new_stick_class < 0 )
+ continue;
+
+ if ( stick_class != new_stick_class ) {
+ if ( joy->parent.info.num_sticks >= _AL_MAX_JOYSTICK_STICKS-1 )
+ break;
+
+ joy->parent.info.num_sticks++;
+
+ stick_index++;
+ axis_index = 0;
+
+ stick_class = new_stick_class;
+
+ char *buf = al_malloc(20);
+ sprintf(buf, "Stick %d", stick_index);
+ joy->parent.info.stick[stick_index].name = buf;
}
- else if ((usage == kHIDUsage_GD_Z ||
- usage == kHIDUsage_GD_Rz) &&
- joy->num_z_axes < _AL_MAX_JOYSTICK_STICKS) {
- joy->min[joy->num_z_axes][2] = min;
- joy->max[joy->num_z_axes][2] = max;
- sprintf(default_name, "Axis 2");
- const char *name = get_element_name(elem, default_name);
- char *str = al_malloc(strlen(name)+1);
- strcpy(str, name);
- joy->parent.info.stick[joy->num_z_axes].axis[2].name = str;
- joy->axes[joy->num_z_axes++][2] = elem;
+ else
+ axis_index++;
+
+ if (stick_class == 3)
+ {
+ joy->dpad_stick = stick_index;
+ joy->dpad = elem;
+
+ joy->dpad_axis_horiz = axis_index;
+ sprintf(default_name, "Axis %i", axis_index);
+ char *str = al_malloc(strlen(default_name)+1);
+ strcpy(str, default_name);
+ joy->parent.info.stick[stick_index].axis[axis_index].name = str;
+
+ ++axis_index;
+ joy->dpad_axis_vert = axis_index;
+ sprintf(default_name, "Axis %i", axis_index);
+ str = al_malloc(strlen(default_name)+1);
+ strcpy(str, default_name);
+ add_axis(joy, stick_index, axis_index, min, max, str, elem );
+ joy->parent.info.stick[stick_index].axis[axis_index].name = str;
+
+ joy->parent.info.stick[stick_index].num_axes = 2;
+ }
+ else
+ {
+ sprintf(default_name, "Axis %i", axis_index);
+ const char *name = get_element_name(elem, default_name);
+ char *str = al_malloc(strlen(name)+1);
+ strcpy(str, name);
+ add_axis(joy, stick_index, axis_index, min, max, str, elem );
}
}
}
@@ -284,21 +338,6 @@ static void device_add_callback(
CFRelease(elements);
- // Fill in ALLEGRO_JOYSTICK properties
- joy->parent.info.num_sticks = joy->num_x_axes;
- joy->parent.info.num_buttons = joy->num_buttons;
- for (i = 0; i < joy->num_x_axes; i++) {
- int axes = 1;
- if (joy->num_y_axes >= i)
- axes++;
- if (joy->num_z_axes >= i)
- axes++;
- joy->parent.info.stick[i].num_axes = axes;
- char *buf = al_malloc(20);
- sprintf(buf, "Stick %d", i);
- joy->parent.info.stick[i].name = buf;
- }
-
refCF = IOHIDDeviceGetProperty(ref, CFSTR(kIOHIDVendorIDKey));
if (refCF) {
CFNumberGetValue(refCF, kCFNumberSInt32Type, &joy->parent.info.guid.data[0]);
@@ -339,8 +378,8 @@ static void device_add_callback(
osx_joy_generate_configure_event();
- ALLEGRO_INFO("Found joystick (%d buttons, %d %d %d axes)\n",
- joy->num_buttons, joy->num_x_axes, joy->num_y_axes, joy->num_z_axes);
+ ALLEGRO_INFO("Found joystick (%d buttons, %d sticks)\n",
+ joy->parent.info.num_buttons, joy->parent.info.num_sticks);
}
static void device_remove_callback(
@@ -407,6 +446,24 @@ static void osx_joy_generate_button_event(ALLEGRO_JOYSTICK_OSX *joy, int button,
_al_event_source_emit_event(es, &event);
}
+static const int MAX_HAT_DIRECTIONS = 9;
+struct HAT_MAPPING
+{
+ int axisV;
+ int axisH;
+} hat_mapping[MAX_HAT_DIRECTIONS]=
+{
+ { -1, 0 }, // 0
+ { -1, 1 }, // 1
+ { 0, 1 }, // 2
+ { 1, 1 }, // 3
+ { 1, 0 }, // 4
+ { 1, -1 }, // 5
+ { 0, -1 }, // 6
+ { -1, -1 }, // 7
+ { 0, 0 }, // 8
+};
+
static void value_callback(
void *context,
IOReturn result,
@@ -429,7 +486,7 @@ static void value_callback(
_al_event_source_lock(es);
int i;
- for (i = 0; i < joy->num_buttons; i++) {
+ for (i = 0; i < joy->parent.info.num_buttons; i++) {
if (joy->buttons[i] == elem) {
ALLEGRO_EVENT_TYPE type;
if (IOHIDValueGetIntegerValue(value) == 0)
@@ -440,28 +497,24 @@ static void value_callback(
goto done;
}
}
+
int int_value = IOHIDValueGetIntegerValue(value);
- int stick = -1;
- int axis = -1;
- for (i = 0; i < joy->num_x_axes; i++) {
- if (joy->axes[i][0] == elem) {
- stick = i;
- axis = 0;
- goto gen_axis_event;
- }
- }
- for (i = 0; i < joy->num_y_axes; i++) {
- if (joy->axes[i][1] == elem) {
- stick = i;
- axis = 1;
- goto gen_axis_event;
+
+ if (joy->dpad == elem){
+ if (int_value>=0 && int_value<MAX_HAT_DIRECTIONS) {
+ osx_joy_generate_axis_event(joy, joy->dpad_stick, joy->dpad_axis_vert, (float)hat_mapping[int_value].axisV );
+ osx_joy_generate_axis_event(joy, joy->dpad_stick, joy->dpad_axis_horiz, (float)hat_mapping[int_value].axisH );
}
+ goto done;
}
- for (i = 0; i < joy->num_z_axes; i++) {
- if (joy->axes[i][2] == elem) {
- stick = i;
- axis = 2;
- goto gen_axis_event;
+
+ int stick = -1;
+ int axis = -1;
+ for (stick = 0; stick < joy->parent.info.num_sticks; stick++) {
+ for(axis = 0; axis < joy->parent.info.stick[stick].num_axes; ++axis){
+ if (joy->axes[stick][axis] == elem) {
+ goto gen_axis_event;
+ }
}
}
@@ -708,13 +761,10 @@ static bool reconfigure_joysticks(void)
al_free(joy->parent.info.stick[i].axis[j].name);
}
}
- joy_null(joy);
- joy->num_buttons =
- joy->num_x_axes =
- joy->num_y_axes =
- joy->num_z_axes = 0;
+ joy_null(joy);
memset(joy->buttons, 0, _AL_MAX_JOYSTICK_BUTTONS*sizeof(IOHIDElementRef));
memset(&joy->state, 0, sizeof(ALLEGRO_JOYSTICK_STATE));
+ joy->dpad=0;
}
else if (joy->cfg_state == JOY_STATE_BORN)
joy->cfg_state = JOY_STATE_ALIVE;