forked from Grumbel/udraw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
usb_device.hpp
186 lines (165 loc) · 4.74 KB
/
usb_device.hpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Linux driver for the uDraw graphic tablet
// Copyright (C) 2012 Ingo Ruhnke <grumbel@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef HEADER_USB_DEVICE_HPP
#define HEADER_USB_DEVICE_HPP
class USBDevice
{
private:
struct usb_device* dev;
struct usb_dev_handle* handle;
public:
USBDevice(struct usb_device* dev_) :
dev(dev_),
handle()
{
handle = usb_open(dev);
if (!handle)
{
throw std::runtime_error("Error opening usb device");
}
}
~USBDevice()
{
usb_close(handle);
}
void reset()
{
if (usb_reset(handle) != 0)
{
std::cout << "Failure to reset" << std::endl;
}
}
void detach_kernel_driver(int iface)
{
if (usb_detach_kernel_driver_np(handle, iface) < 0)
{
std::cerr << "couldn't detach interface " << iface << std::endl;
}
}
void claim_interface(int iface)
{
if (usb_claim_interface(handle, iface) != 0)
{
std::ostringstream str;
str << "Couldn't claim interface " << iface;
throw std::runtime_error(str.str());
}
}
void release_interface(int iface)
{
if (usb_release_interface(handle, iface) != 0)
{
std::ostringstream str;
str << "Couldn't release interface " << iface;
throw std::runtime_error(str.str());
}
}
void set_configuration(int configuration)
{
if (usb_set_configuration(handle, configuration) != 0)
{
std::ostringstream str;
str << "Couldn't set configuration " << configuration;
throw std::runtime_error(str.str());
}
}
void set_altinterface(int interface)
{
if (usb_set_altinterface(handle, interface) != 0)
{
std::ostringstream str;
str << "Couldn't set alternative interface " << interface;
throw std::runtime_error(str.str());
}
}
int read(int endpoint, uint8_t* data, int len)
{
return usb_interrupt_read(handle, endpoint, (char*)data, len, 0);
}
int write(int endpoint, uint8_t* data, int len)
{
return usb_interrupt_write(handle, endpoint, (char*)data, len, 0);
}
/* uint8_t requesttype
uint8_t request
uint16_t value;
uint16_t index;
uint16_t length;
*/
int ctrl_msg(int requesttype, int request,
int value, int index,
uint8_t* data, int size)
{
return usb_control_msg(handle,
requesttype, request,
value, index,
(char*)data, size,
0 /* timeout */);
}
void print_info()
{
for(int i = 0; i < dev->descriptor.bNumConfigurations; ++i)
{
std::cout << "Configuration: " << i << std::endl;
for(int j = 0; j < dev->config[i].bNumInterfaces; ++j)
{
std::cout << " Interface " << j << ":" << std::endl;
for(int k = 0; k < dev->config[i].interface[j].num_altsetting; ++k)
{
for(int l = 0; l < dev->config[i].interface[j].altsetting[k].bNumEndpoints; ++l)
{
std::cout << " Endpoint: "
<< int(dev->config[i].interface[j].altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)
<< ((dev->config[i].interface[j].altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? " (IN)" : " (OUT)")
<< std::endl;
}
}
}
}
}
void listen(int endpoint, std::function<void (uint8_t* data, int)> callback)
{
try
{
bool this_quit = false;
std::cout << "Reading from endpoint " << endpoint << std::endl;;
while(!this_quit)
{
uint8_t data[8192];
int ret = read(endpoint, data, sizeof(data));
if (ret < 0)
{
std::cerr << "USBError: " << ret << "\n" << usb_strerror() << std::endl;
std::cerr << "Shutting down" << std::endl;
this_quit = true;
}
else
{
callback(data, ret);
}
}
}
catch(std::exception& err)
{
std::cout << "Error: " << err.what() << std::endl;
}
}
private:
USBDevice(const USBDevice&) = delete;
USBDevice& operator=(const USBDevice&) = delete;
};
#endif
/* EOF */