Initial commit

This commit is contained in:
Aodhan Collins
2026-02-22 12:51:32 +00:00
commit 0267543622
21 changed files with 2888 additions and 0 deletions

218
libazeron/device.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* Azeron Linux Configuration Library - Device Communication
* Copyright (C) 2024 Azeron Linux Project
*
* SPDX-License-Identifier: MIT
*/
#include "azeron.h"
#include "internal.h"
#include <libusb-1.0/libusb.h>
#include <string.h>
/* Claim device interfaces */
int azeron_device_claim(struct azeron_device *device)
{
int ret;
if (!device || !device->handle) {
return AZERON_ERROR_INVALID_PARAM;
}
if (device->claimed) {
return AZERON_SUCCESS;
}
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);
}
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");
return AZERON_SUCCESS;
}
/* Release device interfaces */
int azeron_device_release(struct azeron_device *device)
{
int ret;
int overall_ret = AZERON_SUCCESS;
if (!device || !device->handle) {
return AZERON_ERROR_INVALID_PARAM;
}
if (!device->claimed) {
return AZERON_SUCCESS;
}
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);
}
}
device->claimed = false;
pthread_mutex_unlock(&device->mutex);
AZERON_LOG("Device interfaces released");
return overall_ret;
}
/* Read data from endpoint */
int azeron_device_read(struct azeron_device *device, uint8_t endpoint, uint8_t *data, size_t size, int timeout)
{
int transferred;
int ret;
if (!device || !device->handle || !data) {
return AZERON_ERROR_INVALID_PARAM;
}
if (!device->claimed) {
ret = azeron_device_claim(device);
if (ret != AZERON_SUCCESS) {
return ret;
}
}
pthread_mutex_lock(&device->mutex);
ret = libusb_interrupt_transfer(device->handle, endpoint, data, size, &transferred, timeout);
pthread_mutex_unlock(&device->mutex);
if (ret < 0) {
AZERON_ERROR("Failed to read from endpoint 0x%02x: %s", endpoint, azeron_usb_error_string(ret));
return azeron_libusb_to_azeron_error(ret);
}
AZERON_LOG("Read %d bytes from endpoint 0x%02x", transferred, endpoint);
return transferred;
}
/* Write data to endpoint */
int azeron_device_write(struct azeron_device *device, uint8_t endpoint, const uint8_t *data, size_t size, int timeout)
{
int transferred;
int ret;
if (!device || !device->handle || !data) {
return AZERON_ERROR_INVALID_PARAM;
}
if (!device->claimed) {
ret = azeron_device_claim(device);
if (ret != AZERON_SUCCESS) {
return ret;
}
}
pthread_mutex_lock(&device->mutex);
ret = libusb_interrupt_transfer(device->handle, endpoint, (uint8_t *)data, size, &transferred, timeout);
pthread_mutex_unlock(&device->mutex);
if (ret < 0) {
AZERON_ERROR("Failed to write to endpoint 0x%02x: %s", endpoint, azeron_usb_error_string(ret));
return azeron_libusb_to_azeron_error(ret);
}
AZERON_LOG("Wrote %d bytes to endpoint 0x%02x", transferred, endpoint);
return transferred;
}
/* Perform control transfer */
int azeron_device_control_transfer(struct azeron_device *device, uint8_t request_type, uint8_t request,
uint16_t value, uint16_t index, uint8_t *data, size_t size, int timeout)
{
int ret;
if (!device || !device->handle) {
return AZERON_ERROR_INVALID_PARAM;
}
if (!device->claimed) {
ret = azeron_device_claim(device);
if (ret != AZERON_SUCCESS) {
return ret;
}
}
pthread_mutex_lock(&device->mutex);
ret = libusb_control_transfer(device->handle, request_type, request, value, index, data, size, timeout);
pthread_mutex_unlock(&device->mutex);
if (ret < 0) {
AZERON_ERROR("Control transfer failed: %s", azeron_usb_error_string(ret));
return azeron_libusb_to_azeron_error(ret);
}
AZERON_LOG("Control transfer: %d bytes transferred", ret);
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";
}
}