Initial HYTE CNVS controller implementation using serial port

This commit is contained in:
Adam Honse
2023-07-19 22:45:18 -05:00
parent 653f025635
commit 6473a22e89
8 changed files with 440 additions and 42 deletions

View File

@@ -0,0 +1,71 @@
/*---------------------------------------------------------*\
| HYTEMousematController.cpp |
| |
| Driver for HYTE CNVS RGB mousemat controller |
| |
| Adam Honse (calcprogrammer1@gmail.com), 7/18/2023 |
\*---------------------------------------------------------*/
#include "HYTEMousematController.h"
HYTEMousematController::HYTEMousematController(char* port)
{
port_name = port;
/*-----------------------------------------------------*\
| Open the port |
| Baud rate doesn't matter for ACM device |
\*-----------------------------------------------------*/
serialport = new serial_port(port_name.c_str(), 2000000);
FirmwareAnimationControl(false);
}
HYTEMousematController::~HYTEMousematController()
{
}
std::string HYTEMousematController::GetLocation()
{
return(port_name);
}
void HYTEMousematController::FirmwareAnimationControl(bool enabled)
{
unsigned char serial_buf[4];
memset(serial_buf, 0, sizeof(serial_buf));
serial_buf[0] = 0xFF;
serial_buf[1] = 0xDC;
serial_buf[2] = 0x05;
serial_buf[3] = enabled;
serialport->serial_write((char *)serial_buf, sizeof(serial_buf));
}
void HYTEMousematController::StreamingCommand(RGBColor* colors)
{
unsigned char serial_buf[157];
memset(serial_buf, 0, sizeof(serial_buf));
serial_buf[0] = 0xFF;
serial_buf[1] = 0xEE;
serial_buf[2] = 0x02;
serial_buf[3] = 0x01;
serial_buf[4] = 0x00;
serial_buf[5] = 0x32;
serial_buf[6] = 0x00;
for(unsigned int color_idx = 0; color_idx < 50; color_idx++)
{
serial_buf[7 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]);
serial_buf[8 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]);
serial_buf[9 + (color_idx * 3)] = RGBGetBValue(colors[color_idx]);
}
serialport->serial_write((char *)serial_buf, sizeof(serial_buf));
serialport->serial_flush_tx();
}

View File

@@ -0,0 +1,29 @@
/*---------------------------------------------------------*\
| HYTEMousematController.h |
| |
| Definitions for HYTE CNVS RGB mousemat controller |
| |
| Adam Honse (calcprogrammer1@gmail.com), 7/18/2023 |
\*---------------------------------------------------------*/
#pragma once
#include "RGBController.h"
#include "serial_port.h"
#include <vector>
class HYTEMousematController
{
public:
HYTEMousematController(char* port);
~HYTEMousematController();
std::string GetLocation();
void FirmwareAnimationControl(bool enabled);
void StreamingCommand(RGBColor* colors);
private:
std::string port_name;
serial_port * serialport = nullptr;
};

View File

@@ -0,0 +1,62 @@
#include "Detector.h"
#include "HYTEMousematController.h"
#include "RGBController.h"
#include "RGBController_HYTEMousemat.h"
#include "find_usb_serial_port.h"
#include <vector>
#define HYTE_VID 0x3402
#define HYTE_CNVS_HW_VER_1_PID 0x0B00
#define HYTE_CNVS_HW_VER_2_PID 0x0B01
struct hyte_mousemat_type
{
unsigned short vid;
unsigned short pid;
const char * name;
};
#define HYTE_MOUSEMAT_NUM_DEVICES 2
static const hyte_mousemat_type hyte_mousemat_devices[] =
{
{ HYTE_VID, HYTE_CNVS_HW_VER_1_PID, "HYTE CNVS" },
{ HYTE_VID, HYTE_CNVS_HW_VER_2_PID, "HYTE CNVS" },
};
/******************************************************************************************\
* *
* DetectHYTEMousematControllers *
* *
* Detect devices supported by the HyteMousemat driver *
* *
\******************************************************************************************/
void DetectHYTEMousematControllers()
{
for(unsigned int device_id = 0; device_id < HYTE_MOUSEMAT_NUM_DEVICES; device_id++)
{
std::vector<std::string *> ports = find_usb_serial_port(hyte_mousemat_devices[device_id].vid, hyte_mousemat_devices[device_id].pid);
for(unsigned int i = 0; i < ports.size(); i++)
{
if(*ports[i] != "")
{
HYTEMousematController * controller = new HYTEMousematController((char *)ports[i]->c_str());
RGBController_HYTEMousemat * rgb_controller = new RGBController_HYTEMousemat(controller);
rgb_controller->name = hyte_mousemat_devices[device_id].name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
}
} /* DetectHYTEMousematControllers() */
REGISTER_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers);
/*---------------------------------------------------------------------------------------------------------*\
| Entries for dynamic UDEV rules |
| |
| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B00 ) |
| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B01 ) |
\*---------------------------------------------------------------------------------------------------------*/

View File

@@ -0,0 +1,85 @@
/*-----------------------------------------*\
| RGBController_HYTEMousemat.cpp |
| |
| Generic RGB Interface for HYTE CNVS RGB |
| mousemat |
| |
| Adam Honse (CalcProgrammer1) 7/18/2023 |
\*-----------------------------------------*/
#include "RGBController_HYTEMousemat.h"
RGBController_HYTEMousemat::RGBController_HYTEMousemat(HYTEMousematController* controller_ptr)
{
controller = controller_ptr;
name = "HYTE Mousemat";
description = "HYTE Mousemat Device";
type = DEVICE_TYPE_MOUSEMAT;
location = controller->GetLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
RGBController_HYTEMousemat::~RGBController_HYTEMousemat()
{
}
void RGBController_HYTEMousemat::SetupZones()
{
zone mousemat_zone;
mousemat_zone.name = "Mousemat";
mousemat_zone.type = ZONE_TYPE_LINEAR;
mousemat_zone.leds_min = 50;
mousemat_zone.leds_max = 50;
mousemat_zone.leds_count = 50;
mousemat_zone.matrix_map = NULL;
zones.push_back(mousemat_zone);
for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++)
{
led mousemat_led;
mousemat_led.name = "Mousemat LED";
leds.push_back(mousemat_led);
}
SetupColors();
}
void RGBController_HYTEMousemat::ResizeZone(int /*zone*/, int /*new_size*/)
{
}
void RGBController_HYTEMousemat::DeviceUpdateLEDs()
{
printf("DeviceUpdateLEDs called\r\n");
controller->StreamingCommand(&colors[0]);
}
void RGBController_HYTEMousemat::UpdateZoneLEDs(int /*zone*/)
{
}
void RGBController_HYTEMousemat::UpdateSingleLED(int /*led*/)
{
}
void RGBController_HYTEMousemat::DeviceUpdateMode()
{
}

View File

@@ -0,0 +1,32 @@
/*-----------------------------------------*\
| RGBController_HYTEMousemat.h |
| |
| Generic RGB Interface for HYTE CNVS RGB |
| mousemat |
| |
| Adam Honse (CalcProgrammer1) 7/18/2023 |
\*-----------------------------------------*/
#pragma once
#include "RGBController.h"
#include "HYTEMousematController.h"
class RGBController_HYTEMousemat : public RGBController
{
public:
RGBController_HYTEMousemat(HYTEMousematController* controller_ptr);
~RGBController_HYTEMousemat();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
HYTEMousematController* controller;
};

View File

@@ -172,6 +172,7 @@ INCLUDEPATH +=
Controllers/HyperXMicrophoneController/ \
Controllers/HyperXMouseController/ \
Controllers/HyperXMousematController/ \
Controllers/HYTEMousematController/ \
Controllers/IntelArcA770LEController/ \
Controllers/IonicoController/ \
Controllers/LEDStripController/ \
@@ -533,6 +534,8 @@ HEADERS +=
Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h \
Controllers/HyperXMousematController/HyperXMousematController.h \
Controllers/HyperXMousematController/RGBController_HyperXMousemat.h \
Controllers/HYTEMousematController/HYTEMousematController.h \
Controllers/HYTEMousematController/RGBController_HYTEMousemat.h \
Controllers/IntelArcA770LEController/IntelArcA770LEController.h \
Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h \
Controllers/IonicoController/IonicoController.h \
@@ -1181,6 +1184,9 @@ SOURCES +=
Controllers/HyperXMousematController/HyperXMousematController.cpp \
Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp \
Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp \
Controllers/HYTEMousematController/HYTEMousematController.cpp \
Controllers/HYTEMousematController/HYTEMousematControllerDetect.cpp \
Controllers/HYTEMousematController/RGBController_HYTEMousemat.cpp \
Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp \
Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp \
Controllers/IonicoController/IonicoController.cpp \

View File

@@ -24,12 +24,20 @@ std::vector<std::string *> find_usb_serial_port(unsigned short vid, unsigned sho
DIR* dir;
char symlink_path[1024] = {0};
struct dirent* ent;
char vid_pid[10] = {0}; //Store VID/PID
char target_vid[10] = {0};
char target_pid[10] = {0};
/*-----------------------------------------------------------------*\
| Target VID/PID strings |
\*-----------------------------------------------------------------*/
snprintf(target_vid, 10, "%04x", vid);
snprintf(target_pid, 10, "%04x", pid);
/*-----------------------------------------------------------------*\
| Open /sys/class/tty |
\*-----------------------------------------------------------------*/
dir = opendir("/sys/class/tty");
//dir = opendir("/sys/class/tty");
dir = opendir("/sys/bus/usb/devices");
if(dir == NULL)
{
@@ -47,33 +55,18 @@ std::vector<std::string *> find_usb_serial_port(unsigned short vid, unsigned sho
{
if(ent->d_type == DT_LNK)
{
char tty_path[1024];
strcpy(tty_path, "/sys/class/tty/");
strcat(tty_path, ent->d_name);
char usb_path[1024];
strcpy(usb_path, "/sys/bus/usb/devices/");
strcat(usb_path, ent->d_name);
/*-----------------------------------------------------------------*\
| readlink() does not null-terminate, so manually terminate it |
\*-----------------------------------------------------------------*/
ssize_t link_path_size = readlink(tty_path, symlink_path, 1024);
ssize_t link_path_size = readlink(usb_path, symlink_path, 1024);
symlink_path[link_path_size] = '\0';
char * usb_string = strstr(symlink_path, "usb");
if(usb_string != NULL)
if(1)
{
char * usb_dev = strstr(usb_string, "/");
usb_dev++;
char * usb_end = strstr(usb_dev, "/tty");
*usb_end = '\0';
usb_end = strrchr(usb_dev, '/');
*usb_end = '\0';
char usb_path[1024];
strcpy(usb_path, "/sys/bus/usb/devices/");
strcat(usb_path, usb_dev);
char vendor_path[1024];
char product_path[1024];
@@ -94,26 +87,57 @@ std::vector<std::string *> find_usb_serial_port(unsigned short vid, unsigned sho
std::getline(vendor_file, vendor_string);
std::getline(product_file, product_string);
snprintf(vid_pid, 10, "%04x", vid);
if(strcmp(vid_pid, vendor_string.c_str()) == 0)
if(strcmp(target_vid, vendor_string.c_str()) == 0)
{
snprintf(vid_pid, 10, "%04x", pid);
if(strcmp(vid_pid, product_string.c_str()) == 0)
if(strcmp(target_pid, product_string.c_str()) == 0)
{
char* port_string = NULL;
for(int i = strlen(tty_path); i > 0; i--)
{
if(tty_path[i] == '/')
{
port_string = &tty_path[i + 1];
break;
}
}
tmp_string = new std::string("/dev/");
tmp_string->append(port_string);
DIR* usb_dev_dir;
struct dirent* usb_dev_ent;
ret_vector.push_back(tmp_string);
usb_dev_dir = opendir(usb_path);
usb_dev_ent = readdir(usb_dev_dir);
while(usb_dev_ent != NULL)
{
if(usb_dev_ent->d_type == DT_DIR)
{
char tty_path[1024];
strcpy(tty_path, usb_path);
strcat(tty_path, "/");
strcat(tty_path, usb_dev_ent->d_name);
strcat(tty_path, "/tty");
DIR* tty_dir;
tty_dir = opendir(tty_path);
if(tty_dir != NULL)
{
struct dirent* tty_ent;
tty_ent = readdir(tty_dir);
while(tty_ent != NULL)
{
if(tty_ent->d_type == DT_DIR)
{
if(strncmp(tty_ent->d_name, "tty", 3) == 0)
{
tmp_string = new std::string("/dev/" + std::string(tty_ent->d_name));
ret_vector.push_back(tmp_string);
}
}
tty_ent = readdir(tty_dir);
}
}
}
usb_dev_ent = readdir(usb_dev_dir);
}
}
}
}
@@ -122,6 +146,95 @@ std::vector<std::string *> find_usb_serial_port(unsigned short vid, unsigned sho
ent = readdir(dir);
}
closedir(dir);
return ret_vector;
// /*-----------------------------------------------------------------*\
// | Loop through all symlinks in /sys/class/tty directory to find |
// | paths with "usb" in them. These links should have the USB device |
// | index which can be used to find the VID/PID |
// \*-----------------------------------------------------------------*/
// ent = readdir(dir);
// while(ent != NULL)
// {
// if(ent->d_type == DT_LNK)
// {
// char tty_path[1024];
// strcpy(tty_path, "/sys/class/tty/");
// strcat(tty_path, ent->d_name);
// /*-----------------------------------------------------------------*\
// | readlink() does not null-terminate, so manually terminate it |
// \*-----------------------------------------------------------------*/
// ssize_t link_path_size = readlink(tty_path, symlink_path, 1024);
// symlink_path[link_path_size] = '\0';
// char * usb_string = strstr(symlink_path, "usb");
// if(usb_string != NULL)
// {
// char * usb_dev = strstr(usb_string, "/");
// usb_dev++;
// char * usb_end = strstr(usb_dev, "/tty");
// *usb_end = '\0';
// usb_end = strrchr(usb_dev, '/');
// *usb_end = '\0';
// char usb_path[1024];
// strcpy(usb_path, "/sys/bus/usb/devices/");
// strcat(usb_path, usb_dev);
// char vendor_path[1024];
// char product_path[1024];
// strcpy(vendor_path, usb_path);
// strcat(vendor_path, "/idVendor");
// strcpy(product_path, usb_path);
// strcat(product_path, "/idProduct");
// std::ifstream vendor_file;
// std::ifstream product_file;
// std::string vendor_string;
// std::string product_string;
// vendor_file.open(vendor_path);
// product_file.open(product_path);
// std::getline(vendor_file, vendor_string);
// std::getline(product_file, product_string);
// snprintf(vid_pid, 10, "%04x", vid);
// if(strcmp(vid_pid, vendor_string.c_str()) == 0)
// {
// snprintf(vid_pid, 10, "%04x", pid);
// if(strcmp(vid_pid, product_string.c_str()) == 0)
// {
// char* port_string = NULL;
// for(int i = strlen(tty_path); i > 0; i--)
// {
// if(tty_path[i] == '/')
// {
// port_string = &tty_path[i + 1];
// break;
// }
// }
// tmp_string = new std::string("/dev/");
// tmp_string->append(port_string);
// ret_vector.push_back(tmp_string);
// }
// }
// }
// }
// ent = readdir(dir);
// }
closedir(dir);
return ret_vector;

View File

@@ -219,7 +219,7 @@ bool serial_port::serial_open()
/*-----------------------------------------*\
| Open the port read/write with no delay |
\*-----------------------------------------*/
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_DSYNC);
if(file_descriptor < 0)
{
@@ -566,9 +566,9 @@ int serial_port::serial_write(char * buffer, int length)
\*-----------------------------------------------------*/
#ifdef __linux__
int byteswritten;
tcdrain(file_descriptor);
//tcdrain(file_descriptor);
byteswritten = write(file_descriptor, buffer, length);
tcdrain(file_descriptor);
//tcdrain(file_descriptor);
return byteswritten;
#endif