blob: a23e1b339e9d3dc7d50ed47faa01055208ca73d5 (
plain)
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#ifndef DEVICE_H
#define DEVICE_H
#include <chrono>
#include <hidapi/hidapi.h>
#include <cstdint>
#include <string>
#define HID_REPORT_SIZE 65
#include <atomic>
namespace nitrokey {
namespace device {
using namespace std::chrono_literals;
using std::chrono::milliseconds;
struct EnumClassHash
{
template <typename T>
std::size_t operator()(T t) const
{
return static_cast<std::size_t>(t);
}
};
enum class DeviceModel{
PRO,
STORAGE
};
class Device {
public:
struct ErrorCounters{
int wrong_CRC;
int CRC_other_than_awaited;
int busy;
int total_retries;
int sending_error;
int receiving_error;
int total_comm_runs;
int storage_commands;
int successful;
std::string get_as_string();
} m_counters = {};
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);
virtual ~Device(){show_stats(); disconnect();}
// lack of device is not actually an error,
// so it doesn't throw
virtual bool connect();
virtual bool disconnect();
/*
* Sends packet of HID_REPORT_SIZE.
*/
virtual int send(const void *packet);
/*
* Gets packet of HID_REPORT_SIZE.
* Can sleep. See below.
*/
virtual int recv(void *packet);
bool is_connected();
void show_stats();
ErrorCounters get_stats(){ return m_counters; }
int get_retry_receiving_count() const { return m_retry_receiving_count; };
int get_retry_sending_count() const { return m_retry_sending_count; };
std::chrono::milliseconds get_retry_timeout() const { return m_retry_timeout; };
std::chrono::milliseconds get_send_receive_delay() const {return m_send_receive_delay;}
int get_last_command_status() {int a = std::atomic_exchange(&last_command_status, static_cast<uint8_t>(0)); return a;};
void set_last_command_status(uint8_t _err) { last_command_status = _err;} ;
bool last_command_sucessfull() const {return last_command_status == 0;};
DeviceModel get_device_model() const {return m_model;}
private:
std::atomic<uint8_t> last_command_status;
protected:
const uint16_t m_vid;
const uint16_t m_pid;
const DeviceModel m_model;
/*
* While the project uses Signal11 portable HIDAPI
* library, there's no way of doing it asynchronously,
* hence polling.
*/
const int m_retry_sending_count;
const int m_retry_receiving_count;
const std::chrono::milliseconds m_retry_timeout;
const std::chrono::milliseconds m_send_receive_delay;
std::atomic<hid_device *>mp_devhandle;
};
class Stick10 : public Device {
public:
Stick10();
};
class Stick20 : public Device {
public:
Stick20();
};
}
}
#endif
|