Implement initial profile reading and writing with little-endian offsets and CLI tool

This commit is contained in:
Aodhan Collins
2026-02-22 17:53:05 +00:00
parent 224271e639
commit db5c3505da
72 changed files with 7090 additions and 126 deletions

View File

@@ -273,14 +273,13 @@ int azeron_device_open(struct azeron_device **device, uint16_t vendor_id, uint16
dev->context = g_context;
pthread_mutex_init(&dev->mutex, NULL);
ret = libusb_open_device_with_vid_pid(g_context, vendor_id, product_id);
if (!ret) {
dev->handle = libusb_open_device_with_vid_pid(g_context, vendor_id, product_id);
if (!dev->handle) {
AZERON_ERROR("Failed to open device %04x:%04x", vendor_id, product_id);
free(dev);
return AZERON_ERROR_NOT_FOUND;
}
dev->handle = ret;
azeron_device_info_from_libusb(dev, libusb_get_device(dev->handle));
*device = dev;
@@ -380,9 +379,89 @@ int azeron_device_get_info(struct azeron_device *device, struct azeron_device_in
}
memcpy(info, &device->info, sizeof(struct azeron_device_info));
/* Update active profile info */
azeron_device_get_active_profile(device, &info->active_profile);
device->info.active_profile = info->active_profile;
return AZERON_SUCCESS;
}
/* Get active profile ID */
int azeron_device_get_active_profile(struct azeron_device *device, uint8_t *profile_id)
{
if (!device || !profile_id) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_get_active_profile(device, profile_id);
}
/* Set active profile ID */
int azeron_device_set_active_profile(struct azeron_device *device, uint8_t profile_id)
{
if (!device) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_set_active_profile(device, profile_id);
}
/* Save profile to device EEPROM */
int azeron_device_save_profile(struct azeron_device *device, uint8_t profile_id)
{
if (!device) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_save_to_device(device, profile_id);
}
/* Get button mapping */
int azeron_device_get_button_mapping(struct azeron_device *device, uint8_t button_id,
struct azeron_button_mapping *mapping)
{
if (!device || !mapping) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_get_button_mapping(device, button_id, mapping);
}
/* Set button mapping */
int azeron_protocol_set_button_mapping(struct azeron_device *device, const struct azeron_button_mapping *mapping);
int azeron_device_set_button_mapping(struct azeron_device *device,
const struct azeron_button_mapping *mapping)
{
if (!device || !mapping) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_set_button_mapping(device, mapping);
}
/* Get stick configuration */
int azeron_device_get_stick_config(struct azeron_device *device,
struct azeron_stick_config *config)
{
if (!device || !config) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_get_stick_config(device, config);
}
/* Set stick configuration */
int azeron_device_set_stick_config(struct azeron_device *device,
const struct azeron_stick_config *config)
{
if (!device || !config) {
return AZERON_ERROR_INVALID_PARAM;
}
return azeron_protocol_set_stick_config(device, config);
}
/* Button type to string */
const char *azeron_button_type_string(enum azeron_button_type type)
{

View File

@@ -130,6 +130,7 @@ int azeron_device_get_profile(struct azeron_device *device, uint8_t profile_id,
struct azeron_profile *profile);
int azeron_device_set_profile(struct azeron_device *device,
const struct azeron_profile *profile);
int azeron_device_save_profile(struct azeron_device *device, uint8_t profile_id);
/* Configuration import/export */
int azeron_device_export_config(struct azeron_device *device, const char *filename);

View File

@@ -10,6 +10,8 @@
#include <libusb-1.0/libusb.h>
#include <string.h>
#define AZERON_CONFIG_INTERFACE 4
/* Claim device interfaces */
int azeron_device_claim(struct azeron_device *device)
{
@@ -25,26 +27,34 @@ int azeron_device_claim(struct azeron_device *device)
pthread_mutex_lock(&device->mutex);
/* Claim all interfaces - the device has 5 interfaces (0-4) */
for (int i = 0; i <= 4; i++) {
ret = libusb_claim_interface(device->handle, i);
if (ret < 0) {
AZERON_ERROR("Failed to claim interface %d: %s", i, azeron_usb_error_string(ret));
/* Release already claimed interfaces */
for (int j = 0; j < i; j++) {
libusb_release_interface(device->handle, j);
}
/*
* The device has 5 interfaces (0-4).
* Interfaces 1, 2, and 3 are handled by the kernel for input (HID).
* Interface 4 is the configuration interface we need.
*/
/* Detach kernel driver if active on Interface 4 */
if (libusb_kernel_driver_active(device->handle, AZERON_CONFIG_INTERFACE) == 1) {
ret = libusb_detach_kernel_driver(device->handle, AZERON_CONFIG_INTERFACE);
if (ret < 0 && ret != LIBUSB_ERROR_NOT_FOUND) {
AZERON_ERROR("Failed to detach kernel driver: %s", azeron_usb_error_string(ret));
pthread_mutex_unlock(&device->mutex);
return azeron_libusb_to_azeron_error(ret);
}
}
/* Claim configuration interface */
ret = libusb_claim_interface(device->handle, AZERON_CONFIG_INTERFACE);
if (ret < 0) {
AZERON_ERROR("Failed to claim interface %d: %s", AZERON_CONFIG_INTERFACE, azeron_usb_error_string(ret));
pthread_mutex_unlock(&device->mutex);
return azeron_libusb_to_azeron_error(ret);
}
device->claimed = true;
pthread_mutex_unlock(&device->mutex);
AZERON_LOG("Device interfaces claimed");
AZERON_LOG("Device configuration interface claimed");
return AZERON_SUCCESS;
}
@@ -53,7 +63,6 @@ int azeron_device_claim(struct azeron_device *device)
int azeron_device_release(struct azeron_device *device)
{
int ret;
int overall_ret = AZERON_SUCCESS;
if (!device || !device->handle) {
return AZERON_ERROR_INVALID_PARAM;
@@ -65,21 +74,20 @@ int azeron_device_release(struct azeron_device *device)
pthread_mutex_lock(&device->mutex);
/* Release all interfaces */
for (int i = 0; i <= 4; i++) {
ret = libusb_release_interface(device->handle, i);
if (ret < 0) {
AZERON_ERROR("Failed to release interface %d: %s", i, azeron_usb_error_string(ret));
overall_ret = azeron_libusb_to_azeron_error(ret);
}
ret = libusb_release_interface(device->handle, AZERON_CONFIG_INTERFACE);
if (ret < 0) {
AZERON_ERROR("Failed to release interface %d: %s", AZERON_CONFIG_INTERFACE, azeron_usb_error_string(ret));
}
/* Re-attach kernel driver */
libusb_attach_kernel_driver(device->handle, AZERON_CONFIG_INTERFACE);
device->claimed = false;
pthread_mutex_unlock(&device->mutex);
AZERON_LOG("Device interfaces released");
AZERON_LOG("Device interface released");
return overall_ret;
return (ret < 0) ? azeron_libusb_to_azeron_error(ret) : AZERON_SUCCESS;
}
/* Read data from endpoint */
@@ -180,39 +188,3 @@ int azeron_device_control_transfer(struct azeron_device *device, uint8_t request
return ret;
}
/* Get button type string */
const char *azeron_button_type_string(enum azeron_button_type type)
{
switch (type) {
case AZERON_BTN_KEYBOARD:
return "keyboard";
case AZERON_BTN_MOUSE:
return "mouse";
case AZERON_BTN_GAMEPAD:
return "gamepad";
case AZERON_BTN_MACRO:
return "macro";
case AZERON_BTN_LAYER_SWITCH:
return "layer_switch";
default:
return "unknown";
}
}
/* Get stick mode string */
const char *azeron_stick_mode_string(enum azeron_stick_mode mode)
{
switch (mode) {
case AZERON_STICK_ANALOG:
return "analog";
case AZERON_STICK_DIGITAL_4:
return "digital_4";
case AZERON_STICK_DIGITAL_8:
return "digital_8";
case AZERON_STICK_MOUSE:
return "mouse";
default:
return "unknown";
}
}

View File

@@ -11,6 +11,7 @@
#include "azeron.h"
#include <libusb-1.0/libusb.h>
#include <pthread.h>
#include <stdio.h>
#define AZERON_USB_TIMEOUT 1000
#define AZERON_MAX_STRING_LENGTH 256
@@ -36,15 +37,17 @@ struct azeron_device {
/* Protocol functions */
int azeron_protocol_init(struct azeron_device *device);
int azeron_protocol_read_config(struct azeron_device *device, uint8_t *data, size_t *size);
int azeron_protocol_read_config(struct azeron_device *device, uint32_t offset, uint8_t *data, size_t *size);
int azeron_protocol_write_config(struct azeron_device *device, const uint8_t *data, size_t size);
int azeron_protocol_get_button_mapping(struct azeron_device *device, uint8_t button_id, struct azeron_button_mapping *mapping);
int azeron_protocol_set_button_mapping(struct azeron_device *device, const struct azeron_button_mapping *mapping);
int azeron_protocol_get_stick_config(struct azeron_device *device, struct azeron_stick_config *config);
int azeron_protocol_set_stick_config(struct azeron_device *device, const struct azeron_stick_config *config);
int azeron_protocol_get_active_profile(struct azeron_device *device, uint8_t *profile_id);
int azeron_protocol_set_active_profile(struct azeron_device *device, uint8_t profile_id);
int azeron_protocol_get_profile(struct azeron_device *device, uint8_t profile_id, struct azeron_profile *profile);
int azeron_protocol_set_profile(struct azeron_device *device, const struct azeron_profile *profile);
int azeron_protocol_save_to_device(struct azeron_device *device);
int azeron_protocol_save_to_device(struct azeron_device *device, uint8_t profile_id);
/* Device functions */
int azeron_device_claim(struct azeron_device *device);

View File

@@ -8,23 +8,204 @@
#include "azeron.h"
#include "internal.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
/* Configuration Interface Constants */
#define AZERON_CONFIG_ENDPOINT_OUT 0x06
#define AZERON_CONFIG_ENDPOINT_IN 0x85
#define AZERON_CONFIG_PACKET_SIZE 64
/* 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
/* Operation types */
#define AZERON_OP_READ_STATUS 0x0101
#define AZERON_OP_READ_CONFIG 0x0101
#define AZERON_OP_WRITE_PROFILE_0 0x0200
#define AZERON_OP_WRITE_PROFILE_1 0x0201
#define AZERON_OP_WRITE_PROFILE_2 0x0202
#define AZERON_OP_SAVE_PROFILE 0x0202
/* Offsets for profile data */
#define AZERON_PROFILE_BASE_OFFSET 0x0439
#define AZERON_BUTTON_MAPPING_SIZE 4
#define AZERON_STICK_CONFIG_OFFSET 58
/* Helper to dump hex data */
static void dump_hex(const char *label, const uint8_t *data, size_t len)
{
#ifdef AZERON_DEBUG
fprintf(stderr, "[AZERON DEBUG] %s (%zu bytes):", label, len);
for (size_t i = 0; i < len; i++) {
fprintf(stderr, " %02x", data[i]);
}
fprintf(stderr, "\n");
#endif
}
/* Build a standard 64-byte configuration packet */
static int build_config_packet(uint8_t *packet, uint16_t command, uint16_t operation,
const uint8_t *data, size_t data_len)
{
if (!packet || data_len > 58) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Clear packet */
memset(packet, 0, AZERON_CONFIG_PACKET_SIZE);
/* Build header */
packet[0] = 0x00; /* Request packet */
packet[1] = 0x3a; /* Payload length (fixed 58 bytes for config) */
packet[2] = (command >> 8) & 0xFF; /* Command ID high byte */
packet[3] = command & 0xFF; /* Command ID low byte */
packet[4] = (operation >> 8) & 0xFF; /* Operation high byte */
packet[5] = operation & 0xFF; /* Operation low byte */
/* Copy data payload if provided */
if (data && data_len > 0) {
memcpy(&packet[6], data, data_len);
}
return AZERON_SUCCESS;
}
/* Send a configuration command and wait for response */
static int send_config_command(struct azeron_device *device, uint16_t command, uint16_t operation,
const uint8_t *request_data, size_t request_len,
uint8_t *response, size_t *response_len)
{
uint8_t request_packet[AZERON_CONFIG_PACKET_SIZE];
uint8_t response_packet[AZERON_CONFIG_PACKET_SIZE];
int ret;
if (!device || !response || !response_len) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Build request packet */
ret = build_config_packet(request_packet, command, operation, request_data, request_len);
if (ret != AZERON_SUCCESS) {
return ret;
}
dump_hex("Request", request_packet, AZERON_CONFIG_PACKET_SIZE);
/* Send request */
ret = azeron_device_write(device, AZERON_CONFIG_ENDPOINT_OUT,
request_packet, AZERON_CONFIG_PACKET_SIZE, AZERON_USB_TIMEOUT);
if (ret < 0) {
AZERON_ERROR("Failed to send command 0x%04x: %s", command, azeron_error_string(ret));
return ret;
}
/* Wait for device to process - configuration read might take longer */
usleep(50000); /* 50ms */
/* Read response */
ret = azeron_device_read(device, AZERON_CONFIG_ENDPOINT_IN,
response_packet, AZERON_CONFIG_PACKET_SIZE, AZERON_USB_TIMEOUT);
if (ret < 0) {
AZERON_ERROR("Failed to read response for command 0x%04x: %s", command, azeron_error_string(ret));
return ret;
}
dump_hex("Response", response_packet, AZERON_CONFIG_PACKET_SIZE);
/* Validate response */
if (ret != AZERON_CONFIG_PACKET_SIZE) {
AZERON_ERROR("Invalid response size: %d (expected %d)", ret, AZERON_CONFIG_PACKET_SIZE);
return AZERON_ERROR_PROTOCOL;
}
/* Check response type */
if (response_packet[0] != 0x01 && response_packet[0] != 0x00) {
AZERON_ERROR("Invalid response type: 0x%02x", response_packet[0]);
return AZERON_ERROR_PROTOCOL;
}
/* Check command ID matches */
uint16_t response_command = (response_packet[2] << 8) | response_packet[3];
if (response_command != command) {
AZERON_ERROR("Command mismatch: sent 0x%04x, got 0x%04x", command, response_command);
return AZERON_ERROR_PROTOCOL;
}
/* Check status - Byte 6 seems to be 0x01 for success in most responses */
if (response_packet[6] != 0x01 && response_packet[6] != 0x00) {
AZERON_ERROR("Command failed with status: 0x%02x", response_packet[6]);
return AZERON_ERROR_PROTOCOL;
}
/* Copy response data (skip 6-byte header) */
*response_len = ret - 6;
if (*response_len > 0) {
memcpy(response, &response_packet[6], *response_len);
}
AZERON_LOG("Command 0x%04x completed successfully", command);
return AZERON_SUCCESS;
}
/* Protocol initialization */
int azeron_protocol_init(struct azeron_device *device)
{
(void)device;
AZERON_LOG("Protocol initialization - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t response[64];
size_t response_len;
int ret;
if (!device) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Send status command to verify communication */
ret = send_config_command(device, AZERON_CMD_STATUS, AZERON_OP_READ_STATUS,
NULL, 0, response, &response_len);
if (ret != AZERON_SUCCESS) {
AZERON_ERROR("Failed to initialize protocol: %s", azeron_error_string(ret));
return ret;
}
AZERON_LOG("Protocol initialized successfully");
return AZERON_SUCCESS;
}
/* Read configuration from device */
int azeron_protocol_read_config(struct azeron_device *device, uint8_t *data, size_t *size)
/* Read configuration from device at specific offset */
int azeron_protocol_read_config(struct azeron_device *device, uint32_t offset, uint8_t *data, size_t *size)
{
(void)device;
(void)data;
(void)size;
AZERON_LOG("Read config - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t response[64];
size_t response_len;
uint8_t request_data[58] = {0};
int ret;
if (!device || !data || !size) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Set offset in request (LITTLE ENDIAN) */
request_data[0] = offset & 0xFF;
request_data[1] = (offset >> 8) & 0xFF;
request_data[2] = (offset >> 16) & 0xFF;
request_data[3] = (offset >> 24) & 0xFF;
ret = send_config_command(device, AZERON_CMD_READ_CONFIG, AZERON_OP_READ_CONFIG,
request_data, 4, response, &response_len);
if (ret != AZERON_SUCCESS) {
return ret;
}
if (response_len > *size) {
response_len = *size;
}
memcpy(data, response, response_len);
*size = response_len;
return AZERON_SUCCESS;
}
/* Write configuration to device */
@@ -41,41 +222,219 @@ int azeron_protocol_write_config(struct azeron_device *device, const uint8_t *da
int azeron_protocol_get_button_mapping(struct azeron_device *device, uint8_t button_id,
struct azeron_button_mapping *mapping)
{
(void)device;
(void)button_id;
(void)mapping;
AZERON_LOG("Get button mapping - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t config[64];
size_t size = sizeof(config);
int ret;
if (!device || !mapping) {
return AZERON_ERROR_INVALID_PARAM;
}
if (button_id >= AZERON_MAX_BUTTONS) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Calculate offset for this button's 4-byte mapping */
uint32_t offset = AZERON_PROFILE_BASE_OFFSET + 8 + (button_id * AZERON_BUTTON_MAPPING_SIZE);
ret = azeron_protocol_read_config(device, offset, config, &size);
if (ret != AZERON_SUCCESS) {
return ret;
}
/*
* Payload structure in response after 6-byte header:
* Bytes 0-3: Echoed offset?
* Bytes 4-7: The 4-byte mapping
*/
mapping->button_id = button_id;
/*
* Mapping format:
* Byte 0: Type (0xf0 = keyboard, 0xf1 = mouse, etc)
* Byte 1: Key code
*/
uint8_t type_byte = config[4];
mapping->key_code = config[5];
switch (type_byte) {
case 0xf0: mapping->type = AZERON_BTN_KEYBOARD; break;
case 0xf1: mapping->type = AZERON_BTN_MOUSE; break;
case 0xf2: mapping->type = AZERON_BTN_GAMEPAD; break;
default: mapping->type = AZERON_BTN_KEYBOARD; break;
}
mapping->macro = NULL;
mapping->layer_target = 0;
return AZERON_SUCCESS;
}
/* Set button mapping */
int azeron_protocol_set_button_mapping(struct azeron_device *device,
const struct azeron_button_mapping *mapping)
{
(void)device;
(void)mapping;
AZERON_LOG("Set button mapping - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t response[64];
size_t response_len;
uint8_t data[58] = {0};
uint32_t offset;
uint16_t operation;
uint8_t active_profile;
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;
}
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)
*/
data[0] = offset & 0xFF;
data[1] = (offset >> 8) & 0xFF;
data[2] = (offset >> 16) & 0xFF;
data[3] = (offset >> 24) & 0xFF;
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;
default: return AZERON_ERROR_UNSUPPORTED;
}
data[5] = mapping->key_code & 0xFF;
data[6] = 0x00; /* No modifiers for now */
data[7] = 0x00;
ret = send_config_command(device, AZERON_CMD_WRITE_PROFILE, operation,
data, 8, response, &response_len);
return ret;
}
/* Get stick configuration */
int azeron_protocol_get_stick_config(struct azeron_device *device,
struct azeron_stick_config *config)
{
(void)device;
(void)config;
AZERON_LOG("Get stick config - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t data[64];
size_t size = sizeof(data);
int ret;
if (!device || !config) {
return AZERON_ERROR_INVALID_PARAM;
}
uint32_t offset = AZERON_PROFILE_BASE_OFFSET + AZERON_STICK_CONFIG_OFFSET;
ret = azeron_protocol_read_config(device, offset, data, &size);
if (ret != AZERON_SUCCESS) {
return ret;
}
/* Payload: [Offset(4)] [Deadzone(1)] [Curve(1)] [Sensitivity(1)] [Invert(1)] */
config->deadzone = data[4];
config->response_curve = data[5];
config->sensitivity = data[6];
config->invert_x = data[7] & 0x01;
config->invert_y = (data[7] >> 1) & 0x01;
config->mode = AZERON_STICK_ANALOG;
return AZERON_SUCCESS;
}
/* Set stick configuration */
int azeron_protocol_set_stick_config(struct azeron_device *device,
const struct azeron_stick_config *config)
{
(void)device;
(void)config;
AZERON_LOG("Set stick config - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t response[64];
size_t response_len;
uint8_t data[58] = {0};
uint32_t offset;
uint16_t operation;
uint8_t active_profile;
int ret;
if (!device || !config) {
return AZERON_ERROR_INVALID_PARAM;
}
/* Get active profile */
ret = azeron_protocol_get_active_profile(device, &active_profile);
if (ret != AZERON_SUCCESS) {
return ret;
}
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;
}
offset = AZERON_PROFILE_BASE_OFFSET + AZERON_STICK_CONFIG_OFFSET;
data[0] = offset & 0xFF;
data[1] = (offset >> 8) & 0xFF;
data[2] = (offset >> 16) & 0xFF;
data[3] = (offset >> 24) & 0xFF;
data[4] = config->deadzone;
data[5] = config->response_curve;
data[6] = config->sensitivity;
data[7] = 0;
if (config->invert_x) data[7] |= 0x01;
if (config->invert_y) data[7] |= 0x02;
ret = send_config_command(device, AZERON_CMD_WRITE_PROFILE, operation,
data, 8, response, &response_len);
return ret;
}
/* Get active profile */
int azeron_protocol_get_active_profile(struct azeron_device *device, uint8_t *profile_id)
{
uint8_t response[64];
size_t response_len;
int ret;
if (!device || !profile_id) {
return AZERON_ERROR_INVALID_PARAM;
}
ret = send_config_command(device, AZERON_CMD_STATUS, AZERON_OP_READ_STATUS,
NULL, 0, response, &response_len);
if (ret != AZERON_SUCCESS) {
return ret;
}
/* Byte 1 of payload data (skipping 6-byte header) is profile ID */
*profile_id = response[1];
AZERON_LOG("Active profile: %d", *profile_id);
return AZERON_SUCCESS;
}
/* Set active profile */
int azeron_protocol_set_active_profile(struct azeron_device *device, uint8_t profile_id)
{
return azeron_protocol_save_to_device(device, profile_id);
}
/* Get profile */
@@ -85,7 +444,6 @@ int azeron_protocol_get_profile(struct azeron_device *device, uint8_t profile_id
(void)device;
(void)profile_id;
(void)profile;
AZERON_LOG("Get profile - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
}
@@ -95,14 +453,30 @@ int azeron_protocol_set_profile(struct azeron_device *device,
{
(void)device;
(void)profile;
AZERON_LOG("Set profile - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
}
/* Save configuration to device */
int azeron_protocol_save_to_device(struct azeron_device *device)
int azeron_protocol_save_to_device(struct azeron_device *device, uint8_t profile_id)
{
(void)device;
AZERON_LOG("Save to device - not yet implemented");
return AZERON_ERROR_UNSUPPORTED;
uint8_t response[64];
size_t response_len;
int ret;
if (device == NULL) {
return AZERON_ERROR_INVALID_PARAM;
}
if (profile_id > 2) {
AZERON_ERROR("Invalid profile ID: %d (must be 0, 1 or 2)", profile_id);
return AZERON_ERROR_INVALID_PARAM;
}
uint8_t save_data[58] = {0};
save_data[0] = profile_id;
ret = send_config_command(device, AZERON_CMD_SAVE_PROFILE, AZERON_OP_SAVE_PROFILE,
save_data, 1, response, &response_len);
return ret;
}

View File

@@ -6,6 +6,7 @@
*/
#include "azeron.h"
#include "internal.h"
#include <linux/input-event-codes.h>
#include <string.h>