00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "common.h"
00023 #include "probe.h"
00024 #include "usbwrap.h"
00025 #include "data.h"
00026 #include "endian.h"
00027 #include "error.h"
00028 #include "debug.h"
00029 #include "packet.h"
00030 #include "socket.h"
00031 #include "protocol.h"
00032 #include "record-internal.h"
00033 #include "strnlen.h"
00034 #include "configfile.h"
00035 #include <iomanip>
00036 #include <errno.h>
00037 #include <string.h>
00038
00039 using namespace Usb;
00040
00041 namespace Barry {
00042
00043 unsigned char Intro_Sends[][32] = {
00044
00045 { 0x00, 0x00, 0x10, 0x00, 0x01, 0xff, 0x00, 0x00,
00046 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 }
00047 };
00048
00049
00050 unsigned char Intro_Receives[][32] = {
00051
00052 { 0x00, 0x00, 0x10, 0x00, 0x02, 0xff, 0x00, 0x00,
00053 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 }
00054 };
00055
00056 namespace {
00057
00058 unsigned int GetSize(const unsigned char *packet)
00059 {
00060 uint16_t size = *((uint16_t *)&packet[2]);
00061 return btohs(size);
00062 }
00063
00064 bool Intro(int IntroIndex, const EndpointPair &ep, Device &dev, Data &response)
00065 {
00066 dev.BulkWrite(ep.write, Intro_Sends[IntroIndex],
00067 GetSize(Intro_Sends[IntroIndex]));
00068 try {
00069 dev.BulkRead(ep.read, response, 500);
00070 }
00071 catch( Usb::Timeout &to ) {
00072 ddout("BulkRead: " << to.what());
00073 return false;
00074 }
00075 ddout("BulkRead (" << (unsigned int)ep.read << "):\n" << response);
00076 return true;
00077 }
00078
00079 }
00080
00081
00082 bool Probe::CheckSize(const Data &data, unsigned int required)
00083 {
00084 const unsigned char *pd = data.GetData();
00085
00086 if( GetSize(pd) != (unsigned int) data.GetSize() ||
00087 data.GetSize() < required ||
00088 pd[4] != SB_COMMAND_FETCHED_ATTRIBUTE )
00089 {
00090 dout("Probe: Parse data failure: GetSize(pd): " << GetSize(pd)
00091 << ", data.GetSize(): " << data.GetSize()
00092 << ", pd[4]: " << (unsigned int) pd[4]);
00093 return false;
00094 }
00095
00096 return true;
00097 }
00098
00099 bool Probe::ParsePIN(const Data &data, uint32_t &pin)
00100 {
00101
00102 const unsigned char *pd = data.GetData();
00103
00104 if( !CheckSize(data, 0x14) )
00105 return false;
00106
00107
00108 pin = btohl(*((uint32_t *) &pd[16]));
00109
00110 return true;
00111 }
00112
00113 bool Probe::ParseDesc(const Data &data, std::string &desc)
00114 {
00115 if( !CheckSize(data, 29) )
00116 return false;
00117
00118
00119 const char *d = (const char*) &data.GetData()[28];
00120 int maxlen = data.GetSize() - 28;
00121 desc.assign(d, strnlen(d, maxlen));
00122
00123 return true;
00124 }
00125
00126 Probe::Probe(const char *busname, const char *devname,
00127 const Usb::EndpointPair *epp)
00128 : m_fail_count(0)
00129 , m_epp_override(epp)
00130 {
00131 if( m_epp_override ) {
00132 m_epp = *epp;
00133 }
00134
00135
00136 if( busname && !strlen(busname) )
00137 busname = 0;
00138 if( devname && !strlen(devname) )
00139 devname = 0;
00140
00141
00142 ProbeMatching(VENDOR_RIM, PRODUCT_RIM_BLACKBERRY, busname, devname);
00143
00144
00145
00146
00147
00148
00149
00150 ProbeMatching(VENDOR_RIM, PRODUCT_RIM_PEARL_DUAL, busname, devname);
00151
00152
00153 ProbeMatching(VENDOR_RIM, PRODUCT_RIM_PEARL_8120, busname, devname);
00154
00155 ProbeMatching(VENDOR_RIM, PRODUCT_RIM_PEARL_FLIP, busname, devname);
00156
00157
00158 ProbeMatching(VENDOR_RIM, PRODUCT_RIM_STORM, busname, devname);
00159 }
00160
00161 void Probe::ProbeMatching(int vendor, int product,
00162 const char *busname, const char *devname)
00163 {
00164 Usb::DeviceIDType devid;
00165
00166 Match match(vendor, product, busname, devname);
00167 while( match.next_device(&devid) ) try {
00168 ProbeDevice(devid);
00169 }
00170 catch( Usb::Error &e ) {
00171 dout("Usb::Error exception caught: " << e.what());
00172 if( e.libusb_errcode() == -EBUSY ) {
00173 m_fail_count++;
00174 m_fail_msgs.push_back(e.what());
00175 }
00176 else {
00177 throw;
00178 }
00179 }
00180 }
00181
00182 void Probe::ProbeDevice(Usb::DeviceIDType devid)
00183 {
00184
00185 DeviceDiscovery discover(devid);
00186 ConfigDesc &config = discover.configs[BLACKBERRY_CONFIGURATION];
00187
00188
00189 InterfaceDiscovery::base_type::iterator idi = config.interfaces.begin();
00190 for( ; idi != config.interfaces.end(); idi++ ) {
00191 if( idi->second.desc.bInterfaceClass == BLACKBERRY_DB_CLASS )
00192 break;
00193 }
00194 if( idi == config.interfaces.end() ) {
00195 dout("Probe: Interface with BLACKBERRY_DB_CLASS ("
00196 << BLACKBERRY_DB_CLASS << ") not found.");
00197 return;
00198 }
00199
00200 unsigned char InterfaceNumber = idi->second.desc.bInterfaceNumber;
00201 dout("Probe: using InterfaceNumber: " << (unsigned int) InterfaceNumber);
00202
00203
00204 EndpointDiscovery &ed = config.interfaces[InterfaceNumber].endpoints;
00205 if( !ed.IsValid() || ed.GetEndpointPairs().size() == 0 ) {
00206 dout("Probe: endpoint invalid. ed.IsValud() == "
00207 << (ed.IsValid() ? "true" : "false")
00208 << ", ed.GetEndpointPairs().size() == "
00209 << ed.GetEndpointPairs().size());
00210 return;
00211 }
00212
00213 ProbeResult result;
00214 result.m_dev = devid;
00215 result.m_interface = InterfaceNumber;
00216 result.m_zeroSocketSequence = 0;
00217
00218
00219 Device dev(devid);
00220
00221
00222
00223
00224 unsigned char cfg;
00225 if( !dev.GetConfiguration(cfg) )
00226 throw Usb::Error(dev.GetLastError(),
00227 "Probe: GetConfiguration failed");
00228 if( cfg != BLACKBERRY_CONFIGURATION ) {
00229 if( !dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
00230 throw Usb::Error(dev.GetLastError(),
00231 "Probe: SetConfiguration failed");
00232 }
00233
00234
00235 Interface iface(dev, InterfaceNumber);
00236
00237 if( m_epp_override ) {
00238
00239 uint32_t pin;
00240 uint8_t zeroSocketSequence;
00241 std::string desc;
00242 if( ProbePair(dev, m_epp, pin, desc, zeroSocketSequence) ) {
00243
00244 result.m_ep = m_epp;
00245 result.m_pin = pin;
00246 result.m_description = desc;
00247 result.m_zeroSocketSequence = zeroSocketSequence;
00248 }
00249 }
00250 else {
00251
00252
00253
00254
00255 size_t i;
00256 for(i = ed.GetEndpointPairs().size() > 1 ? 1 : 0;
00257 i < ed.GetEndpointPairs().size();
00258 i++ )
00259 {
00260 const EndpointPair &ep = ed.GetEndpointPairs()[i];
00261 if( ep.type == USB_ENDPOINT_TYPE_BULK ) {
00262
00263 uint32_t pin;
00264 uint8_t zeroSocketSequence;
00265 std::string desc;
00266 if( ProbePair(dev, ep, pin, desc, zeroSocketSequence) ) {
00267 result.m_ep = ep;
00268 result.m_pin = pin;
00269 result.m_description = desc;
00270 result.m_zeroSocketSequence = zeroSocketSequence;
00271 break;
00272 }
00273 }
00274 else {
00275 dout("Probe: Skipping non-bulk endpoint pair (offset: "
00276 << i-1 << ") ");
00277 }
00278 }
00279
00280
00281 i++;
00282 if( i < ed.GetEndpointPairs().size() ) {
00283 const EndpointPair &ep = ed.GetEndpointPairs()[i];
00284 if( ProbeModem(dev, ep) ) {
00285 result.m_epModem = ep;
00286 }
00287 }
00288 }
00289
00290
00291 if( result.m_ep.IsComplete() ) {
00292
00293
00294
00295 try {
00296 ConfigFile cfg(result.m_pin);
00297 result.m_cfgDeviceName = cfg.GetDeviceName();
00298 }
00299 catch( Barry::ConfigFileError & ) {
00300
00301 }
00302
00303 m_results.push_back(result);
00304 ddout("Using ReadEndpoint: " << (unsigned int)result.m_ep.read);
00305 ddout(" WriteEndpoint: " << (unsigned int)result.m_ep.write);
00306 }
00307 else {
00308 ddout("Unable to discover endpoint pair for one device.");
00309 }
00310 }
00311
00312 bool Probe::ProbePair(Usb::Device &dev,
00313 const Usb::EndpointPair &ep,
00314 uint32_t &pin,
00315 std::string &desc,
00316 uint8_t &zeroSocketSequence)
00317 {
00318 dev.ClearHalt(ep.read);
00319 dev.ClearHalt(ep.write);
00320
00321 Data data;
00322 dev.BulkDrain(ep.read);
00323 if( !Intro(0, ep, dev, data) ) {
00324 dout("Probe: Intro(0) failed");
00325 return false;
00326 }
00327
00328 SocketZero socket(dev, ep.write, ep.read);
00329
00330 Data send, receive;
00331 ZeroPacket packet(send, receive);
00332
00333
00334 packet.GetAttribute(SB_OBJECT_INITIAL_UNKNOWN,
00335 SB_ATTR_INITIAL_UNKNOWN);
00336 socket.Send(packet);
00337
00338
00339 packet.GetAttribute(SB_OBJECT_PROFILE, SB_ATTR_PROFILE_PIN);
00340 socket.Send(packet);
00341 if( packet.ObjectID() != SB_OBJECT_PROFILE ||
00342 packet.AttributeID() != SB_ATTR_PROFILE_PIN ||
00343 !ParsePIN(receive, pin) )
00344 {
00345 dout("Probe: unable to fetch PIN");
00346 return false;
00347 }
00348
00349
00350 packet.GetAttribute(SB_OBJECT_PROFILE, SB_ATTR_PROFILE_DESC);
00351 socket.Send(packet);
00352
00353 if(
00354 packet.AttributeID() != SB_ATTR_PROFILE_DESC ||
00355 !ParseDesc(receive, desc) )
00356 {
00357 dout("Probe: unable to fetch description");
00358 }
00359
00360
00361 for( uint16_t attr = 5; attr < 9; attr++ ) {
00362 packet.GetAttribute(SB_OBJECT_SOCKET_UNKNOWN, attr);
00363 socket.Send(packet);
00364
00365
00366 }
00367
00368
00369 zeroSocketSequence = socket.GetZeroSocketSequence();
00370 return true;
00371 }
00372
00373 bool Probe::ProbeModem(Usb::Device &dev, const Usb::EndpointPair &ep)
00374 {
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 return true;
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 }
00409
00410 int Probe::FindActive(Barry::Pin pin) const
00411 {
00412 return FindActive(m_results, pin);
00413 }
00414
00415 int Probe::FindActive(const Barry::Probe::Results &results, Barry::Pin pin)
00416 {
00417 int i = Find(results, pin);
00418
00419 if( i == -1 && pin == 0 ) {
00420
00421 if( results.size() == 1 )
00422 return 0;
00423 }
00424
00425 return i;
00426 }
00427
00428 int Probe::Find(const Results &results, Barry::Pin pin)
00429 {
00430 Barry::Probe::Results::const_iterator ci = results.begin();
00431 for( int i = 0; ci != results.end(); i++, ++ci ) {
00432 if( ci->m_pin == pin )
00433 return i;
00434 }
00435
00436 return -1;
00437 }
00438
00439 void ProbeResult::DumpAll(std::ostream &os) const
00440 {
00441 os << *this
00442 << ", Interface: 0x" << std::hex << (unsigned int) m_interface
00443 << ", Endpoints: (read: 0x" << std::hex << (unsigned int) m_ep.read
00444 << ", write: 0x" << std::hex << (unsigned int) m_ep.write
00445 << ", type: 0x" << std::hex << (unsigned int) m_ep.type
00446 << ", ZeroSocketSequence: 0x" << std::hex << (unsigned int) m_zeroSocketSequence;
00447 }
00448
00449 std::ostream& operator<< (std::ostream &os, const ProbeResult &pr)
00450 {
00451 os << "Device ID: " << pr.m_dev
00452 << ". PIN: " << pr.m_pin.str()
00453 << ", Description: " << pr.m_description;
00454 if( pr.m_cfgDeviceName.size() )
00455 os << ", Name: " << pr.m_cfgDeviceName;
00456 return os;
00457 }
00458
00459 }
00460