mirror of
https://github.com/ckb-next/ckb-next.git
synced 2026-10-10 12:27:21 -04:00
Add support for bragi battery reading
Also clean up the GUI battery code.
This commit is contained in:
@@ -145,6 +145,8 @@ typedef union devcmd {
|
||||
|
||||
device_io write;
|
||||
device_io read;
|
||||
|
||||
void (*get_battery_info)(usbdevice* kb);
|
||||
};
|
||||
} devcmd;
|
||||
|
||||
|
||||
@@ -274,3 +274,26 @@ void clear_input_and_rgb(usbdevice* kb, const int active){
|
||||
inputupdate(kb);
|
||||
queued_mutex_unlock(imutex(kb));
|
||||
}
|
||||
|
||||
static const ushort nxp_battery_lut[5] = {
|
||||
0,
|
||||
15,
|
||||
30,
|
||||
50,
|
||||
100,
|
||||
};
|
||||
|
||||
void nxp_get_battery_info(usbdevice* kb){
|
||||
uchar msg[MSG_SIZE] = { CMD_GET, FIELD_BATTERY };
|
||||
uchar in[MSG_SIZE] = { 0 };
|
||||
if(!usbrecv(kb, msg, sizeof(msg), in)){
|
||||
ckb_err("ckb%d: Failed to get battery info. Returning last known state.", INDEX_OF(kb, keyboard));
|
||||
return;
|
||||
}
|
||||
if(in[4] > (sizeof(nxp_battery_lut)/sizeof(*nxp_battery_lut)) - 1){
|
||||
ckb_err("ckb%d: Invalid battery level received 0x%hhx.", INDEX_OF(kb, keyboard), in[4]);
|
||||
return;
|
||||
}
|
||||
kb->battery_level = nxp_battery_lut[in[4]];
|
||||
kb->battery_status = in[5];
|
||||
}
|
||||
|
||||
+3
-3
@@ -99,9 +99,6 @@ int cmd_pollrate(usbdevice* kb, usbmode* dummy1, int dummy2, int rate, const cha
|
||||
int cmd_pollrate_legacy(usbdevice* kb, usbmode* dummy1, int dummy2, int rate, const char* dummy3);
|
||||
int cmd_pollrate_bragi(usbdevice* kb, usbmode* dummy1, int dummy2, int rate, const char* dummy3);
|
||||
|
||||
// Reads the battery of a wireless device
|
||||
void* read_battery(void* context);
|
||||
|
||||
// Sets a device's current mode index. This is only used on the legacy K95; the RGB keyboards have no gettable HW index.
|
||||
void setmodeindex_legacy(usbdevice* kb, int index);
|
||||
|
||||
@@ -111,6 +108,9 @@ void nxp_reset(usbdevice* kb, usbmode* mode, int dummy1, int dummy2, const char*
|
||||
// Used to clear the input struct and force an rgb update when switching between hw and sw modes
|
||||
void clear_input_and_rgb(usbdevice* kb, const int active);
|
||||
|
||||
void nxp_get_battery_info(usbdevice* kb);
|
||||
void bragi_get_battery_info(usbdevice* kb);
|
||||
|
||||
// Per-key input settings for device setup
|
||||
// The upper nybble controls input mode. 0x80 generates a normal HID interrupt, 0x40 generates a proprietary interrupt. 0xc0 generates both.
|
||||
// The exceptions are the proprietary Corsair keys, which only report HID input in BIOS mode and only report Corsair input in non-BIOS mode.
|
||||
|
||||
@@ -264,3 +264,14 @@ int cmd_idle_bragi(usbdevice* kb, usbmode* dummy1, int dummy2, int dummy3, const
|
||||
|
||||
return setactive_bragi(kb, BRAGI_MODE_HARDWARE);
|
||||
}
|
||||
|
||||
void bragi_get_battery_info(usbdevice* kb){
|
||||
long int stat = bragi_get_property(kb, BRAGI_BATTERY_STATUS);
|
||||
long int chg = bragi_get_property(kb, BRAGI_BATTERY_LEVEL);
|
||||
if(stat < 0 || chg < 0){
|
||||
ckb_err("ckb%d: Failed to get bragi battery properties", INDEX_OF(kb, keyboard));
|
||||
return;
|
||||
}
|
||||
kb->battery_level = chg / 10;
|
||||
kb->battery_status = stat;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ static int int1_int_none(usbdevice* kb, int dummy){
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void int0_void_none(usbdevice* kb){
|
||||
(void)kb;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int cmd_io_stub(usbdevice* kb, void* ptr, int len, int is_recv, const char* file, int line){
|
||||
@@ -107,6 +110,7 @@ const devcmd vtable_keyboard = {
|
||||
.fill_input_eps = nxp_fill_input_eps,
|
||||
.write = nxp_usb_write,
|
||||
.read = nxp_usb_read,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
const devcmd vtable_keyboard_wireless = {
|
||||
@@ -157,6 +161,7 @@ const devcmd vtable_keyboard_wireless = {
|
||||
.fill_input_eps = nxp_fill_input_eps,
|
||||
.write = nxp_usb_write,
|
||||
.read = nxp_usb_read,
|
||||
.get_battery_info = nxp_get_battery_info,
|
||||
};
|
||||
|
||||
// Legacy keyboard vtable (K70)
|
||||
@@ -208,6 +213,7 @@ const devcmd vtable_keyboard_legacy = {
|
||||
.fill_input_eps = legacy_fill_input_eps,
|
||||
.write = legacy_dev_io,
|
||||
.read = legacy_dev_io,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
// RGB mouse vtable
|
||||
@@ -259,6 +265,7 @@ const devcmd vtable_mouse = {
|
||||
.fill_input_eps = nxp_fill_input_eps,
|
||||
.write = nxp_usb_write,
|
||||
.read = nxp_usb_read,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
const devcmd vtable_mouse_wireless = {
|
||||
@@ -309,6 +316,7 @@ const devcmd vtable_mouse_wireless = {
|
||||
.fill_input_eps = nxp_fill_input_eps,
|
||||
.write = nxp_usb_write,
|
||||
.read = nxp_usb_read,
|
||||
.get_battery_info = nxp_get_battery_info,
|
||||
};
|
||||
|
||||
// RGB Mousepad vtable
|
||||
@@ -360,6 +368,7 @@ const devcmd vtable_mousepad = {
|
||||
.fill_input_eps = nxp_fill_input_eps,
|
||||
.write = nxp_usb_write,
|
||||
.read = nxp_usb_read,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
// Legacy mouse vtable
|
||||
@@ -411,6 +420,7 @@ const devcmd vtable_mouse_legacy = {
|
||||
.fill_input_eps = legacy_fill_input_eps,
|
||||
.write = legacy_dev_io,
|
||||
.read = legacy_dev_io,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
// Bragi vtables
|
||||
@@ -461,6 +471,7 @@ const devcmd vtable_bragi_mouse = {
|
||||
.fill_input_eps = bragi_fill_input_eps,
|
||||
.write = bragi_usb_write,
|
||||
.read = bragi_usb_read,
|
||||
.get_battery_info = bragi_get_battery_info,
|
||||
};
|
||||
|
||||
const devcmd vtable_bragi_keyboard = {
|
||||
@@ -510,6 +521,7 @@ const devcmd vtable_bragi_keyboard = {
|
||||
.fill_input_eps = bragi_fill_input_eps,
|
||||
.write = bragi_usb_write,
|
||||
.read = bragi_usb_read,
|
||||
.get_battery_info = bragi_get_battery_info,
|
||||
};
|
||||
|
||||
const devcmd vtable_bragi_dongle = {
|
||||
@@ -559,4 +571,5 @@ const devcmd vtable_bragi_dongle = {
|
||||
.fill_input_eps = bragi_fill_input_eps,
|
||||
.write = bragi_usb_write,
|
||||
.read = bragi_usb_read,
|
||||
.get_battery_info = int0_void_none,
|
||||
};
|
||||
|
||||
+11
-17
@@ -4,6 +4,7 @@
|
||||
#include "led.h"
|
||||
#include "notify.h"
|
||||
#include "profile.h"
|
||||
#include "command.h"
|
||||
|
||||
void nprintf(usbdevice* kb, int nodenumber, usbmode* mode, const char* format, ...){
|
||||
if(!kb)
|
||||
@@ -15,10 +16,10 @@ void nprintf(usbdevice* kb, int nodenumber, usbmode* mode, const char* format, .
|
||||
// If node number was given, print to that node (if open)
|
||||
if((fifo = kb->outfifo[nodenumber] - 1) != -1){
|
||||
va_start(va_args, format);
|
||||
if(mode)
|
||||
dprintf(fifo, "mode %d ", INDEX_OF(mode, profile->mode) + 1);
|
||||
vdprintf(fifo, format, va_args);
|
||||
va_end(va_args);
|
||||
if(mode)
|
||||
dprintf(fifo, "mode %d ", INDEX_OF(mode, profile->mode) + 1);
|
||||
vdprintf(fifo, format, va_args);
|
||||
va_end(va_args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -26,10 +27,10 @@ void nprintf(usbdevice* kb, int nodenumber, usbmode* mode, const char* format, .
|
||||
for(int i = 0; i < OUTFIFO_MAX; i++){
|
||||
if((fifo = kb->outfifo[i] - 1) != -1){
|
||||
va_start(va_args, format);
|
||||
if(mode)
|
||||
dprintf(fifo, "mode %d ", INDEX_OF(mode, profile->mode) + 1);
|
||||
vdprintf(fifo, format, va_args);
|
||||
va_end(va_args);
|
||||
if(mode)
|
||||
dprintf(fifo, "mode %d ", INDEX_OF(mode, profile->mode) + 1);
|
||||
vdprintf(fifo, format, va_args);
|
||||
va_end(va_args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,17 +93,10 @@ void cmd_notify(usbdevice* kb, usbmode* mode, int nnumber, int keyindex, const c
|
||||
static void _cmd_get(usbdevice* kb, usbmode* mode, int nnumber, const char* setting){
|
||||
usbprofile* profile = kb->profile;
|
||||
if(!strcmp(setting, ":battery")){
|
||||
if(!IS_WIRELESS_DEV(kb) || kb->protocol != PROTO_NXP)
|
||||
return;
|
||||
uchar msg[MSG_SIZE] = { CMD_GET, FIELD_BATTERY };
|
||||
uchar in[MSG_SIZE] = {};
|
||||
queued_mutex_unlock(imutex(kb));
|
||||
if(!usbrecv(kb, msg, sizeof(msg), in)){
|
||||
queued_mutex_lock(imutex(kb));
|
||||
return;
|
||||
}
|
||||
kb->vtable->get_battery_info(kb);
|
||||
queued_mutex_lock(imutex(kb));
|
||||
nprintf(kb, nnumber, 0, "battery %hhu:%hhu\n", in[4], in[5]);
|
||||
nprintf(kb, nnumber, 0, "battery %hhu:%hhu\n", kb->battery_level, kb->battery_status & 0xFF);
|
||||
} else if(!strcmp(setting, ":mode")){
|
||||
// Get the current mode number
|
||||
nprintf(kb, nnumber, mode, "switch\n");
|
||||
|
||||
@@ -344,6 +344,14 @@ typedef struct usbdevice_ {
|
||||
struct usbdevice_* children[8];
|
||||
// Bragi child device id
|
||||
unsigned char bragi_child_id;
|
||||
// Battery information
|
||||
enum {
|
||||
BATT_STATUS_UNKNOWN,
|
||||
BATT_STATUS_CHARGING,
|
||||
BATT_STATUS_DISCHARGING,
|
||||
BATT_STATUS_CHARGED,
|
||||
} battery_status;
|
||||
unsigned char battery_level;
|
||||
} usbdevice;
|
||||
|
||||
#ifdef OS_LINUX
|
||||
|
||||
@@ -2,19 +2,26 @@
|
||||
#include "batterysystemtrayicon.h"
|
||||
#include "kb.h"
|
||||
|
||||
void BatteryStatusTrayIcon::setBattery(uint battery, uint charging){
|
||||
QString iconName = charging == 2 ? QString("charging") : QString::number(battery);
|
||||
QIcon icon = QIcon(QString(":/img/ckb-next_battery_%1.png")
|
||||
.arg(iconName));
|
||||
QString tooltip = QString("%1:")
|
||||
.arg(name);
|
||||
QString subtooltip = QString("%2, %3")
|
||||
.arg(BATTERY_VALUES[battery])
|
||||
.arg(BATTERY_CHARGING_VALUES[charging]);
|
||||
void BatteryStatusTrayIcon::setBattery(uint battery, BatteryStatus charging){
|
||||
const int chglvl = getBatteryString(battery);
|
||||
const QString chglvlstr = BATTERY_VALUES[chglvl];
|
||||
const QString chgstatstr = BATTERY_STATUS_VALUES[charging];
|
||||
|
||||
setIcon(icon, QString("ckb-next_battery_%1").arg(iconName));
|
||||
setToolTip(icon, tooltip, subtooltip);
|
||||
|
||||
QString iconName = charging == BatteryStatus::BATT_STATUS_CHARGING ? QString("charging") : QString::number(chglvl);
|
||||
QIcon icon = QIcon(QString(":/img/ckb-next_battery_%1.png").arg(iconName));
|
||||
setIcon(icon, QString("ckb-next_battery_%1").arg(iconName));
|
||||
|
||||
const QString tooltip = QString("%1:").arg(name);
|
||||
const QString batlevelstr = batTrayLevel.arg(chglvlstr, QString::number(battery));
|
||||
const QString subtooltip = QString("%1, %2").arg(batlevelstr, chgstatstr);
|
||||
setToolTip(icon, tooltip, subtooltip);
|
||||
|
||||
batLevel->setText(batlevelstr);
|
||||
batStatus->setText(batTrayStatus.arg(chgstatstr));
|
||||
}
|
||||
|
||||
const QString BatteryStatusTrayIcon::BATTERY_VALUES[5] = {tr("Not connected"), tr("Critical"), tr("Low"), tr("Medium"), tr("High")};
|
||||
const QString BatteryStatusTrayIcon::BATTERY_CHARGING_VALUES[3] = {tr("N/A"), tr("Not charging"), tr("Charging")};
|
||||
const QString BatteryStatusTrayIcon::BATTERY_STATUS_VALUES[4] = {tr("N/A"), tr("Discharging"), tr("Charging"), tr("Fully Charged")};
|
||||
const QString BatteryStatusTrayIcon::batTrayLevel = tr("Battery: %1 (%2%)");
|
||||
const QString BatteryStatusTrayIcon::batTrayStatus = tr("Status: %1");
|
||||
|
||||
@@ -1,20 +1,60 @@
|
||||
#ifndef BATTERYSYSTEMTRAYICON_H
|
||||
#define BATTERYSYSTEMTRAYICON_H
|
||||
#include "ckbsystemtrayicon.h"
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
enum BatteryStatus {
|
||||
BATT_STATUS_UNKNOWN,
|
||||
BATT_STATUS_CHARGING,
|
||||
BATT_STATUS_DISCHARGING,
|
||||
BATT_STATUS_CHARGED,
|
||||
BATT_STATUS_INVALID, // Used for safety checks
|
||||
};
|
||||
|
||||
class BatteryStatusTrayIcon : public CkbSystemTrayIcon {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BatteryStatusTrayIcon( QString _name, QObject* parent = 0 )
|
||||
: CkbSystemTrayIcon(QIcon(), "", parent), name(_name) {}
|
||||
: CkbSystemTrayIcon(QIcon(":/img/ckb-next-monochrome.png"), "ckb-next-monochrome", parent), name(_name) {
|
||||
QMenu* menu = new QMenu();
|
||||
QAction* nameAct = new QAction(name);
|
||||
nameAct->setDisabled(true);
|
||||
menu->addAction(nameAct);
|
||||
menu->addSeparator();
|
||||
|
||||
batLevel = new QAction();
|
||||
batLevel->setEnabled(false);
|
||||
|
||||
batStatus = new QAction();
|
||||
batStatus->setEnabled(false);
|
||||
|
||||
menu->addAction(batLevel);
|
||||
menu->addAction(batStatus);
|
||||
setContextMenu(menu);
|
||||
}
|
||||
|
||||
// Battery strings for indexes
|
||||
const static QString BATTERY_VALUES[5];
|
||||
const static QString BATTERY_CHARGING_VALUES[3];
|
||||
const static QString BATTERY_STATUS_VALUES[4];
|
||||
static_assert(sizeof(BATTERY_STATUS_VALUES)/sizeof(*BATTERY_STATUS_VALUES) == BATT_STATUS_INVALID, "BatteryStatus enum is not the same length as BATTERY_STATUS_VALUES");
|
||||
const static QString batTrayLevel;
|
||||
const static QString batTrayStatus;
|
||||
static int getBatteryString(uint bat) {
|
||||
if(bat > 50)
|
||||
return 4;
|
||||
if(bat > 30)
|
||||
return 3;
|
||||
if(bat > 15)
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
public slots:
|
||||
void setBattery(uint battery, uint charging);
|
||||
void setBattery(uint battery, BatteryStatus charging);
|
||||
private:
|
||||
QString name;
|
||||
QAction* batLevel;
|
||||
QAction* batStatus;
|
||||
};
|
||||
#endif
|
||||
|
||||
+7
-6
@@ -19,7 +19,7 @@ bool Kb::_dither = false, Kb::_mouseAccel = true;
|
||||
Kb::Kb(QObject *parent, const QString& path) :
|
||||
QThread(parent), features(QStringList()), firmware("N/A"), pollrate("N/A"), monochrome(false), hwload(false), adjrate(false),
|
||||
batteryTimer(0), batteryIcon(0), showBatteryIndicator(false), devpath(path), cmdpath(path + "/cmd"), notifyPath(path + "/notify1"), macroPath(path + "/notify2"),
|
||||
_currentProfile(0), _currentMode(0), _model(KeyMap::NO_MODEL), battery(0), charging(0),
|
||||
_currentProfile(0), _currentMode(0), _model(KeyMap::NO_MODEL), batteryLevel(0), batteryStatus(BatteryStatus::BATT_STATUS_UNKNOWN),
|
||||
lastAutoSave(QDateTime::currentMSecsSinceEpoch()),
|
||||
_hwProfile(0), prevProfile(0), prevMode(0),
|
||||
cmd(cmdpath), notifyNumber(1), macroNumber(2), _needsSave(false), _layout(KeyMap::NO_LAYOUT), _maxDpi(0),
|
||||
@@ -551,11 +551,12 @@ void Kb::readNotify(const QString& line){
|
||||
return;
|
||||
// Convert battery values into human readable text
|
||||
bool ok, ok2;
|
||||
uint newBattery = bComponents[0].toUInt(&ok), newCharging = bComponents[1].toUInt(&ok2);
|
||||
if(!ok || !ok2 || newBattery > 4 || newCharging > 4 || (battery == newBattery && charging == newCharging)) return;
|
||||
battery = newBattery;
|
||||
charging = newCharging;
|
||||
emit batteryChanged(newBattery, newCharging);
|
||||
uint newBatteryLevel = bComponents[0].toUInt(&ok), newBatteryStatus = bComponents[1].toUInt(&ok2);
|
||||
if(!ok || !ok2 || newBatteryStatus >= BatteryStatus::BATT_STATUS_INVALID || (batteryLevel == newBatteryLevel && batteryStatus == newBatteryStatus))
|
||||
return;
|
||||
batteryLevel = newBatteryLevel;
|
||||
batteryStatus = static_cast<BatteryStatus>(newBatteryStatus);
|
||||
emit batteryChanged(batteryLevel, batteryStatus);
|
||||
} else if(components[0] == "i"){
|
||||
// Indicator event
|
||||
QString i = components[1];
|
||||
|
||||
+3
-2
@@ -138,7 +138,7 @@ signals:
|
||||
// Profile/mode updates
|
||||
void profileAdded();
|
||||
void profileRenamed();
|
||||
void batteryChanged(uint battery, uint charging);
|
||||
void batteryChanged(uint batteryLevel, BatteryStatus batteryStatus);
|
||||
|
||||
void profileChanged();
|
||||
void profileAboutToChange();
|
||||
@@ -196,7 +196,8 @@ private:
|
||||
|
||||
KeyMap::Model _model;
|
||||
|
||||
uint battery, charging;
|
||||
uint batteryLevel;
|
||||
BatteryStatus batteryStatus;
|
||||
|
||||
// Indicator light state
|
||||
bool iState[KbPerf::HW_I_COUNT];
|
||||
|
||||
@@ -357,10 +357,11 @@ void KbWidget::devUpdate(){
|
||||
ui->batteryTrayBox->setChecked(device->showBatteryIndicator);
|
||||
}
|
||||
|
||||
void KbWidget::updateBattery(uint battery, uint charging){
|
||||
QString label = QString("%1, %2")
|
||||
.arg(BatteryStatusTrayIcon::BATTERY_VALUES[battery])
|
||||
.arg(BatteryStatusTrayIcon::BATTERY_CHARGING_VALUES[charging]);
|
||||
void KbWidget::updateBattery(uint battery, BatteryStatus charging){
|
||||
QString label = QString("%1 (%2%), %3")
|
||||
.arg(BatteryStatusTrayIcon::BATTERY_VALUES[BatteryStatusTrayIcon::getBatteryString(battery)],
|
||||
QString::number(battery),
|
||||
BatteryStatusTrayIcon::BATTERY_STATUS_VALUES[charging]);
|
||||
ui->batteryStatusLabel->setText(label);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ private slots:
|
||||
void batteryTrayBox_stateChanged(int state);
|
||||
|
||||
void devUpdate();
|
||||
void updateBattery(uint battery, uint charging);
|
||||
void updateBattery(uint battery, BatteryStatus charging);
|
||||
void on_hwSaveButton_clicked();
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
void on_fwUpdButton_clicked();
|
||||
|
||||
Reference in New Issue
Block a user