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 

Generated on Tue Mar 1 17:50:15 2011 for Barry by  doxygen 1.5.6