Instrument Neutral Distributed Interface INDI 2.2.5
indiusbdevice.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright(c) 2011 Gerry Rozema. All rights reserved.
3
4 Upgrade to libusb 1.0 by CloudMakers, s. r. o.
5 Copyright(c) 2013 CloudMakers, s. r. o. All rights reserved.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License version 2 as published by the Free Software Foundation.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*******************************************************************************/
21
22#include "indiusbdevice.h"
23
24#include <config-usb.h>
25
26#ifndef USB1_HAS_LIBUSB_ERROR_NAME
27const char *LIBUSB_CALL libusb_error_name(int errcode)
28{
29 static char buffer[30];
30 sprintf(buffer, "error %d", errcode);
31 return buffer;
32}
33#endif
34
35static libusb_context *ctx = nullptr;
36
37namespace INDI
38{
39
41{
42 dev = nullptr;
43 usb_handle = nullptr;
45 InputEndpoint = 0;
46
47 if (ctx == nullptr)
48 {
49 int rc = libusb_init(&ctx);
50 if (rc < 0)
51 {
52 fprintf(stderr, "USBDevice: Can't initialize libusb\n");
53 }
54 }
55}
56
58{
59 libusb_exit(ctx);
60}
61
62libusb_device *USBDevice::FindDevice(int vendor, int product, int searchindex)
63{
64 int index = 0;
65 libusb_device **usb_devices;
66 struct libusb_device_descriptor descriptor;
67 ssize_t total = libusb_get_device_list(ctx, &usb_devices);
68 if (total < 0)
69 {
70 fprintf(stderr, "USBDevice: Can't get device list\n");
71 return 0;
72 }
73 for (int i = 0; i < total; i++)
74 {
75 libusb_device *device = usb_devices[i];
76 if (!libusb_get_device_descriptor(device, &descriptor))
77 {
78 if (descriptor.idVendor == vendor && descriptor.idProduct == product)
79 {
80 if (index == searchindex)
81 {
82 libusb_ref_device(device);
83 libusb_free_device_list(usb_devices, 1);
84 fprintf(stderr, "Found device %04x/%04x/%d\n", descriptor.idVendor, descriptor.idProduct, index);
85 return device;
86 }
87 else
88 {
89 fprintf(stderr, "Skipping device %04x/%04x/%d\n", descriptor.idVendor, descriptor.idProduct, index);
90 index++;
91 }
92 }
93 else
94 {
95 fprintf(stderr, "Skipping device %04x/%04x\n", descriptor.idVendor, descriptor.idProduct);
96 }
97 }
98 }
99 libusb_free_device_list(usb_devices, 1);
100 return nullptr;
101}
102
104{
105 if (dev == nullptr)
106 return -1;
107
108 int rc = libusb_open(dev, &usb_handle);
109
110 if (rc >= 0)
111 {
112 if (libusb_kernel_driver_active(usb_handle, 0) == 1)
113 {
114 rc = libusb_detach_kernel_driver(usb_handle, 0);
115 if (rc < 0)
116 {
117 fprintf(stderr, "USBDevice: libusb_detach_kernel_driver -> %s\n", libusb_error_name(rc));
118 }
119 }
120 if (rc >= 0)
121 {
122 rc = libusb_claim_interface(usb_handle, 0);
123 if (rc < 0)
124 {
125 fprintf(stderr, "USBDevice: libusb_claim_interface -> %s\n", libusb_error_name(rc));
126 }
127 }
128 return FindEndpoints();
129 }
130 return rc;
131}
132
134{
135 libusb_close(usb_handle);
136}
137
139{
140 struct libusb_config_descriptor *config;
141 struct libusb_interface_descriptor *interface;
142 int rc = libusb_get_config_descriptor(dev, 0, &config);
143 if (rc < 0)
144 {
145 fprintf(stderr, "USBDevice: libusb_get_config_descriptor -> %s\n", libusb_error_name(rc));
146 return rc;
147 }
148
149 interface = (struct libusb_interface_descriptor *) & (config->interface[0].altsetting[0]);
150 for (int i = 0; i < interface->bNumEndpoints; i++)
151 {
152 fprintf(stderr, "Endpoint %04x %04x\n", interface->endpoint[i].bEndpointAddress,
153 interface->endpoint[i].bmAttributes);
154 int dir = interface->endpoint[i].bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK;
155 if (dir == LIBUSB_ENDPOINT_IN)
156 {
157 fprintf(stderr, "Got an input endpoint\n");
158 InputEndpoint = interface->endpoint[i].bEndpointAddress;
159 InputType = interface->endpoint[i].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK;
160 }
161 else if (dir == LIBUSB_ENDPOINT_OUT)
162 {
163 fprintf(stderr, "Got an output endpoint\n");
164 OutputEndpoint = interface->endpoint[i].bEndpointAddress;
165 OutputType = interface->endpoint[i].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK;
166 }
167 }
168 return 0;
169}
170
171int USBDevice::ReadInterrupt(unsigned char *buf, int count, int timeout)
172{
173 int transferred;
174 int rc = libusb_interrupt_transfer(usb_handle, InputEndpoint, buf, count, &transferred, timeout);
175 if (rc < 0)
176 {
177 fprintf(stderr, "USBDevice: libusb_interrupt_transfer -> %s\n", libusb_error_name(rc));
178 }
179 return rc < 0 ? rc : transferred;
180}
181
182int USBDevice::WriteInterrupt(unsigned char *buf, int count, int timeout)
183{
184 int transferred;
185 int rc = libusb_interrupt_transfer(usb_handle, OutputEndpoint, buf, count, &transferred, timeout);
186 if (rc < 0)
187 {
188 fprintf(stderr, "USBDevice: libusb_interrupt_transfer -> %s\n", libusb_error_name(rc));
189 }
190 return rc < 0 ? rc : transferred;
191}
192
193int USBDevice::ReadBulk(unsigned char *buf, int count, int timeout)
194{
195 int transferred;
196 int rc = libusb_bulk_transfer(usb_handle, InputEndpoint, buf, count, &transferred, timeout);
197 if (rc < 0)
198 {
199 fprintf(stderr, "USBDevice: libusb_bulk_transfer -> %s\n", libusb_error_name(rc));
200 }
201 return rc < 0 ? rc : transferred;
202}
203
204int USBDevice::WriteBulk(unsigned char *buf, int count, int timeout)
205{
206 int transferred;
207 int rc = libusb_bulk_transfer(usb_handle, OutputEndpoint, buf, count, &transferred, timeout);
208 if (rc < 0)
209 {
210 fprintf(stderr, "USBDevice: libusb_bulk_transfer -> %s\n", libusb_error_name(rc));
211 }
212 return rc < 0 ? rc : transferred;
213}
214
215int USBDevice::ControlMessage(unsigned char request_type, unsigned char request, unsigned int value,
216 unsigned int index, unsigned char *data, unsigned char len)
217{
218 int rc = libusb_control_transfer(usb_handle, request_type, request, value, index, data, len, 5000);
219 if (rc < 0)
220 {
221 fprintf(stderr, "USBDevice: libusb_control_transfer -> %s\n", libusb_error_name(rc));
222 }
223 return rc;
224}
225
226}
hid_device * device
int WriteBulk(unsigned char *buf, int nbytes, int timeout)
int WriteInterrupt(unsigned char *, int, int)
libusb_device * dev
int ReadBulk(unsigned char *buf, int nbytes, int timeout)
libusb_device_handle * usb_handle
int ReadInterrupt(unsigned char *, int, int)
int ControlMessage(unsigned char request_type, unsigned char request, unsigned int value, unsigned int index, unsigned char *data, unsigned char len)
libusb_device * FindDevice(int, int, int)
const char *LIBUSB_CALL libusb_error_name(int errcode)
Namespace to encapsulate INDI client, drivers, and mediator classes.