blob: 83cf245d83f03653044b25600eac56451972aca3 [file] [log] [blame]
Austin Schuh9b360e92013-03-27 04:47:04 +00001#include "libusb_wrap.h"
2
Brian Silverman798c7782013-03-28 16:48:02 -07003#include <iostream>
4
5#include "aos/common/logging/logging.h"
6
Austin Schuh9b360e92013-03-27 04:47:04 +00007LibUSB::LibUSB() {
Brian Silverman798c7782013-03-28 16:48:02 -07008 if (libusb_init(&ctx_) < 0) {
9 LOG(FATAL, "libusb_init(%p) failed\n", &ctx_);
10 }
Austin Schuh9b360e92013-03-27 04:47:04 +000011 libusb_set_debug(ctx_, 3);
12}
13
14LibUSBDeviceHandle *LibUSB::FindDeviceWithVIDPID(int vid, int pid) {
15 int r;
16 libusb_device **devs;
17 libusb_device_handle *dev_handle;
18
19 ssize_t cnt;
20 cnt = libusb_get_device_list(ctx_, &devs);
Brian Silverman798c7782013-03-28 16:48:02 -070021 if (cnt < 0) {
22 LOG(ERROR, "Get Device Error\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000023 return NULL;
24 }
Brian Silverman798c7782013-03-28 16:48:02 -070025 LOG(INFO, "%d Devices in list.\n", cnt);
Austin Schuh9b360e92013-03-27 04:47:04 +000026 bool found = false;
27 for (int i = 0; i < cnt; ++i) {
28 struct libusb_device_descriptor desc;
29 r = libusb_get_device_descriptor(devs[i], &desc);
Brian Silverman798c7782013-03-28 16:48:02 -070030 if (r < 0) {
31 LOG(FATAL, "lib_usb_get_device_descriptor(%p, %p) failed\n",
32 devs[i], &desc);
33 }
Austin Schuh9b360e92013-03-27 04:47:04 +000034 if (desc.idVendor == vid && desc.idProduct == pid) {
Brian Silverman798c7782013-03-28 16:48:02 -070035 LOG(INFO, "Device %d:%d matches\n",
36 (int)libusb_get_bus_number(devs[i]),
37 (int)libusb_get_device_address(devs[i]));
Austin Schuh9b360e92013-03-27 04:47:04 +000038 r = libusb_open(devs[i], &dev_handle);
39 if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070040 LOG(INFO, "Device already in use, trying next one.\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000041 continue;
42 }
43 if (r < 0) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070044 LOG(WARNING, "Failed to open device.\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000045 } else {
46 found = true;
47 break;
48 }
49 }
50 }
51 libusb_free_device_list(devs, 1);
52 if (!found) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070053 LOG(ERROR, "Couldn't open device.\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000054 return NULL;
55 }
56
57 if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070058 LOG(INFO, "Kernel Driver Active\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000059 if (libusb_detach_kernel_driver(dev_handle, 0) == 0) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070060 LOG(INFO, "Kernel Driver Detached!\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000061 } else {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070062 LOG(ERROR, "Couldn't detach kernel driver.\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000063 return NULL;
64 }
65 }
66
67 r = libusb_claim_interface(dev_handle, 0);
68 if (r < 0) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070069 LOG(ERROR, "Cannot Claim Interface\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000070 return 0;
71 }
Brian Silvermana4f9ef22013-03-30 14:31:16 -070072 LOG(INFO, "Claimed Interface\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000073 return new LibUSBDeviceHandle(dev_handle);
74}
75
76LibUSB::~LibUSB() {
77 libusb_exit(ctx_);
78}
79
Brian Silverman4ad17832013-03-31 01:26:08 -070080void LibUSB::HandleEvents() {
81 int ret = libusb_handle_events(ctx_);
82 if (ret != 0) {
83 LOG(FATAL, "libusb_handle_events(%p) returned %d\n", ctx_, ret);
84 }
85}
86
Austin Schuh9b360e92013-03-27 04:47:04 +000087LibUSBDeviceHandle::LibUSBDeviceHandle(
88 libusb_device_handle *dev_handle) : dev_handle_(dev_handle) { }
89
90LibUSBDeviceHandle::~LibUSBDeviceHandle() {
Brian Silverman2e0dcfd2013-03-30 22:44:40 -070091 int r = libusb_release_interface(dev_handle_, 0);
Austin Schuh9b360e92013-03-27 04:47:04 +000092 if (r != 0) {
Brian Silvermana4f9ef22013-03-30 14:31:16 -070093 LOG(FATAL, "Cannot Release Interface\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000094 }
Brian Silvermana4f9ef22013-03-30 14:31:16 -070095 LOG(INFO, "Released Interface\n");
Austin Schuh9b360e92013-03-27 04:47:04 +000096
97 libusb_close(dev_handle_);
98}
99
100int LibUSBDeviceHandle::interrupt_transfer(
101 unsigned char endpoint, unsigned char *data, int length,
102 int *transferred, unsigned int timeout) {
103 return libusb_interrupt_transfer(dev_handle_, endpoint, data, length,
104 transferred, timeout);
105}
106
107int LibUSBDeviceHandle::bulk_transfer(
108 unsigned char endpoint, unsigned char *data,
109 int length, int *transferred, unsigned int timeout) {
110 return libusb_bulk_transfer(dev_handle_, endpoint, data, length,
111 transferred, timeout);
112}
Brian Silverman4ad17832013-03-31 01:26:08 -0700113
114namespace libusb {
115
116Transfer::Transfer(size_t data_length,
117 void (*callback)(Transfer *, void *),
118 void *user_data)
119 : transfer_(libusb_alloc_transfer(0)),
120 data_(new uint8_t[data_length]),
121 data_length_(data_length),
122 callback_(callback),
123 user_data_(user_data) {
124}
125Transfer::~Transfer() {
126 libusb_free_transfer(transfer_);
127 delete data_;
128}
129
130void Transfer::FillInterrupt(LibUSBDeviceHandle *device,
131 unsigned char endpoint,
132 unsigned int timeout) {
133 libusb_fill_interrupt_transfer(transfer_,
134 device->dev_handle_,
135 endpoint,
136 data_,
137 data_length_,
138 StaticTransferCallback,
139 this,
140 timeout);
141}
142
143void Transfer::Submit() {
144 int ret = libusb_submit_transfer(transfer_);
145 if (ret != 0) {
146 if (ret == LIBUSB_ERROR_BUSY) {
147 LOG(FATAL, "transfer %p already submitted\n", this);
148 }
149 LOG(FATAL, "libusb error %d submitting transfer %p\n",
150 ret, this);
151 }
152}
153
154void Transfer::Cancel() {
155 int ret = libusb_cancel_transfer(transfer_);
156 if (ret != 0) {
157 LOG(FATAL, "libusb error %d cancelling transfer %p\n",
158 ret, this);
159 }
160}
161
162void Transfer::TransferCallback() {
163 callback_(this, user_data_);
164}
165
Brian Silvermanc554a8f2013-03-31 19:07:49 -0700166IsochronousTransfer::IsochronousTransfer(size_t packet_length,
167 int num_packets,
168 void (*callback)(Transfer *, void *),
169 void *user_data)
170 : Transfer(packet_length * num_packets, callback, user_data),
171 num_packets_(num_packets) {
172}
173
174void IsochronousTransfer::FillIsochronous(LibUSBDeviceHandle *device,
175 unsigned char endpoint,
176 unsigned int timeout) {
177 (void)device;
178 (void)endpoint;
179 (void)timeout;
180 /*libusb_fill_iso_transfer(transfer_,
181 device->dev_handle_,
182 endpoint,
183 data_,
184 data_length_,
185 num_packets_,
186 StaticTransferCallback,
187 this,
188 timeout);*/
189}
190
Brian Silverman4ad17832013-03-31 01:26:08 -0700191} // namespace libusb