feat: implement initial cyborg multi-action button mappings
- Added support for Single, Long, and Double press actions in libazeron. - Mapped Cyborg surgical command IDs (0x20F6, 0x20F8, 0x204A). - Updated azeron-cli to support --long and --double mapping flags. - Updated protocol documentation with newly discovered Cyborg commands. - Added TODO.md for remaining joystick and timing tasks.
This commit is contained in:
@@ -19,8 +19,15 @@
|
||||
/* Command IDs */
|
||||
#define AZERON_CMD_STATUS 0x122a
|
||||
#define AZERON_CMD_READ_CONFIG 0x26FB
|
||||
#define AZERON_CMD_WRITE_PROFILE 0x26FC
|
||||
#define AZERON_CMD_SAVE_PROFILE 0x26FD
|
||||
#define AZERON_CMD_WRITE_PROFILE 0x26EC
|
||||
#define AZERON_CMD_SAVE_PROFILE 0x26ED
|
||||
|
||||
/* Cyborg Specific Surgical Commands */
|
||||
#define AZERON_CMD_SET_SINGLE 0x20F6
|
||||
#define AZERON_CMD_SET_LONG 0x20F8
|
||||
#define AZERON_CMD_SET_DOUBLE 0x204A
|
||||
#define AZERON_CMD_COMMIT_BTN 0x204B
|
||||
#define AZERON_CMD_SET_GLOBAL 0x2000
|
||||
|
||||
/* Operation types */
|
||||
#define AZERON_OP_READ_STATUS 0x0101
|
||||
@@ -31,7 +38,7 @@
|
||||
#define AZERON_OP_SAVE_PROFILE 0x0202
|
||||
|
||||
/* Offsets for profile data */
|
||||
#define AZERON_PROFILE_BASE_OFFSET 0x0439
|
||||
#define AZERON_PROFILE_BASE_OFFSET 0x0339
|
||||
#define AZERON_BUTTON_MAPPING_SIZE 4
|
||||
#define AZERON_STICK_CONFIG_OFFSET 58
|
||||
|
||||
@@ -277,53 +284,56 @@ int azeron_protocol_set_button_mapping(struct azeron_device *device,
|
||||
uint8_t response[64];
|
||||
size_t response_len;
|
||||
uint8_t data[58] = {0};
|
||||
uint32_t offset;
|
||||
uint16_t operation;
|
||||
uint8_t active_profile;
|
||||
uint16_t command;
|
||||
int ret;
|
||||
|
||||
if (!device || !mapping) {
|
||||
return AZERON_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Get active profile to know which operation to use */
|
||||
ret = azeron_protocol_get_active_profile(device, &active_profile);
|
||||
if (ret != AZERON_SUCCESS) {
|
||||
return ret;
|
||||
/* Select surgical command based on action type */
|
||||
switch (mapping->action) {
|
||||
case AZERON_ACTION_SINGLE: command = AZERON_CMD_SET_SINGLE; break;
|
||||
case AZERON_ACTION_LONG: command = AZERON_CMD_SET_LONG; break;
|
||||
case AZERON_ACTION_DOUBLE: command = AZERON_CMD_SET_DOUBLE; break;
|
||||
default: return AZERON_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
switch (active_profile) {
|
||||
case 0: operation = AZERON_OP_WRITE_PROFILE_0; break;
|
||||
case 1: operation = AZERON_OP_WRITE_PROFILE_1; break;
|
||||
case 2: operation = AZERON_OP_WRITE_PROFILE_2; break;
|
||||
default: return AZERON_ERROR_PROTOCOL;
|
||||
}
|
||||
|
||||
/* Calculate offset: Base + 8 (header + color) + (ButtonID * 4) */
|
||||
offset = AZERON_PROFILE_BASE_OFFSET + 8 + (mapping->button_id * AZERON_BUTTON_MAPPING_SIZE);
|
||||
|
||||
/* Data payload for 0x26FC:
|
||||
* Bytes 0-3: Offset (LITTLE ENDIAN)
|
||||
* Bytes 4-7: Mapping (4 bytes)
|
||||
/* Surgical payload structure for Cyborg:
|
||||
* Byte 4: 0x01 (fixed?)
|
||||
* Byte 5: 0x01 (fixed?)
|
||||
* Byte 10: Button ID
|
||||
* Byte 11: Sub-action index? (usually 0x01 or 0x02)
|
||||
* Byte 22: Key Type
|
||||
* Byte 23: Key Code
|
||||
*/
|
||||
data[0] = offset & 0xFF;
|
||||
data[1] = (offset >> 8) & 0xFF;
|
||||
data[2] = (offset >> 16) & 0xFF;
|
||||
data[3] = (offset >> 24) & 0xFF;
|
||||
|
||||
data[4] = 0x01;
|
||||
data[10] = mapping->button_id;
|
||||
|
||||
switch (mapping->action) {
|
||||
case AZERON_ACTION_SINGLE: data[11] = 0x01; break;
|
||||
case AZERON_ACTION_LONG: data[11] = 0x00; break; /* As seen in capture */
|
||||
case AZERON_ACTION_DOUBLE: data[11] = 0x00; break; /* As seen in capture */
|
||||
}
|
||||
|
||||
switch (mapping->type) {
|
||||
case AZERON_BTN_KEYBOARD: data[4] = 0xf0; break;
|
||||
case AZERON_BTN_MOUSE: data[4] = 0xf1; break;
|
||||
case AZERON_BTN_GAMEPAD: data[4] = 0xf2; break;
|
||||
case AZERON_BTN_KEYBOARD: data[22] = 0xf0; break;
|
||||
case AZERON_BTN_MOUSE: data[22] = 0xf1; break;
|
||||
case AZERON_BTN_GAMEPAD: data[22] = 0xf2; break;
|
||||
default: return AZERON_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
data[5] = mapping->key_code & 0xFF;
|
||||
data[6] = 0x00; /* No modifiers for now */
|
||||
data[7] = 0x00;
|
||||
data[23] = mapping->key_code & 0xFF;
|
||||
|
||||
ret = send_config_command(device, AZERON_CMD_WRITE_PROFILE, operation,
|
||||
data, 8, response, &response_len);
|
||||
ret = send_config_command(device, command, 0x0101,
|
||||
data, 24, response, &response_len);
|
||||
|
||||
if (ret == AZERON_SUCCESS) {
|
||||
/* Follow up with commitment command to make it live */
|
||||
ret = send_config_command(device, AZERON_CMD_COMMIT_BTN, 0x0101,
|
||||
NULL, 0, response, &response_len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user