mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
hid: properly support joysticks and gamepads
This commit is contained in:
@@ -65,7 +65,7 @@
|
|||||||
#define HID_BUTTON_SIDE 0x04
|
#define HID_BUTTON_SIDE 0x04
|
||||||
#define HID_BUTTON_EXTRA 0x05
|
#define HID_BUTTON_EXTRA 0x05
|
||||||
#define HID_BUTTON_FORWARD 0x06
|
#define HID_BUTTON_FORWARD 0x06
|
||||||
#define HID_BUTTON_MAX HID_BUTTON_FORWARD
|
#define HID_BUTTON_MAX 16
|
||||||
|
|
||||||
#define HID_KEYBOARD_KEYPAD_MAX 0xe7
|
#define HID_KEYBOARD_KEYPAD_MAX 0xe7
|
||||||
|
|
||||||
@@ -646,6 +646,38 @@ static void hid_emit_event_keyboard_keypad(hid_application_t *application, hid_i
|
|||||||
static uint16_t hid_generic_desktop_to_input_rel(uint32_t usage);
|
static uint16_t hid_generic_desktop_to_input_rel(uint32_t usage);
|
||||||
static uint16_t hid_generic_desktop_to_input_abs(uint32_t usage);
|
static uint16_t hid_generic_desktop_to_input_abs(uint32_t usage);
|
||||||
|
|
||||||
|
static void hid_emit_event_hat_switch(hid_input_t *input, uint64_t value, input_event_t *events, size_t *events_emitted) {
|
||||||
|
static const int hat_to_axis[8][2] = {
|
||||||
|
{ 0, -1 },
|
||||||
|
{ 1, -1 },
|
||||||
|
{ 1, 0 },
|
||||||
|
{ 1, 1 },
|
||||||
|
{ 0, 1 },
|
||||||
|
{ -1, 1 },
|
||||||
|
{ -1, 0 },
|
||||||
|
{ -1, -1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int64_t hat = hid_input_value_signed(input, value) - input->logical_minimum;
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
if (hat >= 0 && hat < 8) {
|
||||||
|
x = hat_to_axis[hat][0];
|
||||||
|
y = hat_to_axis[hat][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
input_event_t event = {
|
||||||
|
.type = INPUT_EV_ABS,
|
||||||
|
.code = INPUT_ABS_HAT0X,
|
||||||
|
.value = x
|
||||||
|
};
|
||||||
|
push_event(event, events, events_emitted);
|
||||||
|
|
||||||
|
event.code = INPUT_ABS_HAT0Y;
|
||||||
|
event.value = y;
|
||||||
|
push_event(event, events, events_emitted);
|
||||||
|
}
|
||||||
|
|
||||||
static void hid_emit_event_generic_desktop(hid_input_t *input, hid_usage_t *usage, size_t idx, uint64_t value, input_event_t *events, size_t *events_emitted) {
|
static void hid_emit_event_generic_desktop(hid_input_t *input, hid_usage_t *usage, size_t idx, uint64_t value, input_event_t *events, size_t *events_emitted) {
|
||||||
if (input->flags & HID_INPUT_CONSTANT)
|
if (input->flags & HID_INPUT_CONSTANT)
|
||||||
return;
|
return;
|
||||||
@@ -657,6 +689,11 @@ static void hid_emit_event_generic_desktop(hid_input_t *input, hid_usage_t *usag
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((input->flags & HID_INPUT_RELATIVE) == 0 && hid_usage == HID_GD_HAT_SWITCH) {
|
||||||
|
hid_emit_event_hat_switch(input, value, events, events_emitted);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t signed_value = hid_input_value_signed(input, value);
|
int64_t signed_value = hid_input_value_signed(input, value);
|
||||||
|
|
||||||
input_event_t event = {0};
|
input_event_t event = {0};
|
||||||
@@ -812,7 +849,7 @@ static void hid_handle_key_changes(hid_application_t *application, input_event_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t hid_button_to_input_key(uint32_t usage);
|
static uint16_t hid_button_to_input_key(hid_application_t *application, uint32_t usage);
|
||||||
|
|
||||||
static void hid_handle_button_changes(hid_application_t *application, input_event_t *events, size_t *events_emitted, uint64_t old_buttons) {
|
static void hid_handle_button_changes(hid_application_t *application, input_event_t *events, size_t *events_emitted, uint64_t old_buttons) {
|
||||||
uint64_t changes = old_buttons ^ application->pressed_buttons;
|
uint64_t changes = old_buttons ^ application->pressed_buttons;
|
||||||
@@ -822,7 +859,7 @@ static void hid_handle_button_changes(hid_application_t *application, input_even
|
|||||||
|
|
||||||
input_event_t event = {0};
|
input_event_t event = {0};
|
||||||
event.type = INPUT_EV_KEY;
|
event.type = INPUT_EV_KEY;
|
||||||
event.code = hid_button_to_input_key(button);
|
event.code = hid_button_to_input_key(application, button);
|
||||||
if (event.code != INPUT_KEY_RESERVED) {
|
if (event.code != INPUT_KEY_RESERVED) {
|
||||||
event.value = (application->pressed_buttons & (1ull << bit)) ? 1 : 0;
|
event.value = (application->pressed_buttons & (1ull << bit)) ? 1 : 0;
|
||||||
push_event(event, events, events_emitted);
|
push_event(event, events, events_emitted);
|
||||||
@@ -931,6 +968,20 @@ static uint16_t hid_generic_desktop_to_input_abs(uint32_t usage) {
|
|||||||
return INPUT_ABS_X;
|
return INPUT_ABS_X;
|
||||||
case HID_GD_Y:
|
case HID_GD_Y:
|
||||||
return INPUT_ABS_Y;
|
return INPUT_ABS_Y;
|
||||||
|
case HID_GD_Z:
|
||||||
|
return INPUT_ABS_Z;
|
||||||
|
case HID_GD_RX:
|
||||||
|
return INPUT_ABS_RX;
|
||||||
|
case HID_GD_RY:
|
||||||
|
return INPUT_ABS_RY;
|
||||||
|
case HID_GD_RZ:
|
||||||
|
return INPUT_ABS_RZ;
|
||||||
|
case HID_GD_SLIDER:
|
||||||
|
return INPUT_ABS_THROTTLE;
|
||||||
|
case HID_GD_DIAL:
|
||||||
|
return INPUT_ABS_RUDDER;
|
||||||
|
case HID_GD_WHEEL:
|
||||||
|
return INPUT_ABS_WHEEL;
|
||||||
default:
|
default:
|
||||||
return INPUT_ABS_MAX + 1;
|
return INPUT_ABS_MAX + 1;
|
||||||
}
|
}
|
||||||
@@ -955,6 +1006,16 @@ static void hid_advertise_abs(input_device_t *device, hid_input_t *input, uint16
|
|||||||
device->abs_info[code].max = input->logical_maximum;
|
device->abs_info[code].max = input->logical_maximum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hid_advertise_hat_switch(input_device_t *device) {
|
||||||
|
bitmap_set(&device->ev_bits, INPUT_EV_ABS, 1);
|
||||||
|
bitmap_set(&device->abs_bits, INPUT_ABS_HAT0X, 1);
|
||||||
|
bitmap_set(&device->abs_bits, INPUT_ABS_HAT0Y, 1);
|
||||||
|
device->abs_info[INPUT_ABS_HAT0X].min = -1;
|
||||||
|
device->abs_info[INPUT_ABS_HAT0X].max = 1;
|
||||||
|
device->abs_info[INPUT_ABS_HAT0Y].min = -1;
|
||||||
|
device->abs_info[INPUT_ABS_HAT0Y].max = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void hid_advertise_generic_desktop(input_device_t *device, hid_input_t *input, hid_usage_t *usage) {
|
static void hid_advertise_generic_desktop(input_device_t *device, hid_input_t *input, hid_usage_t *usage) {
|
||||||
if (input->flags & HID_INPUT_CONSTANT)
|
if (input->flags & HID_INPUT_CONSTANT)
|
||||||
return;
|
return;
|
||||||
@@ -968,11 +1029,14 @@ static void hid_advertise_generic_desktop(input_device_t *device, hid_input_t *i
|
|||||||
bitmap_set(&device->rel_bits, code, 1);
|
bitmap_set(&device->rel_bits, code, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hid_advertise_abs(device, input, hid_generic_desktop_to_input_abs(hid_usage));
|
if (hid_usage == HID_GD_HAT_SWITCH)
|
||||||
|
hid_advertise_hat_switch(device);
|
||||||
|
else
|
||||||
|
hid_advertise_abs(device, input, hid_generic_desktop_to_input_abs(hid_usage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t hid_usage = usage->minimum; hid_usage <= usage->maximum && hid_usage <= HID_GD_WHEEL; ++hid_usage) {
|
for (uint32_t hid_usage = usage->minimum; hid_usage <= usage->maximum && hid_usage <= HID_GD_HAT_SWITCH; ++hid_usage) {
|
||||||
if (input->flags & HID_INPUT_RELATIVE) {
|
if (input->flags & HID_INPUT_RELATIVE) {
|
||||||
uint16_t code = hid_generic_desktop_to_input_rel(hid_usage);
|
uint16_t code = hid_generic_desktop_to_input_rel(hid_usage);
|
||||||
if (code <= INPUT_REL_MAX) {
|
if (code <= INPUT_REL_MAX) {
|
||||||
@@ -980,12 +1044,100 @@ static void hid_advertise_generic_desktop(input_device_t *device, hid_input_t *i
|
|||||||
bitmap_set(&device->rel_bits, code, 1);
|
bitmap_set(&device->rel_bits, code, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hid_advertise_abs(device, input, hid_generic_desktop_to_input_abs(hid_usage));
|
if (hid_usage == HID_GD_HAT_SWITCH)
|
||||||
|
hid_advertise_hat_switch(device);
|
||||||
|
else
|
||||||
|
hid_advertise_abs(device, input, hid_generic_desktop_to_input_abs(hid_usage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t hid_button_to_input_key(uint32_t usage) {
|
static inline bool hid_application_is_gamepad(hid_application_t *application) {
|
||||||
|
return USAGE_PAGE(application->usage) == HID_USAGE_PAGE_GENERIC_DESKTOP && USAGE(application->usage) == HID_GD_GAMEPAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool hid_application_is_joystick(hid_application_t *application) {
|
||||||
|
if (USAGE_PAGE(application->usage) != HID_USAGE_PAGE_GENERIC_DESKTOP)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (USAGE(application->usage)) {
|
||||||
|
case HID_GD_JOYSTICK:
|
||||||
|
case HID_GD_MULTI_AXIS_CONTROLLER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t hid_gamepad_button_to_input_key(uint32_t usage) {
|
||||||
|
switch (usage) {
|
||||||
|
case 1:
|
||||||
|
return INPUT_KEY_BTN_SOUTH;
|
||||||
|
case 2:
|
||||||
|
return INPUT_KEY_BTN_EAST;
|
||||||
|
case 3:
|
||||||
|
return INPUT_KEY_BTN_C;
|
||||||
|
case 4:
|
||||||
|
return INPUT_KEY_BTN_NORTH;
|
||||||
|
case 5:
|
||||||
|
return INPUT_KEY_BTN_WEST;
|
||||||
|
case 6:
|
||||||
|
return INPUT_KEY_BTN_Z;
|
||||||
|
case 7:
|
||||||
|
return INPUT_KEY_BTN_TL;
|
||||||
|
case 8:
|
||||||
|
return INPUT_KEY_BTN_TR;
|
||||||
|
case 9:
|
||||||
|
return INPUT_KEY_BTN_TL2;
|
||||||
|
case 10:
|
||||||
|
return INPUT_KEY_BTN_TR2;
|
||||||
|
case 11:
|
||||||
|
return INPUT_KEY_BTN_SELECT;
|
||||||
|
case 12:
|
||||||
|
return INPUT_KEY_BTN_START;
|
||||||
|
case 13:
|
||||||
|
return INPUT_KEY_BTN_MODE;
|
||||||
|
case 14:
|
||||||
|
return INPUT_KEY_BTN_THUMBL;
|
||||||
|
case 15:
|
||||||
|
return INPUT_KEY_BTN_THUMBR;
|
||||||
|
default:
|
||||||
|
return INPUT_KEY_RESERVED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t hid_joystick_button_to_input_key(uint32_t usage) {
|
||||||
|
switch (usage) {
|
||||||
|
case 1:
|
||||||
|
return INPUT_KEY_BTN_TRIGGER;
|
||||||
|
case 2:
|
||||||
|
return INPUT_KEY_BTN_THUMB;
|
||||||
|
case 3:
|
||||||
|
return INPUT_KEY_BTN_THUMB2;
|
||||||
|
case 4:
|
||||||
|
return INPUT_KEY_BTN_TOP;
|
||||||
|
case 5:
|
||||||
|
return INPUT_KEY_BTN_TOP2;
|
||||||
|
case 6:
|
||||||
|
return INPUT_KEY_BTN_PINKIE;
|
||||||
|
case 7:
|
||||||
|
return INPUT_KEY_BTN_BASE;
|
||||||
|
case 8:
|
||||||
|
return INPUT_KEY_BTN_BASE2;
|
||||||
|
case 9:
|
||||||
|
return INPUT_KEY_BTN_BASE3;
|
||||||
|
case 10:
|
||||||
|
return INPUT_KEY_BTN_BASE4;
|
||||||
|
case 11:
|
||||||
|
return INPUT_KEY_BTN_BASE5;
|
||||||
|
case 12:
|
||||||
|
return INPUT_KEY_BTN_BASE6;
|
||||||
|
default:
|
||||||
|
return INPUT_KEY_RESERVED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t hid_mouse_button_to_input_key(uint32_t usage) {
|
||||||
switch (usage) {
|
switch (usage) {
|
||||||
case HID_BUTTON_PRIMARY:
|
case HID_BUTTON_PRIMARY:
|
||||||
return INPUT_KEY_BTN_LEFT;
|
return INPUT_KEY_BTN_LEFT;
|
||||||
@@ -1004,12 +1156,21 @@ static uint16_t hid_button_to_input_key(uint32_t usage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_advertise_button(input_device_t *device, hid_input_t *input, hid_usage_t *usage) {
|
static uint16_t hid_button_to_input_key(hid_application_t *application, uint32_t usage) {
|
||||||
|
if (hid_application_is_gamepad(application))
|
||||||
|
return hid_gamepad_button_to_input_key(usage);
|
||||||
|
if (hid_application_is_joystick(application))
|
||||||
|
return hid_joystick_button_to_input_key(usage);
|
||||||
|
|
||||||
|
return hid_mouse_button_to_input_key(usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hid_advertise_button(hid_application_t *application, input_device_t *device, hid_input_t *input, hid_usage_t *usage) {
|
||||||
if (input->flags & HID_INPUT_CONSTANT)
|
if (input->flags & HID_INPUT_CONSTANT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (usage->minimum == 0 && usage->maximum == 0) {
|
if (usage->minimum == 0 && usage->maximum == 0) {
|
||||||
uint16_t code = hid_button_to_input_key(USAGE(usage->usage));
|
uint16_t code = hid_button_to_input_key(application, USAGE(usage->usage));
|
||||||
if (code != INPUT_KEY_RESERVED) {
|
if (code != INPUT_KEY_RESERVED) {
|
||||||
bitmap_set(&device->ev_bits, INPUT_EV_KEY, 1);
|
bitmap_set(&device->ev_bits, INPUT_EV_KEY, 1);
|
||||||
bitmap_set(&device->key_bits, code, 1);
|
bitmap_set(&device->key_bits, code, 1);
|
||||||
@@ -1017,7 +1178,7 @@ static void hid_advertise_button(input_device_t *device, hid_input_t *input, hid
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t button = usage->minimum; button <= usage->maximum && button <= HID_BUTTON_MAX; ++button) {
|
for (uint32_t button = usage->minimum; button <= usage->maximum && button <= HID_BUTTON_MAX; ++button) {
|
||||||
uint16_t code = hid_button_to_input_key(button);
|
uint16_t code = hid_button_to_input_key(application, button);
|
||||||
if (code != INPUT_KEY_RESERVED) {
|
if (code != INPUT_KEY_RESERVED) {
|
||||||
bitmap_set(&device->ev_bits, INPUT_EV_KEY, 1);
|
bitmap_set(&device->ev_bits, INPUT_EV_KEY, 1);
|
||||||
bitmap_set(&device->key_bits, code, 1);
|
bitmap_set(&device->key_bits, code, 1);
|
||||||
@@ -1040,7 +1201,7 @@ static void hid_advertise_input(hid_parser_t *parser, hid_input_t *input) {
|
|||||||
hid_advertise_keyboard_keypad(device, input, usage);
|
hid_advertise_keyboard_keypad(device, input, usage);
|
||||||
break;
|
break;
|
||||||
case HID_USAGE_PAGE_BUTTON:
|
case HID_USAGE_PAGE_BUTTON:
|
||||||
hid_advertise_button(device, input, usage);
|
hid_advertise_button(application, device, input, usage);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
name=astral
|
name=astral
|
||||||
revision=7
|
revision=8
|
||||||
from_source=astral
|
from_source=astral
|
||||||
imagedeps="build-essential nasm"
|
imagedeps="build-essential nasm"
|
||||||
hostdeps="xgcc xbinutils limine"
|
hostdeps="xgcc xbinutils limine"
|
||||||
|
|||||||
Reference in New Issue
Block a user