- renamed Changelog to ChangeLog in preparation for autoconf
[barry.git] / src / probe.cc
blobf5e0d3f10d1fb807e01925e160d92d838ba713dc
1 ///
2 /// \file probe.cc
3 /// USB Blackberry detection routines
4 ///
6 /*
7 Copyright (C) 2005-2006, Net Direct Inc. (http://www.netdirect.ca/)
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.
22 #include "common.h"
23 #include "probe.h"
24 #include "usbwrap.h"
25 #include "data.h"
26 #include "error.h"
27 #include "debug.h"
28 #include <iomanip>
30 using namespace Usb;
32 namespace Barry {
34 unsigned char Intro_Sends[][32] = {
35 // packet #1
36 { 0x00, 0x00, 0x10, 0x00, 0x01, 0xff, 0x00, 0x00,
37 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 },
39 // packet #2
40 { 0x00, 0x00, 0x0c, 0x00, 0x05, 0xff, 0x00, 0x01,
41 0x14, 0x00, 0x01, 0x00 },
43 // packet #3
44 { 0x00, 0x00, 0x0c, 0x00, 0x05, 0xff, 0x00, 0x02,
45 0x08, 0x00, 0x04, 0x00 }
49 unsigned char Intro_Receives[][32] = {
50 // response to packet #1
51 { 0x00, 0x00, 0x10, 0x00, 0x02, 0xff, 0x00, 0x00,
52 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 },
54 // response to packet #2
55 { 0x00, 0x00, 0x20, 0x00, 0x06, 0xff, 0x00, 0x01,
56 0x14, 0x00, 0x01, 0x00, 0x51, 0xe1, 0x33, 0x6b,
57 0xf3, 0x09, 0xbc, 0x37, 0x3b, 0xa3, 0x5e, 0xed,
58 0xff, 0x30, 0xa1, 0x3a, 0x60, 0xc9, 0x81, 0x8e },
60 { 0x00, 0x00, 0x14, 0x00, 0x06, 0xff, 0x00, 0x02,
61 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
62 0xe3, 0xef, 0x09, 0x30 }
65 namespace {
67 unsigned int GetSize(const unsigned char *packet)
69 return *((uint16_t *)&packet[2]);
72 bool Intro(int IntroIndex, const EndpointPair &ep, Device &dev, Data &response)
74 IO rd = dev.ABulkRead(ep.read, response);
75 IO wr = dev.ABulkWrite(ep.write, Intro_Sends[IntroIndex],
76 GetSize(Intro_Sends[IntroIndex]));
78 rd.Wait();
79 wr.Wait();
81 response.ReleaseBuffer(rd.GetStatus() >= 0 ? rd.GetSize() : 0);
82 return rd.GetStatus() >= 0;
85 } // anonymous namespace
88 bool Probe::Parse(const Data &data, ProbeResult &result)
90 // validate response data
91 const unsigned char *pd = data.GetData();
92 if( GetSize(pd) != (unsigned int) data.GetSize() ||
93 data.GetSize() < 0x14 ||
94 pd[4] != 0x06 )
96 return false;
97 // throw BError("Probe: Unexpected reponse data in parse");
100 // capture the PIN
101 result.m_pin = *((uint32_t *) &pd[16]);
102 return true;
105 Probe::Probe()
107 Match match(VENDOR_RIM, PRODUCT_RIM_BLACKBERRY);
109 libusb_device_id_t devid;
110 while( match.next_device(&devid) ) {
112 // skip if we can't properly discover device config
113 DeviceDiscovery discover(devid);
114 EndpointDiscovery &ed = discover.configs[BLACKBERRY_CONFIGURATION]
115 .interfaces[BLACKBERRY_INTERFACE]
116 .endpoints;
117 if( !ed.IsValid() || ed.GetEndpointPairs().size() == 0 )
118 continue;
121 ProbeResult result;
122 result.m_dev = devid;
124 // find the first bulk read/write endpoint pair that answers
125 // to our probe commands
126 // Search in reverse, since evidence indicates the last pairs
127 // are the ones we need.
128 for(size_t i = ed.GetEndpointPairs().size(); i; i-- ) {
129 const EndpointPair &ep = ed.GetEndpointPairs()[i-1];
130 if( ep.type == USB_ENDPOINT_TYPE_BULK ) {
131 result.m_ep = ep;
133 Device dev(devid);
134 dev.Reset();
135 sleep(5);
137 if( !dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
138 throw BError(dev.GetLastError(),
139 "Probe: SetConfiguration failed");
141 Interface iface(dev, BLACKBERRY_INTERFACE);
143 Data data;
144 if( Intro(0, ep, dev, data) && Intro(1, ep, dev, data) &&
145 Intro(2, ep, dev, data) && Parse(data, result) )
147 // all info obtained, add to list
148 m_results.push_back(result);
149 ddout("Using ReadEndpoint: " << (unsigned int)result.m_ep.read);
150 ddout(" WriteEndpoint: " << (unsigned int)result.m_ep.write);
151 break;
156 if( !result.m_ep.IsComplete() )
157 ddout("Unable to discover endpoint pair for one device.");
161 std::ostream& operator<< (std::ostream &os, const ProbeResult &pr)
163 os << "Device ID: " << pr.m_dev << std::setbase(16) << ". PIN: "
164 << pr.m_pin;
165 return os;
168 } // namespace Barry