36 #include <libusb-1.0/libusb.h> 45 libusb_get_port_number(dev),
46 libusb_get_device_address(dev),
51 bool UsbDevice::handleError(
int err)
54 switch ((libusb_error)err) {
58 case LIBUSB_ERROR_TIMEOUT:
61 case LIBUSB_ERROR_BUSY:
62 case LIBUSB_ERROR_OVERFLOW:
63 case LIBUSB_ERROR_INVALID_PARAM:
64 case LIBUSB_ERROR_INTERRUPTED:
65 case LIBUSB_ERROR_NO_MEM:
66 case LIBUSB_ERROR_PIPE:
71 case LIBUSB_ERROR_ACCESS:
72 case LIBUSB_ERROR_NO_DEVICE:
73 case LIBUSB_ERROR_NOT_FOUND:
74 case LIBUSB_ERROR_NOT_SUPPORTED:
75 case LIBUSB_ERROR_OTHER:
84 void UsbDevice::throwError(
int err)
86 error_code_ = (libusb_error)err;
87 error_str_ = libusb_error_name(err);
92 int UsbDevice::getLastError(std::string &str)
const 97 void UsbDevice::setDebugLevel(uint8_t level)
99 if (level > LIBUSB_LOG_LEVEL_DEBUG) {
100 level = LIBUSB_LOG_LEVEL_DEBUG;
102 #if LIBUSB_API_VERSION >= 0x01000107 103 libusb_set_option(ctx_, LIBUSB_OPTION_LOG_LEVEL, level);
105 libusb_set_debug(ctx_, level);
109 void UsbDevice::init()
113 libusb_handle_ = NULL;
114 throw_errors_ =
false;
115 memset(bulk_threads_enable_, 0x00,
sizeof(bulk_threads_enable_));
116 memset(interrupt_threads_enable_, 0x00,
sizeof(interrupt_threads_enable_));
119 #if LIBUSB_API_VERSION >= 0x01000107 120 libusb_set_option(ctx_, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
122 libusb_set_debug(ctx_, LIBUSB_LOG_LEVEL_NONE);
126 UsbDevice::UsbDevice(uint16_t vid, uint16_t pid, uint8_t mi)
129 setDevceIds(vid, pid, mi);
131 UsbDevice::UsbDevice(uint16_t vid, uint16_t pid)
134 setDevceIds(vid, pid, 0x00);
136 UsbDevice::UsbDevice()
139 setDevceIds(0x0000, 0x0000, 0x00);
141 UsbDevice::~UsbDevice()
150 void UsbDevice::setDevceIds(uint16_t vid, uint16_t pid, uint8_t mi)
157 void UsbDevice::listDevices(uint16_t vid, uint16_t pid, std::vector<Location> &vec)
159 const std::vector<UsbIds> ids(1,
UsbIds(vid, pid));
160 listDevices(ids, vec);
163 void UsbDevice::listDevices(
const std::vector<UsbIds> &ids, std::vector<Location> &vec)
167 libusb_context *ctx = NULL;
169 #if LIBUSB_API_VERSION >= 0x01000107 170 libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
172 libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_NONE);
175 libusb_device **list;
176 ssize_t cnt = libusb_get_device_list(ctx, &list);
178 for (ssize_t i = 0; i < cnt; i++) {
179 libusb_device *device = list[i];
180 struct libusb_device_descriptor desc;
181 if (libusb_get_device_descriptor(device, &desc) == LIBUSB_SUCCESS) {
182 for (
size_t i = 0; i < ids.size(); i++) {
183 if ((!ids[i].vid || ids[i].vid == desc.idVendor) && (!ids[i].pid || ids[i].pid == desc.idProduct)) {
191 libusb_free_device_list(list, 1);
196 void UsbDevice::listDevices(std::vector<Location> &vec)
const 198 listDevices(vid_, pid_, vec);
205 libusb_device **list;
206 ssize_t cnt = libusb_get_device_list(ctx_, &list);
209 for (i = 0; i < cnt; i++) {
210 libusb_device *device = list[i];
211 struct libusb_device_descriptor desc;
212 if (libusb_get_device_descriptor(device, &desc) == LIBUSB_SUCCESS) {
213 if ((!vid_ || vid_ == desc.idVendor) && (!pid_ || pid_ == desc.idProduct)) {
215 if (location.
match(loc)) {
216 libusb_device_handle *handle;
217 if (libusb_open(device, &handle) == LIBUSB_SUCCESS) {
218 if (libusb_kernel_driver_active(handle, mi_) == 1) {
219 libusb_detach_kernel_driver(handle, mi_);
221 if (libusb_claim_interface(handle, mi_) == LIBUSB_SUCCESS) {
223 libusb_handle_ = handle;
227 libusb_close(handle);
235 libusb_free_device_list(list, 1);
239 void UsbDevice::close()
241 for (
int i = 0; i < 128; i++) {
242 bulk_threads_enable_[i] =
false;
243 interrupt_threads_enable_[i] =
false;
248 void UsbDevice::closeDevice()
252 if (libusb_handle_) {
253 libusb_release_interface(libusb_handle_, 0);
254 libusb_close(libusb_handle_);
257 libusb_handle_ = NULL;
260 bool UsbDevice::bulkWrite(
const void * data,
int size,
unsigned char endpoint,
int timeout)
262 if ((libusb_handle_ == NULL) || !open_) {
266 int err = libusb_bulk_transfer(libusb_handle_, endpoint & ~LIBUSB_ENDPOINT_IN, (
unsigned char *)data, size, &actual,
269 success = handleError(err);
270 success &= size == actual;
273 int UsbDevice::bulkRead(
void * data,
int size,
unsigned char endpoint,
int timeout)
275 if ((libusb_handle_ == NULL) || !open_) {
279 int err = libusb_bulk_transfer(libusb_handle_, endpoint | LIBUSB_ENDPOINT_IN, (
unsigned char *)data, size, &actual,
281 return handleError(err) ? actual : -1;
283 bool UsbDevice::interruptWrite(
const void * data,
int size,
unsigned char endpoint,
int timeout)
285 if ((libusb_handle_ == NULL) || !open_) {
289 int err = libusb_interrupt_transfer(libusb_handle_, endpoint & ~LIBUSB_ENDPOINT_IN, (
unsigned char *)data, size,
292 success = handleError(err);
293 success &= size == actual;
296 int UsbDevice::interruptRead(
void * data,
int size,
unsigned char endpoint,
int timeout)
298 if ((libusb_handle_ == NULL) || !open_) {
302 int err = libusb_interrupt_transfer(libusb_handle_, endpoint | LIBUSB_ENDPOINT_IN, (
unsigned char *)data, size,
304 return handleError(err) ? actual : -1;
307 void UsbDevice::bulkReadThread(
Callback callback,
unsigned char endpoint)
312 while (bulk_threads_enable_[endpoint]) {
314 size = bulkRead(data,
sizeof(data), endpoint, 100);
316 callback(data, size);
319 bulk_threads_enable_[endpoint] = 0;
324 void UsbDevice::interruptReadThread(
Callback callback,
unsigned char endpoint)
329 while (interrupt_threads_enable_[endpoint]) {
331 size = interruptRead(data,
sizeof(data), endpoint, 100);
333 callback(data, size);
336 interrupt_threads_enable_[endpoint] =
false;
342 void UsbDevice::stopBulkReadThread(
unsigned char endpoint)
345 bulk_threads_enable_[endpoint] =
false;
346 if (bulk_threads_[endpoint].joinable()) {
347 bulk_threads_[endpoint].join();
350 void UsbDevice::startBulkReadThread(
Callback callback,
unsigned char endpoint)
353 stopBulkReadThread(endpoint);
354 bulk_threads_enable_[endpoint] =
true;
355 bulk_threads_[endpoint] = boost::thread(&UsbDevice::bulkReadThread,
this, callback, endpoint);
357 void UsbDevice::stopInterruptReadThread(
unsigned char endpoint)
361 interrupt_threads_enable_[endpoint] =
false;
362 if (interrupt_threads_[endpoint].joinable()) {
363 interrupt_threads_[endpoint].join();
366 void UsbDevice::startInterruptReadThread(
Callback callback,
unsigned char endpoint)
369 stopBulkReadThread(endpoint);
370 interrupt_threads_enable_[endpoint] =
true;
371 interrupt_threads_[endpoint] = boost::thread(&UsbDevice::interruptReadThread,
this, callback, endpoint);
static bool match(const Location &a, const Location &b)
static UsbDevice::Location locationFromLibUsbDevice(libusb_device *dev, const libusb_device_descriptor desc)
boost::function< void(const void *data, int size)> Callback