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