118 lines
2.2 KiB
C++
118 lines
2.2 KiB
C++
|
#include "ergodox.hpp"
|
||
|
|
||
|
|
||
|
|
||
|
Ergodox::Ergodox(
|
||
|
unsigned short vendor_id,
|
||
|
unsigned short product_id,
|
||
|
unsigned short usage,
|
||
|
unsigned short usage_page
|
||
|
) :
|
||
|
vendor_id(vendor_id),
|
||
|
product_id(product_id),
|
||
|
usage(usage),
|
||
|
usage_page(usage_page),
|
||
|
handle(NULL)
|
||
|
{
|
||
|
hid_init();
|
||
|
open();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
Initialize Ergodox interface.
|
||
|
|
||
|
Should be called once at start of execution. Arguments are the USB parameters of the keyboard.
|
||
|
|
||
|
Returns instance of singleton.
|
||
|
*/
|
||
|
Ergodox& Ergodox::init(
|
||
|
unsigned short vendor_id,
|
||
|
unsigned short product_id,
|
||
|
unsigned short usage,
|
||
|
unsigned short usage_page
|
||
|
) {
|
||
|
static bool has_been_initialized = false;
|
||
|
static Ergodox Instance(
|
||
|
vendor_id,
|
||
|
product_id,
|
||
|
usage,
|
||
|
usage_page
|
||
|
);
|
||
|
|
||
|
// This isn't strictly necessary, but there is no reason
|
||
|
// to call init() twice.
|
||
|
if (has_been_initialized) {
|
||
|
has_been_initialized = true;
|
||
|
throw std::runtime_error("Ergodox has already been initialized!");
|
||
|
}
|
||
|
|
||
|
return Instance;
|
||
|
}
|
||
|
|
||
|
Ergodox::~Ergodox() {
|
||
|
close();
|
||
|
hid_exit();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Try to open this keyboard's hid device.
|
||
|
Throws a runtime error if device is already open,
|
||
|
or if we can't find a device with the given params.
|
||
|
*/
|
||
|
void Ergodox::open() {
|
||
|
if (handle != NULL) {
|
||
|
throw std::runtime_error("Device already open");
|
||
|
}
|
||
|
|
||
|
struct hid_device_info *devs, *cur_dev;
|
||
|
const char *path_to_open = NULL;
|
||
|
|
||
|
devs = hid_enumerate(vendor_id, product_id);
|
||
|
cur_dev = devs;
|
||
|
while (cur_dev) {
|
||
|
if (cur_dev->vendor_id == vendor_id &&
|
||
|
cur_dev->product_id == product_id &&
|
||
|
cur_dev->usage == usage &&
|
||
|
cur_dev->usage_page == usage_page
|
||
|
) {
|
||
|
path_to_open = cur_dev->path;
|
||
|
break;
|
||
|
}
|
||
|
cur_dev = cur_dev->next;
|
||
|
}
|
||
|
|
||
|
if (path_to_open) {
|
||
|
handle = hid_open_path(path_to_open);
|
||
|
hid_free_enumeration(devs);
|
||
|
} else {
|
||
|
hid_free_enumeration(devs);
|
||
|
throw std::runtime_error("Could not open hid device");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Close hid device if it is open.
|
||
|
void Ergodox::close() {
|
||
|
if (handle != NULL) {
|
||
|
hid_close(handle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Send data to Ergodox.
|
||
|
|
||
|
@param data Data to send
|
||
|
@param length How many bytes to send
|
||
|
@returns Actual number of bytes written, or -1 on error.
|
||
|
*/
|
||
|
int Ergodox::write(uint8_t* data, size_t length) const {
|
||
|
if (handle == NULL) {
|
||
|
throw std::runtime_error("Cannot write, device is not open!");
|
||
|
}
|
||
|
|
||
|
return hid_write(handle, data, length);
|
||
|
}
|