Instrument Neutral Distributed Interface INDI  2.0.2
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
27 const 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 
35 static libusb_context *ctx = nullptr;
36 
37 namespace INDI
38 {
39 
41 {
42  dev = nullptr;
43  usb_handle = nullptr;
44  OutputEndpoint = 0;
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 
62 libusb_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 
171 int 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 
182 int 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 
193 int 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 
204 int 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 
215 int 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
Definition: indiusbdevice.h:40
int ReadBulk(unsigned char *buf, int nbytes, int timeout)
virtual ~USBDevice()
libusb_device_handle * usb_handle
Definition: indiusbdevice.h:41
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)
std::vector< uint8_t > buffer
Namespace to encapsulate INDI client, drivers, and mediator classes.