debian: first review version for intrigeri: 0.18.5-1~rc1
[barry.git] / src / m_javaloader.cc
blob1b79ba4ab17fc636333541c0c44ead91d7f0359d
1 ///
2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
4 ///
6 /*
7 Copyright (C) 2005-2013, 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 "i18n.h"
26 #include "m_javaloader.h"
27 #include "data.h"
28 #include "protocol.h"
29 #include "protostructs.h"
30 #include "packet.h"
31 #include "endian.h"
32 #include "error.h"
33 #include "usbwrap.h"
34 #include "controller.h"
35 #include "cod.h"
36 #include <stdexcept>
37 #include <sstream>
38 #include <iomanip>
39 #include <vector>
40 #include <string.h>
41 #include <sys/time.h>
42 #include <time.h>
43 #include <stdio.h>
44 #include "ios_state.h"
46 #include "debug.h"
48 using namespace std;
50 namespace Barry {
53 ///////////////////////////////////////////////////////////////////////////////
54 // JLScreenInfo class
56 JLScreenInfo::JLScreenInfo()
60 JLScreenInfo::~JLScreenInfo()
66 ///////////////////////////////////////////////////////////////////////////////
67 // JLDirectory class
69 JLDirectory::JLDirectory(int level)
70 : m_level(level)
74 JLDirectory::~JLDirectory()
78 void JLDirectory::ParseTable(const Data &table_packet)
80 m_idTable.clear();
82 size_t count = table_packet.GetSize() / 2;
83 uint16_t *item = (uint16_t*) table_packet.GetData();
84 for( size_t i = 0; i < count; i++, item++ ) {
85 m_idTable.push_back( be_btohs(*item) );
89 void JLDirectory::Dump(std::ostream &os) const
91 ios_format_state state(os);
93 int indent = m_level * 2;
95 os << setfill(' ') << setw(indent) << "";
96 os << "Directory: " << m_idTable.size() << "/" << size() << " entries\n";
98 const_iterator i = begin(), e = end();
99 for( ; i != e; ++i ) {
100 os << setfill(' ') << setw(indent + 2) << "";
101 os << *i << "\n";
107 ///////////////////////////////////////////////////////////////////////////////
108 // JLDirectoryEntry class
110 JLDirectoryEntry::JLDirectoryEntry()
111 : m_level(0)
112 , SubDir(1)
116 JLDirectoryEntry::JLDirectoryEntry(int level)
117 : m_level(level)
118 , SubDir(level + 1)
122 void JLDirectoryEntry::Parse(uint16_t id, const Data &entry_packet)
124 size_t needed = SB_JLDIRENTRY_HEADER_SIZE;
125 size_t have = entry_packet.GetSize();
126 if( have < needed )
127 throw BadSize("JLDE:Parse(1)", have, needed);
129 const unsigned char *ptr = entry_packet.GetData();
130 Protocol::JLDirEntry *entry = (Protocol::JLDirEntry*) ptr;
132 Id = id;
133 Timestamp = be_btohl(entry->timestamp);
135 uint16_t len = be_btohs(entry->filename_size);
136 needed += len;
137 if( have < needed )
138 throw BadSize("JLDE:Parse(2)", have, needed);
139 Name.assign((char *)entry->filename, len);
141 // need parsed data + string size
142 ptr += needed;
143 needed += 2;
144 if( have < needed )
145 throw BadSize("JLDE:Parse(3)", have, needed);
147 len = be_btohs( *((uint16_t*)(ptr)) );
148 ptr += sizeof(uint16_t);
149 needed += len;
150 if( have < needed )
151 throw BadSize("JLDE:Parse(4)", have, needed);
152 Version.assign((char*)ptr, len);
154 // need parsed data + string size
155 ptr += len;
156 needed += sizeof(uint32_t);
157 if( have < needed )
158 throw BadSize("JLDE:Parse(5)", have, needed);
159 CodSize = be_btohl( *((uint32_t*)(ptr)) );
162 void JLDirectoryEntry::Dump(std::ostream &os) const
164 ios_format_state state(os);
166 os << left << setfill(' ') << setw(50) << Name;
168 os << "\n";
169 os << left << setw(28) << " ";
171 os << "0x" << setfill('0') << setw(4) << hex << Id;
172 os << " " << setw(10) << Version;
173 os << " " << setw(7) << std::dec << CodSize;
175 std::string ts = ctime(&Timestamp);
176 ts.erase(ts.size() - 1);
177 os << " " << ts;
179 if( SubDir.size() )
180 os << "\n" << SubDir;
184 ///////////////////////////////////////////////////////////////////////////////
185 // JLEventlog class
187 void JLEventlog::Dump(std::ostream &os) const
189 const_iterator i = begin(), e = end();
190 for( ; i != e; ++i ) {
191 (*i).Dump(os);
196 ///////////////////////////////////////////////////////////////////////////////
197 // JLEventlogEntry class, static members
200 // Note! These functions currently only pass the same values through.
201 // In actuality, these are technically two different values:
202 // one on the raw protocol side, and the other part of the
203 // guaranteed Barry API. If the Blackberry ever changes the
204 // meanings for these codes, do the translation here.
207 JLEventlogEntry::Severity_t JLEventlogEntry::SeverityProto2Rec(unsigned int s)
209 return (Severity_t)s;
212 unsigned int JLEventlogEntry::SeverityRec2Proto(Severity_t s)
214 return s;
217 JLEventlogEntry::ViewerType_t JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v)
219 return (ViewerType_t)v;
222 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t v)
224 return v;
228 ///////////////////////////////////////////////////////////////////////////////
229 // JLEventlogEntry class
231 void JLEventlogEntry::Parse(uint16_t size, const char* buf)
233 // example of a single log entry
234 //guid:92E11214401C3 time:0x11F133E6470 severity:0 type:2 app:UI data:GS-D 2c89868b
236 std::string src = std::string(buf, size);
237 std::istringstream ss(src);
239 ss.ignore(5); // skip "guid:"
240 ss >> Guid;
241 if( ss.fail() )
242 throw BadData(_("JLEventlogEntry:Parse bad guid field"));
244 ss.ignore(6); // skip " time:"
245 ss >> hex >> MSTimestamp;
246 if( ss.fail() )
247 throw BadData(_("JLEventlogEntry:Parse bad time field"));
249 ss.ignore(10); // skip " severity:"
250 unsigned int severity;
251 ss >> severity;
252 Severity = SeverityProto2Rec(severity);
253 if( ss.fail() )
254 throw BadData(_("JLEventlogEntry:Parse bad severity field"));
256 ss.ignore(6); // skip " type:"
257 unsigned int type;
258 ss >> type;
259 Type = ViewerTypeProto2Rec(type);
260 if( ss.fail() )
261 throw BadData(_("JLEventlogEntry:Parse bad type field"));
263 ss.ignore(5); // skip " app:"
264 ss >> App;
265 if( ss.fail() )
266 throw BadData(_("JLEventlogEntry:Parse bad app field"));
268 ss.ignore(6); // skip " data:"
270 // use stringbuf to extract rest of data from stream
271 stringbuf databuf;
272 ss >> &databuf;
273 if( ss.fail() )
274 throw BadData(_("JLEventlogEntry:Parse bad data field"));
276 Data = databuf.str();
279 std::string JLEventlogEntry::GetFormattedTimestamp() const
281 char buf[21];
282 struct tm split;
283 time_t timestamp = (time_t) (MSTimestamp / 1000);
285 if( localtime_r(&timestamp, &split) == NULL )
286 return "";
288 if( strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S.", &split) == 0 )
289 return "";
291 std::ostringstream oss;
292 oss << buf << (MSTimestamp % 1000);
293 return oss.str();
296 void JLEventlogEntry::Dump(std::ostream &os) const
298 ios_format_state state(os);
300 static const char *SeverityNames[] = {
301 N_("Always Log"),
302 N_("Severe Error"),
303 N_("Error"),
304 N_("Warning"),
305 N_("Information"),
306 N_("Debug Info")
308 static const char *ViewerTypes[] = {
310 N_("Number"),
311 N_("String"),
312 N_("Exception")
315 os << _("guid:") << Guid;
316 os << _(" time:") << GetFormattedTimestamp();
317 os << _(" severity:") << gettext( SeverityNames[Severity] );
318 os << _(" type:") << gettext( ViewerTypes[Type] );
319 os << _(" app:") << App;
320 os << _(" data:") << Data << endl;
324 ///////////////////////////////////////////////////////////////////////////////
325 // JLDeviceInfo class
327 void JLDeviceInfo::Dump(std::ostream &os) const
329 ios_format_state state(os);
331 os << left << setfill(' ') << setw(17) << _("Hardware Id:");
332 os << "0x" << hex << HardwareId << endl;
334 os << left << setfill(' ') << setw(17) << _("PIN:");
335 os << "0x" << Pin.Str() << endl;
337 os << left << setfill(' ') << setw(17) << _("OS Version:");
338 os << dec << OsVersion.Major << '.' << OsVersion.Minor << '.' << OsVersion.SubMinor << '.' << OsVersion.Build << endl;
340 os << left << setfill(' ') << setw(17) << _("VM Version:");
341 os << dec << VmVersion.Major << '.' << VmVersion.Minor << '.' << VmVersion.SubMinor << '.' << VmVersion.Build << endl;
343 os << left << setfill(' ') << setw(17) << _("Radio ID:");
344 os << "0x" << hex << RadioId << endl;
346 os << left << setfill(' ') << setw(17) << _("Vendor ID:");
347 os << dec << VendorId << endl;
349 // WAF = Wireless Access Families
350 os << left << setfill(' ') << setw(17) << _("Active Wireless Access Families:");
351 os << "0x" << hex << ActiveWafs << endl;
353 os << left << setfill(' ') << setw(17) << _("OS Metrics:") << endl;
354 os << OsMetrics;
356 os << left << setfill(' ') << setw(17) << _("Bootrom Metrics:") << endl;
357 os << BootromMetrics;
361 namespace Mode {
363 ///////////////////////////////////////////////////////////////////////////////
364 // JavaLoader Mode class
366 JavaLoader::JavaLoader(Controller &con)
367 : Mode(con, Controller::JavaLoader)
368 , m_StreamStarted(false)
372 JavaLoader::~JavaLoader()
374 try {
375 if( m_StreamStarted )
376 StopStream();
378 catch( std::exception &DEBUG_ONLY(e) ) {
379 dout("Exception ignored in ~JavaLoader(): " << e.what());
381 catch( ... ) {
382 dout("Unknown exception in ~JavaLoader()");
386 ///////////////////////////////////////////////////////////////////////////////
387 // protected members
390 ///////////////////////////////////////////////////////////////////////////////
391 // public API
393 void JavaLoader::OnOpen()
395 Data response;
396 m_socket->Receive(response, -1);
399 // These commands are sent to prepare the data stream
400 void JavaLoader::StartStream()
402 Data cmd(-1, 8), data(-1, 8), response;
403 JLPacket packet(cmd, data, response);
405 packet.Hello();
406 m_socket->Packet(packet);
408 if( packet.Command() != SB_COMMAND_JL_HELLO_ACK ) {
409 ThrowJLError(_("JavaLoader::StartStream Hello"), packet.Command());
412 packet.SetUnknown1();
413 m_socket->Packet(packet);
415 if( packet.Command() != SB_COMMAND_JL_ACK ) {
416 ThrowJLError(_("JavaLoader::StartStream Unknown1"), packet.Command());
419 m_StreamStarted = true;
423 // This function permits to send a COD application
424 // WARNING : Before, you have to call the "Start" function,
425 // After, you have to call the "Stop" function.
427 // From the USB traces, the max size of packet is : 0x07FC
428 // Packet header :
429 // 04 00 08 00 68 00 F8 07
430 // ^^^^^ : about size
431 // ^^ : command
432 // ^^ : size of packet header
433 // ^^^^^ : socket
434 // Response :
435 // 00 00 0C 00 13 04 01 00 0A 00 00 00
436 // Packet format :
437 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
438 // ^^^^^ ............. ^^^^^ : data (the file content)
439 // ^^^^^ : packet size
440 // ^^^^^ : socket
443 // WARNING : A COD file starts with the integer 0xDEC0FFFF (FIXME)
444 // An application can contain several COD parts. In this case we can read a header (start with PK)
445 // In this sample, we have to skip the file header :
446 // 00000000 50 4B 03 04 0A 00 00 00 00 00 A0 00 51 35 BA 9F 99 5D 30 CE PK..........Q5...]0.
447 // 00000014 00 00 30 CE 00 00 15 00 04 00 4D 65 74 72 6F 56 69 65 77 65 ..0.......MetroViewe
448 // 00000028 72 2E 50 61 72 69 73 2E 63 6F 64 FE CA 00 00 DE C0 FF FF 00 r.Paris.cod.........
449 // ^^ Start of data sent !
450 // 0000003C 00 00 00 00 00 00 00 0F 10 34 45 00 00 00 00 00 00 00 00 21 .........4E........!
451 // 00000050 00 FF FF FF FF FF FF FF FF FF FF 4E 00 9C 08 68 C5 00 00 F0 ...........N...h....
452 // 00000064 B8 BC C0 A1 C0 14 00 81 00 00 01 01 04 0E 3F 6D 00 02 00 6D ..............?m...m
453 void JavaLoader::SendStream(std::istream &input, size_t module_size)
455 char buffer[MAX_PACKET_DATA_SIZE - SB_JLPACKET_HEADER_SIZE];
456 size_t max_data_size = sizeof(buffer);
458 size_t remaining = module_size;
460 Data cmd(-1, 8), data(-1, 8), response;
461 JLPacket packet(cmd, data, response);
463 packet.SetCodSize(module_size);
464 m_socket->Packet(packet);
466 if( packet.Command() != SB_COMMAND_JL_ACK ) {
467 ThrowJLError(_("JavaLoader::SendStream: set code size first"), packet.Command());
470 while( remaining > 0 ) {
471 size_t size = min(remaining, max_data_size);
473 input.read(buffer, size);
474 if( input.fail() || (size_t)input.gcount() != size ) {
475 throw Error(_("JavaLoader::SendStream: input stream read failed"));
478 packet.PutData(buffer, size);
479 m_socket->Packet(packet);
481 if( packet.Command() == SB_COMMAND_JL_NOT_ENOUGH_MEMORY ) {
482 throw Error(_("JavaLoader::SendStream: not enough memory to install the application"));
485 if( packet.Command() != SB_COMMAND_JL_ACK ) {
486 ThrowJLError(_("JavaLoader::SendStream: send data"), packet.Command());
489 remaining -= size;
493 void JavaLoader::LoadApp(std::istream &input)
495 uint32_t module_size;
496 while( (module_size = SeekNextCod(input)) != 0 ) {
497 SendStream(input, module_size);
502 // StopStream
504 /// Must be called at the end of a JavaLoader session. The JL_GOODBYE
505 /// command is sent to the device. When the device responds with
506 /// RESET_REQUIRED the device reset command will be sent when the
507 /// socket is closed.
509 /// \return true when a device reset was required
511 bool JavaLoader::StopStream()
513 Data cmd(-1, 8), data(-1, 8), response;
515 JLPacket packet(cmd, data, response);
516 packet.Goodbye();
517 try {
518 m_socket->Packet(packet);
519 } catch( BadPacket &bp ) {
520 // on some devices, such as the 7750 and the 7130,
521 // the Goodbye command receives NOT_SUPPORTED
522 // instead of the usual ACK... this is not an
523 // error, so catch that case here and ignore it.
524 // otherwise, throw it to higher levels
525 if( bp.response() != SB_COMMAND_JL_NOT_SUPPORTED )
526 throw;
529 m_StreamStarted = false;
531 if( packet.Command() == SB_COMMAND_JL_RESET_REQUIRED ) {
532 m_socket->ResetOnClose(true);
533 return true;
535 else if( packet.Command() != SB_COMMAND_JL_ACK &&
536 packet.Command() != SB_COMMAND_JL_NOT_SUPPORTED )
538 ThrowJLError(_("JavaLoader::StopStream error"), packet.Command());
541 return false;
544 void JavaLoader::SetTime(time_t when)
546 Data cmd(-1, 8), data(-1, 8), response;
548 JLPacket packet(cmd, data, response);
549 packet.SetTime(when);
550 m_socket->Packet(packet);
551 if( packet.Command() != SB_COMMAND_JL_ACK ) {
552 ThrowJLError(_("JavaLoader::SetTime error"), packet.Command());
556 void JavaLoader::ThrowJLError(const std::string &msg, uint8_t cmd)
558 std::ostringstream oss;
559 oss << msg << ": " << _("unexpected packet command code: ")
560 << "0x" << std::hex << (unsigned int) cmd;
561 throw Error(oss.str());
564 void JavaLoader::GetDirectoryEntries(JLPacket &packet,
565 uint8_t entry_cmd,
566 JLDirectory &dir,
567 bool include_subdirs)
569 JLDirectory::TableIterator i = dir.TableBegin(), e = dir.TableEnd();
570 for( ; i != e; ++i ) {
571 packet.GetDirEntry(entry_cmd, *i);
572 m_socket->Packet(packet);
573 if( packet.Command() != SB_COMMAND_JL_ACK ) {
574 ThrowJLError("JavaLoader::GetDirectoryEntries", packet.Command());
577 Data &response = packet.GetReceive();
578 m_socket->Receive(response);
579 JLDirectoryEntry entry(dir.Level());
580 Protocol::CheckSize(response, 4);
581 entry.Parse(*i, Data(response.GetData() + 4, response.GetSize() - 4));
583 if( include_subdirs ) {
584 packet.GetSubDir(*i);
585 GetDir(packet, SB_COMMAND_JL_GET_SUBDIR_ENTRY, entry.SubDir, false);
588 // add to list
589 dir.push_back(entry);
593 void JavaLoader::GetDir(JLPacket &packet,
594 uint8_t entry_cmd,
595 JLDirectory &dir,
596 bool include_subdirs)
598 m_socket->Packet(packet);
599 if( packet.Command() != SB_COMMAND_JL_ACK ) {
600 ThrowJLError("JavaLoader::GetDir", packet.Command());
603 // ack response will contain length of module ID array in next packet
604 unsigned int expect = packet.Size();
606 if( expect > 0 ) {
607 Data &response = packet.GetReceive();
608 m_socket->Receive(response);
609 Protocol::CheckSize(response, 4);
610 dir.ParseTable(Data(response.GetData() + 4, response.GetSize() - 4));
611 GetDirectoryEntries(packet, entry_cmd, dir, include_subdirs);
615 void JavaLoader::GetDirectory(JLDirectory &dir, bool include_subdirs)
617 Data cmd(-1, 8), data(-1, 8), response;
618 JLPacket packet(cmd, data, response);
620 packet.GetDirectory();
621 GetDir(packet, SB_COMMAND_JL_GET_DATA_ENTRY, dir, include_subdirs);
625 // This function permits to receive a ScreenShot (maybe other...)
626 // WARNING : Before, you have to call the "Start" function,
627 // After, you have to call the "Stop" function.
629 // From the USB traces, the max size of packet is : 0x07FC
630 // When you are ready, we send the packet :
631 // 04 00 08 00 68 00 00 00
632 // Then, we receive an acknoledge and the data.
633 // The data is composed of two packets : header and content.
634 // Packet header :
635 // 04 00 08 00 6E 00 F8 07
636 // ^^^^^ : size + 4 bytes
637 // ^^ : command
638 // ^^^^^ : size of packet header
639 // ^^^^^ : socket
640 // Packet content :
641 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
642 // ^^^^^ ............. ^^^^^ : data (the file content)
643 // ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
644 // ^^^^^ : socket
647 // GetScreenshot
649 /// Downloads screenshot from device, and fills info with size data
650 /// and the given Data buffer image with the bitmap.
652 void JavaLoader::GetScreenshot(JLScreenInfo &info, Data &image)
654 // start fresh
655 image.Zap();
657 Data cmd(-1, 8), data(-1, 8), response;
658 JLPacket packet(cmd, data, response);
660 // Send the screenshot command :
661 // 00000000: 04 00 08 00 87 00 04 00
662 packet.GetScreenshot();
664 m_socket->Packet(packet);
666 if( packet.Command() != SB_COMMAND_JL_ACK ) {
667 ThrowJLError("JavaLoader::GetScreenshot", packet.Command());
670 // Get Info :
671 // 00000000: 04 00 14 00 00 05 46 00 40 03 01 68 01 e0 00 10 ......F.@..h....
672 // ^^^^^x^^^^^ : width x height
673 // ^^^^^ : packet size
674 // ^^^^^ : socket ID
675 // 00000010: 00 00 00 00 ....
677 m_socket->Receive(response);
679 // Parse response...
680 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLSCREENINFO_SIZE);
681 MAKE_JLPACKET(rpack, response);
683 info.width = be_btohs(rpack->u.screeninfo.width);
684 info.height = be_btohs(rpack->u.screeninfo.height);
687 // Read stream
688 for (;;) {
689 // Send the packet :
690 // 04 00 08 00 68 00 00 00
691 packet.GetData();
693 m_socket->Packet(packet);
695 // Read and parse the response
696 // 04 00 08 00 64 00 00 00
697 // or
698 // 04 00 08 00 6e 00 f8 07
700 if( packet.Command() == SB_COMMAND_JL_ACK )
701 return;
703 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
704 ThrowJLError("JavaLoader::GetScreenShot ", packet.Command());
707 // Read the size of next packet
708 size_t expect = packet.Size();
711 // Read the stream
712 m_socket->Receive(response);
715 // Save data in buffer
716 Protocol::CheckSize(response, 4);
717 const unsigned char *pd = response.GetData();
718 size_t bytereceived = response.GetSize() - 4;
721 // Check the size read into the previous packet
722 if( expect != bytereceived ) {
723 ThrowJLError(_("JavaLoader::GetScreenShot expect"), expect);
727 // Copy data
728 unsigned char *buffer = image.GetBuffer(image.GetSize() + bytereceived);
729 memcpy(buffer + image.GetSize(), pd + 4, bytereceived);
731 // New size
732 image.ReleaseBuffer(image.GetSize() + bytereceived);
736 void JavaLoader::DoErase(uint8_t cmd, const std::string &cod_name)
738 Data command(-1, 8), data(-1, 8), response;
740 JLPacket packet(command, data, response);
742 // set filename, device responds with an ID
743 packet.SetCodFilename(cod_name);
744 m_socket->Packet(packet);
745 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
746 throw Error(string(_("JavaLoader::DoErase: module not found: ")) + cod_name);
748 if( packet.Command() != SB_COMMAND_JL_ACK ) {
749 ThrowJLError("JavaLoader::DoErase", packet.Command());
752 // make sure there is an ID coming
753 if( packet.Size() != 2 )
754 throw Error(_("JavaLoader::DoErase: expected code ID not available"));
756 // get ID
757 m_socket->Receive(response);
758 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
759 MAKE_JLPACKET(jpack, response);
760 uint16_t id = be_btohs(jpack->u.id);
762 // send erase command, with application ID
763 packet.Erase(cmd, id);
764 m_socket->Packet(packet);
765 if( packet.Command() == SB_COMMAND_JL_COD_IN_USE ) {
766 throw Error(_("JavaLoader::DoErase: COD file in use."));
768 if( packet.Command() != SB_COMMAND_JL_ACK ) {
769 ThrowJLError("JavaLoader::DoErase", packet.Command());
773 void JavaLoader::Erase(const std::string &cod_name)
775 DoErase(SB_COMMAND_JL_ERASE, cod_name);
778 void JavaLoader::ForceErase(const std::string &cod_name)
780 DoErase(SB_COMMAND_JL_FORCE_ERASE, cod_name);
783 void JavaLoader::GetEventlog(JLEventlog &log)
785 Data command(-1, 8), data(-1, 8), response;
786 JLPacket packet(command, data, response);
788 packet.GetEventlog();
790 m_socket->Packet(packet);
792 if( packet.Command() != SB_COMMAND_JL_ACK ) {
793 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
796 m_socket->Receive(response);
797 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
799 // number of eventlog entries
800 MAKE_JLPACKET(jpack, response);
801 uint16_t count = be_btohs(jpack->u.response.expect);
803 for( uint16_t i = 0; i < count; ++ i ) {
804 packet.GetEventlogEntry(i);
806 m_socket->Packet(packet);
808 if( packet.Command() != SB_COMMAND_JL_ACK ) {
809 ThrowJLError("JavaLoader::GetEventlog", packet.Command());
812 m_socket->Receive(response);
813 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE);
815 MAKE_JLPACKET(jpack, response);
816 uint16_t size = be_btohs(jpack->u.logentry.size);
818 JLEventlogEntry entry;
819 entry.Parse(size, (const char *)(response.GetData() + SB_JLPACKET_HEADER_SIZE + SB_JLEVENTLOG_ENTRY_HEADER_SIZE));
821 log.push_back(entry);
825 void JavaLoader::ClearEventlog()
827 Data command(-1, 8), data(-1, 8), response;
828 JLPacket packet(command, data, response);
830 packet.ClearEventlog();
831 m_socket->Packet(packet);
833 if( packet.Command() != SB_COMMAND_JL_ACK ) {
834 ThrowJLError("JavaLoader::ClearEventlog", packet.Command());
838 void JavaLoader::SaveData(JLPacket &packet, uint16_t id, CodFileBuilder &builder, std::ostream &output)
840 packet.SaveModule(id);
841 m_socket->Packet(packet);
843 if( packet.Command() != SB_COMMAND_JL_ACK ) {
844 ThrowJLError("JavaLoader::SaveData", packet.Command());
847 // get total size of cod file or this sibling cod file
848 Data &response = packet.GetReceive();
849 m_socket->Receive(response);
850 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint32_t));
851 MAKE_JLPACKET(jpack, response);
852 uint32_t total_size = be_btohl(jpack->u.cod_size);
854 // allocate buffer to hold data for this sibling
855 Data buffer(-1, total_size);
856 uint32_t offset = 0;
858 for( ;; ) {
859 packet.GetData();
860 m_socket->Packet(packet);
862 if( packet.Command() == SB_COMMAND_JL_ACK )
863 break;
865 if( packet.Command() != SB_COMMAND_JL_GET_DATA_ENTRY ) {
866 ThrowJLError("JavaLoader::SaveData", packet.Command());
869 // expected size of data in response packet
870 unsigned int expect = packet.Size();
872 m_socket->Receive(response);
873 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
875 memcpy(buffer.GetBuffer(offset + expect) + offset,
876 response.GetData() + SB_JLPACKET_HEADER_SIZE,
877 expect);
879 offset += expect;
880 buffer.ReleaseBuffer(offset);
883 builder.WriteNextHeader(output, buffer.GetData(), buffer.GetSize());
884 output.write((const char *)buffer.GetData(), buffer.GetSize());
887 void JavaLoader::Save(const std::string &cod_name, std::ostream &output)
889 Data command(-1, 8), data(-1, 8), response;
891 JLPacket packet(command, data, response);
893 // set filename, device responds with an ID
894 packet.SetCodFilename(cod_name);
895 m_socket->Packet(packet);
897 if( packet.Command() == SB_COMMAND_JL_COD_NOT_FOUND ) {
898 throw Error(string(_("JavaLoader::Save: module not found: ")) + cod_name);
901 if( packet.Command() != SB_COMMAND_JL_ACK ) {
902 ThrowJLError("JavaLoader::Save", packet.Command());
905 // make sure there is an ID coming
906 if( packet.Size() != 2 )
907 throw Error(_("JavaLoader::Save: expected module ID, but not available"));
909 // get ID
910 m_socket->Receive(response);
911 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + sizeof(uint16_t));
912 MAKE_JLPACKET(jpack, response);
913 uint16_t id = be_btohs(jpack->u.id);
915 // get list of sibling modules
916 packet.GetSubDir(id);
917 m_socket->Packet(packet);
919 if( packet.Command() != SB_COMMAND_JL_ACK ) {
920 ThrowJLError("JavaLoader::Save", packet.Command());
923 // expected number of module ID's
924 unsigned int expect = packet.Size();
926 // get list of sibling module ID's
927 m_socket->Receive(response);
928 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + expect);
930 // copy array of module ID's since we reuse the response packet buffer
931 size_t count = expect / 2;
932 const uint16_t *begin = (const uint16_t*) (response.GetData() + SB_JLPACKET_HEADER_SIZE);
933 const uint16_t *end = begin + count;
934 vector<uint16_t> ids(begin, end);
936 CodFileBuilder builder(cod_name, count);
938 // save each block of data
939 for( size_t i = 0; i < count; i++ ) {
940 SaveData(packet, be_btohs(ids[i]), builder, output);
943 builder.WriteFooter(output);
946 void JavaLoader::DeviceInfo(JLDeviceInfo &info)
948 Data command(-1, 8), data(-1, 8), response;
949 JLPacket packet(command, data, response);
951 packet.DeviceInfo();
953 m_socket->Packet(packet);
955 if( packet.Command() != SB_COMMAND_JL_ACK ) {
956 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
959 m_socket->Receive(response);
961 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE + SB_JLDEVICEINFO_SIZE);
962 MAKE_JLPACKET(rpack, response);
964 info.HardwareId = be_btohl(rpack->u.devinfo.hardware_id);
965 info.Pin = be_btohl(rpack->u.devinfo.pin);
966 info.OsVersion = be_btohl(rpack->u.devinfo.os_version);
967 info.VmVersion = be_btohl(rpack->u.devinfo.vm_version);
968 info.RadioId = be_btohl(rpack->u.devinfo.radio_id);
969 info.VendorId = be_btohl(rpack->u.devinfo.vendor_id);
970 info.ActiveWafs = be_btohl(rpack->u.devinfo.active_wafs);
972 packet.OsMetrics();
974 m_socket->Packet(packet);
976 if( packet.Command() != SB_COMMAND_JL_ACK ) {
977 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
980 m_socket->Receive(response);
981 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
983 size_t offset = SB_JLPACKET_HEADER_SIZE;
984 size_t size = response.GetSize()-offset;
985 unsigned char* buf = info.OsMetrics.GetBuffer(size);
986 memcpy(buf, response.GetData()+offset, size);
987 info.OsMetrics.ReleaseBuffer(size);
989 packet.BootromMetrics();
991 m_socket->Packet(packet);
993 if( packet.Command() != SB_COMMAND_JL_ACK ) {
994 ThrowJLError("JavaLoader::DeviceInfo", packet.Command());
997 m_socket->Receive(response);
998 Protocol::CheckSize(response, SB_JLPACKET_HEADER_SIZE);
1000 offset = SB_JLPACKET_HEADER_SIZE;
1001 size = response.GetSize()-offset;
1002 buf = info.BootromMetrics.GetBuffer(size);
1003 memcpy(buf, response.GetData()+offset, size);
1004 info.BootromMetrics.ReleaseBuffer(size);
1007 void JavaLoader::Wipe(bool apps, bool fs)
1009 Data command(-1, 8), data(-1, 8), response;
1010 JLPacket packet(command, data, response);
1012 if( apps ) {
1013 packet.WipeApps();
1014 m_socket->Packet(packet);
1016 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1017 ThrowJLError("JavaLoader::WipeApps", packet.Command());
1021 if( fs ) {
1022 packet.WipeFs();
1023 m_socket->Packet(packet);
1025 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1026 ThrowJLError("JavaLoader::WipeFs", packet.Command());
1031 void JavaLoader::LogStackTraces()
1033 Data command(-1, 8), data(-1, 8), response;
1034 JLPacket packet(command, data, response);
1036 packet.LogStackTraces();
1037 m_socket->Packet(packet);
1039 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1040 ThrowJLError("JavaLoader::LogStackTraces", packet.Command());
1044 void JavaLoader::ResetToFactory()
1046 Data command(-1, 8), data(-1, 8), response;
1047 JLPacket packet(command, data, response);
1049 packet.ResetToFactory();
1050 m_socket->Packet(packet);
1052 if( packet.Command() != SB_COMMAND_JL_ACK ) {
1053 ThrowJLError("JavaLoader::ResetToFactory", packet.Command());
1057 }} // namespace Barry::Mode