3 /// USB Blackberry detection routines
7 Copyright (C) 2005-2007, 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.
38 unsigned char Intro_Sends
[][32] = {
40 { 0x00, 0x00, 0x10, 0x00, 0x01, 0xff, 0x00, 0x00,
41 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 }
45 unsigned char Intro_Receives
[][32] = {
46 // response to packet #1
47 { 0x00, 0x00, 0x10, 0x00, 0x02, 0xff, 0x00, 0x00,
48 0xa8, 0x18, 0xda, 0x8d, 0x6c, 0x02, 0x00, 0x00 }
53 unsigned int GetSize(const unsigned char *packet
)
55 uint16_t size
= *((uint16_t *)&packet
[2]);
59 bool Intro(int IntroIndex
, const EndpointPair
&ep
, Device
&dev
, Data
&response
)
61 dev
.BulkWrite(ep
.write
, Intro_Sends
[IntroIndex
],
62 GetSize(Intro_Sends
[IntroIndex
]));
63 dev
.BulkRead(ep
.read
, response
);
64 ddout("BulkRead (" << (unsigned int)ep
.read
<< "):\n" << response
);
68 } // anonymous namespace
71 bool Probe::Parse(const Data
&data
, ProbeResult
&result
)
73 // validate response data
74 const unsigned char *pd
= data
.GetData();
76 if( GetSize(pd
) != (unsigned int) data
.GetSize() ||
77 data
.GetSize() < 0x14 ||
80 dout("Probe: Parse data failure: GetSize(pd): " << GetSize(pd
)
81 << ", data.GetSize(): " << data
.GetSize()
82 << ", pd[4]: " << (unsigned int) pd
[4]);
87 result
.m_pin
= btohl(*((uint32_t *) &pd
[16]));
94 Usb::DeviceIDType devid
;
96 // Search for standard product ID first
98 Match
match(VENDOR_RIM
, PRODUCT_RIM_BLACKBERRY
);
99 while( match
.next_device(&devid
) )
103 // Search for Pearl devices second
105 // productID 6 devices (PRODUCT_RIM_PEARL) do not expose
106 // the USB class 255 interface we need, but only the
107 // Mass Storage one. Here we search for PRODUCT_RIM_PEARL_DUAL,
108 // (ID 4) which has both enabled.
109 Match
match(VENDOR_RIM
, PRODUCT_RIM_PEARL_DUAL
);
110 while( match
.next_device(&devid
) )
115 void Probe::ProbeDevice(Usb::DeviceIDType devid
)
117 // skip if we can't properly discover device config
118 DeviceDiscovery
discover(devid
);
119 ConfigDesc
&config
= discover
.configs
[BLACKBERRY_CONFIGURATION
];
121 // search for interface class
122 InterfaceDiscovery::base_type::iterator i
= config
.interfaces
.begin();
123 for( ; i
!= config
.interfaces
.end(); i
++ ) {
124 if( i
->second
.desc
.bInterfaceClass
== BLACKBERRY_DB_CLASS
)
127 if( i
== config
.interfaces
.end() ) {
128 dout("Probe: Interface with BLACKBERRY_DB_CLASS ("
129 << BLACKBERRY_DB_CLASS
<< ") not found.");
133 unsigned char InterfaceNumber
= i
->second
.desc
.bInterfaceNumber
;
134 dout("Probe: using InterfaceNumber: " << (unsigned int) InterfaceNumber
);
136 // check endpoint validity
137 EndpointDiscovery
&ed
= config
.interfaces
[InterfaceNumber
].endpoints
;
138 if( !ed
.IsValid() || ed
.GetEndpointPairs().size() == 0 ) {
139 dout("Probe: endpoint invalid. ed.IsValud() == "
140 << (ed
.IsValid() ? "true" : "false")
141 << ", ed.GetEndpointPairs().size() == "
142 << ed
.GetEndpointPairs().size());
147 result
.m_dev
= devid
;
148 result
.m_interface
= InterfaceNumber
;
149 result
.m_zeroSocketSequence
= 0;
151 // find the first bulk read/write endpoint pair that answers
152 // to our probe commands
153 // Start with second pair, since evidence indicates the later pairs
154 // are the ones we need.
155 for(size_t i
= ed
.GetEndpointPairs().size() > 1 ? 1 : 0;
156 i
< ed
.GetEndpointPairs().size();
159 const EndpointPair
&ep
= ed
.GetEndpointPairs()[i
];
160 if( ep
.type
== USB_ENDPOINT_TYPE_BULK
) {
167 if( !dev
.SetConfiguration(BLACKBERRY_CONFIGURATION
) )
168 throw Error(dev
.GetLastError(),
169 "Probe: SetConfiguration failed");
171 Interface
iface(dev
, InterfaceNumber
);
174 dev
.BulkDrain(ep
.read
);
175 if( !Intro(0, ep
, dev
, data
) ) {
176 dout("Probe: Intro(0) failed");
180 Socket
socket(dev
, ep
.write
, ep
.read
);
183 ZeroPacket
packet(send
, receive
);
185 // unknown attribute: 0x14 / 0x01
186 packet
.GetAttribute(SB_OBJECT_INITIAL_UNKNOWN
,
187 SB_ATTR_INITIAL_UNKNOWN
);
191 packet
.GetAttribute(SB_OBJECT_PROFILE
, SB_ATTR_PROFILE_PIN
);
193 if( packet
.ObjectID() != SB_OBJECT_PROFILE
||
194 packet
.AttributeID() != SB_ATTR_PROFILE_PIN
||
195 !Parse(receive
, result
) )
197 dout("Probe: unable to fetch PIN");
202 for( uint16_t attr
= 5; attr
< 9; attr
++ ) {
203 packet
.GetAttribute(SB_OBJECT_SOCKET_UNKNOWN
, attr
);
205 // FIXME parse these responses, if they turn
206 // out to be important
210 // all info obtained, add to list
211 result
.m_zeroSocketSequence
= socket
.GetZeroSocketSequence();
212 m_results
.push_back(result
);
213 ddout("Using ReadEndpoint: " << (unsigned int)result
.m_ep
.read
);
214 ddout(" WriteEndpoint: " << (unsigned int)result
.m_ep
.write
);
218 dout("Probe: Skipping non-bulk endpoint pair (offset: "
223 if( !result
.m_ep
.IsComplete() )
224 ddout("Unable to discover endpoint pair for one device.");
227 int Probe::FindActive(uint32_t pin
) const
229 for( int i
= 0; i
< GetCount(); i
++ ) {
230 if( Get(i
).m_pin
== pin
)
234 // can we default to a single device?
235 if( GetCount() == 1 )
243 std::ostream
& operator<< (std::ostream
&os
, const ProbeResult
&pr
)
245 os
<< "Device ID: " << pr
.m_dev
<< std::setbase(16) << ". PIN: "