-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathusb_driver.cpp
More file actions
221 lines (176 loc) · 5.28 KB
/
Copy pathusb_driver.cpp
File metadata and controls
221 lines (176 loc) · 5.28 KB
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include "stdafx.h"
#include "usb_driver.h"
/* static struct to ensure the USB subsystem is initialized on start */
struct USBInit
{
USBInit() { usb_init(); usb_find_busses(); usb_find_devices(); }
};
static struct USBInit g_USBInit;
static struct usb_device *FindDevice(int iVendorID, int iProductID)
{
for (usb_bus *bus = usb_get_busses(); bus; bus = bus->next)
for (struct usb_device *dev = bus->devices; dev; dev = dev->next)
if (iVendorID == dev->descriptor.idVendor && iProductID == dev->descriptor.idProduct)
return dev;
printf("FindDevice(): no match for VID 0x%04x, PID 0x%04x.", iVendorID, iProductID);
return NULL;
}
bool USBDriver_Impl::DeviceExists(uint16_t iVendorID, uint16_t iProductID)
{
return FindDevice(iVendorID, iProductID) != NULL;
}
USBDriver_Impl::USBDriver_Impl()
{
m_pHandle = NULL;
}
USBDriver_Impl::~USBDriver_Impl()
{
Close();
}
bool USBDriver_Impl::Open(int iVendorID, int iProductID)
{
Close();
if (usb_find_busses() < 0)
{
printf("Libusb: usb_find_busses: %s", usb_strerror());
return false;
}
if (usb_find_devices() < 0)
{
printf("Libusb: usb_find_devices: %s", usb_strerror());
return false;
}
struct usb_device *dev = FindDevice(iVendorID, iProductID);
if (dev == NULL)
{
printf("Libusb: no match for %04x, %04x.", iVendorID, iProductID);
return false;
}
m_pHandle = usb_open(dev);
if (m_pHandle == NULL)
{
printf("Libusb: usb_open: %s", usb_strerror());
return false;
}
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
// The device may be claimed by a kernel driver. Attempt to reclaim it.
for (unsigned iface = 0; iface < dev->config->bNumInterfaces; iface++)
{
int iResult = usb_detach_kernel_driver_np(m_pHandle, iface);
// no attached driver, no error -- ignore these
if (iResult == -ENODATA || iResult == 0)
continue;
printf("usb_detach_kernel_driver_np: %s\n", usb_strerror());
#ifdef LIBUSB_HAS_GET_DRIVER_NP
// on EPERM, a driver exists and we can't detach - report which one
if (iResult == -EPERM)
{
char szDriverName[16];
strcpy(szDriverName, "(unknown)");
usb_get_driver_np(m_pHandle, iface, szDriverName, 16);
printf("(cannot detach kernel driver \"%s\")", szDriverName);
}
#endif // LIBUSB_HAS_GET_DRIVER_NP
Close();
return false;
}
#endif // LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
if (!SetConfiguration(dev->config->bConfigurationValue))
{
printf("Libusb: usb_set_configuration: %s", usb_strerror());
Close();
return false;
}
// attempt to claim all interfaces for this device
for (unsigned i = 0; i < dev->config->bNumInterfaces; i++)
{
if (!ClaimInterface(i))
{
printf("Libusb: usb_claim_interface(%i): %s", i, usb_strerror());
Close();
return false;
}
}
return true;
}
void USBDriver_Impl::Close()
{
// never opened
if (m_pHandle == NULL)
return;
usb_set_altinterface(m_pHandle, 0);
usb_reset(m_pHandle);
usb_close(m_pHandle);
m_pHandle = NULL;
}
int USBDriver_Impl::ControlMessage(int iType, int iRequest, int iValue, int iIndex, char *pData, int iSize, int iTimeout)
{
return usb_control_msg(m_pHandle, iType, iRequest, iValue, iIndex, pData, iSize, iTimeout);
}
int USBDriver_Impl::BulkRead(int iEndpoint, char *pData, int iSize, int iTimeout)
{
return usb_bulk_read(m_pHandle, iEndpoint, pData, iSize, iTimeout);
}
int USBDriver_Impl::BulkWrite(int iEndpoint, char *pData, int iSize, int iTimeout)
{
return usb_bulk_write(m_pHandle, iEndpoint, pData, iSize, iTimeout);
}
int USBDriver_Impl::InterruptRead(int iEndpoint, char *pData, int iSize, int iTimeout)
{
return usb_interrupt_read(m_pHandle, iEndpoint, pData, iSize, iTimeout);
}
int USBDriver_Impl::InterruptWrite(int iEndpoint, char *pData, int iSize, int iTimeout)
{
return usb_interrupt_write(m_pHandle, iEndpoint, pData, iSize, iTimeout);
}
bool USBDriver_Impl::SetConfiguration(int iConfig)
{
return usb_set_configuration(m_pHandle, iConfig) == 0;
}
bool USBDriver_Impl::ClaimInterface(int iInterface)
{
return usb_claim_interface(m_pHandle, iInterface) == 0;
}
bool USBDriver_Impl::ReleaseInterface(int iInterface)
{
return usb_release_interface(m_pHandle, iInterface) == 0;
}
const char* USBDriver_Impl::GetError() const
{
return usb_strerror();
}
USBDriver::USBDriver()
{
m_pDriver = NULL;
}
USBDriver::~USBDriver()
{
delete m_pDriver;
}
bool USBDriver::OpenInternal(uint16_t iVendorID, uint16_t iProductID)
{
Close();
/* see if this device actually exists before trying to open it */
if (!USBDriver_Impl::DeviceExists(iVendorID, iProductID))
{
printf("USBDriver::OpenInternal(0x%04x, 0x%04x): device does not exist\n", iVendorID, iProductID);
return false;
}
m_pDriver = new USBDriver_Impl();
/* if !m_pDriver, this build cannot support USB drivers. */
if (m_pDriver == NULL)
{
printf("USBDriver::OpenInternal(): Create failed. (No driver impl?");
return false;
}
return m_pDriver->Open(iVendorID, iProductID);
}
bool USBDriver::Open()
{
return false;
}
void USBDriver::Close()
{
if (m_pDriver)
m_pDriver->Close();
}