# m_javaloader.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       m_javaloader.cc
    00003 ///             Mode class for the JavaLoader mode
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00008     Copyright (C) 2008-2009, Nicolas VIVIEN
    00009
    00010         Some parts are inspired from m_desktop.h
    00011
    00012     This program is free software; you can redistribute it and/or modify
    00013     it under the terms of the GNU General Public License as published by
    00014     the Free Software Foundation; either version 2 of the License, or
    00015     (at your option) any later version.
    00016
    00017     This program is distributed in the hope that it will be useful,
    00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00020
    00021     See the GNU General Public License in the COPYING file at the
    00022     root directory of this project for more details.
    00023 */
    00024
    00025 #include "m_javaloader.h"
    00026 #include "data.h"
    00027 #include "protocol.h"
    00028 #include "protostructs.h"
    00029 #include "packet.h"
    00030 #include "endian.h"
    00031 #include "error.h"
    00032 #include "usbwrap.h"
    00033 #include "controller.h"
    00034 #include "cod.h"
    00035 #include <stdexcept>
    00036 #include <sstream>
    00037 #include <iomanip>
    00038 #include <vector>
    00039 #include <string.h>
    00040 #include <time.h>
    00041 #include <stdio.h>
    00042
    00043 #include "debug.h"
    00044
    00045 using namespace std;
    00046
    00047 namespace Barry {
    00048
    00049
    00050 ///////////////////////////////////////////////////////////////////////////////
    00051 // JLScreenInfo class
    00052
    00053 JLScreenInfo::JLScreenInfo()
    00054 {
    00055 }
    00056
    00057 JLScreenInfo::~JLScreenInfo()
    00058 {
    00059 }
    00060
    00061
    00062
    00063 ///////////////////////////////////////////////////////////////////////////////
    00064 // JLDirectory class
    00065
    00066 JLDirectory::JLDirectory(int level)
    00067         : m_level(level)
    00068 {
    00069 }
    00070
    00071 JLDirectory::~JLDirectory()
    00072 {
    00073 }
    00074
    00075 void JLDirectory::ParseTable(const Data &table_packet)
    00076 {
    00077         m_idTable.clear();
    00078
    00079         size_t count = table_packet.GetSize() / 2;
    00080         uint16_t *item = (uint16_t*) table_packet.GetData();
    00081         for( size_t i = 0; i < count; i++, item++ ) {
    00082                 m_idTable.push_back( be_btohs(*item) );
    00083         }
    00084 }
    00085
    00086 void JLDirectory::Dump(std::ostream &os) const
    00087 {
    00088         int indent = m_level * 2;
    00089
    00090         os << setfill(' ') << setw(indent) << "";
    00091         os << "Directory: " << m_idTable.size() << "/" << size() << " entries\n";
    00092
    00093         const_iterator i = begin(), e = end();
    00094         for( ; i != e; ++i ) {
    00095                 os << setfill(' ') << setw(indent + 2) << "";
    00096                 os << *i << "\n";
    00097         }
    00098 }
    00099
    00100
    00101
    00102 ///////////////////////////////////////////////////////////////////////////////
    00103 // JLDirectoryEntry class
    00104
    00105 JLDirectoryEntry::JLDirectoryEntry(int level)
    00106         : m_level(level)
    00107         , SubDir(level + 1)
    00108 {
    00109 }
    00110
    00111 void JLDirectoryEntry::Parse(uint16_t id, const Data &entry_packet)
    00112 {
    00113         size_t needed = SB_JLDIRENTRY_HEADER_SIZE;
    00114         size_t have = entry_packet.GetSize();
    00115         if( have < needed )
    00116                 throw BadSize("JLDE:Parse(1)", have, needed);
    00117
    00118         const unsigned char *ptr = entry_packet.GetData();
    00119         Protocol::JLDirEntry *entry = (Protocol::JLDirEntry*) ptr;
    00120
    00121         Id = id;
    00122         Timestamp = be_btohl(entry->timestamp);
    00123
    00124         uint16_t len = be_btohs(entry->filename_size);
    00125         needed += len;
    00126         if( have < needed )
    00127                 throw BadSize("JLDE:Parse(2)", have, needed);
    00128         Name.assign((char *)entry->filename, len);
    00129
    00130         // need parsed data + string size
    00131         ptr += needed;
    00132         needed += 2;
    00133         if( have < needed )
    00134                 throw BadSize("JLDE:Parse(3)", have, needed);
    00135
    00136         len = be_btohs( *((uint16_t*)(ptr)) );
    00137         ptr += sizeof(uint16_t);
    00138         needed += len;
    00139         if( have < needed )
    00140                 throw BadSize("JLDE:Parse(4)", have, needed);
    00141         Version.assign((char*)ptr, len);
    00142
    00143         // need parsed data + string size
    00144         ptr += len;
    00145         needed += sizeof(uint32_t);
    00146         if( have < needed )
    00147                 throw BadSize("JLDE:Parse(5)", have, needed);
    00148         CodSize = be_btohl( *((uint32_t*)(ptr)) );
    00149 }
    00150
    00151 void JLDirectoryEntry::Dump(std::ostream &os) const
    00152 {
    00153         os << left << setfill(' ') << setw(50) << Name;
    00154
    00155         os << "\n";
    00156         os << left << setw(28) << " ";
    00157
    00158         os << "0x" << setfill('0') << setw(4) << hex << Id;
    00159         os << " " << setw(10) << Version;
    00160         os << " " << setw(7) << std::dec << CodSize;
    00161
    00162         std::string ts = ctime(&Timestamp);
    00163         ts.erase(ts.size() - 1);
    00164         os << " " << ts;
    00165
    00166         if( SubDir.size() )
    00167                 os << "\n" << SubDir;
    00168 }
    00169
    00170
    00171 ///////////////////////////////////////////////////////////////////////////////
    00172 // JLEventlog class
    00173
    00174 void JLEventlog::Dump(std::ostream &os) const
    00175 {
    00176         const_iterator i = begin(), e = end();
    00177         for( ; i != e; ++i ) {
    00178                 (*i).Dump(os);
    00179         }
    00180 }
    00181
    00182
    00183 ///////////////////////////////////////////////////////////////////////////////
    00184 // JLEventlogEntry class, static members
    00185
    00186 //
    00187 // Note! These functions currently only pass the same values through.
    00188 //       In actuality, these are technically two different values:
    00189 //       one on the raw protocol side, and the other part of the
    00190 //       guaranteed Barry API.  If the Blackberry ever changes the
    00191 //       meanings for these codes, do the translation here.
    00192 //
    00193
    00194 JLEventlogEntry::Severity_t JLEventlogEntry::SeverityProto2Rec(unsigned int s)
    00195 {
    00196         return (Severity_t)s;
    00197 }
    00198
    00199 unsigned int JLEventlogEntry::SeverityRec2Proto(Severity_t s)
    00200 {
    00201         return s;
    00202 }
    00203
    00204 JLEventlogEntry::ViewerType_t JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v)
    00205 {
    00206         return (ViewerType_t)v;
    00207 }
    00208
    00209 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t v)
    00210 {
    00211         return v;
    00212 }
    00213
    00214
    00215 ///////////////////////////////////////////////////////////////////////////////
    00216 // JLEventlogEntry class
    00217
    00218 void JLEventlogEntry::Parse(uint16_t size, const char* buf)
    00219 {
    00220         // example of a single log entry
    00221         //guid:92E11214401C3 time:0x11F133E6470 severity:0 type:2 app:UI data:GS-D 2c89868b
    00222
    00223         std::string src = std::string(buf, size);
    00224         std::istringstream ss(src);
    00225
    00226         ss.ignore(5); // skip "guid:"
    00227         ss >> Guid;
    00228         if( ss.fail() )
    00229                 throw BadData("JLEventlogEntry:Parse bad guid field");
    00230
    00231         ss.ignore(6); // skip " time:"
    00232         ss >> hex >> MSTimestamp;
    00233         if( ss.fail() )
    00234                 throw BadData("JLEventlogEntry:Parse bad time field");
    00235
    00236         ss.ignore(10); // skip " severity:"
    00237         unsigned int severity;
    00238         ss >> severity;
    00239         Severity = SeverityProto2Rec(severity);
    00240         if( ss.fail() )
    00241                 throw BadData("JLEventlogEntry:Parse bad severity field");
    00242
    00243         ss.ignore(6); // skip " type:"
    00244         unsigned int type;
    00245         ss >> type;
    00246         Type = ViewerTypeProto2Rec(type);
    00247         if( ss.fail() )
    00248                 throw BadData("JLEventlogEntry:Parse bad type field");
    00249
    00250         ss.ignore(5); // skip " app:"
    00251         ss >> App;
    00252         if( ss.fail() )
    00253                 throw BadData("JLEventlogEntry:Parse bad app field");
    00254
    00255         ss.ignore(6); // skip " data:"
    00256
    00257         // use stringbuf to extract rest of data from stream
    00258         stringbuf databuf;
    00259         ss >> &databuf;
    00260         if( ss.fail() )
    00261                 throw BadData("JLEventlogEntry:Parse bad data field");
    00262
    00263         Data = databuf.str();
    00264 }
    00265
    00266 std::string JLEventlogEntry::GetFormattedTimestamp() const
    00267 {
    00268         char buf[21];
    00269         struct tm split;
    00270         time_t timestamp = (time_t) (MSTimestamp / 1000);
    00271
    00272         if( localtime_r(&timestamp, &split) == NULL )
    00273                 return "";
    00274
    00275         if( strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S.", &split) == 0 )
    00276                 return "";
    00277
    00278         std::ostringstream oss;
    00279         oss << buf << (MSTimestamp % 1000);
    00280         return oss.str();
    00281 }
    00282
    00283 void JLEventlogEntry::Dump(std::ostream &os) const
    00284 {
    00285         static const char *SeverityNames[] = { "Always Log", "Severe Error", "Error",
    00286                 "Warning", "Information", "Debug Info"};
    00287         static const char *ViewerTypes[] = { "", "Number", "String", "Exception" };
    00288
    00289         os << "guid:"      << Guid;
    00290         os << " time:"     << GetFormattedTimestamp();
    00291         os << " severity:" << SeverityNames[Severity];
    00292         os << " type:"     << ViewerTypes[Type];
    00293         os << " app:"      << App;
    00294         os << " data:"     << Data << endl;
    00295 }
    00296
    00297
    00298 ///////////////////////////////////////////////////////////////////////////////
    00299 // JLDeviceInfo class
    00300
    00301 void JLDeviceInfo::Dump(std::ostream &os) const
    00302 {
    00303         os << left << setfill(' ') << setw(17) << "Hardware Id:";
    00304         os << "0x" << hex << HardwareId << endl;
    00305
    00306         os << left << setfill(' ') << setw(17) << "PIN:";
    00307         os << "0x" << Pin.Str() << endl;
    00308
    00309         os << left << setfill(' ') << setw(17) << "OS Version:";
    00310         os << dec << OsVersion.Major << '.' << OsVersion.Minor << '.' << OsVersion.SubMinor << '.' << OsVersion.Build << endl;
    00311
    00312         os << left << setfill(' ') << setw(17) << "VM Version:";
    00313         os << dec << VmVersion.Major << '.' << VmVersion.Minor << '.' << VmVersion.SubMinor << '.' << VmVersion.Build << endl;
    00314
    00315         os << left << setfill(' ') << setw(17) << "Radio ID:";
    00316         os << "0x" << hex << RadioId << endl;
    00317
    00318         os << left << setfill(' ') << setw(17) << "Vendor ID:";
    00319         os << dec << VendorId << endl;
    00320
    00321         os << left << setfill(' ') << setw(17) << "Active WAFs:";
    00322         os << "0x" << hex << ActiveWafs << endl;
    00323
    00324         os << left << setfill(' ') << setw(17) << "OS Metrics:" << endl;
    00325         os << OsMetrics;
    00326
    00327         os << left << setfill(' ') << setw(17) << "Bootrom Metrics:" << endl;
    00328         os << BootromMetrics;
    00329 }
    00330
    00331
    00332 namespace Mode {
    00333
    00334 ///////////////////////////////////////////////////////////////////////////////
    00335 // JavaLoader Mode class
    00336
    00337 JavaLoader::JavaLoader(Controller &con)
    00338         : Mode(con, Controller::JavaLoader)
    00339         , m_StreamStarted(false)
    00340 {
    00341 }
    00342
    00343 JavaLoader::~JavaLoader()
    00344 {
    00345         if( m_StreamStarted )
    00346                 StopStream();
    00347 }
    00348
    00349 ///////////////////////////////////////////////////////////////////////////////
    00350 // protected members
    00351
    00352
    00353 ///////////////////////////////////////////////////////////////////////////////
    00354 // public API
    00355
    00356 void JavaLoader::OnOpen()
    00357 {
    00358         Data response;
    00359         m_socket->Receive(response, -1);
    00360 }
    00361
    00362 // These commands are sent to prepare the data stream
    00363 void JavaLoader::StartStream()
    00364 {
    00365         Data cmd(-1, 8), data(-1, 8), response;
    00366         JLPacket packet(cmd, data, response);
    00367
    00368         packet.Hello();
    00369         m_socket->Packet(packet);
    00370
    00371         if( packet.Command() != SB_COMMAND_JL_HELLO_ACK ) {
    00372                 ThrowJLError("JavaLoader::StartStream Hello", packet.Command());
    00373         }
    00374
    00375         packet.SetUnknown1();
    00376         m_socket->Packet(packet);
    00377
    00378         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00379                 ThrowJLError("JavaLoader::StartStream Unknown1", packet.Command());
    00380         }
    00381
    00382         m_StreamStarted = true;
    00383 }
    00384
    00385
    00386 // This function permits to send a COD application
    00387 // WARNING : Before, you have to call the "Start" function,
    00388 //           After, you have to call the "Stop" function.
    00389 //
    00390 // From the USB traces, the max size of packet is : 0x07FC
    00391 // Packet header :
    00392 //  04 00 08 00 68 00 F8 07
    00393 //                    ^^^^^ : about size
    00394 //              ^^ : command
    00395 //        ^^ : size of packet header
    00396 //  ^^^^^ : socket
    00397 // Response :
    00398 //  00 00 0C 00 13 04 01 00 0A 00 00 00
    00399 // Packet format :
    00400 //  04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
    00401 //              ^^^^^ ............. ^^^^^ : data (the file content)
    00402 //        ^^^^^ : packet size
    00403 //  ^^^^^ : socket
    00404 //
    00405 //
    00406 // WARNING : A COD file starts with the integer 0xDEC0FFFF (FIXME)
    00407 // An application can contain several COD parts. In this case we can read a header (start with PK)
    00408 // In this sample, we have to skip the file header :
    00409 //   00000000   50 4B 03 04  0A 00 00 00  00 00 A0 00  51 35 BA 9F  99 5D 30 CE  PK..........Q5...]0.
    00410 //   00000014   00 00 30 CE  00 00 15 00  04 00 4D 65  74 72 6F 56  69 65 77 65  ..0.......MetroViewe
    00411 //   00000028   72 2E 50 61  72 69 73 2E  63 6F 64 FE  CA 00 00 DE  C0 FF FF 00  r.Paris.cod.........
    00412 //                                                              ^^ Start of data sent !
    00413 //   0000003C   00 00 00 00  00 00 00 0F  10 34 45 00  00 00 00 00  00 00 00 21  .........4E........!
    00414 //   00000050   00 FF FF FF  FF FF FF FF  FF FF FF 4E  00 9C 08 68  C5 00 00 F0  ...........N...h....
    00415 //   00000064   B8 BC C0 A1  C0 14 00 81  00 00 01 01  04 0E 3F 6D  00 02 00 6D  ..............?m...m
    00416 void JavaLoader::SendStream(std::istream &input, size_t module_size)
    00417 {
    00418         char buffer[MAX_PACKET_DATA_SIZE - SB_JLPACKET_HEADER_SIZE];
    00419         size_t max_data_size = sizeof(buffer);
    00420
    00421         size_t remaining = module_size;
    00422
    00423         Data cmd(-1, 8), data(-1, 8), response;
    00424         JLPacket packet(cmd, data, response);
    00425
    00426         packet.SetCodSize(module_size);
    00427         m_socket->Packet(packet);
    00428
    00429         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00430                 ThrowJLError("JavaLoader::SendStream set code size", packet.Command());
    00431         }
    00432
    00433         while( remaining > 0 ) {
    00434                 size_t size = min(remaining, max_data_size);
    00435
    00436                 input.read(buffer, size);
    00437                 if( input.fail() || (size_t)input.gcount() != size ) {
    00438                         throw Error("JavaLoader::SendStream input stream read failed");
    00439                 }
    00440
    00441                 packet.PutData(buffer, size);
    00442                 m_socket->Packet(packet);
    00443
    00444                 if( packet.Command() == SB_COMMAND_JL_NOT_ENOUGH_MEMORY ) {
    00445                         throw Error("JavaLoader::SendStream not enough memory to install the application");
    00446                 }
    00447
    00448                 if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00449                         ThrowJLError("JavaLoader::SendStream send data", packet.Command());
    00450                 }
    00451
    00452                 remaining -= size;
    00453         }
    00454 }
    00455
    00456 void JavaLoader::LoadApp(std::istream &input)
    00457 {
    00458         uint32_t module_size;
    00459         while( (module_size = SeekNextCod(input)) != 0 ) {
    00460                 SendStream(input, module_size);
    00461         }
    00462 }
    00463
    00464 //
    00465 // StopStream
    00466 //
    00467 /// Must be called at the end of a JavaLoader session.  The JL_GOODBYE
    00468 /// command is sent to the device.  When the device responds with
    00469 /// RESET_REQUIRED the device reset command will be sent when the
    00470 /// socket is closed.
    00471 ///
    00472 /// \return true when a device reset was required
    00473 ///
    00474 bool JavaLoader::StopStream()
    00475 {
    00476         Data cmd(-1, 8), data(-1, 8), response;
    00477
    00478         JLPacket packet(cmd, data, response);
    00479         packet.Goodbye();
    00480         try {
    00481                 m_socket->Packet(packet);
    00482         } catch( BadPacket &bp ) {
    00483                 // on some devices, such as the 7750 and the 7130,
    00484                 // the Goodbye command receives NOT_SUPPORTED
    00485                 // instead of the usual ACK... this is not an
    00486                 // error, so catch that case here and ignore it.
    00487                 // otherwise, throw it to higher levels
    00488                 if( bp.response() != SB_COMMAND_JL_NOT_SUPPORTED )
    00489                         throw;
    00490         }
    00491
    00492         m_StreamStarted = false;
    00493
    00494         if( packet.Command() == SB_COMMAND_JL_RESET_REQUIRED ) {
    00495                 m_con.m_zero.SetResetOnClose(true);
    00496                 return true;
    00497         }
    00498         else if( packet.Command() != SB_COMMAND_JL_ACK &&
    00499                  packet.Command() != SB_COMMAND_JL_NOT_SUPPORTED )
    00500         {
    00501                 ThrowJLError("JavaLoader::StopStream", packet.Command());
    00502         }
    00503
    00504         return false;
    00505 }
    00506
    00507 void JavaLoader::SetTime(time_t when)
    00508 {
    00509         Data cmd(-1, 8), data(-1, 8), response;
    00510
    00511         JLPacket packet(cmd, data, response);
    00512         packet.SetTime(when);
    00513         m_socket->Packet(packet);
    00514         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00515                 ThrowJLError("JavaLoader::SetTime", packet.Command());
    00516         }
    00517 }
    00518
    00519 void JavaLoader::ThrowJLError(const std::string &msg, uint8_t cmd)
    00520 {
    00521         std::ostringstream oss;
    00522         oss << msg << ": unexpected packet command code: 0x"
    00523                 << std::hex << (unsigned int) cmd;
    00524         throw Error(oss.str());
    00525 }
    00526
    00527 void JavaLoader::GetDirectoryEntries(JLPacket &packet,
    00528                                      uint8_t entry_cmd,
    00529                                      JLDirectory &dir,
    00530                                      bool include_subdirs)
    00531 {
    00532         JLDirectory::TableIterator i = dir.TableBegin(), e = dir.TableEnd();
    00533         for( ; i != e; ++i ) {
    00534                 packet.GetDirEntry(entry_cmd, *i);
    00535                 m_socket->Packet(packet);
    00536                 if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00537                         ThrowJLError("JavaLoader::GetDirectoryEntries", packet.Command());
    00538                 }
    00539
    00540                 Data &response = packet.GetReceive();
    00541                 m_socket->Receive(response);
    00542                 JLDirectoryEntry entry(dir.Level());
    00543                 Protocol::CheckSize(response, 4);
    00544                 entry.Parse(*i, Data(response.GetData() + 4, response.GetSize() - 4));
    00545
    00546                 if( include_subdirs ) {
    00547                         packet.GetSubDir(*i);
    00548                         GetDir(packet, SB_COMMAND_JL_GET_SUBDIR_ENTRY, entry.SubDir, false);
    00549                 }
    00550
    00551                 // add to list
    00552                 dir.push_back(entry);
    00553         }
    00554 }
    00555
    00556 void JavaLoader::GetDir(JLPacket &packet,
    00557                         uint8_t entry_cmd,
    00558                         JLDirectory &dir,
    00559                         bool include_subdirs)
    00560 {
    00561         m_socket->Packet(packet);
    00562         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00563                 ThrowJLError("JavaLoader::GetDir", packet.Command());
    00564         }
    00565
    00566         // ack response will contain length of module ID array in next packet
    00567         unsigned int expect = packet.Size();
    00568
    00569         if( expect > 0 ) {
    00570                 Data &response = packet.GetReceive();
    00571                 m_socket->Receive(response);
    00572                 Protocol::CheckSize(response, 4);
    00573                 dir.ParseTable(Data(response.GetData() + 4, response.GetSize() - 4));
    00574                 GetDirectoryEntries(packet, entry_cmd, dir, include_subdirs);
    00575         }
    00576 }
    00577
    00578 void JavaLoader::GetDirectory(JLDirectory &dir, bool include_subdirs)
    00579 {
    00580         Data cmd(-1, 8), data(-1, 8), response;
    00581         JLPacket packet(cmd, data, response);
    00582
    00583         packet.GetDirectory();
    00584         GetDir(packet, SB_COMMAND_JL_GET_DATA_ENTRY, dir, include_subdirs);
    00585 }
    00586
    00587
    00588 // This function permits to receive a ScreenShot (maybe other...)
    00589 // WARNING : Before, you have to call the "Start" function,
    00590 //           After, you have to call the "Stop" function.
    00591 //
    00592 // From the USB traces, the max size of packet is : 0x07FC
    00593 // When you are ready, we send the packet :
    00594 //  04 00 08 00 68 00 00 00
    00595 // Then, we receive an acknoledge and the data.
    00596 // The data is composed of two packets : header and content.
    00597 // Packet header :
    00598 //  04 00 08 00 6E 00 F8 07
    00599 //                    ^^^^^ : size + 4 bytes
    00600 //              ^^ : command
    00601 //        ^^^^^ : size of packet header
    00602 //  ^^^^^ : socket
    00603 // Packet content :
    00604 //  04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
    00605 //              ^^^^^ ............. ^^^^^ : data (the file content)
    00606 //        ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
    00607 //  ^^^^^ : socket
    00608 //
    00609 //
    00610 // GetScreenshot
    00611 //
    00612 /// Downloads screenshot from device, and fills info with size data
    00613 /// and the given Data buffer image with the bitmap.
    00614 ///
    00615 void JavaLoader::GetScreenshot(JLScreenInfo &info, Data &image)
    00616 {
    00617         // start fresh
    00618         image.Zap();
    00619
    00620         Data cmd(-1, 8), data(-1, 8), response;
    00621         JLPacket packet(cmd, data, response);
    00622
    00623         // Send the screenshot command :
    00624         //    00000000: 04 00 08 00 87 00 04 00
    00625         packet.GetScreenshot();
    00626
    00627         m_socket->Packet(packet);
    00628
    00629         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00630                 ThrowJLError("JavaLoader::GetScreenshot", packet.Command());
    00631         }
    00632
    00633         // Get Info :
    00634         //    00000000: 04 00 14 00 00 05 46 00 40 03 01 68 01 e0 00 10  ......F.@..h....
    00635         //                                            ^^^^^x^^^^^ : width x height
    00636         //                    ^^^^^ : packet size
    00637         //              ^^^^^ : socket ID
    00638         //    00000010: 00 00 00 00                                      ....
    00639
    00640         m_socket->Receive(response);
    00641
    00642         // Parse response...
    00643         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLSCREENINFO_SIZE);
    00644         MAKE_JLPACKET(rpack, response);
    00645
    00646         info.width = be_btohs(rpack->u.screeninfo.width);
    00647         info.height = be_btohs(rpack->u.screeninfo.height);
    00648
    00649
    00650         // Read stream
    00651         for (;;) {
    00652                 // Send the packet :
    00653                 //   04 00 08 00 68 00 00 00
    00654                 packet.GetData();
    00655
    00656                 m_socket->Packet(packet);
    00657
    00658                 // Read and parse the response
    00659                 //   04 00 08 00 64 00 00 00
    00660                 // or
    00661                 //   04 00 08 00 6e 00 f8 07
    00662
    00663                 if( packet.Command() == SB_COMMAND_JL_ACK )
    00664                         return;
    00665
    00666                 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
    00667                         ThrowJLError("JavaLoader::GetScreenShot ", packet.Command());
    00668                 }
    00669
    00670                 // Read the size of next packet
    00671                 size_t expect = packet.Size();
    00672
    00673
    00674                 // Read the stream
    00675                 m_socket->Receive(response);
    00676
    00677
    00678                 // Save data in buffer
    00679                 Protocol::CheckSize(response, 4);
    00680                 const unsigned char *pd = response.GetData();
    00681                 size_t bytereceived = response.GetSize() - 4;
    00682
    00683
    00684                 // Check the size read into the previous packet
    00685                 if( expect != bytereceived ) {
    00686                         ThrowJLError("JavaLoader::GetScreenShot expect", expect);
    00687                 }
    00688
    00689
    00690                 // Copy data
    00691                 unsigned char *buffer = image.GetBuffer(image.GetSize() + bytereceived);
    00692                 memcpy(buffer + image.GetSize(), pd + 4, bytereceived);
    00693
    00694                 // New size
    00695                 image.ReleaseBuffer(image.GetSize() + bytereceived);
    00696         }
    00697 }
    00698
    00699 void JavaLoader::DoErase(uint8_t cmd, const std::string &cod_name)
    00700 {
    00701         Data command(-1, 8), data(-1, 8), response;
    00702
    00703         JLPacket packet(command, data, response);
    00704
    00705         // set filename, device responds with an ID
    00706         packet.SetCodFilename(cod_name);
    00707         m_socket->Packet(packet);
    00708         if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
    00709                 throw Error(string("JavaLoader::DoErase: module ") + cod_name + " not found");
    00710         }
    00711         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00712                 ThrowJLError("JavaLoader::DoErase", packet.Command());
    00713         }
    00714
    00715         // make sure there is an ID coming
    00716         if( packet.Size() != 2 )
    00717                 throw Error("JavaLoader::DoErase: expected code not available");
    00718
    00719         // get ID
    00720         m_socket->Receive(response);
    00721         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
    00722         MAKE_JLPACKET(jpack, response);
    00723         uint16_t id = be_btohs(jpack->u.id);
    00724
    00725         // send erase command, with application ID
    00726         packet.Erase(cmd, id);
    00727         m_socket->Packet(packet);
    00728         if( packet.Command() == SB_COMMAND_JL_COD_IN_USE ) {
    00729                 throw Error("JavaLoader::DoErase: COD file in use.");
    00730         }
    00731         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00732                 ThrowJLError("JavaLoader::DoErase", packet.Command());
    00733         }
    00734 }
    00735
    00736 void JavaLoader::Erase(const std::string &cod_name)
    00737 {
    00738         DoErase(SB_COMMAND_JL_ERASE, cod_name);
    00739 }
    00740
    00741 void JavaLoader::ForceErase(const std::string &cod_name)
    00742 {
    00743         DoErase(SB_COMMAND_JL_FORCE_ERASE, cod_name);
    00744 }
    00745
    00746 void JavaLoader::GetEventlog(JLEventlog &log)
    00747 {
    00748         Data command(-1, 8), data(-1, 8), response;
    00749         JLPacket packet(command, data, response);
    00750
    00751         packet.GetEventlog();
    00752
    00753         m_socket->Packet(packet);
    00754
    00755         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00756                 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
    00757         }
    00758
    00759         m_socket->Receive(response);
    00760         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
    00761
    00762         // number of eventlog entries
    00763         MAKE_JLPACKET(jpack, response);
    00764         uint16_t count = be_btohs(jpack->u.response.expect);
    00765
    00766         for( uint16_t i = 0; i < count; ++ i ) {
    00767                 packet.GetEventlogEntry(i);
    00768
    00769                 m_socket->Packet(packet);
    00770
    00771                 if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00772                         ThrowJLError("JavaLoader::GetEventlog", packet.Command());
    00773                 }
    00774
    00775                 m_socket->Receive(response);
    00776                 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE);
    00777
    00778                 MAKE_JLPACKET(jpack, response);
    00779                 uint16_t size = be_btohs(jpack->u.logentry.size);
    00780
    00781                 JLEventlogEntry entry;
    00782                 entry.Parse(size, (const char *)(response.GetData() + SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE));
    00783
    00784                 log.push_back(entry);
    00785         }
    00786 }
    00787
    00788 void JavaLoader::ClearEventlog()
    00789 {
    00790         Data command(-1, 8), data(-1, 8), response;
    00791         JLPacket packet(command, data, response);
    00792
    00793         packet.ClearEventlog();
    00794         m_socket->Packet(packet);
    00795
    00796         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00797                 ThrowJLError("JavaLoader::ClearEventlog", packet.Command());
    00798         }
    00799 }
    00800
    00801 void JavaLoader::SaveData(JLPacket &packet, uint16_t id, CodFileBuilder &builder, std::ostream &output)
    00802 {
    00803         packet.SaveModule(id);
    00804         m_socket->Packet(packet);
    00805
    00806         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00807                 ThrowJLError("JavaLoader::SaveData", packet.Command());
    00808         }
    00809
    00810         // get total size of cod file or this sibling cod file
    00811         Data &response = packet.GetReceive();
    00812         m_socket->Receive(response);
    00813         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint32_t));
    00814         MAKE_JLPACKET(jpack, response);
    00815         uint32_t total_size = be_btohl(jpack->u.cod_size);
    00816
    00817         // allocate buffer to hold data for this sibling
    00818         Data buffer(-1, total_size);
    00819         uint32_t offset = 0;
    00820
    00821         for( ;; ) {
    00822                 packet.GetData();
    00823                 m_socket->Packet(packet);
    00824
    00825                 if( packet.Command() == SB_COMMAND_JL_ACK )
    00826                         break;
    00827
    00828                 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
    00829                         ThrowJLError("JavaLoader::SaveData", packet.Command());
    00830                 }
    00831
    00832                 // expected size of data in response packet
    00833                 unsigned int expect = packet.Size();
    00834
    00835                 m_socket->Receive(response);
    00836                 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
    00837
    00838                 memcpy(buffer.GetBuffer(offset + expect) + offset,
    00839                         response.GetData() + SB_JLPACKET_HEADER_SIZE,
    00840                         expect);
    00841
    00842                 offset += expect;
    00843         }
    00844
    00845         buffer.ReleaseBuffer(offset);
    00846
    00847         builder.WriteNextHeader(output, buffer.GetData(), buffer.GetSize());
    00848         output.write((const char *)buffer.GetData(), buffer.GetSize());
    00849 }
    00850
    00851 void JavaLoader::Save(const std::string &cod_name, std::ostream &output)
    00852 {
    00853         Data command(-1, 8), data(-1, 8), response;
    00854
    00855         JLPacket packet(command, data, response);
    00856
    00857         // set filename, device responds with an ID
    00858         packet.SetCodFilename(cod_name);
    00859         m_socket->Packet(packet);
    00860
    00861         if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
    00862                 throw Error(string("JavaLoader::Save: module ") + cod_name + " not found");
    00863         }
    00864
    00865         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00866                 ThrowJLError("JavaLoader::Save", packet.Command());
    00867         }
    00868
    00869         // make sure there is an ID coming
    00870         if( packet.Size() != 2 )
    00871                 throw Error("JavaLoader::Save: expected module ID");
    00872
    00873         // get ID
    00874         m_socket->Receive(response);
    00875         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
    00876         MAKE_JLPACKET(jpack, response);
    00877         uint16_t id = be_btohs(jpack->u.id);
    00878
    00879         // get list of sibling modules
    00880         packet.GetSubDir(id);
    00881         m_socket->Packet(packet);
    00882
    00883         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00884                 ThrowJLError("JavaLoader::Save", packet.Command());
    00885         }
    00886
    00887         // expected number of module ID's
    00888         unsigned int expect = packet.Size();
    00889
    00890         // get list of sibling module ID's
    00891         m_socket->Receive(response);
    00892         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
    00893
    00894         // copy array of module ID's since we reuse the response packet buffer
    00895         size_t count = expect / 2;
    00896         const uint16_t *begin = (const uint16_t*) (response.GetData() + SB_JLPACKET_HEADER_SIZE);
    00897         const uint16_t *end = begin + count;
    00898         vector<uint16_t> ids(begin, end);
    00899
    00900         CodFileBuilder builder(cod_name, count);
    00901
    00902         // save each block of data
    00903         for( size_t i = 0; i < count; i++ ) {
    00904                 SaveData(packet, be_btohs(ids[i]), builder, output);
    00905         }
    00906
    00907         builder.WriteFooter(output);
    00908 }
    00909
    00910 void JavaLoader::DeviceInfo(JLDeviceInfo &info)
    00911 {
    00912         Data command(-1, 8), data(-1, 8), response;
    00913         JLPacket packet(command, data, response);
    00914
    00915         packet.DeviceInfo();
    00916
    00917         m_socket->Packet(packet);
    00918
    00919         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00920                 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
    00921         }
    00922
    00923         m_socket->Receive(response);
    00924
    00925         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLDEVICEINFO_SIZE);
    00926         MAKE_JLPACKET(rpack, response);
    00927
    00928         info.HardwareId = be_btohl(rpack->u.devinfo.hardware_id);
    00929         info.Pin = be_btohl(rpack->u.devinfo.pin);
    00930         info.OsVersion = be_btohl(rpack->u.devinfo.os_version);
    00931         info.VmVersion = be_btohl(rpack->u.devinfo.vm_version);
    00932         info.RadioId = be_btohl(rpack->u.devinfo.radio_id);
    00933         info.VendorId = be_btohl(rpack->u.devinfo.vendor_id);
    00934         info.ActiveWafs = be_btohl(rpack->u.devinfo.active_wafs);
    00935
    00936         packet.OsMetrics();
    00937
    00938         m_socket->Packet(packet);
    00939
    00940         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00941                 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
    00942         }
    00943
    00944         m_socket->Receive(response);
    00945         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
    00946
    00947         size_t offset = SB_JLPACKET_HEADER_SIZE;
    00948         size_t size = response.GetSize()-offset;
    00949         unsigned char* buf = info.OsMetrics.GetBuffer(size);
    00950         memcpy(buf, response.GetData()+offset, size);
    00951         info.OsMetrics.ReleaseBuffer(size);
    00952
    00953         packet.BootromMetrics();
    00954
    00955         m_socket->Packet(packet);
    00956
    00957         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00958                 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
    00959         }
    00960
    00961         m_socket->Receive(response);
    00962         Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
    00963
    00964         offset = SB_JLPACKET_HEADER_SIZE;
    00965         size = response.GetSize()-offset;
    00966         buf = info.BootromMetrics.GetBuffer(size);
    00967         memcpy(buf, response.GetData()+offset, size);
    00968         info.BootromMetrics.ReleaseBuffer(size);
    00969 }
    00970
    00971 void JavaLoader::Wipe(bool apps, bool fs)
    00972 {
    00973         Data command(-1, 8), data(-1, 8), response;
    00974         JLPacket packet(command, data, response);
    00975
    00976         if( apps ) {
    00977                 packet.WipeApps();
    00978                 m_socket->Packet(packet);
    00979
    00980                 if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00981                         ThrowJLError("JavaLoader::WipeApps", packet.Command());
    00982                 }
    00983         }
    00984
    00985         if( fs ) {
    00986                 packet.WipeFs();
    00987                 m_socket->Packet(packet);
    00988
    00989                 if( packet.Command() != SB_COMMAND_JL_ACK ) {
    00990                         ThrowJLError("JavaLoader::WipeFs", packet.Command());
    00991                 }
    00992         }
    00993 }
    00994
    00995 void JavaLoader::LogStackTraces()
    00996 {
    00997         Data command(-1, 8), data(-1, 8), response;
    00998         JLPacket packet(command, data, response);
    00999
    01000         packet.LogStackTraces();
    01001         m_socket->Packet(packet);
    01002
    01003         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    01004                 ThrowJLError("JavaLoader::LogStackTraces", packet.Command());
    01005         }
    01006 }
    01007
    01008 void JavaLoader::ResetToFactory()
    01009 {
    01010         Data command(-1, 8), data(-1, 8), response;
    01011         JLPacket packet(command, data, response);
    01012
    01013         packet.ResetToFactory();
    01014         m_socket->Packet(packet);
    01015
    01016         if( packet.Command() != SB_COMMAND_JL_ACK ) {
    01017                 ThrowJLError("JavaLoader::ResetToFactory", packet.Command());
    01018         }
    01019 }
    01020
    01021 }} // namespace Barry::Mode
    01022