Gamepad (Linux): detect battery capacity

This commit is contained in:
李通洲
2024-01-06 20:40:20 +08:00
parent 2ba878cbab
commit 5b4a26393d
6 changed files with 61 additions and 15 deletions
+1
View File
@@ -6,6 +6,7 @@ typedef struct FFGamepadDevice
{
FFstrbuf identifier;
FFstrbuf name;
uint8_t battery; // 0-100%
} FFGamepadDevice;
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */);
+1
View File
@@ -13,6 +13,7 @@ static void enumSet(const void* value, void *context)
ffCfStrGetString(serialNumber, &device->identifier);
ffStrbufInit(&device->name);
ffCfStrGetString(product, &device->name);
device->battery = 0;
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
+1
View File
@@ -44,6 +44,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, di.udi_serial);
ffStrbufInitF(&device->name, "%s %s", di.udi_vendor, di.udi_product);
device->battery = 0;
}
}
}
+46 -13
View File
@@ -5,39 +5,72 @@
#include <dirent.h>
#include <ctype.h>
static void detectGamepad(FFlist* devices, FFstrbuf* name, FFstrbuf* path)
{
uint32_t baseLen = path->length;
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInit(&device->identifier);
ffStrbufInitMove(&device->name, name);
device->battery = 0;
ffStrbufAppendS(path, "uniq");
if (ffAppendFileBuffer(path->chars, &device->identifier))
ffStrbufTrimRightSpace(&device->identifier);
ffStrbufSubstrBefore(path, baseLen);
ffStrbufAppendS(path, "device/power_supply/"); // /sys/class/input/jsX/device/device/power_supply
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path->chars);
if (dirp)
{
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.' || (entry->d_type != DT_DIR && entry->d_type != DT_UNKNOWN))
continue;
ffStrbufAppendS(path, entry->d_name);
ffStrbufAppendS(path, "/capacity"); // /sys/class/input/jsX/device/device/power_supply/XXX/capacity
char capacity[32];
ssize_t nRead = ffReadFileData(path->chars, sizeof(capacity) - 1, capacity);
if (nRead > 0)
{
capacity[nRead] = '\0';
device->battery = (uint8_t) strtoul(capacity, NULL, 10);
}
}
}
}
const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
{
DIR* dirp = opendir("/sys/class/input/");
if(dirp == NULL)
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/input/");
if (dirp == NULL)
return "opendir(\"/sys/class/input/\") == NULL";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/class/input/");
uint32_t baseLen = path.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
while ((entry = readdir(dirp)) != NULL)
{
if(!ffStrStartsWith(entry->d_name, "js"))
if (!ffStrStartsWith(entry->d_name, "js"))
continue;
if(!isdigit(entry->d_name[2]))
if (!isdigit(entry->d_name[2]))
continue;
ffStrbufAppendS(&path, entry->d_name);
ffStrbufAppendS(&path, "/device/name");
if (ffPathExists(path.chars, FF_PATHTYPE_FILE))
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
if (ffAppendFileBuffer(path.chars, &name))
{
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitS(&device->identifier, entry->d_name);
ffStrbufInit(&device->name);
if (ffAppendFileBuffer(path.chars, &device->name))
ffStrbufTrimRightSpace(&device->name);
ffStrbufTrimRightSpace(&name);
ffStrbufSubstrBefore(&path, path.length - 4);
detectGamepad(devices, &name, &path);
}
ffStrbufSubstrBefore(&path, baseLen);
}
closedir(dirp);
return NULL;
}
+1
View File
@@ -119,6 +119,7 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */)
FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices);
ffStrbufInitWS(&device->identifier, devName);
ffStrbufInit(&device->name);
device->battery = 0;
const char* knownGamepad = detectKnownGamepad(rdi.hid.dwVendorId, rdi.hid.dwProductId);
if (knownGamepad)
+11 -2
View File
@@ -1,3 +1,4 @@
#include "common/bar.h"
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/gamepad/gamepad.h"
@@ -10,14 +11,21 @@ static void printDevice(FFGamepadOptions* options, const FFGamepadDevice* device
{
if(options->moduleArgs.outputFormat.length == 0)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreateCopy(&device->name);
ffPrintLogoAndKey(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
ffStrbufPutTo(&device->name, stdout);
if (device->battery > 0 && device->battery <= 100)
{
ffStrbufAppendC(&buffer, ' ');
ffAppendPercentNum(&buffer, device->battery, 51, 21, true);
}
ffStrbufPutTo(&buffer, stdout);
}
else
{
ffPrintFormat(FF_GAMEPAD_MODULE_NAME, index, &options->moduleArgs, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) {
{FF_FORMAT_ARG_TYPE_STRBUF, &device->name},
{FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier},
{FF_FORMAT_ARG_TYPE_UINT8, &device->battery},
});
}
}
@@ -121,7 +129,8 @@ void ffPrintGamepadHelpFormat(void)
{
ffPrintModuleFormatHelp(FF_GAMEPAD_MODULE_NAME, "{1}", FF_GAMEPAD_NUM_FORMAT_ARGS, (const char* []) {
"Name",
"Identifier"
"Identifier",
"Battery",
});
}