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__
30 #define USBWRAP_DEFAULT_TIMEOUT 10000
34 /// Namespace for the libusb-related wrapper classes. This namespace
35 /// may change in the future.
38 /// \addtogroup exceptions
41 /// Thrown on low level USB errors.
42 class UsbError
: public std::runtime_error
45 UsbError(const std::string
&str
) : std::runtime_error(str
) {}
53 libusb_match_handle_t
*m_match
;
56 Match(int vendor
, int product
)
59 if( libusb_match_devices_by_vendor(&m_match
, vendor
, product
) < 0 )
60 throw UsbError("match failed");
65 libusb_free_match(m_match
);
68 bool next_device(libusb_device_id_t
*devid
)
70 m_lasterror
= libusb_match_next_device(m_match
, devid
);
71 return m_lasterror
>= 0;
80 // This class behaves a lot like std::auto_ptr<>, in that only one
81 // object can ever own a given libusb_io_handle_t at a time. The
82 // copy constructors and operator=() make it safe to store in a vector.
86 mutable libusb_io_handle_t
*m_handle
;
91 IO(Device
*dev
, libusb_io_handle_t
*handle
);
93 IO(Device
&dev
, libusb_io_handle_t
*handle
);
95 // copyable... the copied-to object will contain the handle,
96 // and other will be invalidated
98 IO
& operator=(const IO
&other
);
100 // will cancel if not complete, and will always free if valid
105 bool operator==(libusb_io_handle_t
*h
) const { return m_handle
== h
; }
107 // if valid, this object contains a pending usb io transfer handle...
108 // when compeleted, canceled, or freed, this will return false
109 bool IsValid() const { return m_handle
!= 0; }
110 void Forget() { m_handle
= 0; }
111 void Free() { cleanup(); }
114 bool IsCompleted() const;
117 int GetStatus() const;
119 int GetReqSize() const;
120 int GetEndpoint() const;
121 Device
& GetDevice() const { return *m_dev
; }
122 unsigned char * GetData();
123 const unsigned char * GetData() const;
125 // static helpers for various states
126 static IO
InvalidIO() { return IO(0, 0); }
130 // Const IO - used by Device when it wishes to safely expose its list
131 // of tracked IO handles, without letting the caller take ownership
137 CIO(const IO
&io
) : m_io(io
) {}
140 bool operator==(libusb_io_handle_t
*h
) const
141 { return m_io
.operator==(h
); }
143 // if valid, this object contains a pending usb io transfer handle...
144 // when compeleted, canceled, or freed, this will return false
145 bool IsValid() const { return m_io
.IsValid(); }
148 bool IsCompleted() const { return m_io
.IsCompleted(); }
149 int GetStatus() const { return m_io
.GetStatus();}
150 int GetSize() const { return m_io
.GetSize(); }
151 int GetReqSize() const { return m_io
.GetReqSize();}
152 int GetEndpoint() const { return m_io
.GetEndpoint(); }
153 Device
& GetDevice() const { return m_io
.GetDevice(); }
154 const unsigned char * GetData() const { return m_io
.GetData(); }
162 typedef std::vector
<IO
> io_list_type
;
165 libusb_device_id_t m_id
;
166 libusb_dev_handle_t
*m_handle
;
174 Device(libusb_device_id_t id
)
175 : m_id(id
), m_timeout(USBWRAP_DEFAULT_TIMEOUT
)
177 if( libusb_open(m_id
, &m_handle
) < 0 )
178 throw UsbError("open failed");
183 ClearIO(); // remove all pending IO before close
184 libusb_close(m_handle
);
187 /////////////////////////////
190 libusb_device_id_t
GetID() const { return m_id
; }
191 libusb_dev_handle_t
* GetHandle() const { return m_handle
; }
192 int GetLastError() const { return m_lasterror
; }
195 /////////////////////////////
196 // Device manipulation
198 bool SetConfiguration(unsigned char cfg
);
202 /////////////////////////////
205 // perform async io and track the handles inside Device
206 void TrackBulkRead(int ep
, Data
&data
);
207 void TrackBulkWrite(int ep
, const Data
&data
);
208 void TrackInterruptRead(int ep
, Data
&data
);
209 void TrackInterruptWrite(int ep
, const Data
&data
);
210 IO
PollCompletions(); //< extracts from tracking list!
211 void ClearIO() { m_ios
.clear(); }
212 void ClearIO(int index
);
214 // perform async io and don't track handles in Device, but
215 // return the IO handle immediately for the caller to deal with
216 // It is safe to use PollCompletions() along with these calls,
217 // keep in mind that PollCompletions() will return IO's for handles
218 // that it doesn't track, thereby duplicating IO's that you
219 // get from these async functions. The IO destructor will properly
220 // handle multiple cleanups, but if one IO is destroyed, the other
221 // becomes invalid on the low level, but the object doesn't know it.
223 // Best to use one or the other IO style. Remember you can IO.Wait()
224 // to block if needed.
226 IO
ABulkRead(int ep
, Data
&data
);
227 IO
ABulkWrite(int ep
, const Data
&data
);
228 IO
ABulkWrite(int ep
, const void *data
, size_t size
);
229 IO
AInterruptRead(int ep
, Data
&data
);
230 IO
AInterruptWrite(int ep
, const Data
&data
);
232 // tracking list access
233 int GetIOCount() const { return m_ios
.size(); }
234 CIO
GetIO(int index
) const { return CIO(m_ios
[index
]); }
242 Interface(Device
&dev
, int iface
)
243 : m_dev(dev
), m_iface(iface
)
245 if( libusb_claim_interface(dev
.GetHandle(), iface
) < 0 )
246 throw UsbError("claim interface failed");
251 libusb_release_interface(m_dev
.GetHandle(), m_iface
);