Removed unnecessary utf8 codes from some doc files
[barry.git] / src / m_javaloader.cc
blob4e74bbd0c669abb5591bd19769cd7605d75df5c4
1 ///
2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
4 ///
6 /*
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"
26 #include "data.h"
27 #include "protocol.h"
28 #include "protostructs.h"
29 #include "packet.h"
30 #include "endian.h"
31 #include "error.h"
32 #include "usbwrap.h"
33 #include "controller.h"
34 #include <stdexcept>
35 #include <sstream>
36 #include <string.h>
38 #include "debug.h"
40 namespace Barry { namespace Mode {
43 ///////////////////////////////////////////////////////////////////////////////
44 // JavaLoader Mode class
46 JavaLoader::JavaLoader(Controller &con)
47 : m_con(con)
48 , m_ModeSocket(0)
52 JavaLoader::~JavaLoader()
56 ///////////////////////////////////////////////////////////////////////////////
57 // protected members
60 ///////////////////////////////////////////////////////////////////////////////
61 // public API
64 // Open
66 /// Select device mode. This is required before using any other mode-based
67 /// operations.
68 ///
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.
75 ///
76 /// You can retry the password by catching Barry::BadPassword and
77 /// calling RetryPassword() with the new password.
78 ///
79 /// \exception Barry::Error
80 /// Thrown on protocol error.
81 ///
82 /// \exception std::logic_error()
83 /// Thrown if unsupported mode is requested, or if socket
84 /// already open.
85 ///
86 /// \exception Barry::BadPassword
87 /// Thrown when password is invalid or if not enough retries
88 /// left in the device.
89 ///
90 void JavaLoader::Open(const char *password)
92 if( m_ModeSocket ) {
93 m_socket->Close();
94 m_socket.reset();
95 m_ModeSocket = 0;
98 m_ModeSocket = m_con.SelectMode(Controller::JavaLoader);
99 RetryPassword(password);
103 // RetryPassword
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);
127 Data response;
128 m_socket->Receive(response, -1);
133 // These commands are sent to prepare the data stream
134 void JavaLoader::StartStream()
136 // 1°/
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));
141 Data response;
143 try {
144 m_socket->Packet(command1, response);
146 catch( Usb::Error & ) {
147 eout("JavaLoader: command1 error");
148 eeout(command1, response);
149 throw;
152 // 2°/
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));
158 try {
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);
166 throw;
169 // 3°/
170 char rawCommand3[] = { 4, 0, 0x05, 0, 0 };
171 *((uint16_t*) rawCommand3) = htobs(m_socket->GetSocket());
173 Data command3(rawCommand3, sizeof(rawCommand3));
175 try {
176 m_socket->PacketData(command3, response);
178 catch( Usb::Error & ) {
179 eout("JavaLoader: command3 error");
180 eeout(command1, response);
181 throw;
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
191 // Packet header :
192 // 04 00 08 00 68 00 F8 07
193 // ^^^^^ : about size
194 // ^^ : command
195 // ^^ : size of packet header
196 // ^^^^^ : socket
197 // Response :
198 // 00 00 0C 00 13 04 01 00 0A 00 00 00
199 // Packet format :
200 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
201 // ^^^^^ ............. ^^^^^ : data (the file content)
202 // ^^^^^ : packet size
203 // ^^^^^ : socket
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)
218 int bytesent = 0;
220 unsigned char rawCommand6[] = { 4, 0, 0x08, 0, 0x68, 0, 0xf8, 0x07 };
223 // 4°/
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));
228 Data response;
230 try {
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);
238 throw;
241 // 5°/
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;
249 #else
250 *(((uint32_t*) rawCommand5) + 1) = bswap_32(buffsize);
251 #endif
253 Data command5(rawCommand5, sizeof(rawCommand5));
255 try {
256 m_socket->PacketData(command5, response);
258 catch( Usb::Error & ) {
259 eout("JavaLoader: command5 error");
260 eeout(command5, response);
261 throw;
265 // Read the buffer...
266 while (bytesent < buffsize) {
267 // Read data buffer
268 int size;
270 if (buffsize - bytesent > 0x7f8)
271 size = 0x7f8;
272 else
273 size = buffsize - bytesent;
275 char rawCommand7[0x7f8 + 4];
276 memcpy(&rawCommand7[4], buffer, size);
279 // 1st packet
280 //------------
281 // Packet Header
282 *((uint16_t*) rawCommand6) = htobs(m_socket->GetSocket());
283 *(((uint16_t*) rawCommand6) + 3) = htobs(size);
285 Data command6(rawCommand6, sizeof(rawCommand6));
287 try {
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);
295 throw;
298 // 2nd packet
299 //------------
300 // Packet data
301 *((uint16_t*) rawCommand7) = htobs(m_socket->GetSocket());
302 *(((uint16_t*) rawCommand7) + 1) = htobs(size + 4);
304 Data command7(rawCommand7, size + 4);
306 try {
307 m_socket->PacketData(command7, response);
309 catch( Usb::Error & ) {
310 eout("JavaLoader: command7 error");
311 eeout(command7, response);
312 throw;
315 // Next...
316 bytesent += size;
317 buffer += size;
322 // This command is sent to avert that the data stream is finished
323 void JavaLoader::StopStream(void)
325 // 7°/
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));
330 Data response;
332 try {
333 m_socket->Packet(command, response);
335 catch( Usb::Error & ) {
336 eout("JavaLoader: stop command error");
337 eeout(command, response);
338 throw;
342 }} // namespace Barry::Mode