2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
7 Copyright (C) 2005-2009, Net Direct Inc. (http://www.netdirect.ca/)
8 Copyright (C) 2008-2009, Nicolas VIVIEN
10 Some parts are inspired from m_desktop.h
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU General Public License in the COPYING file at the
22 root directory of this project for more details.
25 #include "m_javaloader.h"
28 #include "protostructs.h"
33 #include "controller.h"
40 namespace Barry
{ namespace Mode
{
43 ///////////////////////////////////////////////////////////////////////////////
44 // JavaLoader Mode class
46 JavaLoader::JavaLoader(Controller
&con
)
52 JavaLoader::~JavaLoader()
56 ///////////////////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////////////////
66 /// Select device mode. This is required before using any other mode-based
69 /// This function opens a socket to the device for communicating in Desktop
70 /// mode. If the device requires it, specify the password with a const char*
71 /// string in password. The password will not be stored in memory
72 /// inside this class, only a hash will be generated from it. After
73 /// using the hash, the hash memory will be set to 0. The application
74 /// is responsible for safely handling the raw password data.
76 /// You can retry the password by catching Barry::BadPassword and
77 /// calling RetryPassword() with the new password.
79 /// \exception Barry::Error
80 /// Thrown on protocol error.
82 /// \exception std::logic_error()
83 /// Thrown if unsupported mode is requested, or if socket
86 /// \exception Barry::BadPassword
87 /// Thrown when password is invalid or if not enough retries
88 /// left in the device.
90 void JavaLoader::Open(const char *password
)
98 m_ModeSocket
= m_con
.SelectMode(Controller::JavaLoader
);
99 RetryPassword(password
);
105 /// Retry a failed password attempt from the first call to Open().
106 /// Only call this function in response to Barry::BadPassword exceptions
107 /// that are thrown from Open().
109 /// \exception Barry::Error
110 /// Thrown on protocol error.
112 /// \exception std::logic_error()
113 /// Thrown if in unsupported mode, or if socket already open.
115 /// \exception Barry::BadPassword
116 /// Thrown when password is invalid or if not enough retries
117 /// left in the device.
119 void JavaLoader::RetryPassword(const char *password
)
121 if( m_socket
.get() != 0 )
122 throw std::logic_error("Socket alreay open in RetryPassword");
124 m_socket
= m_con
.m_zero
.Open(m_ModeSocket
, password
);
128 m_socket
->Receive(response
, -1);
133 // These commands are sent to prepare the data stream
134 void JavaLoader::StartStream()
137 char rawCommand1
[] = { 4, 0, 0x08, 0, 0x64, 0, 0, 0 };
138 *((uint16_t*) rawCommand1
) = htobs(m_socket
->GetSocket());
140 Data
command1(rawCommand1
, sizeof(rawCommand1
));
144 m_socket
->Packet(command1
, response
);
146 catch( Usb::Error
& ) {
147 eout("JavaLoader: command1 error");
148 eeout(command1
, response
);
153 char rawCommand2
[] = { 4, 0, 0x08, 0, 0x70, 0, 0x01, 0 };
154 *((uint16_t*) rawCommand2
) = htobs(m_socket
->GetSocket());
156 Data
command2(rawCommand2
, sizeof(rawCommand2
));
159 m_socket
->SetSequencePacket(false);
160 m_socket
->Packet(command2
, response
);
161 m_socket
->SetSequencePacket(true);
163 catch( Usb::Error
& ) {
164 eout("JavaLoader: command2 error");
165 eeout(command2
, response
);
170 char rawCommand3
[] = { 4, 0, 0x05, 0, 0 };
171 *((uint16_t*) rawCommand3
) = htobs(m_socket
->GetSocket());
173 Data
command3(rawCommand3
, sizeof(rawCommand3
));
176 m_socket
->PacketData(command3
, response
);
178 catch( Usb::Error
& ) {
179 eout("JavaLoader: command3 error");
180 eeout(command1
, response
);
186 // This function permits to send a COD application
187 // WARNING : Before, you have to call the "Start" function,
188 // After, you have to call the "Stop" function.
190 // From the USB traces, the max size of packet is : 0x07FC
192 // 04 00 08 00 68 00 F8 07
193 // ^^^^^ : about size
195 // ^^ : size of packet header
198 // 00 00 0C 00 13 04 01 00 0A 00 00 00
200 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
201 // ^^^^^ ............. ^^^^^ : data (the file content)
202 // ^^^^^ : packet size
206 // WARNING : A COD file starts with the integer 0xDEC0FFFF (FIXME)
207 // An application can contain several COD parts. In this case we can read a header (start with PK)
208 // In this sample, we have to skip the file header :
209 // 00000000 50 4B 03 04 0A 00 00 00 00 00 A0 00 51 35 BA 9F 99 5D 30 CE PK..........Q5...]0.
210 // 00000014 00 00 30 CE 00 00 15 00 04 00 4D 65 74 72 6F 56 69 65 77 65 ..0.......MetroViewe
211 // 00000028 72 2E 50 61 72 69 73 2E 63 6F 64 FE CA 00 00 DE C0 FF FF 00 r.Paris.cod.........
212 // ^^ Start of data sent !
213 // 0000003C 00 00 00 00 00 00 00 0F 10 34 45 00 00 00 00 00 00 00 00 21 .........4E........!
214 // 00000050 00 FF FF FF FF FF FF FF FF FF FF 4E 00 9C 08 68 C5 00 00 F0 ...........N...h....
215 // 00000064 B8 BC C0 A1 C0 14 00 81 00 00 01 01 04 0E 3F 6D 00 02 00 6D ..............?m...m
216 void JavaLoader::SendStream(char *buffer
, int buffsize
)
220 unsigned char rawCommand6
[] = { 4, 0, 0x08, 0, 0x68, 0, 0xf8, 0x07 };
224 char rawCommand4
[] = { 4, 0, 0x08, 0, 0x67, 0x01, 0x04, 0 };
225 *((uint16_t*) rawCommand4
) = htobs(m_socket
->GetSocket());
227 Data
command4(rawCommand4
, sizeof(rawCommand4
));
231 m_socket
->SetSequencePacket(false);
232 m_socket
->Packet(command4
, response
);
233 m_socket
->SetSequencePacket(true);
235 catch( Usb::Error
& ) {
236 eout("JavaLoader: command4 error");
237 eeout(command4
, response
);
242 char rawCommand5
[] = { 4, 0, 0x08, 0, 0, 0, 0x00, 0x00 };
243 *((uint16_t*) rawCommand5
) = htobs(m_socket
->GetSocket());
244 // Blackberry expects the size in big endian format here.
245 // All the 'htob*()' functions assume Blackberry data is
246 // little endian, so do it manually here.
247 #ifdef WORDS_BIGENDIAN
248 *(((uint32_t*) rawCommand5
) + 1) = buffsize
;
250 *(((uint32_t*) rawCommand5
) + 1) = bswap_32(buffsize
);
253 Data
command5(rawCommand5
, sizeof(rawCommand5
));
256 m_socket
->PacketData(command5
, response
);
258 catch( Usb::Error
& ) {
259 eout("JavaLoader: command5 error");
260 eeout(command5
, response
);
265 // Read the buffer...
266 while (bytesent
< buffsize
) {
270 if (buffsize
- bytesent
> 0x7f8)
273 size
= buffsize
- bytesent
;
275 char rawCommand7
[0x7f8 + 4];
276 memcpy(&rawCommand7
[4], buffer
, size
);
282 *((uint16_t*) rawCommand6
) = htobs(m_socket
->GetSocket());
283 *(((uint16_t*) rawCommand6
) + 3) = htobs(size
);
285 Data
command6(rawCommand6
, sizeof(rawCommand6
));
288 m_socket
->SetSequencePacket(false);
289 m_socket
->Packet(command6
, response
);
290 m_socket
->SetSequencePacket(true);
292 catch( Usb::Error
& ) {
293 eout("JavaLoader: command6 error");
294 eeout(command6
, response
);
301 *((uint16_t*) rawCommand7
) = htobs(m_socket
->GetSocket());
302 *(((uint16_t*) rawCommand7
) + 1) = htobs(size
+ 4);
304 Data
command7(rawCommand7
, size
+ 4);
307 m_socket
->PacketData(command7
, response
);
309 catch( Usb::Error
& ) {
310 eout("JavaLoader: command7 error");
311 eeout(command7
, response
);
322 // This command is sent to avert that the data stream is finished
323 void JavaLoader::StopStream(void)
326 unsigned char rawCommand
[] = { 4, 0, 0x08, 0, 0x8d, 0, 0, 0 };
327 *((uint16_t*) rawCommand
) = htobs(m_socket
->GetSocket());
329 Data
command(rawCommand
, sizeof(rawCommand
));
333 m_socket
->Packet(command
, response
);
335 catch( Usb::Error
& ) {
336 eout("JavaLoader: stop command error");
337 eeout(command
, response
);
342 }} // namespace Barry::Mode