1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include <chrono>
#include <thread>
#include <cstddef>
#include <stdexcept>
#include <hidapi/hidapi.h>
#include "include/misc.h"
#include "include/device.h"
#include "include/log.h"
using namespace nitrokey::device;
using namespace nitrokey::log;
using namespace std::chrono;
Device::Device(const uint16_t vid, const uint16_t pid, const DeviceModel model,
const milliseconds send_receive_delay, const int retry_receiving_count,
const milliseconds retry_timeout)
: m_vid(vid),
m_pid(pid),
m_retry_sending_count(3),
m_retry_receiving_count(retry_receiving_count),
m_retry_timeout(retry_timeout),
mp_devhandle(NULL),
last_command_status(0),
m_model(model),
m_send_receive_delay(send_receive_delay)
{}
bool Device::disconnect() {
Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2);
if(mp_devhandle == nullptr) return false;
hid_close(mp_devhandle);
mp_devhandle = NULL;
hid_exit();
return true;
}
bool Device::connect() {
Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2);
// hid_init(); // done automatically on hid_open
mp_devhandle = hid_open(m_vid, m_pid, NULL);
return mp_devhandle != NULL;
}
int Device::send(const void *packet) {
Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2);
if (mp_devhandle == NULL)
throw std::runtime_error("Attempted HID send on an invalid descriptor."); //TODO migrate except to library_error
return (hid_send_feature_report(
mp_devhandle, (const unsigned char *)(packet), HID_REPORT_SIZE));
}
int Device::recv(void *packet) {
int status;
int retry_count = 0;
Log::instance()(__PRETTY_FUNCTION__, Loglevel::DEBUG_L2);
if (mp_devhandle == NULL)
throw std::runtime_error("Attempted HID receive on an invalid descriptor."); //TODO migrate except to library_error
// FIXME extract error handling and repeating to parent function in
// device_proto:192
for (;;) {
status = (hid_get_feature_report(mp_devhandle, (unsigned char *)(packet),
HID_REPORT_SIZE));
// FIXME handle getting libhid error message somewhere else
auto pwherr = hid_error(mp_devhandle);
std::wstring wherr = (pwherr != NULL) ? pwherr : L"No error message";
std::string herr(wherr.begin(), wherr.end());
Log::instance()(std::string("libhid error message: ") + herr,
Loglevel::DEBUG_L2);
if (status > 0) break; // success
if (retry_count++ >= m_retry_receiving_count) {
Log::instance()(
"Maximum retry count reached" + std::to_string(retry_count),
Loglevel::WARNING);
break;
}
Log::instance()("Retrying... " + std::to_string(retry_count),
Loglevel::DEBUG);
std::this_thread::sleep_for(m_retry_timeout);
}
return status;
}
Stick10::Stick10():
Device(0x20a0, 0x4108, DeviceModel::PRO, 100ms, 100, 100ms)
{}
Stick20::Stick20():
Device(0x20a0, 0x4109, DeviceModel::STORAGE, 200ms, 40, 200ms)
{}
|