diff --git a/src/daemon/command.c b/src/daemon/command.c
index 69a05dc0..8e279a0c 100644
--- a/src/daemon/command.c
+++ b/src/daemon/command.c
@@ -256,7 +256,7 @@ int readcmd(usbdevice* kb, const char* line){
continue;
case POLLRATE: {
uint rate;
- if(sscanf(word, "%u", &rate) == 1 && (rate == 1 || rate == 2 || rate == 4 || rate == 8))
+ if(HAS_FEATURES(kb, FEAT_ADJRATE) && sscanf(word, "%u", &rate) == 1 && (rate == 1 || rate == 2 || rate == 4 || rate == 8))
TRY_WITH_RESET(vt->pollrate(kb, mode, notifynumber, rate, 0));
continue;
}
diff --git a/src/daemon/device_mouse.c b/src/daemon/device_mouse.c
index 36f6f541..e76fac4e 100644
--- a/src/daemon/device_mouse.c
+++ b/src/daemon/device_mouse.c
@@ -33,9 +33,6 @@ int cmd_pollrate_legacy(usbdevice* kb, usbmode* dummy1, int dummy2, int rate, co
(void)dummy2;
(void)dummy3;
- if(rate > 1 && (rate % 2 || rate > 8))
- return 0;
-
usbsend_control(kb, NULL, 0, 10, rate, 0);
// Device should disconnect+reconnect, but update the poll rate field in case it doesn't
diff --git a/src/daemon/device_vtable.c b/src/daemon/device_vtable.c
index bee5d6c9..196f7623 100644
--- a/src/daemon/device_vtable.c
+++ b/src/daemon/device_vtable.c
@@ -53,7 +53,7 @@ const devcmd vtable_keyboard = {
.hwload = cmd_hwload_kb,
.hwsave = cmd_hwsave_kb,
.fwupdate = cmd_fwupdate,
- .pollrate = cmd_io_none,
+ .pollrate = cmd_pollrate,
.active = cmd_active_kb,
.idle = cmd_idle_kb,
diff --git a/src/daemon/usb.c b/src/daemon/usb.c
index 0aded716..11882920 100644
--- a/src/daemon/usb.c
+++ b/src/daemon/usb.c
@@ -331,8 +331,10 @@ static void* _setupusb(void* context){
ushort vendor = kb->vendor, product = kb->product;
const devcmd* vt = kb->vtable = get_vtable(vendor, product);
kb->features = (IS_LEGACY(vendor, product) ? FEAT_STD_LEGACY : FEAT_STD_RGB) & features_mask;
- if(IS_MOUSE(vendor, product)) kb->features |= FEAT_ADJRATE;
- if(IS_MONOCHROME(vendor, product)) kb->features |= FEAT_MONOCHROME;
+ if(SUPPORTS_ADJRATE(kb))
+ kb->features |= FEAT_ADJRATE;
+ if(IS_MONOCHROME(vendor, product))
+ kb->features |= FEAT_MONOCHROME;
kb->usbdelay = USB_DELAY_DEFAULT;
/// Allocate memory for the os_usbrecv() buffer
diff --git a/src/daemon/usb.h b/src/daemon/usb.h
index 9eadbfef..c091abdb 100644
--- a/src/daemon/usb.h
+++ b/src/daemon/usb.h
@@ -195,6 +195,9 @@ const char* product_str(ushort product);
/// Used for devices that use a file-based hardware animation system.
#define USES_FILE_HWSAVE(kb) ((kb)->product == P_K95_PLATINUM || (kb)->product == P_K70_MK2 || (kb)->product == P_K70_MK2SE || (kb)->product == P_STRAFE_MK2 || (kb)->product == P_GLAIVE || (kb)->product == P_SCIMITAR_PRO || (kb)->product == P_K70_MK2LP || (kb)->product == P_M65_RGB_ELITE)
+/// Devices here support setting the pollrate through software
+#define SUPPORTS_ADJRATE(kb) ((kb)->product == P_K63_NRGB || (kb)->product == P_K66 || (kb)->product == P_K68 || (kb)->product == P_K68_NRGB || (kb)->product == P_K70_MK2 || (kb)->product == P_K70_MK2SE || (kb)->product == P_K70_MK2LP || (kb)->product == P_K95_PLATINUM || (kb)->product == P_STRAFE || (kb)->product == P_STRAFE_NRGB || (kb)->product == P_STRAFE_NRGB_2 || (kb)->product == P_STRAFE_MK2 || (kb)->product == P_M65 || (kb)->product == P_M65_PRO || (kb)->product == P_M65_RGB_ELITE || (kb)->product == P_M95 || (kb)->product == P_SABRE_O || (kb)->product == P_SABRE_L || (kb)->product == P_SABRE_N || (kb)->product == P_SABRE_O2 || (kb)->product == P_SCIMITAR || (kb)->product == P_SCIMITAR_PRO || (kb)->product == P_HARPOON || (kb)->product == P_GLAIVE || (kb)->product == P_KATAR)
+
/// USB delays for when the keyboards get picky about timing
/// That was the original comment, but it is used anytime.
diff --git a/src/gui/kb.cpp b/src/gui/kb.cpp
index b708d6b2..ba140b4a 100644
--- a/src/gui/kb.cpp
+++ b/src/gui/kb.cpp
@@ -17,7 +17,7 @@ int Kb::_frameRate = 30, Kb::_scrollSpeed = 0;
bool Kb::_dither = false, Kb::_mouseAccel = true, Kb::_delay = false;
Kb::Kb(QObject *parent, const QString& path) :
- QThread(parent), features("N/A"), firmware("N/A"), pollrate("N/A"), monochrome(false), hwload(false),
+ QThread(parent), features("N/A"), firmware("N/A"), pollrate("N/A"), monochrome(false), hwload(false), adjrate(false),
devpath(path), cmdpath(path + "/cmd"), notifyPath(path + "/notify1"), macroPath(path + "/notify2"),
_currentProfile(0), _currentMode(0), _model(KeyMap::NO_MODEL),
lastAutoSave(QDateTime::currentMSecsSinceEpoch()),
@@ -80,6 +80,8 @@ Kb::Kb(QObject *parent, const QString& path) :
pollrate = ppath.read(100);
pollrate = pollrate.trimmed();
ppath.close();
+ if(features.contains("adjrate"))
+ adjrate = true;
}
if(hwlayoutPath.open(QIODevice::ReadOnly)){
@@ -834,3 +836,8 @@ void Kb::macroDelay(bool flag) {
KeyMap::Layout Kb::getCurrentLayout(){
return _layout;
}
+
+void Kb::setPollRate(QString poll)
+{
+ cmd.write(QString("\npollrate %1\n").arg(poll).toLatin1());
+}
diff --git a/src/gui/kb.h b/src/gui/kb.h
index b37aed0b..38bdee8d 100644
--- a/src/gui/kb.h
+++ b/src/gui/kb.h
@@ -19,6 +19,7 @@ public:
bool monochrome;
ushort productID;
bool hwload;
+ bool adjrate;
// Keyboard model
inline KeyMap::Model model() const { return _model; }
@@ -115,6 +116,7 @@ public:
inline QString getMacroPath () { return macroPath; }
inline ushort getMaxDpi () {return _maxDpi; }
+ void setPollRate(QString poll);
~Kb();
diff --git a/src/gui/kbwidget.cpp b/src/gui/kbwidget.cpp
index 0bcd90bb..d55681be 100644
--- a/src/gui/kbwidget.cpp
+++ b/src/gui/kbwidget.cpp
@@ -57,7 +57,7 @@ KbWidget::KbWidget(QWidget *parent, Kb *_device) :
// Hide poll rate and FW update as appropriate
if(!device->features.contains("pollrate")){
- ui->pollLabel->hide();
+ ui->pollRateBox->hide();
ui->pollLabel2->hide();
}
if(!device->features.contains("fwupdate")){
@@ -135,6 +135,11 @@ KbWidget::KbWidget(QWidget *parent, Kb *_device) :
// Set max DPI for mice
if(device->isMouse())
ui->mPerfWidget->setMaxDpi(device->getMaxDpi());
+
+ if(!device->adjrate){
+ ui->pollRateBox->setEnabled(false);
+ ui->pollRateBox->setToolTip(tr("This device does not support setting the poll rate through software."));
+ }
}
KbWidget::~KbWidget(){
@@ -379,12 +384,29 @@ void KbWidget::on_modesList_customContextMenuRequested(const QPoint &pos){
}
}
+inline int KbWidget::getPollRateBoxIdx(QString poll){
+ switch(poll.leftRef(1).toInt()){
+ case 1:
+ return 0;
+ case 2:
+ return 1;
+ case 4:
+ return 2;
+ default: // Includes case 8
+ return 3;
+ }
+}
+
void KbWidget::devUpdate(){
// Update device tab
ui->devLabel->setText(device->usbModel);
ui->serialLabel->setText(device->usbSerial);
ui->fwLabel->setText(device->firmware);
- ui->pollLabel->setText(device->pollrate);
+ // This is needed so that the currentIndexChanged event doesn't fire
+ // If it does, we'll end up with an always greyed out box when pollrate != 1
+ bool block = ui->pollRateBox->blockSignals(true);
+ ui->pollRateBox->setCurrentIndex(getPollRateBoxIdx(device->pollrate));
+ ui->pollRateBox->blockSignals(block);
}
void KbWidget::modeUpdate(){
@@ -510,3 +532,9 @@ void KbWidget::switchToMode(QString mode){
return;
}
}
+
+void KbWidget::on_pollRateBox_currentIndexChanged(const QString &arg1)
+{
+ ui->pollRateBox->setEnabled(false);
+ device->setPollRate(arg1.left(1));
+}
diff --git a/src/gui/kbwidget.h b/src/gui/kbwidget.h
index 40fa2cb8..14f7b0c6 100644
--- a/src/gui/kbwidget.h
+++ b/src/gui/kbwidget.h
@@ -45,6 +45,7 @@ private:
const static int GUID = Qt::UserRole;
const static int NEW_FLAG = Qt::UserRole + 1;
+ int getPollRateBoxIdx(QString poll);
private slots:
void updateProfileList();
@@ -69,6 +70,7 @@ private slots:
void on_layoutBox_activated(int index);
void switchToProfile(QString profile);
void switchToMode(QString mode);
+ void on_pollRateBox_currentIndexChanged(const QString &arg1);
};
#endif // KBWIDGET_H
diff --git a/src/gui/kbwidget.ui b/src/gui/kbwidget.ui
index 84426fe1..455ecf02 100644
--- a/src/gui/kbwidget.ui
+++ b/src/gui/kbwidget.ui
@@ -194,47 +194,8 @@
6
- -
-
-
-
- 0
- 34
-
-
-
- Poll rate:
-
-
-
- -
-
-
-
- 0
- 34
-
-
-
- Firmware version:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Qt::Horizontal
-
-
-
- -
-
+
-
+
IBeamCursor
@@ -262,35 +223,17 @@
- -
-
-
-
-
-
- Check for updates
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
+
-
+
+
+ IBeamCursor
+
N/A
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
-
@@ -306,19 +249,6 @@
- -
-
-
-
- 0
- 34
-
-
-
- Status:
-
-
-
-
@@ -332,16 +262,23 @@
- -
-
-
- IBeamCursor
-
+
-
+
- N/A
+ Layout:
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
@@ -414,13 +351,119 @@
- -
-
+
-
+
+
+
+ 0
+ 34
+
+
- Layout:
+ Status:
+ -
+
+
+
+ 0
+ 34
+
+
+
+ Firmware version:
+
+
+
+ -
+
+
-
+
+
+ Check for updates
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 34
+
+
+
+ Poll rate:
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Qt::StrongFocus
+
+
-
+
+ 1 ms
+
+
+ -
+
+ 2 ms
+
+
+ -
+
+ 4 ms
+
+
+ -
+
+ 8 ms
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
@@ -469,11 +512,6 @@
-
- RListWidget
- QListWidget
-
-
KbLightWidget
QWidget
@@ -498,6 +536,16 @@
1
+
+ RListWidget
+ QListWidget
+
+
+
+ NoWheelComboBox
+ QComboBox
+
+