Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions Controllers/NuPhyKeyboardController/NuPhyKeyboardController.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*---------------------------------------------------------*\
| NuPhyKeyboardController.cpp |
| |
| Driver for NuPhy QMK/VIA RGB Matrix keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/

#include <cstring>
#include "NuPhyKeyboardController.h"
#include "StringUtils.h"

#define NUPHY_VIA_MESSAGE_LENGTH 32
#define NUPHY_VIA_GET_PROTOCOL_VERSION 0x01
#define NUPHY_VIA_CUSTOM_SET_VALUE 0x07
#define NUPHY_VIA_CUSTOM_GET_VALUE 0x08
#define NUPHY_VIA_CUSTOM_SAVE 0x09
#define NUPHY_VIA_RGB_MATRIX_CHANNEL 0x03
#define NUPHY_VIA_RGB_MATRIX_BRIGHTNESS 0x01
#define NUPHY_VIA_RGB_MATRIX_EFFECT 0x02
#define NUPHY_VIA_RGB_MATRIX_SPEED 0x03
#define NUPHY_VIA_RGB_MATRIX_COLOR 0x04

NuPhyKeyboardController::NuPhyKeyboardController(hid_device* dev_handle, const char* path, const std::string& device_name)
{
dev = dev_handle;
location = path;
name = device_name;
supported = false;
via_protocol_version = 0;

wchar_t serial_string[256];
if(hid_get_serial_number_string(dev, serial_string, 256) == 0)
{
serial = StringUtils::wstring_to_string(serial_string);
}

unsigned char version[2] = { 0, 0 };
if(SendCommand(NUPHY_VIA_GET_PROTOCOL_VERSION, 0, 0, version, sizeof(version)))
{
via_protocol_version = (version[0] << 8) | version[1];
}

unsigned char brightness = 0;
supported = (via_protocol_version >= 9)
&& SendCommand(NUPHY_VIA_CUSTOM_GET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_BRIGHTNESS, &brightness, sizeof(brightness));
}

NuPhyKeyboardController::~NuPhyKeyboardController()
{
hid_close(dev);
}

std::string NuPhyKeyboardController::GetLocation()
{
return("HID: " + location);
}

std::string NuPhyKeyboardController::GetName()
{
return(name);
}

std::string NuPhyKeyboardController::GetSerial()
{
return(serial);
}

std::string NuPhyKeyboardController::GetVersion()
{
return("VIA: " + std::to_string(via_protocol_version));
}

bool NuPhyKeyboardController::GetSupported()
{
return(supported);
}

unsigned char NuPhyKeyboardController::GetBrightness()
{
unsigned char value = 0;
SendCommand(NUPHY_VIA_CUSTOM_GET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_BRIGHTNESS, &value, sizeof(value));
return(value);
}

unsigned char NuPhyKeyboardController::GetEffect()
{
unsigned char value = 0;
SendCommand(NUPHY_VIA_CUSTOM_GET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_EFFECT, &value, sizeof(value));
return(value);
}

unsigned char NuPhyKeyboardController::GetSpeed()
{
unsigned char value = 0;
SendCommand(NUPHY_VIA_CUSTOM_GET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_SPEED, &value, sizeof(value));
return(value);
}

void NuPhyKeyboardController::GetColor(unsigned char* hue, unsigned char* saturation)
{
unsigned char value[2] = { 0, 0 };
SendCommand(NUPHY_VIA_CUSTOM_GET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_COLOR, value, sizeof(value));
*hue = value[0];
*saturation = value[1];
}

void NuPhyKeyboardController::SetBrightness(unsigned char brightness)
{
SendCommand(NUPHY_VIA_CUSTOM_SET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_BRIGHTNESS, &brightness, sizeof(brightness));
}

void NuPhyKeyboardController::SetEffect(unsigned char effect)
{
SendCommand(NUPHY_VIA_CUSTOM_SET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_EFFECT, &effect, sizeof(effect));
}

void NuPhyKeyboardController::SetSpeed(unsigned char speed)
{
SendCommand(NUPHY_VIA_CUSTOM_SET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_SPEED, &speed, sizeof(speed));
}

void NuPhyKeyboardController::SetColor(unsigned char hue, unsigned char saturation)
{
unsigned char value[2] = { hue, saturation };
SendCommand(NUPHY_VIA_CUSTOM_SET_VALUE, NUPHY_VIA_RGB_MATRIX_CHANNEL, NUPHY_VIA_RGB_MATRIX_COLOR, value, sizeof(value));
}

void NuPhyKeyboardController::Save()
{
SendCommand(NUPHY_VIA_CUSTOM_SAVE, NUPHY_VIA_RGB_MATRIX_CHANNEL, 0, nullptr, 0);
}

bool NuPhyKeyboardController::SendCommand(unsigned char command, unsigned char channel, unsigned char value_id, unsigned char* value, unsigned char value_size)
{
unsigned char usb_buf[NUPHY_VIA_MESSAGE_LENGTH + 1];
memset(usb_buf, 0, sizeof(usb_buf));

usb_buf[1] = command;
usb_buf[2] = channel;
usb_buf[3] = value_id;

if(value_size > 0)
{
memcpy(&usb_buf[4], value, value_size);
}

if(hid_write(dev, usb_buf, sizeof(usb_buf)) < 0)
{
return(false);
}

int bytes_received = hid_read_timeout(dev, usb_buf, NUPHY_VIA_MESSAGE_LENGTH, 1000);
if(bytes_received != NUPHY_VIA_MESSAGE_LENGTH || usb_buf[0] != command)
{
return(false);
}

if(value_size > 0)
{
unsigned char response_offset = (command == NUPHY_VIA_GET_PROTOCOL_VERSION) ? 1 : 3;
memcpy(value, &usb_buf[response_offset], value_size);
}

return(true);
}
47 changes: 47 additions & 0 deletions Controllers/NuPhyKeyboardController/NuPhyKeyboardController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*---------------------------------------------------------*\
| NuPhyKeyboardController.h |
| |
| Driver for NuPhy QMK/VIA RGB Matrix keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/

#pragma once

#include <hidapi.h>
#include <string>

class NuPhyKeyboardController
{
public:
NuPhyKeyboardController(hid_device* dev_handle, const char* path, const std::string& device_name);
~NuPhyKeyboardController();

std::string GetLocation();
std::string GetName();
std::string GetSerial();
std::string GetVersion();
bool GetSupported();

unsigned char GetBrightness();
unsigned char GetEffect();
unsigned char GetSpeed();
void GetColor(unsigned char* hue, unsigned char* saturation);

void SetBrightness(unsigned char brightness);
void SetEffect(unsigned char effect);
void SetSpeed(unsigned char speed);
void SetColor(unsigned char hue, unsigned char saturation);
void Save();

private:
hid_device* dev;
std::string location;
std::string name;
std::string serial;
bool supported;
unsigned short via_protocol_version;

bool SendCommand(unsigned char command, unsigned char channel, unsigned char value_id, unsigned char* value, unsigned char value_size);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*---------------------------------------------------------*\
| NuPhyKeyboardControllerDetect.cpp |
| |
| Detector for NuPhy QMK/VIA RGB Matrix keyboards |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/

#include <hidapi.h>
#include "Detector.h"
#include "NuPhyKeyboardController.h"
#include "RGBController_NuPhyKeyboard.h"

#define NUPHY_VID 0x19F5
#define NUPHY_AIR75_V2_PID 0x3246
#define NUPHY_AIR60_V2_PID 0x3255
#define NUPHY_AIR96_V2_PID 0x3266
#define QMK_VIA_USAGE_PAGE 0xFF60
#define QMK_VIA_USAGE 0x0061

void DetectNuPhyKeyboardControllers(hid_device_info* info, const std::string& name)
{
hid_device* dev = hid_open_path(info->path);

if(dev)
{
NuPhyKeyboardController* controller = new NuPhyKeyboardController(dev, info->path, name);

if(controller->GetSupported())
{
RGBController_NuPhyKeyboard* rgb_controller = new RGBController_NuPhyKeyboard(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
else
{
delete controller;
}
}
}

REGISTER_HID_DETECTOR_PU("NuPhy Air60 V2", DetectNuPhyKeyboardControllers, NUPHY_VID, NUPHY_AIR60_V2_PID, QMK_VIA_USAGE_PAGE, QMK_VIA_USAGE);
REGISTER_HID_DETECTOR_PU("NuPhy Air75 V2", DetectNuPhyKeyboardControllers, NUPHY_VID, NUPHY_AIR75_V2_PID, QMK_VIA_USAGE_PAGE, QMK_VIA_USAGE);
REGISTER_HID_DETECTOR_PU("NuPhy Air96 V2", DetectNuPhyKeyboardControllers, NUPHY_VID, NUPHY_AIR96_V2_PID, QMK_VIA_USAGE_PAGE, QMK_VIA_USAGE);
Loading