2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
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.
26 #include "m_javaloader.h"
29 #include "protostructs.h"
34 #include "controller.h"
44 #include "ios_state.h"
53 ///////////////////////////////////////////////////////////////////////////////
56 JLScreenInfo::JLScreenInfo()
60 JLScreenInfo::~JLScreenInfo()
66 ///////////////////////////////////////////////////////////////////////////////
69 JLDirectory::JLDirectory(int level
)
74 JLDirectory::~JLDirectory()
78 void JLDirectory::ParseTable(const Data
&table_packet
)
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) << "";
107 ///////////////////////////////////////////////////////////////////////////////
108 // JLDirectoryEntry class
110 JLDirectoryEntry::JLDirectoryEntry()
116 JLDirectoryEntry::JLDirectoryEntry(int level
)
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();
127 throw BadSize("JLDE:Parse(1)", have
, needed
);
129 const unsigned char *ptr
= entry_packet
.GetData();
130 Protocol::JLDirEntry
*entry
= (Protocol::JLDirEntry
*) ptr
;
133 Timestamp
= be_btohl(entry
->timestamp
);
135 uint16_t len
= be_btohs(entry
->filename_size
);
138 throw BadSize("JLDE:Parse(2)", have
, needed
);
139 Name
.assign((char *)entry
->filename
, len
);
141 // need parsed data + string size
145 throw BadSize("JLDE:Parse(3)", have
, needed
);
147 len
= be_btohs( *((uint16_t*)(ptr
)) );
148 ptr
+= sizeof(uint16_t);
151 throw BadSize("JLDE:Parse(4)", have
, needed
);
152 Version
.assign((char*)ptr
, len
);
154 // need parsed data + string size
156 needed
+= sizeof(uint32_t);
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
;
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);
180 os
<< "\n" << SubDir
;
184 ///////////////////////////////////////////////////////////////////////////////
187 void JLEventlog::Dump(std::ostream
&os
) const
189 const_iterator i
= begin(), e
= end();
190 for( ; i
!= e
; ++i
) {
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
)
217 JLEventlogEntry::ViewerType_t
JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v
)
219 return (ViewerType_t
)v
;
222 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t 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:"
242 throw BadData(_("JLEventlogEntry:Parse bad guid field"));
244 ss
.ignore(6); // skip " time:"
245 ss
>> hex
>> MSTimestamp
;
247 throw BadData(_("JLEventlogEntry:Parse bad time field"));
249 ss
.ignore(10); // skip " severity:"
250 unsigned int severity
;
252 Severity
= SeverityProto2Rec(severity
);
254 throw BadData(_("JLEventlogEntry:Parse bad severity field"));
256 ss
.ignore(6); // skip " type:"
259 Type
= ViewerTypeProto2Rec(type
);
261 throw BadData(_("JLEventlogEntry:Parse bad type field"));
263 ss
.ignore(5); // skip " app:"
266 throw BadData(_("JLEventlogEntry:Parse bad app field"));
268 ss
.ignore(6); // skip " data:"
270 // use stringbuf to extract rest of data from stream
274 throw BadData(_("JLEventlogEntry:Parse bad data field"));
276 Data
= databuf
.str();
279 std::string
JLEventlogEntry::GetFormattedTimestamp() const
283 time_t timestamp
= (time_t) (MSTimestamp
/ 1000);
285 if( localtime_r(×tamp
, &split
) == NULL
)
288 if( strftime(buf
, sizeof(buf
), "%Y/%m/%d %H:%M:%S.", &split
) == 0 )
291 std::ostringstream oss
;
292 oss
<< buf
<< (MSTimestamp
% 1000);
296 void JLEventlogEntry::Dump(std::ostream
&os
) const
298 ios_format_state
state(os
);
300 static const char *SeverityNames
[] = {
308 static const char *ViewerTypes
[] = {
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
;
356 os
<< left
<< setfill(' ') << setw(17) << _("Bootrom Metrics:") << endl
;
357 os
<< BootromMetrics
;
363 ///////////////////////////////////////////////////////////////////////////////
364 // JavaLoader Mode class
366 JavaLoader::JavaLoader(Controller
&con
)
367 : Mode(con
, Controller::JavaLoader
)
368 , m_StreamStarted(false)
372 JavaLoader::~JavaLoader()
375 if( m_StreamStarted
)
378 catch( std::exception
&DEBUG_ONLY(e
) ) {
379 dout("Exception ignored in ~JavaLoader(): " << e
.what());
382 dout("Unknown exception in ~JavaLoader()");
386 ///////////////////////////////////////////////////////////////////////////////
390 ///////////////////////////////////////////////////////////////////////////////
393 void JavaLoader::OnOpen()
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
);
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
429 // 04 00 08 00 68 00 F8 07
430 // ^^^^^ : about size
432 // ^^ : size of packet header
435 // 00 00 0C 00 13 04 01 00 0A 00 00 00
437 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
438 // ^^^^^ ............. ^^^^^ : data (the file content)
439 // ^^^^^ : packet size
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());
493 void JavaLoader::LoadApp(std::istream
&input
)
495 uint32_t module_size
;
496 while( (module_size
= SeekNextCod(input
)) != 0 ) {
497 SendStream(input
, module_size
);
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
);
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
)
529 m_StreamStarted
= false;
531 if( packet
.Command() == SB_COMMAND_JL_RESET_REQUIRED
) {
532 m_socket
->ResetOnClose(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());
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
,
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);
589 dir
.push_back(entry
);
593 void JavaLoader::GetDir(JLPacket
&packet
,
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();
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.
635 // 04 00 08 00 6E 00 F8 07
636 // ^^^^^ : size + 4 bytes
638 // ^^^^^ : size of packet header
641 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
642 // ^^^^^ ............. ^^^^^ : data (the file content)
643 // ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
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
)
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());
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
675 // 00000010: 00 00 00 00 ....
677 m_socket
->Receive(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
);
690 // 04 00 08 00 68 00 00 00
693 m_socket
->Packet(packet
);
695 // Read and parse the response
696 // 04 00 08 00 64 00 00 00
698 // 04 00 08 00 6e 00 f8 07
700 if( packet
.Command() == SB_COMMAND_JL_ACK
)
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();
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
);
728 unsigned char *buffer
= image
.GetBuffer(image
.GetSize() + bytereceived
);
729 memcpy(buffer
+ image
.GetSize(), pd
+ 4, bytereceived
);
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"));
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
);
860 m_socket
->Packet(packet
);
862 if( packet
.Command() == SB_COMMAND_JL_ACK
)
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
,
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"));
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
);
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
);
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
);
1014 m_socket
->Packet(packet
);
1016 if( packet
.Command() != SB_COMMAND_JL_ACK
) {
1017 ThrowJLError("JavaLoader::WipeApps", packet
.Command());
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