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