- updated usbwrap.h to match latest libusb CVS devel tree
[barry.git] / src / usbwrap.h
blob489a13a2128a87d3bc95f4b4fdaf2e98b4c9d92e
1 ///
2 /// \file usbwrap.h
3 /// USB API wrapper
4 ///
6 /*
7 Copyright (C) 2005, Chris Frey
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
23 #ifndef __SB_USBWRAP_H__
24 #define __SB_USBWRAP_H__
26 #include <libusb.h>
27 #include <vector>
28 #include <map>
29 #include <stdexcept>
31 #define USBWRAP_DEFAULT_TIMEOUT 10000
33 class Data;
35 /// Namespace for the libusb-related wrapper classes. This namespace
36 /// may change in the future.
37 namespace Usb {
39 /// \addtogroup exceptions
40 /// @{
42 /// Thrown on low level USB errors.
43 class UsbError : public std::runtime_error
45 public:
46 UsbError(const std::string &str) : std::runtime_error(str) {}
49 /// @}
52 class Match
54 libusb_match_handle_t m_match;
55 int m_lasterror;
56 public:
57 Match(int vendor, int product)
58 : m_match(0)
60 if( libusb_match_devices_by_vendor(&m_match, vendor, product) < 0 )
61 throw UsbError("match failed");
64 ~Match()
66 libusb_free_match(m_match);
69 bool next_device(libusb_device_id_t *devid)
71 m_lasterror = libusb_match_next_device(m_match, devid);
72 return m_lasterror >= 0;
79 class Device;
81 // This class behaves a lot like std::auto_ptr<>, in that only one
82 // object can ever own a given libusb_io_handle_t at a time. The
83 // copy constructors and operator=() make it safe to store in a vector.
84 class IO
86 Device *m_dev;
87 mutable libusb_io_handle_t *m_handle;
89 // helpers
90 void cleanup();
92 IO(Device *dev, libusb_io_handle_t *handle);
93 public:
94 IO(Device &dev, libusb_io_handle_t *handle);
96 // copyable... the copied-to object will contain the handle,
97 // and other will be invalidated
98 IO(const IO &other);
99 IO& operator=(const IO &other);
101 // will cancel if not complete, and will always free if valid
102 ~IO();
105 // operators
106 bool operator==(libusb_io_handle_t *h) const { return m_handle == h; }
108 // if valid, this object contains a pending usb io transfer handle...
109 // when compeleted, canceled, or freed, this will return false
110 bool IsValid() const { return m_handle != 0; }
111 void Forget() { m_handle = 0; }
112 void Free() { cleanup(); }
114 // API wrappers
115 bool IsCompleted() const;
116 void Wait();
117 void Cancel();
118 int GetStatus() const;
119 int GetSize() const;
120 int GetReqSize() const;
121 int GetEndpoint() const;
122 Device& GetDevice() const { return *m_dev; }
123 unsigned char * GetData();
124 const unsigned char * GetData() const;
126 // static helpers for various states
127 static IO InvalidIO() { return IO(0, 0); }
131 // Const IO - used by Device when it wishes to safely expose its list
132 // of tracked IO handles, without letting the caller take ownership
133 class CIO
135 const IO &m_io;
137 public:
138 CIO(const IO &io) : m_io(io) {}
140 // operators
141 bool operator==(libusb_io_handle_t *h) const
142 { return m_io.operator==(h); }
144 // if valid, this object contains a pending usb io transfer handle...
145 // when compeleted, canceled, or freed, this will return false
146 bool IsValid() const { return m_io.IsValid(); }
148 // API wrappers
149 bool IsCompleted() const { return m_io.IsCompleted(); }
150 int GetStatus() const { return m_io.GetStatus();}
151 int GetSize() const { return m_io.GetSize(); }
152 int GetReqSize() const { return m_io.GetReqSize();}
153 int GetEndpoint() const { return m_io.GetEndpoint(); }
154 Device& GetDevice() const { return m_io.GetDevice(); }
155 const unsigned char * GetData() const { return m_io.GetData(); }
160 class Device
162 public:
163 typedef std::vector<IO> io_list_type;
165 private:
166 libusb_device_id_t m_id;
167 libusb_dev_handle_t m_handle;
169 io_list_type m_ios;
171 int m_timeout;
172 int m_lasterror;
174 public:
175 Device(libusb_device_id_t id)
176 : m_id(id), m_timeout(USBWRAP_DEFAULT_TIMEOUT)
178 if( libusb_open(m_id, &m_handle) < 0 )
179 throw UsbError("open failed");
182 ~Device()
184 ClearIO(); // remove all pending IO before close
185 libusb_close(m_handle);
188 /////////////////////////////
189 // Data access
191 libusb_device_id_t GetID() const { return m_id; }
192 libusb_dev_handle_t GetHandle() const { return m_handle; }
193 int GetLastError() const { return m_lasterror; }
196 /////////////////////////////
197 // Device manipulation
199 bool SetConfiguration(unsigned char cfg);
200 bool ClearHalt(int ep);
201 bool Reset();
204 /////////////////////////////
205 // IO functions
207 // perform async io and track the handles inside Device
208 void TrackBulkRead(int ep, Data &data);
209 void TrackBulkWrite(int ep, const Data &data);
210 void TrackInterruptRead(int ep, Data &data);
211 void TrackInterruptWrite(int ep, const Data &data);
212 IO PollCompletions(); //< extracts from tracking list!
213 void ClearIO() { m_ios.clear(); }
214 void ClearIO(int index);
216 // perform async io and don't track handles in Device, but
217 // return the IO handle immediately for the caller to deal with
218 // It is safe to use PollCompletions() along with these calls,
219 // keep in mind that PollCompletions() will return IO's for handles
220 // that it doesn't track, thereby duplicating IO's that you
221 // get from these async functions. The IO destructor will properly
222 // handle multiple cleanups, but if one IO is destroyed, the other
223 // becomes invalid on the low level, but the object doesn't know it.
225 // Best to use one or the other IO style. Remember you can IO.Wait()
226 // to block if needed.
228 IO ABulkRead(int ep, Data &data);
229 IO ABulkWrite(int ep, const Data &data);
230 IO ABulkWrite(int ep, const void *data, size_t size);
231 IO AInterruptRead(int ep, Data &data);
232 IO AInterruptWrite(int ep, const Data &data);
234 // tracking list access
235 int GetIOCount() const { return m_ios.size(); }
236 CIO GetIO(int index) const { return CIO(m_ios[index]); }
239 class Interface
241 Device &m_dev;
242 int m_iface;
243 public:
244 Interface(Device &dev, int iface)
245 : m_dev(dev), m_iface(iface)
247 if( libusb_claim_interface(dev.GetHandle(), iface) < 0 )
248 throw UsbError("claim interface failed");
251 ~Interface()
253 libusb_release_interface(m_dev.GetHandle(), m_iface);
260 // Map of Endpoint numbers (not indexes) to endpoint descriptors
261 struct EndpointPair
263 unsigned char read;
264 unsigned char write;
265 unsigned char type;
267 EndpointPair() : read(0), write(0), type(0xff) {}
268 bool IsTypeSet() const { return type != 0xff; }
269 bool IsComplete() const { return read && write && IsTypeSet(); }
272 class EndpointDiscovery : public std::map<unsigned char, usb_endpoint_desc>
274 public:
275 typedef std::map<unsigned char, usb_endpoint_desc> base_type;
276 typedef std::vector<EndpointPair> endpoint_array_type;
278 private:
279 bool m_valid;
280 endpoint_array_type m_endpoints;
282 public:
283 EndpointDiscovery() : m_valid(false) {}
285 bool Discover(libusb_device_id_t devid, int cfgidx, int ifcidx, int epcount);
286 bool IsValid() const { return m_valid; }
288 const endpoint_array_type & GetEndpointPairs() const { return m_endpoints; }
293 // Map of Interface numbers (not indexes) to interface descriptors and endpoint map
294 struct InterfaceDesc
296 usb_interface_desc desc;
297 EndpointDiscovery endpoints;
300 class InterfaceDiscovery : public std::map<int, InterfaceDesc>
302 public:
303 typedef std::map<int, InterfaceDesc> base_type;
305 private:
306 bool m_valid;
308 public:
309 InterfaceDiscovery() : m_valid(false) {}
311 bool Discover(libusb_device_id_t devid, int cfgidx, int ifcount);
312 bool IsValid() const { return m_valid; }
318 // Map of Config numbers (not indexes) to config descriptors and interface map
319 struct ConfigDesc
321 usb_config_desc desc;
322 InterfaceDiscovery interfaces;
325 class ConfigDiscovery : public std::map<unsigned char, ConfigDesc>
327 public:
328 typedef std::map<unsigned char, ConfigDesc> base_type;
330 private:
331 bool m_valid;
333 public:
334 ConfigDiscovery() : m_valid(false) {}
336 bool Discover(libusb_device_id_t devid, int cfgcount);
337 bool IsValid() const { return m_valid; }
342 // Discovers all configurations, interfaces, and endpoints for a given device
343 class DeviceDiscovery
345 bool m_valid;
347 public:
348 usb_device_desc desc;
349 ConfigDiscovery configs;
351 public:
352 DeviceDiscovery(libusb_device_id_t devid);
354 bool Discover(libusb_device_id_t devid);
355 bool IsValid() const { return m_valid; }
358 } // namespace Usb
360 #endif