Compare commits
5 Commits
includes
...
gamepad_fi
Author | SHA1 | Date | |
---|---|---|---|
309d0371eb | |||
a582c0cc1b | |||
696295f66d | |||
347169aab6 | |||
75bdd0c831 |
@ -152,8 +152,10 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) {
|
|||||||
return 2;
|
return 2;
|
||||||
case SC_CONTROL_MSG_TYPE_UHID_CREATE:
|
case SC_CONTROL_MSG_TYPE_UHID_CREATE:
|
||||||
sc_write16be(&buf[1], msg->uhid_create.id);
|
sc_write16be(&buf[1], msg->uhid_create.id);
|
||||||
|
sc_write16be(&buf[3], msg->uhid_create.vendor_id);
|
||||||
|
sc_write16be(&buf[5], msg->uhid_create.product_id);
|
||||||
|
|
||||||
size_t index = 3;
|
size_t index = 7;
|
||||||
index += write_string_tiny(&buf[index], msg->uhid_create.name, 127);
|
index += write_string_tiny(&buf[index], msg->uhid_create.name, 127);
|
||||||
|
|
||||||
sc_write16be(&buf[index], msg->uhid_create.report_desc_size);
|
sc_write16be(&buf[index], msg->uhid_create.report_desc_size);
|
||||||
@ -278,9 +280,13 @@ sc_control_msg_log(const struct sc_control_msg *msg) {
|
|||||||
// Quote only if name is not null
|
// Quote only if name is not null
|
||||||
const char *name = msg->uhid_create.name;
|
const char *name = msg->uhid_create.name;
|
||||||
const char *quote = name ? "\"" : "";
|
const char *quote = name ? "\"" : "";
|
||||||
LOG_CMSG("UHID create [%" PRIu16 "] name=%s%s%s "
|
LOG_CMSG("UHID create [%" PRIu16 "] %04" PRIx16 ":%04" PRIx16
|
||||||
"report_desc_size=%" PRIu16, msg->uhid_create.id,
|
" name=%s%s%s report_desc_size=%" PRIu16,
|
||||||
quote, name, quote, msg->uhid_create.report_desc_size);
|
msg->uhid_create.id,
|
||||||
|
msg->uhid_create.vendor_id,
|
||||||
|
msg->uhid_create.product_id,
|
||||||
|
quote, name, quote,
|
||||||
|
msg->uhid_create.report_desc_size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SC_CONTROL_MSG_TYPE_UHID_INPUT: {
|
case SC_CONTROL_MSG_TYPE_UHID_INPUT: {
|
||||||
|
@ -94,6 +94,8 @@ struct sc_control_msg {
|
|||||||
} set_display_power;
|
} set_display_power;
|
||||||
struct {
|
struct {
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
|
uint16_t vendor_id;
|
||||||
|
uint16_t product_id;
|
||||||
const char *name; // pointer to static data
|
const char *name; // pointer to static data
|
||||||
uint16_t report_desc_size;
|
uint16_t report_desc_size;
|
||||||
const uint8_t *report_desc; // pointer to static data
|
const uint8_t *report_desc; // pointer to static data
|
||||||
|
@ -15,6 +15,8 @@ struct sc_hid_input {
|
|||||||
|
|
||||||
struct sc_hid_open {
|
struct sc_hid_open {
|
||||||
uint16_t hid_id;
|
uint16_t hid_id;
|
||||||
|
uint16_t vendor_id;
|
||||||
|
uint16_t product_id;
|
||||||
const char *name; // pointer to static memory
|
const char *name; // pointer to static memory
|
||||||
const uint8_t *report_desc; // pointer to static memory
|
const uint8_t *report_desc; // pointer to static memory
|
||||||
size_t report_desc_size;
|
size_t report_desc_size;
|
||||||
|
@ -52,10 +52,10 @@ static const uint8_t SC_HID_GAMEPAD_REPORT_DESC[] = {
|
|||||||
0x09, 0x30,
|
0x09, 0x30,
|
||||||
// Usage (Y) Left stick y
|
// Usage (Y) Left stick y
|
||||||
0x09, 0x31,
|
0x09, 0x31,
|
||||||
// Usage (Z) Right stick x
|
// Usage (Rx) Right stick x
|
||||||
0x09, 0x32,
|
0x09, 0x33,
|
||||||
// Usage (Rz) Right stick y
|
// Usage (Ry) Right stick y
|
||||||
0x09, 0x35,
|
0x09, 0x34,
|
||||||
// Logical Minimum (0)
|
// Logical Minimum (0)
|
||||||
0x15, 0x00,
|
0x15, 0x00,
|
||||||
// Logical Maximum (65535)
|
// Logical Maximum (65535)
|
||||||
@ -65,15 +65,15 @@ static const uint8_t SC_HID_GAMEPAD_REPORT_DESC[] = {
|
|||||||
0x75, 0x10,
|
0x75, 0x10,
|
||||||
// Report Count (4)
|
// Report Count (4)
|
||||||
0x95, 0x04,
|
0x95, 0x04,
|
||||||
// Input (Data, Variable, Absolute): 4 bytes (X, Y, Z, Rz)
|
// Input (Data, Variable, Absolute): 4x2 bytes (X, Y, Z, Rz)
|
||||||
0x81, 0x02,
|
0x81, 0x02,
|
||||||
|
|
||||||
// Usage Page (Simulation Controls)
|
// Usage Page (Generic Desktop)
|
||||||
0x05, 0x02,
|
0x05, 0x01,
|
||||||
// Usage (Brake)
|
// Usage (Z)
|
||||||
0x09, 0xC5,
|
0x09, 0x32,
|
||||||
// Usage (Accelerator)
|
// Usage (Rz)
|
||||||
0x09, 0xC4,
|
0x09, 0x35,
|
||||||
// Logical Minimum (0)
|
// Logical Minimum (0)
|
||||||
0x15, 0x00,
|
0x15, 0x00,
|
||||||
// Logical Maximum (32767)
|
// Logical Maximum (32767)
|
||||||
@ -82,7 +82,7 @@ static const uint8_t SC_HID_GAMEPAD_REPORT_DESC[] = {
|
|||||||
0x75, 0x10,
|
0x75, 0x10,
|
||||||
// Report Count (2)
|
// Report Count (2)
|
||||||
0x95, 0x02,
|
0x95, 0x02,
|
||||||
// Input (Data, Variable, Absolute): 2 bytes (L2, R2)
|
// Input (Data, Variable, Absolute): 2x2 bytes (L2, R2)
|
||||||
0x81, 0x02,
|
0x81, 0x02,
|
||||||
|
|
||||||
// Usage Page (Buttons)
|
// Usage Page (Buttons)
|
||||||
@ -182,7 +182,7 @@ static const uint8_t SC_HID_GAMEPAD_REPORT_DESC[] = {
|
|||||||
* `------------- SC_GAMEPAD_BUTTON_RIGHT_STICK
|
* `------------- SC_GAMEPAD_BUTTON_RIGHT_STICK
|
||||||
*
|
*
|
||||||
* +---------------+
|
* +---------------+
|
||||||
* byte 14: |0 0 0 . . . . .| hat switch (dpad) position (0-8)
|
* byte 14: |0 0 0 0 . . . .| hat switch (dpad) position (0-8)
|
||||||
* +---------------+
|
* +---------------+
|
||||||
* 9 possible positions and their values:
|
* 9 possible positions and their values:
|
||||||
* 8 1 2
|
* 8 1 2
|
||||||
@ -191,16 +191,19 @@ static const uint8_t SC_HID_GAMEPAD_REPORT_DESC[] = {
|
|||||||
* (8 is top-left, 1 is top, 2 is top-right, etc.)
|
* (8 is top-left, 1 is top, 2 is top-right, etc.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// [-32768 to 32767] -> [0 to 65535]
|
||||||
|
#define AXIS_RESCALE(V) (uint16_t) (((int32_t) V) + 0x8000)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_hid_gamepad_slot_init(struct sc_hid_gamepad_slot *slot,
|
sc_hid_gamepad_slot_init(struct sc_hid_gamepad_slot *slot,
|
||||||
uint32_t gamepad_id) {
|
uint32_t gamepad_id) {
|
||||||
assert(gamepad_id != SC_GAMEPAD_ID_INVALID);
|
assert(gamepad_id != SC_GAMEPAD_ID_INVALID);
|
||||||
slot->gamepad_id = gamepad_id;
|
slot->gamepad_id = gamepad_id;
|
||||||
slot->buttons = 0;
|
slot->buttons = 0;
|
||||||
slot->axis_left_x = 0;
|
slot->axis_left_x = AXIS_RESCALE(0);
|
||||||
slot->axis_left_y = 0;
|
slot->axis_left_y = AXIS_RESCALE(0);
|
||||||
slot->axis_right_x = 0;
|
slot->axis_right_x = AXIS_RESCALE(0);
|
||||||
slot->axis_right_y = 0;
|
slot->axis_right_y = AXIS_RESCALE(0);
|
||||||
slot->axis_left_trigger = 0;
|
slot->axis_left_trigger = 0;
|
||||||
slot->axis_right_trigger = 0;
|
slot->axis_right_trigger = 0;
|
||||||
}
|
}
|
||||||
@ -233,7 +236,9 @@ sc_hid_gamepad_slot_get_id(size_t slot_idx) {
|
|||||||
bool
|
bool
|
||||||
sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid,
|
sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid,
|
||||||
struct sc_hid_open *hid_open,
|
struct sc_hid_open *hid_open,
|
||||||
uint32_t gamepad_id) {
|
uint32_t gamepad_id,
|
||||||
|
uint16_t vendor_id,
|
||||||
|
uint16_t product_id) {
|
||||||
assert(gamepad_id != SC_GAMEPAD_ID_INVALID);
|
assert(gamepad_id != SC_GAMEPAD_ID_INVALID);
|
||||||
ssize_t slot_idx = sc_hid_gamepad_slot_find(hid, SC_GAMEPAD_ID_INVALID);
|
ssize_t slot_idx = sc_hid_gamepad_slot_find(hid, SC_GAMEPAD_ID_INVALID);
|
||||||
if (slot_idx == -1) {
|
if (slot_idx == -1) {
|
||||||
@ -250,6 +255,8 @@ sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid,
|
|||||||
|
|
||||||
uint16_t hid_id = sc_hid_gamepad_slot_get_id(slot_idx);
|
uint16_t hid_id = sc_hid_gamepad_slot_get_id(slot_idx);
|
||||||
hid_open->hid_id = hid_id;
|
hid_open->hid_id = hid_id;
|
||||||
|
hid_open->vendor_id = vendor_id;
|
||||||
|
hid_open->product_id = product_id;
|
||||||
hid_open->name = name;
|
hid_open->name = name;
|
||||||
hid_open->report_desc = SC_HID_GAMEPAD_REPORT_DESC;
|
hid_open->report_desc = SC_HID_GAMEPAD_REPORT_DESC;
|
||||||
hid_open->report_desc_size = sizeof(SC_HID_GAMEPAD_REPORT_DESC);
|
hid_open->report_desc_size = sizeof(SC_HID_GAMEPAD_REPORT_DESC);
|
||||||
@ -423,8 +430,6 @@ sc_hid_gamepad_generate_input_from_axis(struct sc_hid_gamepad *hid,
|
|||||||
|
|
||||||
struct sc_hid_gamepad_slot *slot = &hid->slots[slot_idx];
|
struct sc_hid_gamepad_slot *slot = &hid->slots[slot_idx];
|
||||||
|
|
||||||
// [-32768 to 32767] -> [0 to 65535]
|
|
||||||
#define AXIS_RESCALE(V) (uint16_t) (((int32_t) V) + 0x8000)
|
|
||||||
switch (event->axis) {
|
switch (event->axis) {
|
||||||
case SC_GAMEPAD_AXIS_LEFTX:
|
case SC_GAMEPAD_AXIS_LEFTX:
|
||||||
slot->axis_left_x = AXIS_RESCALE(event->value);
|
slot->axis_left_x = AXIS_RESCALE(event->value);
|
||||||
|
@ -33,7 +33,9 @@ sc_hid_gamepad_init(struct sc_hid_gamepad *hid);
|
|||||||
bool
|
bool
|
||||||
sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid,
|
sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid,
|
||||||
struct sc_hid_open *hid_open,
|
struct sc_hid_open *hid_open,
|
||||||
uint32_t gamepad_id);
|
uint32_t gamepad_id,
|
||||||
|
uint16_t vendor_id,
|
||||||
|
uint16_t product_id);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sc_hid_gamepad_generate_close(struct sc_hid_gamepad *hid,
|
sc_hid_gamepad_generate_close(struct sc_hid_gamepad *hid,
|
||||||
|
@ -335,6 +335,8 @@ sc_hid_keyboard_generate_input_from_mods(struct sc_hid_input *hid_input,
|
|||||||
|
|
||||||
void sc_hid_keyboard_generate_open(struct sc_hid_open *hid_open) {
|
void sc_hid_keyboard_generate_open(struct sc_hid_open *hid_open) {
|
||||||
hid_open->hid_id = SC_HID_ID_KEYBOARD;
|
hid_open->hid_id = SC_HID_ID_KEYBOARD;
|
||||||
|
hid_open->vendor_id = 0;
|
||||||
|
hid_open->product_id = 0;
|
||||||
hid_open->name = NULL; // No name specified after "scrcpy"
|
hid_open->name = NULL; // No name specified after "scrcpy"
|
||||||
hid_open->report_desc = SC_HID_KEYBOARD_REPORT_DESC;
|
hid_open->report_desc = SC_HID_KEYBOARD_REPORT_DESC;
|
||||||
hid_open->report_desc_size = sizeof(SC_HID_KEYBOARD_REPORT_DESC);
|
hid_open->report_desc_size = sizeof(SC_HID_KEYBOARD_REPORT_DESC);
|
||||||
|
@ -190,6 +190,8 @@ sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input,
|
|||||||
|
|
||||||
void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) {
|
void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) {
|
||||||
hid_open->hid_id = SC_HID_ID_MOUSE;
|
hid_open->hid_id = SC_HID_ID_MOUSE;
|
||||||
|
hid_open->vendor_id = 0;
|
||||||
|
hid_open->product_id = 0;
|
||||||
hid_open->name = NULL; // No name specified after "scrcpy"
|
hid_open->name = NULL; // No name specified after "scrcpy"
|
||||||
hid_open->report_desc = SC_HID_MOUSE_REPORT_DESC;
|
hid_open->report_desc = SC_HID_MOUSE_REPORT_DESC;
|
||||||
hid_open->report_desc_size = sizeof(SC_HID_MOUSE_REPORT_DESC);
|
hid_open->report_desc_size = sizeof(SC_HID_MOUSE_REPORT_DESC);
|
||||||
|
@ -412,18 +412,16 @@ struct sc_touch_event {
|
|||||||
float pressure;
|
float pressure;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum sc_gamepad_device_event_type {
|
|
||||||
SC_GAMEPAD_DEVICE_ADDED,
|
|
||||||
SC_GAMEPAD_DEVICE_REMOVED,
|
|
||||||
};
|
|
||||||
|
|
||||||
// As documented in <https://wiki.libsdl.org/SDL2/SDL_JoystickID>:
|
// As documented in <https://wiki.libsdl.org/SDL2/SDL_JoystickID>:
|
||||||
// The ID value starts at 0 and increments from there. The value -1 is an
|
// The ID value starts at 0 and increments from there. The value -1 is an
|
||||||
// invalid ID.
|
// invalid ID.
|
||||||
#define SC_GAMEPAD_ID_INVALID UINT32_C(-1)
|
#define SC_GAMEPAD_ID_INVALID UINT32_C(-1)
|
||||||
|
|
||||||
struct sc_gamepad_device_event {
|
struct sc_gamepad_added_event {
|
||||||
enum sc_gamepad_device_event_type type;
|
uint32_t gamepad_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sc_gamepad_removed_event {
|
||||||
uint32_t gamepad_id;
|
uint32_t gamepad_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -503,16 +501,6 @@ sc_mouse_buttons_state_from_sdl(uint32_t buttons_state) {
|
|||||||
return buttons_state;
|
return buttons_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline enum sc_gamepad_device_event_type
|
|
||||||
sc_gamepad_device_event_type_from_sdl_type(uint32_t type) {
|
|
||||||
assert(type == SDL_CONTROLLERDEVICEADDED
|
|
||||||
|| type == SDL_CONTROLLERDEVICEREMOVED);
|
|
||||||
if (type == SDL_CONTROLLERDEVICEADDED) {
|
|
||||||
return SC_GAMEPAD_DEVICE_ADDED;
|
|
||||||
}
|
|
||||||
return SC_GAMEPAD_DEVICE_REMOVED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline enum sc_gamepad_axis
|
static inline enum sc_gamepad_axis
|
||||||
sc_gamepad_axis_from_sdl(uint8_t axis) {
|
sc_gamepad_axis_from_sdl(uint8_t axis) {
|
||||||
if (axis <= SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
|
if (axis <= SDL_CONTROLLER_AXIS_TRIGGERRIGHT) {
|
||||||
|
@ -908,7 +908,6 @@ sc_input_manager_process_mouse_wheel(struct sc_input_manager *im,
|
|||||||
static void
|
static void
|
||||||
sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
||||||
const SDL_ControllerDeviceEvent *event) {
|
const SDL_ControllerDeviceEvent *event) {
|
||||||
SDL_JoystickID id;
|
|
||||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||||
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
||||||
if (!gc) {
|
if (!gc) {
|
||||||
@ -923,9 +922,12 @@ sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = SDL_JoystickInstanceID(joystick);
|
struct sc_gamepad_added_event evt = {
|
||||||
|
.gamepad_id = SDL_JoystickInstanceID(joystick),
|
||||||
|
};
|
||||||
|
im->gp->ops->process_gamepad_added(im->gp, &evt);
|
||||||
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||||
id = event->which;
|
SDL_JoystickID id = event->which;
|
||||||
|
|
||||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
||||||
if (gc) {
|
if (gc) {
|
||||||
@ -933,16 +935,15 @@ sc_input_manager_process_gamepad_device(struct sc_input_manager *im,
|
|||||||
} else {
|
} else {
|
||||||
LOGW("Unknown gamepad device removed");
|
LOGW("Unknown gamepad device removed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct sc_gamepad_removed_event evt = {
|
||||||
|
.gamepad_id = id,
|
||||||
|
};
|
||||||
|
im->gp->ops->process_gamepad_removed(im->gp, &evt);
|
||||||
} else {
|
} else {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sc_gamepad_device_event evt = {
|
|
||||||
.type = sc_gamepad_device_event_type_from_sdl_type(event->type),
|
|
||||||
.gamepad_id = id,
|
|
||||||
};
|
|
||||||
im->gp->ops->process_gamepad_device(im->gp, &evt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -20,13 +20,22 @@ struct sc_gamepad_processor {
|
|||||||
struct sc_gamepad_processor_ops {
|
struct sc_gamepad_processor_ops {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a gamepad device added or removed
|
* Process a gamepad device added
|
||||||
*
|
*
|
||||||
* This function is mandatory.
|
* This function is mandatory.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
(*process_gamepad_device)(struct sc_gamepad_processor *gp,
|
(*process_gamepad_added)(struct sc_gamepad_processor *gp,
|
||||||
const struct sc_gamepad_device_event *event);
|
const struct sc_gamepad_added_event *event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a gamepad device removed
|
||||||
|
*
|
||||||
|
* This function is mandatory.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
(*process_gamepad_removed)(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_removed_event *event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a gamepad axis event
|
* Process a gamepad axis event
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
/** Downcast gamepad processor to sc_gamepad_uhid */
|
/** Downcast gamepad processor to sc_gamepad_uhid */
|
||||||
#define DOWNCAST(GP) container_of(GP, struct sc_gamepad_uhid, gamepad_processor)
|
#define DOWNCAST(GP) container_of(GP, struct sc_gamepad_uhid, gamepad_processor)
|
||||||
|
|
||||||
|
#define SC_GAMEPAD_UHID_VENDOR_ID 0
|
||||||
|
#define SC_GAMEPAD_UHID_PRODUCT_ID 0
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_gamepad_uhid_send_input(struct sc_gamepad_uhid *gamepad,
|
sc_gamepad_uhid_send_input(struct sc_gamepad_uhid *gamepad,
|
||||||
const struct sc_hid_input *hid_input,
|
const struct sc_hid_input *hid_input,
|
||||||
@ -30,6 +33,8 @@ sc_gamepad_uhid_send_open(struct sc_gamepad_uhid *gamepad,
|
|||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
||||||
msg.uhid_create.id = hid_open->hid_id;
|
msg.uhid_create.id = hid_open->hid_id;
|
||||||
|
msg.uhid_create.vendor_id = hid_open->vendor_id;
|
||||||
|
msg.uhid_create.product_id = hid_open->product_id;
|
||||||
msg.uhid_create.name = hid_open->name;
|
msg.uhid_create.name = hid_open->name;
|
||||||
msg.uhid_create.report_desc = hid_open->report_desc;
|
msg.uhid_create.report_desc = hid_open->report_desc;
|
||||||
msg.uhid_create.report_desc_size = hid_open->report_desc_size;
|
msg.uhid_create.report_desc_size = hid_open->report_desc_size;
|
||||||
@ -52,20 +57,25 @@ sc_gamepad_uhid_send_close(struct sc_gamepad_uhid *gamepad,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
sc_gamepad_processor_process_gamepad_added(struct sc_gamepad_processor *gp,
|
||||||
const struct sc_gamepad_device_event *event) {
|
const struct sc_gamepad_added_event *event) {
|
||||||
struct sc_gamepad_uhid *gamepad = DOWNCAST(gp);
|
struct sc_gamepad_uhid *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
if (event->type == SC_GAMEPAD_DEVICE_ADDED) {
|
|
||||||
struct sc_hid_open hid_open;
|
struct sc_hid_open hid_open;
|
||||||
if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open,
|
if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open,
|
||||||
event->gamepad_id)) {
|
event->gamepad_id,
|
||||||
|
SC_GAMEPAD_UHID_VENDOR_ID,
|
||||||
|
SC_GAMEPAD_UHID_PRODUCT_ID)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc_gamepad_uhid_send_open(gamepad, &hid_open);
|
sc_gamepad_uhid_send_open(gamepad, &hid_open);
|
||||||
} else {
|
}
|
||||||
assert(event->type == SC_GAMEPAD_DEVICE_REMOVED);
|
|
||||||
|
static void
|
||||||
|
sc_gamepad_processor_process_gamepad_removed(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_removed_event *event) {
|
||||||
|
struct sc_gamepad_uhid *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
struct sc_hid_close hid_close;
|
struct sc_hid_close hid_close;
|
||||||
if (!sc_hid_gamepad_generate_close(&gamepad->hid, &hid_close,
|
if (!sc_hid_gamepad_generate_close(&gamepad->hid, &hid_close,
|
||||||
@ -75,7 +85,6 @@ sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
|||||||
|
|
||||||
sc_gamepad_uhid_send_close(gamepad, &hid_close);
|
sc_gamepad_uhid_send_close(gamepad, &hid_close);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_gamepad_processor_process_gamepad_axis(struct sc_gamepad_processor *gp,
|
sc_gamepad_processor_process_gamepad_axis(struct sc_gamepad_processor *gp,
|
||||||
@ -114,7 +123,8 @@ sc_gamepad_uhid_init(struct sc_gamepad_uhid *gamepad,
|
|||||||
gamepad->controller = controller;
|
gamepad->controller = controller;
|
||||||
|
|
||||||
static const struct sc_gamepad_processor_ops ops = {
|
static const struct sc_gamepad_processor_ops ops = {
|
||||||
.process_gamepad_device = sc_gamepad_processor_process_gamepad_device,
|
.process_gamepad_added = sc_gamepad_processor_process_gamepad_added,
|
||||||
|
.process_gamepad_removed = sc_gamepad_processor_process_gamepad_removed,
|
||||||
.process_gamepad_axis = sc_gamepad_processor_process_gamepad_axis,
|
.process_gamepad_axis = sc_gamepad_processor_process_gamepad_axis,
|
||||||
.process_gamepad_button = sc_gamepad_processor_process_gamepad_button,
|
.process_gamepad_button = sc_gamepad_processor_process_gamepad_button,
|
||||||
};
|
};
|
||||||
|
@ -141,6 +141,8 @@ sc_keyboard_uhid_init(struct sc_keyboard_uhid *kb,
|
|||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
||||||
msg.uhid_create.id = SC_HID_ID_KEYBOARD;
|
msg.uhid_create.id = SC_HID_ID_KEYBOARD;
|
||||||
|
msg.uhid_create.vendor_id = hid_open.vendor_id;
|
||||||
|
msg.uhid_create.product_id = hid_open.product_id;
|
||||||
msg.uhid_create.name = hid_open.name;
|
msg.uhid_create.name = hid_open.name;
|
||||||
msg.uhid_create.report_desc = hid_open.report_desc;
|
msg.uhid_create.report_desc = hid_open.report_desc;
|
||||||
msg.uhid_create.report_desc_size = hid_open.report_desc_size;
|
msg.uhid_create.report_desc_size = hid_open.report_desc_size;
|
||||||
|
@ -81,6 +81,8 @@ sc_mouse_uhid_init(struct sc_mouse_uhid *mouse,
|
|||||||
struct sc_control_msg msg;
|
struct sc_control_msg msg;
|
||||||
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE;
|
||||||
msg.uhid_create.id = SC_HID_ID_MOUSE;
|
msg.uhid_create.id = SC_HID_ID_MOUSE;
|
||||||
|
msg.uhid_create.vendor_id = hid_open.vendor_id;
|
||||||
|
msg.uhid_create.product_id = hid_open.product_id;
|
||||||
msg.uhid_create.name = hid_open.name;
|
msg.uhid_create.name = hid_open.name;
|
||||||
msg.uhid_create.report_desc = hid_open.report_desc;
|
msg.uhid_create.report_desc = hid_open.report_desc;
|
||||||
msg.uhid_create.report_desc_size = hid_open.report_desc_size;
|
msg.uhid_create.report_desc_size = hid_open.report_desc_size;
|
||||||
|
@ -7,14 +7,13 @@
|
|||||||
#define DOWNCAST(GP) container_of(GP, struct sc_gamepad_aoa, gamepad_processor)
|
#define DOWNCAST(GP) container_of(GP, struct sc_gamepad_aoa, gamepad_processor)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
sc_gamepad_processor_process_gamepad_added(struct sc_gamepad_processor *gp,
|
||||||
const struct sc_gamepad_device_event *event) {
|
const struct sc_gamepad_added_event *event) {
|
||||||
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
if (event->type == SC_GAMEPAD_DEVICE_ADDED) {
|
|
||||||
struct sc_hid_open hid_open;
|
struct sc_hid_open hid_open;
|
||||||
if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open,
|
if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open,
|
||||||
event->gamepad_id)) {
|
event->gamepad_id, 0, 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,8 +21,12 @@ sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
|||||||
if (!sc_aoa_push_open(gamepad->aoa, &hid_open, false)) {
|
if (!sc_aoa_push_open(gamepad->aoa, &hid_open, false)) {
|
||||||
LOGW("Could not push AOA HID open (gamepad)");
|
LOGW("Could not push AOA HID open (gamepad)");
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
assert(event->type == SC_GAMEPAD_DEVICE_REMOVED);
|
|
||||||
|
static void
|
||||||
|
sc_gamepad_processor_process_gamepad_removed(struct sc_gamepad_processor *gp,
|
||||||
|
const struct sc_gamepad_removed_event *event) {
|
||||||
|
struct sc_gamepad_aoa *gamepad = DOWNCAST(gp);
|
||||||
|
|
||||||
struct sc_hid_close hid_close;
|
struct sc_hid_close hid_close;
|
||||||
if (!sc_hid_gamepad_generate_close(&gamepad->hid, &hid_close,
|
if (!sc_hid_gamepad_generate_close(&gamepad->hid, &hid_close,
|
||||||
@ -35,7 +38,6 @@ sc_gamepad_processor_process_gamepad_device(struct sc_gamepad_processor *gp,
|
|||||||
LOGW("Could not push AOA HID close (gamepad)");
|
LOGW("Could not push AOA HID close (gamepad)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sc_gamepad_processor_process_gamepad_axis(struct sc_gamepad_processor *gp,
|
sc_gamepad_processor_process_gamepad_axis(struct sc_gamepad_processor *gp,
|
||||||
@ -76,7 +78,8 @@ sc_gamepad_aoa_init(struct sc_gamepad_aoa *gamepad, struct sc_aoa *aoa) {
|
|||||||
sc_hid_gamepad_init(&gamepad->hid);
|
sc_hid_gamepad_init(&gamepad->hid);
|
||||||
|
|
||||||
static const struct sc_gamepad_processor_ops ops = {
|
static const struct sc_gamepad_processor_ops ops = {
|
||||||
.process_gamepad_device = sc_gamepad_processor_process_gamepad_device,
|
.process_gamepad_added = sc_gamepad_processor_process_gamepad_added,
|
||||||
|
.process_gamepad_removed = sc_gamepad_processor_process_gamepad_removed,
|
||||||
.process_gamepad_axis = sc_gamepad_processor_process_gamepad_axis,
|
.process_gamepad_axis = sc_gamepad_processor_process_gamepad_axis,
|
||||||
.process_gamepad_button = sc_gamepad_processor_process_gamepad_button,
|
.process_gamepad_button = sc_gamepad_processor_process_gamepad_button,
|
||||||
};
|
};
|
||||||
|
@ -175,7 +175,6 @@ sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
|||||||
assert(screen->gamepad);
|
assert(screen->gamepad);
|
||||||
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
struct sc_gamepad_processor *gp = &screen->gamepad->gamepad_processor;
|
||||||
|
|
||||||
SDL_JoystickID id;
|
|
||||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||||
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
SDL_GameController *gc = SDL_GameControllerOpen(event->which);
|
||||||
if (!gc) {
|
if (!gc) {
|
||||||
@ -190,9 +189,12 @@ sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = SDL_JoystickInstanceID(joystick);
|
struct sc_gamepad_added_event evt = {
|
||||||
|
.gamepad_id = SDL_JoystickInstanceID(joystick),
|
||||||
|
};
|
||||||
|
gp->ops->process_gamepad_added(gp, &evt);
|
||||||
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||||
id = event->which;
|
SDL_JoystickID id = event->which;
|
||||||
|
|
||||||
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
SDL_GameController *gc = SDL_GameControllerFromInstanceID(id);
|
||||||
if (gc) {
|
if (gc) {
|
||||||
@ -200,16 +202,12 @@ sc_screen_otg_process_gamepad_device(struct sc_screen_otg *screen,
|
|||||||
} else {
|
} else {
|
||||||
LOGW("Unknown gamepad device removed");
|
LOGW("Unknown gamepad device removed");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Nothing to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sc_gamepad_device_event evt = {
|
struct sc_gamepad_removed_event evt = {
|
||||||
.type = sc_gamepad_device_event_type_from_sdl_type(event->type),
|
|
||||||
.gamepad_id = id,
|
.gamepad_id = id,
|
||||||
};
|
};
|
||||||
gp->ops->process_gamepad_device(gp, &evt);
|
gp->ops->process_gamepad_removed(gp, &evt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -329,6 +329,8 @@ static void test_serialize_uhid_create(void) {
|
|||||||
.type = SC_CONTROL_MSG_TYPE_UHID_CREATE,
|
.type = SC_CONTROL_MSG_TYPE_UHID_CREATE,
|
||||||
.uhid_create = {
|
.uhid_create = {
|
||||||
.id = 42,
|
.id = 42,
|
||||||
|
.vendor_id = 0x1234,
|
||||||
|
.product_id = 0x5678,
|
||||||
.name = "ABC",
|
.name = "ABC",
|
||||||
.report_desc_size = sizeof(report_desc),
|
.report_desc_size = sizeof(report_desc),
|
||||||
.report_desc = report_desc,
|
.report_desc = report_desc,
|
||||||
@ -337,11 +339,13 @@ static void test_serialize_uhid_create(void) {
|
|||||||
|
|
||||||
uint8_t buf[SC_CONTROL_MSG_MAX_SIZE];
|
uint8_t buf[SC_CONTROL_MSG_MAX_SIZE];
|
||||||
size_t size = sc_control_msg_serialize(&msg, buf);
|
size_t size = sc_control_msg_serialize(&msg, buf);
|
||||||
assert(size == 20);
|
assert(size == 24);
|
||||||
|
|
||||||
const uint8_t expected[] = {
|
const uint8_t expected[] = {
|
||||||
SC_CONTROL_MSG_TYPE_UHID_CREATE,
|
SC_CONTROL_MSG_TYPE_UHID_CREATE,
|
||||||
0, 42, // id
|
0, 42, // id
|
||||||
|
0x12, 0x34, // vendor id
|
||||||
|
0x56, 0x78, // product id
|
||||||
3, // name size
|
3, // name size
|
||||||
65, 66, 67, // "ABC"
|
65, 66, 67, // "ABC"
|
||||||
0, 11, // report desc size
|
0, 11, // report desc size
|
||||||
|
@ -51,6 +51,8 @@ public final class ControlMessage {
|
|||||||
private int id;
|
private int id;
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
private int vendorId;
|
||||||
|
private int productId;
|
||||||
|
|
||||||
private ControlMessage() {
|
private ControlMessage() {
|
||||||
}
|
}
|
||||||
@ -131,10 +133,12 @@ public final class ControlMessage {
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ControlMessage createUhidCreate(int id, String name, byte[] reportDesc) {
|
public static ControlMessage createUhidCreate(int id, int vendorId, int productId, String name, byte[] reportDesc) {
|
||||||
ControlMessage msg = new ControlMessage();
|
ControlMessage msg = new ControlMessage();
|
||||||
msg.type = TYPE_UHID_CREATE;
|
msg.type = TYPE_UHID_CREATE;
|
||||||
msg.id = id;
|
msg.id = id;
|
||||||
|
msg.vendorId = vendorId;
|
||||||
|
msg.productId = productId;
|
||||||
msg.text = name;
|
msg.text = name;
|
||||||
msg.data = reportDesc;
|
msg.data = reportDesc;
|
||||||
return msg;
|
return msg;
|
||||||
@ -237,4 +241,12 @@ public final class ControlMessage {
|
|||||||
public boolean getOn() {
|
public boolean getOn() {
|
||||||
return on;
|
return on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getVendorId() {
|
||||||
|
return vendorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getProductId() {
|
||||||
|
return productId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,9 +142,11 @@ public class ControlMessageReader {
|
|||||||
|
|
||||||
private ControlMessage parseUhidCreate() throws IOException {
|
private ControlMessage parseUhidCreate() throws IOException {
|
||||||
int id = dis.readUnsignedShort();
|
int id = dis.readUnsignedShort();
|
||||||
|
int vendorId = dis.readUnsignedShort();
|
||||||
|
int productId = dis.readUnsignedShort();
|
||||||
String name = parseString(1);
|
String name = parseString(1);
|
||||||
byte[] data = parseByteArray(2);
|
byte[] data = parseByteArray(2);
|
||||||
return ControlMessage.createUhidCreate(id, name, data);
|
return ControlMessage.createUhidCreate(id, vendorId, productId, name, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControlMessage parseUhidInput() throws IOException {
|
private ControlMessage parseUhidInput() throws IOException {
|
||||||
|
@ -290,7 +290,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener {
|
|||||||
Device.rotateDevice(getActionDisplayId());
|
Device.rotateDevice(getActionDisplayId());
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_UHID_CREATE:
|
case ControlMessage.TYPE_UHID_CREATE:
|
||||||
getUhidManager().open(msg.getId(), msg.getText(), msg.getData());
|
getUhidManager().open(msg.getId(), msg.getVendorId(), msg.getProductId(), msg.getText(), msg.getData());
|
||||||
break;
|
break;
|
||||||
case ControlMessage.TYPE_UHID_INPUT:
|
case ControlMessage.TYPE_UHID_INPUT:
|
||||||
getUhidManager().writeInput(msg.getId(), msg.getData());
|
getUhidManager().writeInput(msg.getId(), msg.getData());
|
||||||
|
@ -48,7 +48,7 @@ public final class UhidManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void open(int id, String name, byte[] reportDesc) throws IOException {
|
public void open(int id, int vendorId, int productId, String name, byte[] reportDesc) throws IOException {
|
||||||
try {
|
try {
|
||||||
FileDescriptor fd = Os.open("/dev/uhid", OsConstants.O_RDWR, 0);
|
FileDescriptor fd = Os.open("/dev/uhid", OsConstants.O_RDWR, 0);
|
||||||
try {
|
try {
|
||||||
@ -58,7 +58,7 @@ public final class UhidManager {
|
|||||||
close(old);
|
close(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] req = buildUhidCreate2Req(name, reportDesc);
|
byte[] req = buildUhidCreate2Req(vendorId, productId, name, reportDesc);
|
||||||
Os.write(fd, req, 0, req.length);
|
Os.write(fd, req, 0, req.length);
|
||||||
|
|
||||||
registerUhidListener(id, fd);
|
registerUhidListener(id, fd);
|
||||||
@ -148,7 +148,7 @@ public final class UhidManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] buildUhidCreate2Req(String name, byte[] reportDesc) {
|
private static byte[] buildUhidCreate2Req(int vendorId, int productId, String name, byte[] reportDesc) {
|
||||||
/*
|
/*
|
||||||
* struct uhid_event {
|
* struct uhid_event {
|
||||||
* uint32_t type;
|
* uint32_t type;
|
||||||
@ -183,8 +183,8 @@ public final class UhidManager {
|
|||||||
|
|
||||||
buf.putShort((short) reportDesc.length);
|
buf.putShort((short) reportDesc.length);
|
||||||
buf.putShort(BUS_VIRTUAL);
|
buf.putShort(BUS_VIRTUAL);
|
||||||
buf.putInt(0); // vendor id
|
buf.putInt(vendorId);
|
||||||
buf.putInt(0); // product id
|
buf.putInt(productId);
|
||||||
buf.putInt(0); // version
|
buf.putInt(0); // version
|
||||||
buf.putInt(0); // country;
|
buf.putInt(0); // country;
|
||||||
buf.put(reportDesc);
|
buf.put(reportDesc);
|
||||||
|
Reference in New Issue
Block a user