tools: MimeDump<> can have all static members
[barry.git] / src / m_javaloader.cc
blob74b0f2e8a53c40a08a71440471734f19b7cfd46c
1 ///
2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
4 ///
6 /*
7 Copyright (C) 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)
8 Copyright (C) 2008-2009, Nicolas VIVIEN
10 Some parts are inspired from m_desktop.h
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU General Public License in the COPYING file at the
22 root directory of this project for more details.
25 #include "m_javaloader.h"
26 #include "data.h"
27 #include "protocol.h"
28 #include "protostructs.h"
29 #include "packet.h"
30 #include "endian.h"
31 #include "error.h"
32 #include "usbwrap.h"
33 #include "controller.h"
34 #include "cod.h"
35 #include <stdexcept>
36 #include <sstream>
37 #include <iomanip>
38 #include <vector>
39 #include <string.h>
40 #include <time.h>
41 #include <stdio.h>
43 #include "debug.h"
45 using namespace std;
47 namespace Barry {
50 ///////////////////////////////////////////////////////////////////////////////
51 // JLScreenInfo class
53 JLScreenInfo::JLScreenInfo()
57 JLScreenInfo::~JLScreenInfo()
63 ///////////////////////////////////////////////////////////////////////////////
64 // JLDirectory class
66 JLDirectory::JLDirectory(int level)
67 : m_level(level)
71 JLDirectory::~JLDirectory()
75 void JLDirectory::ParseTable(const Data &table_packet)
77 m_idTable.clear();
79 size_t count = table_packet.GetSize() / 2;
80 uint16_t *item = (uint16_t*) table_packet.GetData();
81 for( size_t i = 0; i < count; i++, item++ ) {
82 m_idTable.push_back( be_btohs(*item) );
86 void JLDirectory::Dump(std::ostream &os) const
88 int indent = m_level * 2;
90 os << setfill(' ') << setw(indent) << "";
91 os << "Directory: " << m_idTable.size() << "/" << size() << " entries\n";
93 const_iterator i = begin(), e = end();
94 for( ; i != e; ++i ) {
95 os << setfill(' ') << setw(indent + 2) << "";
96 os << *i << "\n";
102 ///////////////////////////////////////////////////////////////////////////////
103 // JLDirectoryEntry class
105 JLDirectoryEntry::JLDirectoryEntry(int level)
106 : m_level(level)
107 , SubDir(level + 1)
111 void JLDirectoryEntry::Parse(uint16_t id, const Data &entry_packet)
113 size_t needed = SB_JLDIRENTRY_HEADER_SIZE;
114 size_t have = entry_packet.GetSize();
115 if( have < needed )
116 throw BadSize("JLDE:Parse(1)", have, needed);
118 const unsigned char *ptr = entry_packet.GetData();
119 Protocol::JLDirEntry *entry = (Protocol::JLDirEntry*) ptr;
121 Id = id;
122 Timestamp = be_btohl(entry->timestamp);
124 uint16_t len = be_btohs(entry->filename_size);
125 needed += len;
126 if( have < needed )
127 throw BadSize("JLDE:Parse(2)", have, needed);
128 Name.assign((char *)entry->filename, len);
130 // need parsed data + string size
131 ptr += needed;
132 needed += 2;
133 if( have < needed )
134 throw BadSize("JLDE:Parse(3)", have, needed);
136 len = be_btohs( *((uint16_t*)(ptr)) );
137 ptr += sizeof(uint16_t);
138 needed += len;
139 if( have < needed )
140 throw BadSize("JLDE:Parse(4)", have, needed);
141 Version.assign((char*)ptr, len);
143 // need parsed data + string size
144 ptr += len;
145 needed += sizeof(uint32_t);
146 if( have < needed )
147 throw BadSize("JLDE:Parse(5)", have, needed);
148 CodSize = be_btohl( *((uint32_t*)(ptr)) );
151 void JLDirectoryEntry::Dump(std::ostream &os) const
153 os << left << setfill(' ') << setw(50) << Name;
155 os << "\n";
156 os << left << setw(28) << " ";
158 os << "0x" << setfill('0') << setw(4) << hex << Id;
159 os << " " << setw(10) << Version;
160 os << " " << setw(7) << std::dec << CodSize;
162 std::string ts = ctime(&Timestamp);
163 ts.erase(ts.size() - 1);
164 os << " " << ts;
166 if( SubDir.size() )
167 os << "\n" << SubDir;
171 ///////////////////////////////////////////////////////////////////////////////
172 // JLEventlog class
174 void JLEventlog::Dump(std::ostream &os) const
176 const_iterator i = begin(), e = end();
177 for( ; i != e; ++i ) {
178 (*i).Dump(os);
183 ///////////////////////////////////////////////////////////////////////////////
184 // JLEventlogEntry class, static members
187 // Note! These functions currently only pass the same values through.
188 // In actuality, these are technically two different values:
189 // one on the raw protocol side, and the other part of the
190 // guaranteed Barry API. If the Blackberry ever changes the
191 // meanings for these codes, do the translation here.
194 JLEventlogEntry::Severity_t JLEventlogEntry::SeverityProto2Rec(unsigned int s)
196 return (Severity_t)s;
199 unsigned int JLEventlogEntry::SeverityRec2Proto(Severity_t s)
201 return s;
204 JLEventlogEntry::ViewerType_t JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v)
206 return (ViewerType_t)v;
209 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t v)
211 return v;
215 ///////////////////////////////////////////////////////////////////////////////
216 // JLEventlogEntry class
218 void JLEventlogEntry::Parse(uint16_t size, const char* buf)
220 // example of a single log entry
221 //guid:92E11214401C3 time:0x11F133E6470 severity:0 type:2 app:UI data:GS-D 2c89868b
223 std::string src = std::string(buf, size);
224 std::istringstream ss(src);
226 ss.ignore(5); // skip "guid:"
227 ss >> Guid;
228 if( ss.fail() )
229 throw BadData("JLEventlogEntry:Parse bad guid field");
231 ss.ignore(6); // skip " time:"
232 ss >> hex >> MSTimestamp;
233 if( ss.fail() )
234 throw BadData("JLEventlogEntry:Parse bad time field");
236 ss.ignore(10); // skip " severity:"
237 unsigned int severity;
238 ss >> severity;
239 Severity = SeverityProto2Rec(severity);
240 if( ss.fail() )
241 throw BadData("JLEventlogEntry:Parse bad severity field");
243 ss.ignore(6); // skip " type:"
244 unsigned int type;
245 ss >> type;
246 Type = ViewerTypeProto2Rec(type);
247 if( ss.fail() )
248 throw BadData("JLEventlogEntry:Parse bad type field");
250 ss.ignore(5); // skip " app:"
251 ss >> App;
252 if( ss.fail() )
253 throw BadData("JLEventlogEntry:Parse bad app field");
255 ss.ignore(6); // skip " data:"
257 // use stringbuf to extract rest of data from stream
258 stringbuf databuf;
259 ss >> &databuf;
260 if( ss.fail() )
261 throw BadData("JLEventlogEntry:Parse bad data field");
263 Data = databuf.str();
266 std::string JLEventlogEntry::GetFormattedTimestamp() const
268 char buf[21];
269 struct tm split;
270 time_t timestamp = (time_t) (MSTimestamp / 1000);
272 if( localtime_r(&timestamp, &split) == NULL )
273 return "";
275 if( strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S.", &split) == 0 )
276 return "";
278 std::ostringstream oss;
279 oss << buf << (MSTimestamp % 1000);
280 return oss.str();
283 void JLEventlogEntry::Dump(std::ostream &os) const
285 static const char *SeverityNames[] = { "Always Log", "Severe Error", "Error",
286 "Warning", "Information", "Debug Info"};
287 static const char *ViewerTypes[] = { "", "Number", "String", "Exception" };
289 os << "guid:" << Guid;
290 os << " time:" << GetFormattedTimestamp();
291 os << " severity:" << SeverityNames[Severity];
292 os << " type:" << ViewerTypes[Type];
293 os << " app:" << App;
294 os << " data:" << Data << endl;
298 ///////////////////////////////////////////////////////////////////////////////
299 // JLDeviceInfo class
301 void JLDeviceInfo::Dump(std::ostream &os) const
303 os << left << setfill(' ') << setw(17) << "Hardware Id:";
304 os << "0x" << hex << HardwareId << endl;
306 os << left << setfill(' ') << setw(17) << "PIN:";
307 os << "0x" << Pin.str() << endl;
309 os << left << setfill(' ') << setw(17) << "OS Version:";
310 os << dec << OsVersion.Major << '.' << OsVersion.Minor << '.' << OsVersion.SubMinor << '.' << OsVersion.Build << endl;
312 os << left << setfill(' ') << setw(17) << "VM Version:";
313 os << dec << VmVersion.Major << '.' << VmVersion.Minor << '.' << VmVersion.SubMinor << '.' << VmVersion.Build << endl;
315 os << left << setfill(' ') << setw(17) << "Radio ID:";
316 os << "0x" << hex << RadioId << endl;
318 os << left << setfill(' ') << setw(17) << "Vendor ID:";
319 os << dec << VendorId << endl;
321 os << left << setfill(' ') << setw(17) << "Active WAFs:";
322 os << "0x" << hex << ActiveWafs << endl;
324 os << left << setfill(' ') << setw(17) << "OS Metrics:" << endl;
325 os << OsMetrics;
327 os << left << setfill(' ') << setw(17) << "Bootrom Metrics:" << endl;
328 os << BootromMetrics;
332 namespace Mode {
334 ///////////////////////////////////////////////////////////////////////////////
335 // JavaLoader Mode class
337 JavaLoader::JavaLoader(Controller &con)
338 : Mode(con, Controller::JavaLoader)
339 , m_StreamStarted(false)
343 JavaLoader::~JavaLoader()
345 if( m_StreamStarted )
346 StopStream();
349 ///////////////////////////////////////////////////////////////////////////////
350 // protected members
353 ///////////////////////////////////////////////////////////////////////////////
354 // public API
356 void JavaLoader::OnOpen()
358 Data response;
359 m_socket->Receive(response, -1);
362 // These commands are sent to prepare the data stream
363 void JavaLoader::StartStream()
365 Data cmd(-1, 8), data(-1, 8), response;
366 JLPacket packet(cmd, data, response);
368 packet.Hello();
369 m_socket->Packet(packet);
371 if( packet.Command() != SB_COMMAND_JL_HELLO_ACK ) {
372 ThrowJLError("JavaLoader::StartStream Hello", packet.Command());
375 packet.SetUnknown1();
376 m_socket->Packet(packet);
378 if( packet.Command() != SB_COMMAND_JL_ACK ) {
379 ThrowJLError("JavaLoader::StartStream Unknown1", packet.Command());
382 m_StreamStarted = true;
386 // This function permits to send a COD application
387 // WARNING : Before, you have to call the "Start" function,
388 // After, you have to call the "Stop" function.
390 // From the USB traces, the max size of packet is : 0x07FC
391 // Packet header :
392 // 04 00 08 00 68 00 F8 07
393 // ^^^^^ : about size
394 // ^^ : command
395 // ^^ : size of packet header
396 // ^^^^^ : socket
397 // Response :
398 // 00 00 0C 00 13 04 01 00 0A 00 00 00
399 // Packet format :
400 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
401 // ^^^^^ ............. ^^^^^ : data (the file content)
402 // ^^^^^ : packet size
403 // ^^^^^ : socket
406 // WARNING : A COD file starts with the integer 0xDEC0FFFF (FIXME)
407 // An application can contain several COD parts. In this case we can read a header (start with PK)
408 // In this sample, we have to skip the file header :
409 // 00000000 50 4B 03 04 0A 00 00 00 00 00 A0 00 51 35 BA 9F 99 5D 30 CE PK..........Q5...]0.
410 // 00000014 00 00 30 CE 00 00 15 00 04 00 4D 65 74 72 6F 56 69 65 77 65 ..0.......MetroViewe
411 // 00000028 72 2E 50 61 72 69 73 2E 63 6F 64 FE CA 00 00 DE C0 FF FF 00 r.Paris.cod.........
412 // ^^ Start of data sent !
413 // 0000003C 00 00 00 00 00 00 00 0F 10 34 45 00 00 00 00 00 00 00 00 21 .........4E........!
414 // 00000050 00 FF FF FF FF FF FF FF FF FF FF 4E 00 9C 08 68 C5 00 00 F0 ...........N...h....
415 // 00000064 B8 BC C0 A1 C0 14 00 81 00 00 01 01 04 0E 3F 6D 00 02 00 6D ..............?m...m
416 void JavaLoader::SendStream(std::istream &input, size_t module_size)
418 char buffer[MAX_PACKET_DATA_SIZE - SB_JLPACKET_HEADER_SIZE];
419 size_t max_data_size = sizeof(buffer);
421 size_t remaining = module_size;
423 Data cmd(-1, 8), data(-1, 8), response;
424 JLPacket packet(cmd, data, response);
426 packet.SetCodSize(module_size);
427 m_socket->Packet(packet);
429 if( packet.Command() != SB_COMMAND_JL_ACK ) {
430 ThrowJLError("JavaLoader::SendStream set code size", packet.Command());
433 while( remaining > 0 ) {
434 size_t size = min(remaining, max_data_size);
436 input.read(buffer, size);
437 if( input.fail() || (size_t)input.gcount() != size ) {
438 throw Error("JavaLoader::SendStream input stream read failed");
441 packet.PutData(buffer, size);
442 m_socket->Packet(packet);
444 if( packet.Command() == SB_COMMAND_JL_NOT_ENOUGH_MEMORY ) {
445 throw Error("JavaLoader::SendStream not enough memory to install the application");
448 if( packet.Command() != SB_COMMAND_JL_ACK ) {
449 ThrowJLError("JavaLoader::SendStream send data", packet.Command());
452 remaining -= size;
456 void JavaLoader::LoadApp(std::istream &input)
458 uint32_t module_size;
459 while( (module_size = SeekNextCod(input)) != 0 ) {
460 SendStream(input, module_size);
465 // StopStream
467 /// Must be called at the end of a JavaLoader session. The JL_GOODBYE
468 /// command is sent to the device. When the device responds with
469 /// RESET_REQUIRED the device reset command will be sent when the
470 /// socket is closed.
472 /// \return true when a device reset was required
474 bool JavaLoader::StopStream()
476 Data cmd(-1, 8), data(-1, 8), response;
478 JLPacket packet(cmd, data, response);
479 packet.Goodbye();
480 try {
481 m_socket->Packet(packet);
482 } catch( BadPacket &bp ) {
483 // on some devices, such as the 7750 and the 7130,
484 // the Goodbye command receives NOT_SUPPORTED
485 // instead of the usual ACK... this is not an
486 // error, so catch that case here and ignore it.
487 // otherwise, throw it to higher levels
488 if( bp.response() != SB_COMMAND_JL_NOT_SUPPORTED )
489 throw;
492 m_StreamStarted = false;
494 if( packet.Command() == SB_COMMAND_JL_RESET_REQUIRED ) {
495 m_con.m_zero.SetResetOnClose(true);
496 return true;
498 else if( packet.Command() != SB_COMMAND_JL_ACK &&
499 packet.Command() != SB_COMMAND_JL_NOT_SUPPORTED )
501 ThrowJLError("JavaLoader::StopStream", packet.Command());
504 return false;
507 void JavaLoader::SetTime(time_t when)
509 Data cmd(-1, 8), data(-1, 8), response;
511 JLPacket packet(cmd, data, response);
512 packet.SetTime(when);
513 m_socket->Packet(packet);
514 if( packet.Command() != SB_COMMAND_JL_ACK ) {
515 ThrowJLError("JavaLoader::SetTime", packet.Command());
519 void JavaLoader::ThrowJLError(const std::string &msg, uint8_t cmd)
521 std::ostringstream oss;
522 oss << msg << ": unexpected packet command code: 0x"
523 << std::hex << (unsigned int) cmd;
524 throw Error(oss.str());
527 void JavaLoader::GetDirectoryEntries(JLPacket &packet,
528 uint8_t entry_cmd,
529 JLDirectory &dir,
530 bool include_subdirs)
532 JLDirectory::TableIterator i = dir.TableBegin(), e = dir.TableEnd();
533 for( ; i != e; ++i ) {
534 packet.GetDirEntry(entry_cmd, *i);
535 m_socket->Packet(packet);
536 if( packet.Command() != SB_COMMAND_JL_ACK ) {
537 ThrowJLError("JavaLoader::GetDirectoryEntries", packet.Command());
540 Data &response = packet.GetReceive();
541 m_socket->Receive(response);
542 JLDirectoryEntry entry(dir.Level());
543 Protocol::CheckSize(response, 4);
544 entry.Parse(*i, Data(response.GetData() + 4, response.GetSize() - 4));
546 if( include_subdirs ) {
547 packet.GetSubDir(*i);
548 GetDir(packet, SB_COMMAND_JL_GET_SUBDIR_ENTRY, entry.SubDir, false);
551 // add to list
552 dir.push_back(entry);
556 void JavaLoader::GetDir(JLPacket &packet,
557 uint8_t entry_cmd,
558 JLDirectory &dir,
559 bool include_subdirs)
561 m_socket->Packet(packet);
562 if( packet.Command() != SB_COMMAND_JL_ACK ) {
563 ThrowJLError("JavaLoader::GetDir", packet.Command());
566 // ack response will contain length of module ID array in next packet
567 unsigned int expect = packet.Size();
569 if( expect > 0 ) {
570 Data &response = packet.GetReceive();
571 m_socket->Receive(response);
572 Protocol::CheckSize(response, 4);
573 dir.ParseTable(Data(response.GetData() + 4, response.GetSize() - 4));
574 GetDirectoryEntries(packet, entry_cmd, dir, include_subdirs);
578 void JavaLoader::GetDirectory(JLDirectory &dir, bool include_subdirs)
580 Data cmd(-1, 8), data(-1, 8), response;
581 JLPacket packet(cmd, data, response);
583 packet.GetDirectory();
584 GetDir(packet, SB_COMMAND_JL_GET_DATA_ENTRY, dir, include_subdirs);
588 // This function permits to receive a ScreenShot (maybe other...)
589 // WARNING : Before, you have to call the "Start" function,
590 // After, you have to call the "Stop" function.
592 // From the USB traces, the max size of packet is : 0x07FC
593 // When you are ready, we send the packet :
594 // 04 00 08 00 68 00 00 00
595 // Then, we receive an acknoledge and the data.
596 // The data is composed of two packets : header and content.
597 // Packet header :
598 // 04 00 08 00 6E 00 F8 07
599 // ^^^^^ : size + 4 bytes
600 // ^^ : command
601 // ^^^^^ : size of packet header
602 // ^^^^^ : socket
603 // Packet content :
604 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
605 // ^^^^^ ............. ^^^^^ : data (the file content)
606 // ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
607 // ^^^^^ : socket
610 // GetScreenshot
612 /// Downloads screenshot from device, and fills info with size data
613 /// and the given Data buffer image with the bitmap.
615 void JavaLoader::GetScreenshot(JLScreenInfo &info, Data &image)
617 // start fresh
618 image.Zap();
620 Data cmd(-1, 8), data(-1, 8), response;
621 JLPacket packet(cmd, data, response);
623 // Send the screenshot command :
624 // 00000000: 04 00 08 00 87 00 04 00
625 packet.GetScreenshot();
627 m_socket->Packet(packet);
629 if( packet.Command() != SB_COMMAND_JL_ACK ) {
630 ThrowJLError("JavaLoader::GetScreenshot", packet.Command());
633 // Get Info :
634 // 00000000: 04 00 14 00 00 05 46 00 40 03 01 68 01 e0 00 10 ......F.@..h....
635 // ^^^^^x^^^^^ : width x height
636 // ^^^^^ : packet size
637 // ^^^^^ : socket ID
638 // 00000010: 00 00 00 00 ....
640 m_socket->Receive(response);
642 // Parse response...
643 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLSCREENINFO_SIZE);
644 MAKE_JLPACKET(rpack, response);
646 info.width = be_btohs(rpack->u.screeninfo.width);
647 info.height = be_btohs(rpack->u.screeninfo.height);
650 // Read stream
651 for (;;) {
652 // Send the packet :
653 // 04 00 08 00 68 00 00 00
654 packet.GetData();
656 m_socket->Packet(packet);
658 // Read and parse the response
659 // 04 00 08 00 64 00 00 00
660 // or
661 // 04 00 08 00 6e 00 f8 07
663 if( packet.Command() == SB_COMMAND_JL_ACK )
664 return;
666 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
667 ThrowJLError("JavaLoader::GetScreenShot ", packet.Command());
670 // Read the size of next packet
671 size_t expect = packet.Size();
674 // Read the stream
675 m_socket->Receive(response);
678 // Save data in buffer
679 Protocol::CheckSize(response, 4);
680 const unsigned char *pd = response.GetData();
681 size_t bytereceived = response.GetSize() - 4;
684 // Check the size read into the previous packet
685 if( expect != bytereceived ) {
686 ThrowJLError("JavaLoader::GetScreenShot expect", expect);
690 // Copy data
691 unsigned char *buffer = image.GetBuffer(image.GetSize() + bytereceived);
692 memcpy(buffer + image.GetSize(), pd + 4, bytereceived);
694 // New size
695 image.ReleaseBuffer(image.GetSize() + bytereceived);
699 void JavaLoader::DoErase(uint8_t cmd, const std::string &cod_name)
701 Data command(-1, 8), data(-1, 8), response;
703 JLPacket packet(command, data, response);
705 // set filename, device responds with an ID
706 packet.SetCodFilename(cod_name);
707 m_socket->Packet(packet);
708 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
709 throw Error(string("JavaLoader::DoErase: module ") + cod_name + " not found");
711 if( packet.Command() != SB_COMMAND_JL_ACK ) {
712 ThrowJLError("JavaLoader::DoErase", packet.Command());
715 // make sure there is an ID coming
716 if( packet.Size() != 2 )
717 throw Error("JavaLoader::DoErase: expected code not available");
719 // get ID
720 m_socket->Receive(response);
721 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
722 MAKE_JLPACKET(jpack, response);
723 uint16_t id = be_btohs(jpack->u.id);
725 // send erase command, with application ID
726 packet.Erase(cmd, id);
727 m_socket->Packet(packet);
728 if( packet.Command() == SB_COMMAND_JL_COD_IN_USE ) {
729 throw Error("JavaLoader::DoErase: COD file in use.");
731 if( packet.Command() != SB_COMMAND_JL_ACK ) {
732 ThrowJLError("JavaLoader::DoErase", packet.Command());
736 void JavaLoader::Erase(const std::string &cod_name)
738 DoErase(SB_COMMAND_JL_ERASE, cod_name);
741 void JavaLoader::ForceErase(const std::string &cod_name)
743 DoErase(SB_COMMAND_JL_FORCE_ERASE, cod_name);
746 void JavaLoader::GetEventlog(JLEventlog &log)
748 Data command(-1, 8), data(-1, 8), response;
749 JLPacket packet(command, data, response);
751 packet.GetEventlog();
753 m_socket->Packet(packet);
755 if( packet.Command() != SB_COMMAND_JL_ACK ) {
756 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
759 m_socket->Receive(response);
760 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
762 // number of eventlog entries
763 MAKE_JLPACKET(jpack, response);
764 uint16_t count = be_btohs(jpack->u.response.expect);
766 for( uint16_t i = 0; i < count; ++ i ) {
767 packet.GetEventlogEntry(i);
769 m_socket->Packet(packet);
771 if( packet.Command() != SB_COMMAND_JL_ACK ) {
772 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
775 m_socket->Receive(response);
776 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE);
778 MAKE_JLPACKET(jpack, response);
779 uint16_t size = be_btohs(jpack->u.logentry.size);
781 JLEventlogEntry entry;
782 entry.Parse(size, (const char *)(response.GetData() + SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE));
784 log.push_back(entry);
788 void JavaLoader::ClearEventlog()
790 Data command(-1, 8), data(-1, 8), response;
791 JLPacket packet(command, data, response);
793 packet.ClearEventlog();
794 m_socket->Packet(packet);
796 if( packet.Command() != SB_COMMAND_JL_ACK ) {
797 ThrowJLError("JavaLoader::ClearEventlog", packet.Command());
801 void JavaLoader::SaveData(JLPacket &packet, uint16_t id, CodFileBuilder &builder, std::ostream &output)
803 packet.SaveModule(id);
804 m_socket->Packet(packet);
806 if( packet.Command() != SB_COMMAND_JL_ACK ) {
807 ThrowJLError("JavaLoader::SaveData", packet.Command());
810 // get total size of cod file or this sibling cod file
811 Data &response = packet.GetReceive();
812 m_socket->Receive(response);
813 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint32_t));
814 MAKE_JLPACKET(jpack, response);
815 uint32_t total_size = be_btohl(jpack->u.cod_size);
817 // allocate buffer to hold data for this sibling
818 Data buffer(-1, total_size);
819 uint32_t offset = 0;
821 for( ;; ) {
822 packet.GetData();
823 m_socket->Packet(packet);
825 if( packet.Command() == SB_COMMAND_JL_ACK )
826 break;
828 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
829 ThrowJLError("JavaLoader::SaveData", packet.Command());
832 // expected size of data in response packet
833 unsigned int expect = packet.Size();
835 m_socket->Receive(response);
836 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
838 memcpy(buffer.GetBuffer(offset + expect) + offset,
839 response.GetData() + SB_JLPACKET_HEADER_SIZE,
840 expect);
842 offset += expect;
845 buffer.ReleaseBuffer(offset);
847 builder.WriteNextHeader(output, buffer.GetData(), buffer.GetSize());
848 output.write((const char *)buffer.GetData(), buffer.GetSize());
851 void JavaLoader::Save(const std::string &cod_name, std::ostream &output)
853 Data command(-1, 8), data(-1, 8), response;
855 JLPacket packet(command, data, response);
857 // set filename, device responds with an ID
858 packet.SetCodFilename(cod_name);
859 m_socket->Packet(packet);
861 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
862 throw Error(string("JavaLoader::Save: module ") + cod_name + " not found");
865 if( packet.Command() != SB_COMMAND_JL_ACK ) {
866 ThrowJLError("JavaLoader::Save", packet.Command());
869 // make sure there is an ID coming
870 if( packet.Size() != 2 )
871 throw Error("JavaLoader::Save: expected module ID");
873 // get ID
874 m_socket->Receive(response);
875 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
876 MAKE_JLPACKET(jpack, response);
877 uint16_t id = be_btohs(jpack->u.id);
879 // get list of sibling modules
880 packet.GetSubDir(id);
881 m_socket->Packet(packet);
883 if( packet.Command() != SB_COMMAND_JL_ACK ) {
884 ThrowJLError("JavaLoader::Save", packet.Command());
887 // expected number of module ID's
888 unsigned int expect = packet.Size();
890 // get list of sibling module ID's
891 m_socket->Receive(response);
892 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
894 // copy array of module ID's since we reuse the response packet buffer
895 size_t count = expect / 2;
896 const uint16_t *begin = (const uint16_t*) (response.GetData() + SB_JLPACKET_HEADER_SIZE);
897 const uint16_t *end = begin + count;
898 vector<uint16_t> ids(begin, end);
900 CodFileBuilder builder(cod_name, count);
902 // save each block of data
903 for( size_t i = 0; i < count; i++ ) {
904 SaveData(packet, be_btohs(ids[i]), builder, output);
907 builder.WriteFooter(output);
910 void JavaLoader::DeviceInfo(JLDeviceInfo &info)
912 Data command(-1, 8), data(-1, 8), response;
913 JLPacket packet(command, data, response);
915 packet.DeviceInfo();
917 m_socket->Packet(packet);
919 if( packet.Command() != SB_COMMAND_JL_ACK ) {
920 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
923 m_socket->Receive(response);
925 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLDEVICEINFO_SIZE);
926 MAKE_JLPACKET(rpack, response);
928 info.HardwareId = be_btohl(rpack->u.devinfo.hardware_id);
929 info.Pin = be_btohl(rpack->u.devinfo.pin);
930 info.OsVersion = be_btohl(rpack->u.devinfo.os_version);
931 info.VmVersion = be_btohl(rpack->u.devinfo.vm_version);
932 info.RadioId = be_btohl(rpack->u.devinfo.radio_id);
933 info.VendorId = be_btohl(rpack->u.devinfo.vendor_id);
934 info.ActiveWafs = be_btohl(rpack->u.devinfo.active_wafs);
936 packet.OsMetrics();
938 m_socket->Packet(packet);
940 if( packet.Command() != SB_COMMAND_JL_ACK ) {
941 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
944 m_socket->Receive(response);
945 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
947 size_t offset = SB_JLPACKET_HEADER_SIZE;
948 size_t size = response.GetSize()-offset;
949 unsigned char* buf = info.OsMetrics.GetBuffer(size);
950 memcpy(buf, response.GetData()+offset, size);
951 info.OsMetrics.ReleaseBuffer(size);
953 packet.BootromMetrics();
955 m_socket->Packet(packet);
957 if( packet.Command() != SB_COMMAND_JL_ACK ) {
958 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
961 m_socket->Receive(response);
962 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
964 offset = SB_JLPACKET_HEADER_SIZE;
965 size = response.GetSize()-offset;
966 buf = info.BootromMetrics.GetBuffer(size);
967 memcpy(buf, response.GetData()+offset, size);
968 info.BootromMetrics.ReleaseBuffer(size);
971 void JavaLoader::Wipe(bool apps, bool fs)
973 Data command(-1, 8), data(-1, 8), response;
974 JLPacket packet(command, data, response);
976 if( apps ) {
977 packet.WipeApps();
978 m_socket->Packet(packet);
980 if( packet.Command() != SB_COMMAND_JL_ACK ) {
981 ThrowJLError("JavaLoader::WipeApps", packet.Command());
985 if( fs ) {
986 packet.WipeFs();
987 m_socket->Packet(packet);
989 if( packet.Command() != SB_COMMAND_JL_ACK ) {
990 ThrowJLError("JavaLoader::WipeFs", packet.Command());
995 void JavaLoader::LogStackTraces()
997 Data command(-1, 8), data(-1, 8), response;
998 JLPacket packet(command, data, response);
1000 packet.LogStackTraces();
1001 m_socket->Packet(packet);
1003 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1004 ThrowJLError("JavaLoader::LogStackTraces", packet.Command());
1008 void JavaLoader::ResetToFactory()
1010 Data command(-1, 8), data(-1, 8), response;
1011 JLPacket packet(command, data, response);
1013 packet.ResetToFactory();
1014 m_socket->Packet(packet);
1016 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1017 ThrowJLError("JavaLoader::ResetToFactory", packet.Command());
1021 }} // namespace Barry::Mode