probe.h

Go to the documentation of this file.
00001 ///
00002 /// \file       probe.h
00003 ///             USB Blackberry detection routines
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #ifndef __BARRY_PROBE_H__
00023 #define __BARRY_PROBE_H__
00024 
00025 #include "dll.h"
00026 #include "usbwrap.h"
00027 #include "pin.h"
00028 #include <vector>
00029 #include <iosfwd>
00030 #include <stdint.h>
00031 
00032 namespace Barry {
00033 
00034 class Probe;
00035 
00036 struct BXEXPORT ProbeResult
00037 {
00038         friend class Probe;
00039 
00040         Usb::DeviceID m_dev;
00041         unsigned char m_interface;
00042         unsigned char m_altsetting;
00043         Barry::Pin m_pin;
00044         Usb::EndpointPair m_ep;
00045         Usb::EndpointPair m_epModem;
00046         // Specifies if it's necessary to clear halt on the
00047         // endpoints before using them. On some devices such
00048         // as the 8830 it's essential to clear halt. On other
00049         // devices such as the Curve 8520 calling clear halt
00050         // can cause them to get into a state where they drop
00051         // packets.
00052         bool m_needClearHalt;
00053         // Specifies if it's necessary to call usb_set_altinterface()
00054         // before attempting to use the end points for this device.
00055         //
00056         // This can help to re-synchronize the state between the USB
00057         // host and the device. However it can also cause usb-storage
00058         // URBs to be lost on some device, so it's only used as a
00059         // last resort.
00060         bool m_needSetAltInterface;
00061         uint8_t m_zeroSocketSequence;
00062         std::string m_description;
00063 
00064         // data from a possible ConfigFile (filled in automatically by
00065         // the probe code if available)
00066         std::string m_cfgDeviceName;
00067 
00068 private:
00069         // All ProbeResult objects should come from Probe, therefore
00070         // this constructor is private to force the issue.
00071         ProbeResult()
00072                 : m_dev(0), m_interface(0), m_pin(0)
00073                 , m_needClearHalt(false), m_needSetAltInterface(false)
00074                 , m_zeroSocketSequence(0)
00075                 {}
00076 
00077 public:
00078         void DumpAll(std::ostream &os) const;
00079         bool HasIpModem() const { return m_epModem.IsComplete(); }
00080 
00081         std::string GetDisplayName() const;
00082 
00083         bool operator==(const Barry::Pin &pin) const
00084         {
00085                 return m_pin == pin;
00086         }
00087 };
00088 
00089 BXEXPORT std::ostream& operator<< (std::ostream &os, const ProbeResult &pr);
00090 
00091 
00092 class BXEXPORT Probe
00093 {
00094 public:
00095         typedef std::vector<ProbeResult>                Results;
00096 
00097         enum LogExceptionBits {
00098                 LOG_BUSY = 0x0001,
00099                 LOG_ACCESS = 0x0002,
00100                 LOG_PERM = 0x0004
00101         };
00102 
00103 private:
00104         Usb::DeviceList m_devices;
00105         Results m_results;
00106 
00107         unsigned int m_log_exceptions;
00108         std::vector<std::string> m_fail_msgs;
00109         int m_fail_count;
00110 
00111         bool m_epp_override;
00112         Usb::EndpointPair m_epp;
00113 
00114         BXLOCAL bool CheckSize(const Data &data, unsigned int required);
00115         BXLOCAL bool ParsePIN(const Data &data, uint32_t &pin);
00116         BXLOCAL bool ParseDesc(const Data &data, std::string &desc);
00117 
00118 protected:
00119         void ProbeMatching(int vendor, int product,
00120                 const char *busname, const char *devname);
00121         void ProbeDevice(Usb::DeviceID& devid);
00122         void ProbeDeviceEndpoints(Usb::Device &dev, Usb::EndpointPairings &ed, ProbeResult &result);
00123         bool ProbePair(Usb::Device &dev, const Usb::EndpointPair &ep,
00124                 uint32_t &pin, std::string &desc, uint8_t &zeroSocketSequence,
00125                 bool &needClearHalt);
00126         bool ProbeModem(Usb::Device &dev, const Usb::EndpointPair &ep);
00127 
00128 public:
00129         /// log_exceptions is a bitmask of low level USB errors to
00130         /// log instead of throw on.  If 0, all USB errors will cause
00131         /// an exception, and thereby stop the probe.  If the error
00132         /// is set in the bitmask, the exception will be caught, and
00133         /// logged in m_fail_msgs, which can be retrieved through
00134         /// GetFailCount() and GetFailMsg().  If auto_dump_log is true,
00135         /// all logged messages will be dumped as well, via the eout() macro,
00136         /// to make sure they are seen, even if the application
00137         /// programmer doesn't deal with them via the API.
00138         Probe(const char *busname = 0, const char *devname = 0,
00139                 const Usb::EndpointPair *epp = 0,
00140                 unsigned int log_exceptions = LOG_BUSY | LOG_ACCESS | LOG_PERM,
00141                 bool auto_dump_log = true);
00142 
00143         const Results& GetResults() const { return m_results; }
00144 
00145         int GetCount() const { return m_results.size(); }
00146         int GetFailCount() const { return m_fail_count; }
00147 
00148         const std::string& GetFailMsg(int index) const { return m_fail_msgs.at(index); }
00149         const ProbeResult& Get(int index) const { return m_results.at(index); }
00150 
00151         int FindActive(Barry::Pin pin = 0) const; // returns -1 if pin not found
00152                                                 // or if no devices
00153         static int FindActive(const Results &results, Barry::Pin pin = 0);
00154         static int Find(const Results &results, Barry::Pin pin = 0);
00155 };
00156 
00157 
00158 } // namespace Barry
00159 
00160 #endif
00161