Added connection management
This commit is contained in:
@ -11,10 +11,10 @@ Ergodox::Ergodox(
|
||||
product_id(product_id),
|
||||
usage(usage),
|
||||
usage_page(usage_page),
|
||||
handle(NULL)
|
||||
handle(NULL),
|
||||
connected(false)
|
||||
{
|
||||
hid_init();
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
@ -54,21 +54,23 @@ Ergodox& Ergodox::init(
|
||||
// Instance is a static function variable,
|
||||
// and will be deleted at end of program.
|
||||
Ergodox::~Ergodox() {
|
||||
close();
|
||||
disconnect();
|
||||
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.
|
||||
Throws a runtime error if device is already open.
|
||||
|
||||
If we successfully open a device, this method sends a
|
||||
CMD_HELLO packet.
|
||||
|
||||
@returns True if connection was successful, false otherwise.
|
||||
*/
|
||||
void Ergodox::open() {
|
||||
if (handle != NULL) {
|
||||
bool Ergodox::try_connect() {
|
||||
if (connected) {
|
||||
throw std::runtime_error("Device already open");
|
||||
}
|
||||
|
||||
@ -89,24 +91,47 @@ void Ergodox::open() {
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
|
||||
// Return false if connection failed
|
||||
if (path_to_open) {
|
||||
connected = true;
|
||||
|
||||
handle = hid_open_path(path_to_open);
|
||||
hid_set_nonblocking(handle, 1);
|
||||
hid_free_enumeration(devs);
|
||||
write(CMD_HELLO, NULL, 0);
|
||||
|
||||
#define MAX_STR 255
|
||||
wchar_t wstr[MAX_STR];
|
||||
|
||||
|
||||
wprintf(L"\nConnected to device!\n");
|
||||
|
||||
// Read metadata
|
||||
wstr[0] = 0x0000;
|
||||
hid_get_manufacturer_string(handle, wstr, MAX_STR);
|
||||
wprintf(L"Manufacturer String: %ls\n", wstr);
|
||||
|
||||
wstr[0] = 0x0000;
|
||||
hid_get_product_string(handle, wstr, MAX_STR);
|
||||
wprintf(L"Product String: %ls\n", wstr);
|
||||
|
||||
} else {
|
||||
connected = false;
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
throw std::runtime_error("Could not open hid device");
|
||||
return false;
|
||||
}
|
||||
|
||||
hid_set_nonblocking(handle, 1);
|
||||
|
||||
write(CMD_HELLO, NULL, 0);
|
||||
return connected;
|
||||
}
|
||||
|
||||
|
||||
// Close hid device if it is open.
|
||||
void Ergodox::close() {
|
||||
void Ergodox::disconnect() {
|
||||
connected = false;
|
||||
if (handle != NULL) {
|
||||
hid_close(handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,14 +141,15 @@ Send data to Ergodox.
|
||||
|
||||
@param cmd Command byte
|
||||
@param data Data to send
|
||||
@returns data_len Data length. Must be shorter than packet_size.
|
||||
@param data_len Data length. Must be shorter than packet_size.
|
||||
@returns True if successful, false otherwise.
|
||||
*/
|
||||
int Ergodox::write(uint8_t cmd, const uint8_t* data, uint8_t data_len) const {
|
||||
if (handle == NULL) {
|
||||
throw std::runtime_error("Cannot write, device is not open!");
|
||||
}
|
||||
|
||||
if (data_len > packet_size) {
|
||||
bool Ergodox::write(uint8_t cmd, const uint8_t* data, uint8_t data_len) {
|
||||
if (!connected) {
|
||||
throw std::runtime_error("Not connected, cannot write!");
|
||||
} else if (handle == NULL) {
|
||||
throw std::runtime_error("Tried to write a null handle, something is very wrong.");
|
||||
} else if (data_len > packet_size) {
|
||||
throw std::runtime_error("Data length exceeds packet size");
|
||||
}
|
||||
|
||||
@ -138,7 +164,15 @@ int Ergodox::write(uint8_t cmd, const uint8_t* data, uint8_t data_len) const {
|
||||
// Copy data into rest of packet
|
||||
std::copy(data, data + data_len, packet + 2);
|
||||
|
||||
return hid_write(handle, packet, packet_size + 1);
|
||||
ssize_t res;
|
||||
res = hid_write(handle, packet, packet_size + 1);
|
||||
|
||||
if (res < 0) {
|
||||
wprintf(L"Lost device, disconnecting.\n");
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -148,16 +182,21 @@ Read data from Ergodox into read_buf. If a CMD_SEND_STATE packet is received, pr
|
||||
@returns True if a new command was received, false otherwise.
|
||||
*/
|
||||
bool Ergodox::read() {
|
||||
if (handle == NULL) {
|
||||
throw std::runtime_error("Cannot write, device is not open!");
|
||||
if (!connected) {
|
||||
throw std::runtime_error("Not connected, cannot read!");
|
||||
} else if (handle == NULL) {
|
||||
throw std::runtime_error("Tried to read a null handle, something is very wrong.");
|
||||
}
|
||||
|
||||
ssize_t res;
|
||||
res = hid_read(handle, read_buf, packet_size);
|
||||
|
||||
if (res == 0) {
|
||||
return false;
|
||||
} else if (res < 0) {
|
||||
throw std::runtime_error("Read failed.");
|
||||
wprintf(L"Lost device, disconnecting.\n");
|
||||
disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(read_buf[0]) {
|
||||
@ -173,5 +212,11 @@ bool Ergodox::read() {
|
||||
return false;
|
||||
}
|
||||
|
||||
return res > 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Simple connectivity check
|
||||
void Ergodox::test_connection() {
|
||||
write(CMD_RUTHERE, NULL, 0);
|
||||
}
|
Reference in New Issue
Block a user