7 Copyright (C) 2005-2006, 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__
31 #define USBWRAP_DEFAULT_TIMEOUT 10000
35 /// Namespace for the libusb-related wrapper classes. This namespace
36 /// may change in the future.
39 /// \addtogroup exceptions
42 /// Thrown on low level USB errors.
43 class UsbError
: public std::runtime_error
46 UsbError(const std::string
&str
) : std::runtime_error(str
) {}
54 libusb_match_handle_t
*m_match
;
57 Match(int vendor
, int product
)
60 if( libusb_match_devices_by_vendor(&m_match
, vendor
, product
) < 0 )
61 throw UsbError("match failed");
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;
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.
87 mutable libusb_io_handle_t
*m_handle
;
92 IO(Device
*dev
, libusb_io_handle_t
*handle
);
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
99 IO
& operator=(const IO
&other
);
101 // will cancel if not complete, and will always free if valid
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(); }
115 bool IsCompleted() const;
118 int GetStatus() 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
138 CIO(const IO
&io
) : m_io(io
) {}
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(); }
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(); }
163 typedef std::vector
<IO
> io_list_type
;
166 libusb_device_id_t m_id
;
167 libusb_dev_handle_t
*m_handle
;
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");
184 ClearIO(); // remove all pending IO before close
185 libusb_close(m_handle
);
188 /////////////////////////////
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
);
204 /////////////////////////////
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
]); }
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");
253 libusb_release_interface(m_dev
.GetHandle(), m_iface
);
260 // Map of Endpoint numbers (not indexes) to endpoint descriptors
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
>
275 typedef std::map
<unsigned char, usb_endpoint_desc
> base_type
;
276 typedef std::vector
<EndpointPair
> endpoint_array_type
;
280 endpoint_array_type m_endpoints
;
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
296 usb_interface_desc desc
;
297 EndpointDiscovery endpoints
;
300 class InterfaceDiscovery
: public std::map
<int, InterfaceDesc
>
303 typedef std::map
<int, InterfaceDesc
> base_type
;
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
321 usb_config_desc desc
;
322 InterfaceDiscovery interfaces
;
325 class ConfigDiscovery
: public std::map
<unsigned char, ConfigDesc
>
328 typedef std::map
<unsigned char, ConfigDesc
> base_type
;
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
348 usb_device_desc desc
;
349 ConfigDiscovery configs
;
352 DeviceDiscovery(libusb_device_id_t devid
);
354 bool Discover(libusb_device_id_t devid
);
355 bool IsValid() const { return m_valid
; }