desktop: fixed signed comparison bug, and fixed seconds/minutes bug
[barry/progweb.git] / src / m_javaloader.cc
blobda349a4325b6b8e3d5f84d3256f6beb64dbea564
1 ///
2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
4 ///
6 /*
7 Copyright (C) 2005-2012, 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>
42 #include "ios_state.h"
44 #include "debug.h"
46 using namespace std;
48 namespace Barry {
51 ///////////////////////////////////////////////////////////////////////////////
52 // JLScreenInfo class
54 JLScreenInfo::JLScreenInfo()
58 JLScreenInfo::~JLScreenInfo()
64 ///////////////////////////////////////////////////////////////////////////////
65 // JLDirectory class
67 JLDirectory::JLDirectory(int level)
68 : m_level(level)
72 JLDirectory::~JLDirectory()
76 void JLDirectory::ParseTable(const Data &table_packet)
78 m_idTable.clear();
80 size_t count = table_packet.GetSize() / 2;
81 uint16_t *item = (uint16_t*) table_packet.GetData();
82 for( size_t i = 0; i < count; i++, item++ ) {
83 m_idTable.push_back( be_btohs(*item) );
87 void JLDirectory::Dump(std::ostream &os) const
89 ios_format_state state(os);
91 int indent = m_level * 2;
93 os << setfill(' ') << setw(indent) << "";
94 os << "Directory: " << m_idTable.size() << "/" << size() << " entries\n";
96 const_iterator i = begin(), e = end();
97 for( ; i != e; ++i ) {
98 os << setfill(' ') << setw(indent + 2) << "";
99 os << *i << "\n";
105 ///////////////////////////////////////////////////////////////////////////////
106 // JLDirectoryEntry class
108 JLDirectoryEntry::JLDirectoryEntry(int level)
109 : m_level(level)
110 , SubDir(level + 1)
114 void JLDirectoryEntry::Parse(uint16_t id, const Data &entry_packet)
116 size_t needed = SB_JLDIRENTRY_HEADER_SIZE;
117 size_t have = entry_packet.GetSize();
118 if( have < needed )
119 throw BadSize("JLDE:Parse(1)", have, needed);
121 const unsigned char *ptr = entry_packet.GetData();
122 Protocol::JLDirEntry *entry = (Protocol::JLDirEntry*) ptr;
124 Id = id;
125 Timestamp = be_btohl(entry->timestamp);
127 uint16_t len = be_btohs(entry->filename_size);
128 needed += len;
129 if( have < needed )
130 throw BadSize("JLDE:Parse(2)", have, needed);
131 Name.assign((char *)entry->filename, len);
133 // need parsed data + string size
134 ptr += needed;
135 needed += 2;
136 if( have < needed )
137 throw BadSize("JLDE:Parse(3)", have, needed);
139 len = be_btohs( *((uint16_t*)(ptr)) );
140 ptr += sizeof(uint16_t);
141 needed += len;
142 if( have < needed )
143 throw BadSize("JLDE:Parse(4)", have, needed);
144 Version.assign((char*)ptr, len);
146 // need parsed data + string size
147 ptr += len;
148 needed += sizeof(uint32_t);
149 if( have < needed )
150 throw BadSize("JLDE:Parse(5)", have, needed);
151 CodSize = be_btohl( *((uint32_t*)(ptr)) );
154 void JLDirectoryEntry::Dump(std::ostream &os) const
156 ios_format_state state(os);
158 os << left << setfill(' ') << setw(50) << Name;
160 os << "\n";
161 os << left << setw(28) << " ";
163 os << "0x" << setfill('0') << setw(4) << hex << Id;
164 os << " " << setw(10) << Version;
165 os << " " << setw(7) << std::dec << CodSize;
167 std::string ts = ctime(&Timestamp);
168 ts.erase(ts.size() - 1);
169 os << " " << ts;
171 if( SubDir.size() )
172 os << "\n" << SubDir;
176 ///////////////////////////////////////////////////////////////////////////////
177 // JLEventlog class
179 void JLEventlog::Dump(std::ostream &os) const
181 const_iterator i = begin(), e = end();
182 for( ; i != e; ++i ) {
183 (*i).Dump(os);
188 ///////////////////////////////////////////////////////////////////////////////
189 // JLEventlogEntry class, static members
192 // Note! These functions currently only pass the same values through.
193 // In actuality, these are technically two different values:
194 // one on the raw protocol side, and the other part of the
195 // guaranteed Barry API. If the Blackberry ever changes the
196 // meanings for these codes, do the translation here.
199 JLEventlogEntry::Severity_t JLEventlogEntry::SeverityProto2Rec(unsigned int s)
201 return (Severity_t)s;
204 unsigned int JLEventlogEntry::SeverityRec2Proto(Severity_t s)
206 return s;
209 JLEventlogEntry::ViewerType_t JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v)
211 return (ViewerType_t)v;
214 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t v)
216 return v;
220 ///////////////////////////////////////////////////////////////////////////////
221 // JLEventlogEntry class
223 void JLEventlogEntry::Parse(uint16_t size, const char* buf)
225 // example of a single log entry
226 //guid:92E11214401C3 time:0x11F133E6470 severity:0 type:2 app:UI data:GS-D 2c89868b
228 std::string src = std::string(buf, size);
229 std::istringstream ss(src);
231 ss.ignore(5); // skip "guid:"
232 ss >> Guid;
233 if( ss.fail() )
234 throw BadData("JLEventlogEntry:Parse bad guid field");
236 ss.ignore(6); // skip " time:"
237 ss >> hex >> MSTimestamp;
238 if( ss.fail() )
239 throw BadData("JLEventlogEntry:Parse bad time field");
241 ss.ignore(10); // skip " severity:"
242 unsigned int severity;
243 ss >> severity;
244 Severity = SeverityProto2Rec(severity);
245 if( ss.fail() )
246 throw BadData("JLEventlogEntry:Parse bad severity field");
248 ss.ignore(6); // skip " type:"
249 unsigned int type;
250 ss >> type;
251 Type = ViewerTypeProto2Rec(type);
252 if( ss.fail() )
253 throw BadData("JLEventlogEntry:Parse bad type field");
255 ss.ignore(5); // skip " app:"
256 ss >> App;
257 if( ss.fail() )
258 throw BadData("JLEventlogEntry:Parse bad app field");
260 ss.ignore(6); // skip " data:"
262 // use stringbuf to extract rest of data from stream
263 stringbuf databuf;
264 ss >> &databuf;
265 if( ss.fail() )
266 throw BadData("JLEventlogEntry:Parse bad data field");
268 Data = databuf.str();
271 std::string JLEventlogEntry::GetFormattedTimestamp() const
273 char buf[21];
274 struct tm split;
275 time_t timestamp = (time_t) (MSTimestamp / 1000);
277 if( localtime_r(&timestamp, &split) == NULL )
278 return "";
280 if( strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S.", &split) == 0 )
281 return "";
283 std::ostringstream oss;
284 oss << buf << (MSTimestamp % 1000);
285 return oss.str();
288 void JLEventlogEntry::Dump(std::ostream &os) const
290 ios_format_state state(os);
292 static const char *SeverityNames[] = { "Always Log", "Severe Error", "Error",
293 "Warning", "Information", "Debug Info"};
294 static const char *ViewerTypes[] = { "", "Number", "String", "Exception" };
296 os << "guid:" << Guid;
297 os << " time:" << GetFormattedTimestamp();
298 os << " severity:" << SeverityNames[Severity];
299 os << " type:" << ViewerTypes[Type];
300 os << " app:" << App;
301 os << " data:" << Data << endl;
305 ///////////////////////////////////////////////////////////////////////////////
306 // JLDeviceInfo class
308 void JLDeviceInfo::Dump(std::ostream &os) const
310 ios_format_state state(os);
312 os << left << setfill(' ') << setw(17) << "Hardware Id:";
313 os << "0x" << hex << HardwareId << endl;
315 os << left << setfill(' ') << setw(17) << "PIN:";
316 os << "0x" << Pin.Str() << endl;
318 os << left << setfill(' ') << setw(17) << "OS Version:";
319 os << dec << OsVersion.Major << '.' << OsVersion.Minor << '.' << OsVersion.SubMinor << '.' << OsVersion.Build << endl;
321 os << left << setfill(' ') << setw(17) << "VM Version:";
322 os << dec << VmVersion.Major << '.' << VmVersion.Minor << '.' << VmVersion.SubMinor << '.' << VmVersion.Build << endl;
324 os << left << setfill(' ') << setw(17) << "Radio ID:";
325 os << "0x" << hex << RadioId << endl;
327 os << left << setfill(' ') << setw(17) << "Vendor ID:";
328 os << dec << VendorId << endl;
330 // WAF = Wireless Access Families
331 os << left << setfill(' ') << setw(17) << "Active Wireless Access Families:";
332 os << "0x" << hex << ActiveWafs << endl;
334 os << left << setfill(' ') << setw(17) << "OS Metrics:" << endl;
335 os << OsMetrics;
337 os << left << setfill(' ') << setw(17) << "Bootrom Metrics:" << endl;
338 os << BootromMetrics;
342 namespace Mode {
344 ///////////////////////////////////////////////////////////////////////////////
345 // JavaLoader Mode class
347 JavaLoader::JavaLoader(Controller &con)
348 : Mode(con, Controller::JavaLoader)
349 , m_StreamStarted(false)
353 JavaLoader::~JavaLoader()
355 try {
356 if( m_StreamStarted )
357 StopStream();
359 catch( std::exception &e ) {
360 dout("Exception ignored in ~JavaLoader(): " << e.what());
362 catch( ... ) {
363 dout("Unknown exception in ~JavaLoader()");
367 ///////////////////////////////////////////////////////////////////////////////
368 // protected members
371 ///////////////////////////////////////////////////////////////////////////////
372 // public API
374 void JavaLoader::OnOpen()
376 Data response;
377 m_socket->Receive(response, -1);
380 // These commands are sent to prepare the data stream
381 void JavaLoader::StartStream()
383 Data cmd(-1, 8), data(-1, 8), response;
384 JLPacket packet(cmd, data, response);
386 packet.Hello();
387 m_socket->Packet(packet);
389 if( packet.Command() != SB_COMMAND_JL_HELLO_ACK ) {
390 ThrowJLError("JavaLoader::StartStream Hello", packet.Command());
393 packet.SetUnknown1();
394 m_socket->Packet(packet);
396 if( packet.Command() != SB_COMMAND_JL_ACK ) {
397 ThrowJLError("JavaLoader::StartStream Unknown1", packet.Command());
400 m_StreamStarted = true;
404 // This function permits to send a COD application
405 // WARNING : Before, you have to call the "Start" function,
406 // After, you have to call the "Stop" function.
408 // From the USB traces, the max size of packet is : 0x07FC
409 // Packet header :
410 // 04 00 08 00 68 00 F8 07
411 // ^^^^^ : about size
412 // ^^ : command
413 // ^^ : size of packet header
414 // ^^^^^ : socket
415 // Response :
416 // 00 00 0C 00 13 04 01 00 0A 00 00 00
417 // Packet format :
418 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
419 // ^^^^^ ............. ^^^^^ : data (the file content)
420 // ^^^^^ : packet size
421 // ^^^^^ : socket
424 // WARNING : A COD file starts with the integer 0xDEC0FFFF (FIXME)
425 // An application can contain several COD parts. In this case we can read a header (start with PK)
426 // In this sample, we have to skip the file header :
427 // 00000000 50 4B 03 04 0A 00 00 00 00 00 A0 00 51 35 BA 9F 99 5D 30 CE PK..........Q5...]0.
428 // 00000014 00 00 30 CE 00 00 15 00 04 00 4D 65 74 72 6F 56 69 65 77 65 ..0.......MetroViewe
429 // 00000028 72 2E 50 61 72 69 73 2E 63 6F 64 FE CA 00 00 DE C0 FF FF 00 r.Paris.cod.........
430 // ^^ Start of data sent !
431 // 0000003C 00 00 00 00 00 00 00 0F 10 34 45 00 00 00 00 00 00 00 00 21 .........4E........!
432 // 00000050 00 FF FF FF FF FF FF FF FF FF FF 4E 00 9C 08 68 C5 00 00 F0 ...........N...h....
433 // 00000064 B8 BC C0 A1 C0 14 00 81 00 00 01 01 04 0E 3F 6D 00 02 00 6D ..............?m...m
434 void JavaLoader::SendStream(std::istream &input, size_t module_size)
436 char buffer[MAX_PACKET_DATA_SIZE - SB_JLPACKET_HEADER_SIZE];
437 size_t max_data_size = sizeof(buffer);
439 size_t remaining = module_size;
441 Data cmd(-1, 8), data(-1, 8), response;
442 JLPacket packet(cmd, data, response);
444 packet.SetCodSize(module_size);
445 m_socket->Packet(packet);
447 if( packet.Command() != SB_COMMAND_JL_ACK ) {
448 ThrowJLError("JavaLoader::SendStream set code size", packet.Command());
451 while( remaining > 0 ) {
452 size_t size = min(remaining, max_data_size);
454 input.read(buffer, size);
455 if( input.fail() || (size_t)input.gcount() != size ) {
456 throw Error("JavaLoader::SendStream input stream read failed");
459 packet.PutData(buffer, size);
460 m_socket->Packet(packet);
462 if( packet.Command() == SB_COMMAND_JL_NOT_ENOUGH_MEMORY ) {
463 throw Error("JavaLoader::SendStream not enough memory to install the application");
466 if( packet.Command() != SB_COMMAND_JL_ACK ) {
467 ThrowJLError("JavaLoader::SendStream send data", packet.Command());
470 remaining -= size;
474 void JavaLoader::LoadApp(std::istream &input)
476 uint32_t module_size;
477 while( (module_size = SeekNextCod(input)) != 0 ) {
478 SendStream(input, module_size);
483 // StopStream
485 /// Must be called at the end of a JavaLoader session. The JL_GOODBYE
486 /// command is sent to the device. When the device responds with
487 /// RESET_REQUIRED the device reset command will be sent when the
488 /// socket is closed.
490 /// \return true when a device reset was required
492 bool JavaLoader::StopStream()
494 Data cmd(-1, 8), data(-1, 8), response;
496 JLPacket packet(cmd, data, response);
497 packet.Goodbye();
498 try {
499 m_socket->Packet(packet);
500 } catch( BadPacket &bp ) {
501 // on some devices, such as the 7750 and the 7130,
502 // the Goodbye command receives NOT_SUPPORTED
503 // instead of the usual ACK... this is not an
504 // error, so catch that case here and ignore it.
505 // otherwise, throw it to higher levels
506 if( bp.response() != SB_COMMAND_JL_NOT_SUPPORTED )
507 throw;
510 m_StreamStarted = false;
512 if( packet.Command() == SB_COMMAND_JL_RESET_REQUIRED ) {
513 m_socket->ResetOnClose(true);
514 return true;
516 else if( packet.Command() != SB_COMMAND_JL_ACK &&
517 packet.Command() != SB_COMMAND_JL_NOT_SUPPORTED )
519 ThrowJLError("JavaLoader::StopStream", packet.Command());
522 return false;
525 void JavaLoader::SetTime(time_t when)
527 Data cmd(-1, 8), data(-1, 8), response;
529 JLPacket packet(cmd, data, response);
530 packet.SetTime(when);
531 m_socket->Packet(packet);
532 if( packet.Command() != SB_COMMAND_JL_ACK ) {
533 ThrowJLError("JavaLoader::SetTime", packet.Command());
537 void JavaLoader::ThrowJLError(const std::string &msg, uint8_t cmd)
539 std::ostringstream oss;
540 oss << msg << ": unexpected packet command code: 0x"
541 << std::hex << (unsigned int) cmd;
542 throw Error(oss.str());
545 void JavaLoader::GetDirectoryEntries(JLPacket &packet,
546 uint8_t entry_cmd,
547 JLDirectory &dir,
548 bool include_subdirs)
550 JLDirectory::TableIterator i = dir.TableBegin(), e = dir.TableEnd();
551 for( ; i != e; ++i ) {
552 packet.GetDirEntry(entry_cmd, *i);
553 m_socket->Packet(packet);
554 if( packet.Command() != SB_COMMAND_JL_ACK ) {
555 ThrowJLError("JavaLoader::GetDirectoryEntries", packet.Command());
558 Data &response = packet.GetReceive();
559 m_socket->Receive(response);
560 JLDirectoryEntry entry(dir.Level());
561 Protocol::CheckSize(response, 4);
562 entry.Parse(*i, Data(response.GetData() + 4, response.GetSize() - 4));
564 if( include_subdirs ) {
565 packet.GetSubDir(*i);
566 GetDir(packet, SB_COMMAND_JL_GET_SUBDIR_ENTRY, entry.SubDir, false);
569 // add to list
570 dir.push_back(entry);
574 void JavaLoader::GetDir(JLPacket &packet,
575 uint8_t entry_cmd,
576 JLDirectory &dir,
577 bool include_subdirs)
579 m_socket->Packet(packet);
580 if( packet.Command() != SB_COMMAND_JL_ACK ) {
581 ThrowJLError("JavaLoader::GetDir", packet.Command());
584 // ack response will contain length of module ID array in next packet
585 unsigned int expect = packet.Size();
587 if( expect > 0 ) {
588 Data &response = packet.GetReceive();
589 m_socket->Receive(response);
590 Protocol::CheckSize(response, 4);
591 dir.ParseTable(Data(response.GetData() + 4, response.GetSize() - 4));
592 GetDirectoryEntries(packet, entry_cmd, dir, include_subdirs);
596 void JavaLoader::GetDirectory(JLDirectory &dir, bool include_subdirs)
598 Data cmd(-1, 8), data(-1, 8), response;
599 JLPacket packet(cmd, data, response);
601 packet.GetDirectory();
602 GetDir(packet, SB_COMMAND_JL_GET_DATA_ENTRY, dir, include_subdirs);
606 // This function permits to receive a ScreenShot (maybe other...)
607 // WARNING : Before, you have to call the "Start" function,
608 // After, you have to call the "Stop" function.
610 // From the USB traces, the max size of packet is : 0x07FC
611 // When you are ready, we send the packet :
612 // 04 00 08 00 68 00 00 00
613 // Then, we receive an acknoledge and the data.
614 // The data is composed of two packets : header and content.
615 // Packet header :
616 // 04 00 08 00 6E 00 F8 07
617 // ^^^^^ : size + 4 bytes
618 // ^^ : command
619 // ^^^^^ : size of packet header
620 // ^^^^^ : socket
621 // Packet content :
622 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
623 // ^^^^^ ............. ^^^^^ : data (the file content)
624 // ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
625 // ^^^^^ : socket
628 // GetScreenshot
630 /// Downloads screenshot from device, and fills info with size data
631 /// and the given Data buffer image with the bitmap.
633 void JavaLoader::GetScreenshot(JLScreenInfo &info, Data &image)
635 // start fresh
636 image.Zap();
638 Data cmd(-1, 8), data(-1, 8), response;
639 JLPacket packet(cmd, data, response);
641 // Send the screenshot command :
642 // 00000000: 04 00 08 00 87 00 04 00
643 packet.GetScreenshot();
645 m_socket->Packet(packet);
647 if( packet.Command() != SB_COMMAND_JL_ACK ) {
648 ThrowJLError("JavaLoader::GetScreenshot", packet.Command());
651 // Get Info :
652 // 00000000: 04 00 14 00 00 05 46 00 40 03 01 68 01 e0 00 10 ......F.@..h....
653 // ^^^^^x^^^^^ : width x height
654 // ^^^^^ : packet size
655 // ^^^^^ : socket ID
656 // 00000010: 00 00 00 00 ....
658 m_socket->Receive(response);
660 // Parse response...
661 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLSCREENINFO_SIZE);
662 MAKE_JLPACKET(rpack, response);
664 info.width = be_btohs(rpack->u.screeninfo.width);
665 info.height = be_btohs(rpack->u.screeninfo.height);
668 // Read stream
669 for (;;) {
670 // Send the packet :
671 // 04 00 08 00 68 00 00 00
672 packet.GetData();
674 m_socket->Packet(packet);
676 // Read and parse the response
677 // 04 00 08 00 64 00 00 00
678 // or
679 // 04 00 08 00 6e 00 f8 07
681 if( packet.Command() == SB_COMMAND_JL_ACK )
682 return;
684 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
685 ThrowJLError("JavaLoader::GetScreenShot ", packet.Command());
688 // Read the size of next packet
689 size_t expect = packet.Size();
692 // Read the stream
693 m_socket->Receive(response);
696 // Save data in buffer
697 Protocol::CheckSize(response, 4);
698 const unsigned char *pd = response.GetData();
699 size_t bytereceived = response.GetSize() - 4;
702 // Check the size read into the previous packet
703 if( expect != bytereceived ) {
704 ThrowJLError("JavaLoader::GetScreenShot expect", expect);
708 // Copy data
709 unsigned char *buffer = image.GetBuffer(image.GetSize() + bytereceived);
710 memcpy(buffer + image.GetSize(), pd + 4, bytereceived);
712 // New size
713 image.ReleaseBuffer(image.GetSize() + bytereceived);
717 void JavaLoader::DoErase(uint8_t cmd, const std::string &cod_name)
719 Data command(-1, 8), data(-1, 8), response;
721 JLPacket packet(command, data, response);
723 // set filename, device responds with an ID
724 packet.SetCodFilename(cod_name);
725 m_socket->Packet(packet);
726 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
727 throw Error(string("JavaLoader::DoErase: module ") + cod_name + " not found");
729 if( packet.Command() != SB_COMMAND_JL_ACK ) {
730 ThrowJLError("JavaLoader::DoErase", packet.Command());
733 // make sure there is an ID coming
734 if( packet.Size() != 2 )
735 throw Error("JavaLoader::DoErase: expected code not available");
737 // get ID
738 m_socket->Receive(response);
739 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
740 MAKE_JLPACKET(jpack, response);
741 uint16_t id = be_btohs(jpack->u.id);
743 // send erase command, with application ID
744 packet.Erase(cmd, id);
745 m_socket->Packet(packet);
746 if( packet.Command() == SB_COMMAND_JL_COD_IN_USE ) {
747 throw Error("JavaLoader::DoErase: COD file in use.");
749 if( packet.Command() != SB_COMMAND_JL_ACK ) {
750 ThrowJLError("JavaLoader::DoErase", packet.Command());
754 void JavaLoader::Erase(const std::string &cod_name)
756 DoErase(SB_COMMAND_JL_ERASE, cod_name);
759 void JavaLoader::ForceErase(const std::string &cod_name)
761 DoErase(SB_COMMAND_JL_FORCE_ERASE, cod_name);
764 void JavaLoader::GetEventlog(JLEventlog &log)
766 Data command(-1, 8), data(-1, 8), response;
767 JLPacket packet(command, data, response);
769 packet.GetEventlog();
771 m_socket->Packet(packet);
773 if( packet.Command() != SB_COMMAND_JL_ACK ) {
774 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
777 m_socket->Receive(response);
778 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
780 // number of eventlog entries
781 MAKE_JLPACKET(jpack, response);
782 uint16_t count = be_btohs(jpack->u.response.expect);
784 for( uint16_t i = 0; i < count; ++ i ) {
785 packet.GetEventlogEntry(i);
787 m_socket->Packet(packet);
789 if( packet.Command() != SB_COMMAND_JL_ACK ) {
790 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
793 m_socket->Receive(response);
794 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE);
796 MAKE_JLPACKET(jpack, response);
797 uint16_t size = be_btohs(jpack->u.logentry.size);
799 JLEventlogEntry entry;
800 entry.Parse(size, (const char *)(response.GetData() + SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE));
802 log.push_back(entry);
806 void JavaLoader::ClearEventlog()
808 Data command(-1, 8), data(-1, 8), response;
809 JLPacket packet(command, data, response);
811 packet.ClearEventlog();
812 m_socket->Packet(packet);
814 if( packet.Command() != SB_COMMAND_JL_ACK ) {
815 ThrowJLError("JavaLoader::ClearEventlog", packet.Command());
819 void JavaLoader::SaveData(JLPacket &packet, uint16_t id, CodFileBuilder &builder, std::ostream &output)
821 packet.SaveModule(id);
822 m_socket->Packet(packet);
824 if( packet.Command() != SB_COMMAND_JL_ACK ) {
825 ThrowJLError("JavaLoader::SaveData", packet.Command());
828 // get total size of cod file or this sibling cod file
829 Data &response = packet.GetReceive();
830 m_socket->Receive(response);
831 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint32_t));
832 MAKE_JLPACKET(jpack, response);
833 uint32_t total_size = be_btohl(jpack->u.cod_size);
835 // allocate buffer to hold data for this sibling
836 Data buffer(-1, total_size);
837 uint32_t offset = 0;
839 for( ;; ) {
840 packet.GetData();
841 m_socket->Packet(packet);
843 if( packet.Command() == SB_COMMAND_JL_ACK )
844 break;
846 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
847 ThrowJLError("JavaLoader::SaveData", packet.Command());
850 // expected size of data in response packet
851 unsigned int expect = packet.Size();
853 m_socket->Receive(response);
854 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
856 memcpy(buffer.GetBuffer(offset + expect) + offset,
857 response.GetData() + SB_JLPACKET_HEADER_SIZE,
858 expect);
860 offset += expect;
861 buffer.ReleaseBuffer(offset);
864 builder.WriteNextHeader(output, buffer.GetData(), buffer.GetSize());
865 output.write((const char *)buffer.GetData(), buffer.GetSize());
868 void JavaLoader::Save(const std::string &cod_name, std::ostream &output)
870 Data command(-1, 8), data(-1, 8), response;
872 JLPacket packet(command, data, response);
874 // set filename, device responds with an ID
875 packet.SetCodFilename(cod_name);
876 m_socket->Packet(packet);
878 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
879 throw Error(string("JavaLoader::Save: module ") + cod_name + " not found");
882 if( packet.Command() != SB_COMMAND_JL_ACK ) {
883 ThrowJLError("JavaLoader::Save", packet.Command());
886 // make sure there is an ID coming
887 if( packet.Size() != 2 )
888 throw Error("JavaLoader::Save: expected module ID");
890 // get ID
891 m_socket->Receive(response);
892 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
893 MAKE_JLPACKET(jpack, response);
894 uint16_t id = be_btohs(jpack->u.id);
896 // get list of sibling modules
897 packet.GetSubDir(id);
898 m_socket->Packet(packet);
900 if( packet.Command() != SB_COMMAND_JL_ACK ) {
901 ThrowJLError("JavaLoader::Save", packet.Command());
904 // expected number of module ID's
905 unsigned int expect = packet.Size();
907 // get list of sibling module ID's
908 m_socket->Receive(response);
909 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
911 // copy array of module ID's since we reuse the response packet buffer
912 size_t count = expect / 2;
913 const uint16_t *begin = (const uint16_t*) (response.GetData() + SB_JLPACKET_HEADER_SIZE);
914 const uint16_t *end = begin + count;
915 vector<uint16_t> ids(begin, end);
917 CodFileBuilder builder(cod_name, count);
919 // save each block of data
920 for( size_t i = 0; i < count; i++ ) {
921 SaveData(packet, be_btohs(ids[i]), builder, output);
924 builder.WriteFooter(output);
927 void JavaLoader::DeviceInfo(JLDeviceInfo &info)
929 Data command(-1, 8), data(-1, 8), response;
930 JLPacket packet(command, data, response);
932 packet.DeviceInfo();
934 m_socket->Packet(packet);
936 if( packet.Command() != SB_COMMAND_JL_ACK ) {
937 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
940 m_socket->Receive(response);
942 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLDEVICEINFO_SIZE);
943 MAKE_JLPACKET(rpack, response);
945 info.HardwareId = be_btohl(rpack->u.devinfo.hardware_id);
946 info.Pin = be_btohl(rpack->u.devinfo.pin);
947 info.OsVersion = be_btohl(rpack->u.devinfo.os_version);
948 info.VmVersion = be_btohl(rpack->u.devinfo.vm_version);
949 info.RadioId = be_btohl(rpack->u.devinfo.radio_id);
950 info.VendorId = be_btohl(rpack->u.devinfo.vendor_id);
951 info.ActiveWafs = be_btohl(rpack->u.devinfo.active_wafs);
953 packet.OsMetrics();
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 size_t offset = SB_JLPACKET_HEADER_SIZE;
965 size_t size = response.GetSize()-offset;
966 unsigned char* buf = info.OsMetrics.GetBuffer(size);
967 memcpy(buf, response.GetData()+offset, size);
968 info.OsMetrics.ReleaseBuffer(size);
970 packet.BootromMetrics();
972 m_socket->Packet(packet);
974 if( packet.Command() != SB_COMMAND_JL_ACK ) {
975 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
978 m_socket->Receive(response);
979 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
981 offset = SB_JLPACKET_HEADER_SIZE;
982 size = response.GetSize()-offset;
983 buf = info.BootromMetrics.GetBuffer(size);
984 memcpy(buf, response.GetData()+offset, size);
985 info.BootromMetrics.ReleaseBuffer(size);
988 void JavaLoader::Wipe(bool apps, bool fs)
990 Data command(-1, 8), data(-1, 8), response;
991 JLPacket packet(command, data, response);
993 if( apps ) {
994 packet.WipeApps();
995 m_socket->Packet(packet);
997 if( packet.Command() != SB_COMMAND_JL_ACK ) {
998 ThrowJLError("JavaLoader::WipeApps", packet.Command());
1002 if( fs ) {
1003 packet.WipeFs();
1004 m_socket->Packet(packet);
1006 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1007 ThrowJLError("JavaLoader::WipeFs", packet.Command());
1012 void JavaLoader::LogStackTraces()
1014 Data command(-1, 8), data(-1, 8), response;
1015 JLPacket packet(command, data, response);
1017 packet.LogStackTraces();
1018 m_socket->Packet(packet);
1020 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1021 ThrowJLError("JavaLoader::LogStackTraces", packet.Command());
1025 void JavaLoader::ResetToFactory()
1027 Data command(-1, 8), data(-1, 8), response;
1028 JLPacket packet(command, data, response);
1030 packet.ResetToFactory();
1031 m_socket->Packet(packet);
1033 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1034 ThrowJLError("JavaLoader::ResetToFactory", packet.Command());
1038 }} // namespace Barry::Mode