usbwrap.h

Go to the documentation of this file.
00001 ///
00002 /// \file       usbwrap.h
00003 ///             USB API wrapper
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2012, Chris Frey
00008     Portions Copyright (C) 2011, RealVNC Ltd.
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019     See the GNU General Public License in the COPYING file at the
00020     root directory of this project for more details.
00021 */
00022 
00023 
00024 #ifndef __SB_USBWRAP_H__
00025 #define __SB_USBWRAP_H__
00026 
00027 #include "dll.h"
00028 
00029 #include <memory>
00030 #include <tr1/memory>
00031 #include <vector>
00032 #include <map>
00033 #include "error.h"
00034 
00035 #define USBWRAP_DEFAULT_TIMEOUT 30000
00036 
00037 // Matches any product ID when calling DeviceList::MatchDevices
00038 #define PRODUCT_ANY             0x10000
00039 // Indicates an unknown product ID
00040 #define PRODUCT_UNKNOWN         0x20000
00041 
00042 namespace Barry { class Data; }
00043 
00044 /// Namespace for the libusb-related wrapper classes.  This namespace
00045 /// may change in the future.
00046 namespace Usb {
00047 
00048 /// \addtogroup exceptions
00049 /// @{
00050 
00051 /// Thrown on low level USB errors.
00052 class BXEXPORT Error : public Barry::Error
00053 {
00054         int m_libusb_errcode;
00055 
00056 public:
00057         Error(const std::string &str);
00058         Error(int libusb_errcode, const std::string &str);
00059 
00060         // can return 0 in some case, if unknown error code
00061         int libusb_errcode() const { return m_libusb_errcode; }
00062 
00063         // returns a translated system error code when using libusb 1.0
00064         // returns 0 if unknown or unable to translate
00065         int system_errcode() const;
00066 };
00067 
00068 class BXEXPORT Timeout : public Error
00069 {
00070 public:
00071         Timeout(const std::string &str) : Error(str) {}
00072         Timeout(int errcode, const std::string &str)
00073                 : Error(errcode, str) {}
00074 };
00075 
00076 /// @}
00077 
00078 // Private struct for holding library specific
00079 // a unique identifier to a connected device.
00080 class DeviceIDImpl;
00081 
00082 class BXEXPORT DeviceID
00083 {
00084 public:
00085         std::tr1::shared_ptr<DeviceIDImpl> m_impl;
00086 public:
00087         // Takes ownership of impl
00088         DeviceID(DeviceIDImpl* impl = NULL);
00089         ~DeviceID();
00090         const char* GetBusName() const;
00091         uint16_t GetNumber() const;
00092         const char* GetFilename() const;
00093         uint16_t GetIdProduct() const;
00094 
00095         // Utility function: returns a string that uniquely identifies
00096         // the bus and device, regardless of which libusb you're using
00097         std::string GetUsbName() const;
00098 };
00099 
00100 // Private struct for holding a library specific
00101 // device handle
00102 struct DeviceHandle;
00103 
00104 // Static functions for setting up USB
00105 // The interface that usbwrap.cc uses
00106 // to interact with the USB library
00107 class BXEXPORT LibraryInterface
00108 {
00109 public:
00110         static std::string GetLastErrorString(int libusb_errcode);
00111 
00112         /// Returns 0 if unable to translate libusb error code.
00113         /// Note that this function assumes you already know that libusb_errcode
00114         /// contains an actual error code, and so returns 0 (success)
00115         /// for an unknown error.  This means that "success" means error
00116         /// if you use this function correctly, but if you pass in a success
00117         /// code (>= 0) it will always return 0 as well.
00118         static int TranslateErrcode(int libusb_errcode);
00119 
00120         /// Returns true on success... pass in a pointer to int
00121         /// if the low level error code is important to you.
00122         static bool Init(int *libusb_errno = 0);
00123         static void Uninit();
00124         static void SetDataDump(bool data_dump_mode);
00125 };
00126 
00127 // Forward declaration of descriptor types.
00128 class BXEXPORT DeviceDescriptor;
00129 class BXEXPORT ConfigDescriptor;
00130 class BXEXPORT InterfaceDescriptor;
00131 
00132 // Private struct for holding library specific
00133 // information about endpoint descriptors
00134 struct EndpointDescriptorImpl;
00135 
00136 // Encapsulates an endpoint descriptor
00137 class BXEXPORT EndpointDescriptor
00138 {
00139 public:
00140         enum EpType
00141         {
00142                 ControlType = 0,
00143                 IsochronousType = 1,
00144                 BulkType = 2,
00145                 InterruptType = 3,
00146                 InvalidType = 0xff
00147         };
00148 private:
00149         const std::auto_ptr<EndpointDescriptorImpl> m_impl;
00150         bool m_read;
00151         uint8_t m_addr;
00152         EpType m_type;
00153 public:
00154         EndpointDescriptor(InterfaceDescriptor& dev, int endpoint);
00155         ~EndpointDescriptor();
00156         bool IsRead() const;
00157         uint8_t GetAddress() const;
00158         EpType GetType() const;
00159 };
00160 
00161 // Private struct for holding library specific
00162 // information about interface descriptors
00163 struct InterfaceDescriptorImpl;
00164 
00165 // Encapsulates an interface descriptor
00166 //
00167 // The inherited vector methods look up endpoints
00168 class BXEXPORT InterfaceDescriptor : public std::vector<EndpointDescriptor*>
00169 {
00170         friend class EndpointDescriptor;
00171 public:
00172         typedef std::vector<EndpointDescriptor*> base_type;
00173 private:
00174         const std::auto_ptr<InterfaceDescriptorImpl> m_impl;
00175 public:
00176         InterfaceDescriptor(ConfigDescriptor& cfgdesc,
00177                             int interface, int altsetting);
00178         ~InterfaceDescriptor();
00179         uint8_t GetClass() const;
00180         uint8_t GetNumber() const;
00181         uint8_t GetAltSetting() const;
00182 };
00183 
00184 // Private struct for holding library specific
00185 // information about config descriptors
00186 
00187 struct ConfigDescriptorImpl;
00188 
00189 // Encapsulates a configuration descriptor
00190 //
00191 // The inherited map methods look up interface descriptors
00192 class BXEXPORT ConfigDescriptor : public std::map<int, InterfaceDescriptor*>
00193 {
00194         friend class InterfaceDescriptor;
00195 public:
00196         typedef std::map<int, InterfaceDescriptor*> base_type;
00197 private:
00198         const std::auto_ptr<ConfigDescriptorImpl> m_impl;
00199 public:
00200         ConfigDescriptor(DeviceDescriptor& dev, int cfgnumber);
00201         ~ConfigDescriptor();
00202         uint8_t GetNumber() const;
00203 };
00204 
00205 // Private struct for holding library specific
00206 // information about a device descriptor
00207 struct DeviceDescriptorImpl;
00208 
00209 // Encapsulates a device descriptor
00210 //
00211 // The inherited map methods look up config descriptors
00212 class BXEXPORT DeviceDescriptor : public std::map<int, ConfigDescriptor*>
00213 {
00214         friend class ConfigDescriptor;
00215 public:
00216         typedef std::map<int, ConfigDescriptor*> base_type;
00217 private:
00218         const std::auto_ptr<DeviceDescriptorImpl> m_impl;
00219 public:
00220         DeviceDescriptor(DeviceID& devid);
00221         ~DeviceDescriptor();
00222 };
00223 
00224 // Private struct for holding library specific
00225 // information for devices.
00226 struct DeviceListImpl;
00227 
00228 class BXEXPORT DeviceList
00229 {
00230 private:
00231         // Private implementation structure
00232         const std::auto_ptr<DeviceListImpl> m_impl;
00233 public:
00234         DeviceList();
00235         ~DeviceList();
00236 
00237         std::vector<DeviceID> MatchDevices(int vendor, int product,
00238                                            const char *busname, const char *devname);
00239 
00240 };
00241 
00242 struct PrivateDeviceData;
00243 
00244 class BXEXPORT Device
00245 {
00246 private:
00247         Usb::DeviceID m_id;
00248         std::auto_ptr<Usb::DeviceHandle> m_handle;
00249 
00250         int m_timeout;
00251         int m_lasterror;
00252 
00253 public:
00254         Device(const Usb::DeviceID& id, int timeout = USBWRAP_DEFAULT_TIMEOUT);
00255         ~Device();
00256 
00257         /////////////////////////////
00258         // Data access
00259 
00260         const Usb::DeviceID& GetID() const { return m_id; }
00261         const Usb::DeviceHandle* GetHandle() const { return &*m_handle; }
00262         int GetLastError() const { return m_lasterror; } //< not thread safe...
00263                 //< use the error code stored in the exceptions to track
00264                 //< errors in threaded usage
00265         void SetLastError(int err) { m_lasterror = err; }
00266         int GetDefaultTimeout() const { return m_timeout; }
00267 
00268         /////////////////////////////
00269         // Device information
00270 
00271         int GetPowerLevel();
00272         int FindInterface(int ifaceClass);
00273 
00274         /////////////////////////////
00275         // Device manipulation
00276 
00277         bool SetConfiguration(unsigned char cfg);
00278         bool ClearHalt(int ep);
00279         bool Reset();
00280         bool IsAttachKernelDriver(int iface);
00281         bool DetachKernelDriver(int iface);
00282 
00283         /////////////////////////////
00284         // IO functions
00285 
00286         bool BulkRead(int ep, Barry::Data &data, int timeout = -1);
00287         bool BulkWrite(int ep, const Barry::Data &data, int timeout = -1);
00288         bool BulkWrite(int ep, const void *data, size_t size, int timeout = -1);
00289         bool InterruptRead(int ep, Barry::Data &data, int timeout = -1);
00290         bool InterruptWrite(int ep, const Barry::Data &data, int timeout = -1);
00291 
00292         void BulkDrain(int ep, int timeout = 100);
00293 
00294         bool ControlMsg(int requesttype, int request, int value,
00295                         int index, char *bytes, int size, int timeout);
00296 
00297         /////////////////////////////
00298         // Combo functions
00299 
00300         bool GetConfiguration(unsigned char &cfg);
00301 };
00302 
00303 class BXEXPORT Interface
00304 {
00305         Device &m_dev;
00306         int m_iface;
00307 public:
00308         Interface(Device &dev, int iface);
00309         ~Interface();
00310         bool SetAltInterface(int altSetting);
00311 };
00312 
00313 // Map of Endpoint numbers (not indexes) to endpoint descriptors
00314 struct BXEXPORT EndpointPair
00315 {
00316         unsigned char read;
00317         unsigned char write;
00318         EndpointDescriptor::EpType type;
00319 
00320         EndpointPair();
00321         bool IsTypeSet() const;
00322         bool IsComplete() const;
00323         bool IsBulk() const;
00324 };
00325 
00326 class BXEXPORT EndpointPairings : public std::vector<EndpointPair>
00327 {
00328 public:
00329         typedef std::vector<EndpointPair> base_type;
00330 private:
00331         bool m_valid;
00332 public:
00333         EndpointPairings(const std::vector<EndpointDescriptor*>& eps);
00334         ~EndpointPairings();
00335         bool IsValid() const;
00336 };
00337 
00338 class BXEXPORT Match
00339 {
00340 private:
00341         std::vector<DeviceID> m_list;
00342         std::vector<DeviceID>::iterator m_iter;
00343 public:
00344         // Due to USB libraries having different ownership ideas
00345         // about device IDs, Match objects must be constructed
00346         // with a device list.
00347         Match(DeviceList& devices,
00348               int vendor, int product,
00349               const char *busname = 0, const char *devname = 0);        
00350         ~Match();
00351 
00352         // searches for next match, and if found, fills devid with
00353         // something you can pass on to DeviceDiscover, etc
00354         // returns true if next is found, false if no more
00355         bool next_device(Usb::DeviceID& devid);
00356 };
00357 
00358 }
00359 
00360 #endif