Add files

This commit is contained in:
2023-08-10 23:00:40 +02:00
commit 9f6219a2cf
35 changed files with 73071 additions and 0 deletions

60
sustain-kbd-config/.gitignore vendored Normal file
View File

@@ -0,0 +1,60 @@
# Created by https://www.toptal.com/developers/gitignore/api/c++
# Edit at https://www.toptal.com/developers/gitignore?templates=c++
### C++ ###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# End of https://www.toptal.com/developers/gitignore/api/c++
# Created by https://www.toptal.com/developers/gitignore/api/cmake
# Edit at https://www.toptal.com/developers/gitignore?templates=cmake
### CMake ###
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
### CMake Patch ###
# External projects
*-prefix/
# End of https://www.toptal.com/developers/gitignore/api/cmake

View File

@@ -0,0 +1,74 @@
cmake_minimum_required(VERSION 3.5)
project(sustain-kbd-config VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(PkgConfig REQUIRED)
pkg_search_module(LIBUSB REQUIRED libusb-1.0)
# QtCreator supports the following variables for Android, which are identical to qmake Android variables.
# Check https://doc.qt.io/qt/deployment-android.html for more information.
# They need to be set before the find_package( ...) calls below.
#if(ANDROID)
# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
# if (ANDROID_ABI STREQUAL "armeabi-v7a")
# set(ANDROID_EXTRA_LIBS
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libcrypto.so
# ${CMAKE_CURRENT_SOURCE_DIR}/path/to/libssl.so)
# endif()
#endif()
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets REQUIRED)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
libusbwrapper.cpp
libusbwrapper.h
sustainpedalkeyboard.h
sustainpedalkeyboard.cpp
)
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
qt_add_executable(sustain-kbd-config
MANUAL_FINALIZATION
${PROJECT_SOURCES}
)
else()
if(ANDROID)
add_library(sustain-kbd-config SHARED
${PROJECT_SOURCES}
)
else()
add_executable(sustain-kbd-config
${PROJECT_SOURCES}
)
endif()
endif()
target_link_libraries(sustain-kbd-config PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${LIBUSB_LDFLAGS})
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBUSB_INCLUDE_DIRS})
set_target_properties(sustain-kbd-config PROPERTIES
MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
CXX_STANDARD 17
)
if(QT_VERSION_MAJOR EQUAL 6)
qt_finalize_executable(sustain-kbd-config)
endif()

View File

@@ -0,0 +1,137 @@
#include "libusbwrapper.h"
#include <libusb.h>
#include <iostream>
UsbDevice::UsbDevice(libusb_device *device)
{
int res;
this->dev = device;
res = libusb_get_device_descriptor(device, &this->devdesc);
this->device_handle = nullptr;
if (res == 0) {
this->vendor_id = devdesc.idVendor;
this->product_id = devdesc.idProduct;
}
}
UsbDevice::UsbDevice(UsbDevice &&d)
{
vendor_id = std::move(d.vendor_id);
product_id = std::move(d.product_id);
dev = d.dev;
devdesc = d.devdesc;
device_handle = std::move(d.device_handle);
}
UsbDevice::~UsbDevice()
{
/* Nothing to do here. Our device handle will be automatically closed once the shared pointer is released */
}
std::vector<UsbDevice> UsbDevice::find_devices(uint16_t vendor_id, uint16_t product_id)
{
auto ret_vector = std::vector<UsbDevice>();
libusb_device **devlist;
int res = libusb_get_device_list(NULL, &devlist);
if (res > 0) {
for (int idx = 0; idx < res; idx++) {
auto d = UsbDevice(devlist[idx]);
if (d.get_product_id() == product_id && d.get_vendor_id() == vendor_id)
ret_vector.push_back(std::move(d));
}
}
return ret_vector;
}
bool UsbDevice::opened()
{
return !!(this->device_handle != nullptr);
}
int UsbDevice::open()
{
int ret;
libusb_device_handle *handle;
if (this->dev) {
ret = libusb_open(this->dev, &handle);
} else {
handle = libusb_open_device_with_vid_pid(NULL, this->vendor_id, this->product_id);
if (!handle)
ret = -1;
else
ret = 0;
}
device_handle = std::make_shared<UsbDeviceHandle>(handle);
return ret;
}
uint16_t UsbDevice::get_vendor_id()
{
return this->vendor_id;
}
uint16_t UsbDevice::get_product_id()
{
return this->product_id;
}
int UsbDevice::control_transfer(uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout)
{
if (!opened())
return -1000;
return libusb_control_transfer(this->device_handle->m_handle, request_type, bRequest, wValue, wIndex, data, wLength, timeout);
}
const std::string &UsbDevice::get_serial_number()
{
char buffer[256] = {0};
if (!opened())
return serial;
if (devdesc.iSerialNumber == 0)
return serial;
if (serial.length() > 0) {
return serial;
}
int res = libusb_get_string_descriptor_ascii(device_handle->m_handle, devdesc.iSerialNumber, (unsigned char *)buffer, 255);
if (res > 0) {
serial = std::string(buffer);
return serial;
} else {
return serial;
}
}
void LibUsbInit()
{
libusb_init(NULL);
}
void LibUsbDeInit()
{
libusb_exit(NULL);
}
UsbDeviceHandle::UsbDeviceHandle(libusb_device_handle *handle)
{
m_handle = handle;
}
UsbDeviceHandle::~UsbDeviceHandle()
{
if (m_handle)
libusb_close(m_handle);
m_handle = NULL;
}

View File

@@ -0,0 +1,47 @@
#ifndef LIBUSBWRAPPER_H
#define LIBUSBWRAPPER_H
#include <stdint.h>
#include <vector>
#include <string>
#include <libusb.h>
#include <memory>
void LibUsbInit();
void LibUsbDeInit();
class UsbDeviceHandle {
public:
UsbDeviceHandle(libusb_device_handle *handle);
~UsbDeviceHandle();
libusb_device_handle *m_handle;
};
class UsbDevice {
public:
UsbDevice(libusb_device *device);
UsbDevice(const UsbDevice &d) = default;
UsbDevice(UsbDevice &&d);
~UsbDevice();
static std::vector<UsbDevice> find_devices(uint16_t vendor_id, uint16_t product_id);
bool opened();
int open();
uint16_t get_vendor_id();
uint16_t get_product_id();
int control_transfer(uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout);
const std::string &get_serial_number();
private:
std::shared_ptr<UsbDeviceHandle> device_handle;
libusb_device *dev;
uint16_t vendor_id;
uint16_t product_id;
std::string serial;
struct libusb_device_descriptor devdesc;
};
#endif // LIBUSBWRAPPER_H

View File

@@ -0,0 +1,23 @@
#include "mainwindow.h"
#include "libusbwrapper.h"
#include <iostream>
#include <QApplication>
int main(int argc, char *argv[])
{
int ret;
QApplication a(argc, argv);
MainWindow w;
LibUsbInit();
w.show();
ret = a.exec();
LibUsbDeInit();
return ret;
}

View File

@@ -0,0 +1,228 @@
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "libusbwrapper.h"
#include <QMessageBox>
#include <memory>
#include <iostream>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->rescanButton, SIGNAL(clicked()), this, SLOT(rescan_clicked()));
connect(this, SIGNAL(close()), this, SLOT(on_close()));
connect(ui->deviceComboBox, SIGNAL(currentTextChanged(QString)), this, SLOT(device_changed(QString)));
connect(ui->clearKeycodesButton, SIGNAL(clicked()), this, SLOT(clear_keyboard_config()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::rescan_device_list()
{
if (this->m_usb_devices.size()) {
/* Close old devices */
m_usb_devices.clear();
}
auto temp_vector = UsbDevice::find_devices(0xDEAD, 0xBEEF);
this->m_usb_devices = std::vector<SustainPedalKeyboard>(temp_vector.begin(), temp_vector.end());
ui->deviceComboBox->clear();
/* Update combo box with devices */
for (auto &dev : m_usb_devices) {
dev.open();
auto sn = dev.get_serial_number();
ui->deviceComboBox->addItem(QString::fromStdString(sn));
}
}
UsbDevice *MainWindow::get_device_from_sn(const std::string &sn)
{
for (auto &d : m_usb_devices) {
if (d.get_serial_number() == sn)
return &d;
}
return NULL;
}
UsbHidKeyEvent MainWindow::create_key_event_pedal1()
{
UsbHidKeyEvent event;
event.left_control = ui->checkBoxLControl_1->isChecked();
event.left_shift = ui->checkBoxLShift_1->isChecked();
event.left_alt = ui->checkBoxLAlt_1->isChecked();
event.left_super = ui->checkBoxLSuper_1->isChecked();
event.right_control = ui->checkBoxRControl_1->isChecked();
event.right_shift = ui->checkBoxRShift_1->isChecked();
event.right_alt = ui->checkBoxRAlt_1->isChecked();
event.right_super = ui->checkBoxRSuper_1->isChecked();
event.keycodes[0] = (uint8_t)ui->keycode1_1->value();
event.keycodes[1] = (uint8_t)ui->keycode2_1->value();
event.keycodes[2] = (uint8_t)ui->keycode3_1->value();
return event;
}
UsbHidKeyEvent MainWindow::create_key_event_pedal2()
{
UsbHidKeyEvent event;
event.left_control = ui->checkBoxLControl_2->isChecked();
event.left_shift = ui->checkBoxLShift_2->isChecked();
event.left_alt = ui->checkBoxLAlt_2->isChecked();
event.left_super = ui->checkBoxLSuper_2->isChecked();
event.right_control = ui->checkBoxRControl_2->isChecked();
event.right_shift = ui->checkBoxRShift_2->isChecked();
event.right_alt = ui->checkBoxRAlt_2->isChecked();
event.right_super = ui->checkBoxRSuper_2->isChecked();
event.keycodes[0] = (uint8_t)ui->keycode1_2->value();
event.keycodes[1] = (uint8_t)ui->keycode2_2->value();
event.keycodes[2] = (uint8_t)ui->keycode3_2->value();
return event;
}
void MainWindow::rescan_clicked()
{
rescan_device_list();
}
void MainWindow::device_changed(QString sn)
{
auto dev = get_device_from_sn(sn.toStdString());
if (m_currently_selected_dev.get()) {
m_currently_selected_dev->set_active_indicator(false);
}
m_currently_selected_dev.reset();
if (dev == NULL) {
enable_pedal_gui_elements(false);
return;
}
enable_pedal_gui_elements(true);
m_currently_selected_dev = std::make_unique<SustainPedalKeyboard>(*dev);
m_currently_selected_dev->set_active_indicator(true);
update_gui_from_keyboard();
}
void MainWindow::clear_keyboard_config()
{
if (!m_currently_selected_dev.get()) {
QMessageBox::warning(this, "Error", "No device selected!");
return;
}
UsbHidKeyEvent empty_key;
if (m_currently_selected_dev->program_keyboard_keycode(0, empty_key)) {
QMessageBox::warning(this, "Error", "Request to device failed!");
return;
}
if (m_currently_selected_dev->program_keyboard_keycode(1, empty_key)) {
QMessageBox::warning(this, "Error", "Request to device failed!");
return;
}
update_gui_from_keyboard();
QMessageBox::information(this, "Device Reset", "All configuration deleted!");
}
void MainWindow::update_gui_from_keyboard()
{
UsbHidKeyEvent pedal1, pedal2;
if (!m_currently_selected_dev->read_keyboard_config(&pedal1, &pedal2)) {
ui->checkBoxLControl_1->setChecked(pedal1.left_control);
ui->checkBoxLShift_1->setChecked(pedal1.left_shift);
ui->checkBoxLAlt_1->setChecked(pedal1.left_alt);
ui->checkBoxLSuper_1->setChecked(pedal1.left_super);
ui->checkBoxRControl_1->setChecked(pedal1.right_control);
ui->checkBoxRShift_1->setChecked(pedal1.right_shift);
ui->checkBoxRAlt_1->setChecked(pedal1.right_alt);
ui->checkBoxRSuper_1->setChecked(pedal1.right_super);
ui->checkBoxLControl_2->setChecked(pedal2.left_control);
ui->checkBoxLShift_2->setChecked(pedal2.left_shift);
ui->checkBoxLAlt_2->setChecked(pedal2.left_alt);
ui->checkBoxLSuper_2->setChecked(pedal2.left_super);
ui->checkBoxRControl_2->setChecked(pedal2.right_control);
ui->checkBoxRShift_2->setChecked(pedal2.right_shift);
ui->checkBoxRAlt_2->setChecked(pedal2.right_alt);
ui->checkBoxRSuper_2->setChecked(pedal2.right_super);
ui->keycode1_1->setValue((int)pedal1.keycodes[0]);
ui->keycode2_1->setValue((int)pedal1.keycodes[1]);
ui->keycode3_1->setValue((int)pedal1.keycodes[2]);
ui->keycode1_2->setValue((int)pedal2.keycodes[0]);
ui->keycode2_2->setValue((int)pedal2.keycodes[1]);
ui->keycode3_2->setValue((int)pedal2.keycodes[2]);
}
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (m_currently_selected_dev)
m_currently_selected_dev->set_active_indicator(false);
m_usb_devices.clear();
m_currently_selected_dev.reset();
m_currently_selected_dev = nullptr;
}
void MainWindow::showEvent(QShowEvent *event)
{
QMainWindow::showEvent(event);
enable_pedal_gui_elements(false);
rescan_device_list();
}
void MainWindow::on_buttonProgPedal1_clicked()
{
if (!m_currently_selected_dev.get())
return;
auto ev = create_key_event_pedal1();
m_currently_selected_dev->program_keyboard_keycode(0, ev);
}
void MainWindow::on_buttonProgPedal2_clicked()
{
if (!m_currently_selected_dev.get())
return;
auto ev = create_key_event_pedal2();
m_currently_selected_dev->program_keyboard_keycode(1, ev);
}
void MainWindow::enable_pedal_gui_elements(bool enable)
{
int count1 = ui->verticalLayoutPedal1->count();
int count2 = ui->verticalLayoutPedal2->count();
for (int i = 0; i < count1; i++) {
ui->verticalLayoutPedal1->itemAt(i)->widget()->setEnabled(enable);
}
for (int i = 0; i < count2; i++) {
ui->verticalLayoutPedal2->itemAt(i)->widget()->setEnabled(enable);
}
ui->clearKeycodesButton->setEnabled(enable);
}

View File

@@ -0,0 +1,47 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "sustainpedalkeyboard.h"
#include <vector>
#include <optional>
#include <functional>
#include <memory>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
void rescan_device_list(void);
UsbDevice *get_device_from_sn(const std::string &sn);
std::vector<SustainPedalKeyboard> m_usb_devices;
std::unique_ptr<SustainPedalKeyboard> m_currently_selected_dev;
UsbHidKeyEvent create_key_event_pedal1();
UsbHidKeyEvent create_key_event_pedal2();
private slots:
void rescan_clicked();
void device_changed(QString sn);
void clear_keyboard_config();
void update_gui_from_keyboard();
void on_buttonProgPedal1_clicked();
void on_buttonProgPedal2_clicked();
void enable_pedal_gui_elements(bool enable);
protected:
void closeEvent(QCloseEvent *event);
void showEvent(QShowEvent *event);
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Shimatta Sustain Pedal Keyboard Configuration</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QWidget" name="verticalLayoutWidget_3">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>501</width>
<height>492</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QComboBox" name="deviceComboBox"/>
</item>
<item>
<widget class="QPushButton" name="rescanButton">
<property name="text">
<string>Rescan Device List</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBoxVid"/>
</item>
<item>
<widget class="QSpinBox" name="spinBoxPid"/>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Program VID:PID</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="clearKeycodesButton">
<property name="text">
<string>Clear Keycodes</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="pedalUiElements">
<item>
<layout class="QVBoxLayout" name="verticalLayoutPedal1">
<item>
<widget class="QCheckBox" name="checkBoxLControl_1">
<property name="text">
<string>Left Control</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLShift_1">
<property name="text">
<string>Left Shift</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLAlt_1">
<property name="text">
<string>Left Alt</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLSuper_1">
<property name="text">
<string>Left Super</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRControl_1">
<property name="text">
<string>Right Control</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRShift_1">
<property name="text">
<string>Right Shift</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRAlt_1">
<property name="text">
<string>Right Alt</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRSuper_1">
<property name="text">
<string>Right Super</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode1_1">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode2_1">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode3_1">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonProgPedal1">
<property name="text">
<string>Program Pedal 1</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayoutPedal2">
<item>
<widget class="QCheckBox" name="checkBoxLControl_2">
<property name="text">
<string>Left Control</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLShift_2">
<property name="text">
<string>Left Shift</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLAlt_2">
<property name="text">
<string>Left Alt</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLSuper_2">
<property name="text">
<string>Left Super</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRControl_2">
<property name="text">
<string>Right Control</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRShift_2">
<property name="text">
<string>Right Shift</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRAlt_2">
<property name="text">
<string>Right Alt</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxRSuper_2">
<property name="text">
<string>Right Super</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode1_2">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode2_2">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="keycode3_2">
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonProgPedal2">
<property name="text">
<string>Program Pedal 2</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,155 @@
#include "sustainpedalkeyboard.h"
#include <iostream>
SustainPedalKeyboard::SustainPedalKeyboard(libusb_device *device) : UsbDevice(device)
{
m_control_timeout = 500;
}
SustainPedalKeyboard::SustainPedalKeyboard(const UsbDevice &device) : UsbDevice(device)
{
m_control_timeout = 500;
}
SustainPedalKeyboard::~SustainPedalKeyboard()
{
}
int SustainPedalKeyboard::get_control_timeout()
{
return m_control_timeout;
}
void SustainPedalKeyboard::set_control_timeout(int timeout)
{
m_control_timeout = timeout;
}
int SustainPedalKeyboard::set_led(uint8_t led, bool state)
{
int res = this->control_transfer((1<<6), 0x1, state ? 1 : 0, led, NULL, 0, m_control_timeout);
return res;
}
void SustainPedalKeyboard::set_active_indicator(bool state)
{
(void)set_led(3, state);
}
int SustainPedalKeyboard::program_keyboard_keycode(uint8_t pedal_idx, UsbHidKeyEvent &key)
{
uint32_t word;
uint8_t data[4];
if (pedal_idx > 1)
return -1001;
word = key.to_eeprom_word();
for (int i = 0; i < 4; i++) {
data[i] = word & 0xFF;
word >>= 8;
}
int res = write_eeprom(pedal_idx * 4, data, 4);
if (res < 0)
return res;
else
return 0;
}
int SustainPedalKeyboard::read_keyboard_config(UsbHidKeyEvent *pedal1, UsbHidKeyEvent *pedal2)
{
unsigned char eeprom_data[8];
if (!pedal1 || !pedal2)
return -1000;
int res = read_eeprom(0, eeprom_data, sizeof(eeprom_data));
if (res != 8) {
return -1;
}
pedal1->from_eeprom_data(&eeprom_data[0]);
pedal2->from_eeprom_data(&eeprom_data[4]);
return 0;
}
int SustainPedalKeyboard::write_eeprom(uint16_t offset_addr, unsigned char *data, uint16_t len)
{
return this->control_transfer((1<<6), 0x2, 0, offset_addr, data, len, m_control_timeout);
}
int SustainPedalKeyboard::read_eeprom(uint16_t offset_addr, unsigned char *data, uint16_t len)
{
int ret;
ret = this->control_transfer(0x80 | (1<<6), 0x2, 0x0, offset_addr, data, len, m_control_timeout);
return ret;
}
UsbHidKeyEvent::UsbHidKeyEvent()
{
for (int i = 0; i < 3; i++)
keycodes[i] = 0;
left_control = false;
left_alt = false;
left_shift = false;
left_super = false;
right_control = false;
right_super = false;
right_alt = false;
right_shift = false;
}
uint32_t UsbHidKeyEvent::to_eeprom_word()
{
uint8_t modifiers = 0;
uint32_t ret;
if (left_control)
modifiers |= 1;
if (left_shift)
modifiers |= 2;
if (left_alt)
modifiers |= 4;
if (left_super)
modifiers |= 8;
if (right_control)
modifiers |= 16;
if (right_shift)
modifiers |= 32;
if (right_alt)
modifiers |= 64;
if (right_super)
modifiers |= 128;
ret = (uint32_t)modifiers;
ret |= (((uint32_t)keycodes[0]) << 8);
ret |= (((uint32_t)keycodes[1]) << 16);
ret |= (((uint32_t)keycodes[2]) << 24);
return ret;
}
void UsbHidKeyEvent::from_eeprom_data(uint8_t data[4])
{
left_control = !!(data[0] & 1);
left_shift = !!(data[0] & 2);
left_alt = !!(data[0] & 4);
left_super = !!(data[0] & 8);
right_control = !!(data[0] & 16);
right_shift = !!(data[0] & 32);
right_alt = !!(data[0] & 64);
right_super = !!(data[0] & 128);
for (int i = 0; i < 3; i++) {
keycodes[i] = data[i + 1];
}
}

View File

@@ -0,0 +1,50 @@
#ifndef SUSTAINPEDALKEYBOARD_H
#define SUSTAINPEDALKEYBOARD_H
#include "libusbwrapper.h"
class UsbHidKeyEvent {
public:
UsbHidKeyEvent();
bool left_control;
bool left_shift;
bool left_alt;
bool left_super;
bool right_control;
bool right_shift;
bool right_alt;
bool right_super;
uint8_t keycodes[3];
uint32_t to_eeprom_word();
void from_eeprom_data(uint8_t data[4]);
};
class SustainPedalKeyboard : public UsbDevice
{
public:
SustainPedalKeyboard(libusb_device *device);
SustainPedalKeyboard(const UsbDevice &device);
~SustainPedalKeyboard();
int get_control_timeout();
void set_control_timeout(int timeout);
int set_led(uint8_t led, bool state);
void set_active_indicator(bool state);
int program_keyboard_keycode(uint8_t pedal_idx, UsbHidKeyEvent &key);
int read_keyboard_config(UsbHidKeyEvent *pedal1, UsbHidKeyEvent *pedal2);
private:
int write_eeprom(uint16_t offset_addr, unsigned char *data, uint16_t len);
int read_eeprom(uint16_t offset_addr, unsigned char *data, uint16_t len);
int m_control_timeout;
};
#endif // SUSTAINPEDALKEYBOARD_H