2 /// \file m_javaloader.cc
3 /// Mode class for the JavaLoader mode
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"
28 #include "protostructs.h"
33 #include "controller.h"
42 #include "ios_state.h"
51 ///////////////////////////////////////////////////////////////////////////////
54 JLScreenInfo::JLScreenInfo()
58 JLScreenInfo::~JLScreenInfo()
64 ///////////////////////////////////////////////////////////////////////////////
67 JLDirectory::JLDirectory(int level
)
72 JLDirectory::~JLDirectory()
76 void JLDirectory::ParseTable(const Data
&table_packet
)
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) << "";
105 ///////////////////////////////////////////////////////////////////////////////
106 // JLDirectoryEntry class
108 JLDirectoryEntry::JLDirectoryEntry(int level
)
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();
119 throw BadSize("JLDE:Parse(1)", have
, needed
);
121 const unsigned char *ptr
= entry_packet
.GetData();
122 Protocol::JLDirEntry
*entry
= (Protocol::JLDirEntry
*) ptr
;
125 Timestamp
= be_btohl(entry
->timestamp
);
127 uint16_t len
= be_btohs(entry
->filename_size
);
130 throw BadSize("JLDE:Parse(2)", have
, needed
);
131 Name
.assign((char *)entry
->filename
, len
);
133 // need parsed data + string size
137 throw BadSize("JLDE:Parse(3)", have
, needed
);
139 len
= be_btohs( *((uint16_t*)(ptr
)) );
140 ptr
+= sizeof(uint16_t);
143 throw BadSize("JLDE:Parse(4)", have
, needed
);
144 Version
.assign((char*)ptr
, len
);
146 // need parsed data + string size
148 needed
+= sizeof(uint32_t);
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
;
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);
172 os
<< "\n" << SubDir
;
176 ///////////////////////////////////////////////////////////////////////////////
179 void JLEventlog::Dump(std::ostream
&os
) const
181 const_iterator i
= begin(), e
= end();
182 for( ; i
!= e
; ++i
) {
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
)
209 JLEventlogEntry::ViewerType_t
JLEventlogEntry::ViewerTypeProto2Rec(unsigned int v
)
211 return (ViewerType_t
)v
;
214 unsigned int JLEventlogEntry::ViewerTypeRec2Proto(ViewerType_t 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:"
234 throw BadData("JLEventlogEntry:Parse bad guid field");
236 ss
.ignore(6); // skip " time:"
237 ss
>> hex
>> MSTimestamp
;
239 throw BadData("JLEventlogEntry:Parse bad time field");
241 ss
.ignore(10); // skip " severity:"
242 unsigned int severity
;
244 Severity
= SeverityProto2Rec(severity
);
246 throw BadData("JLEventlogEntry:Parse bad severity field");
248 ss
.ignore(6); // skip " type:"
251 Type
= ViewerTypeProto2Rec(type
);
253 throw BadData("JLEventlogEntry:Parse bad type field");
255 ss
.ignore(5); // skip " app:"
258 throw BadData("JLEventlogEntry:Parse bad app field");
260 ss
.ignore(6); // skip " data:"
262 // use stringbuf to extract rest of data from stream
266 throw BadData("JLEventlogEntry:Parse bad data field");
268 Data
= databuf
.str();
271 std::string
JLEventlogEntry::GetFormattedTimestamp() const
275 time_t timestamp
= (time_t) (MSTimestamp
/ 1000);
277 if( localtime_r(×tamp
, &split
) == NULL
)
280 if( strftime(buf
, sizeof(buf
), "%Y/%m/%d %H:%M:%S.", &split
) == 0 )
283 std::ostringstream oss
;
284 oss
<< buf
<< (MSTimestamp
% 1000);
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
;
337 os
<< left
<< setfill(' ') << setw(17) << "Bootrom Metrics:" << endl
;
338 os
<< BootromMetrics
;
344 ///////////////////////////////////////////////////////////////////////////////
345 // JavaLoader Mode class
347 JavaLoader::JavaLoader(Controller
&con
)
348 : Mode(con
, Controller::JavaLoader
)
349 , m_StreamStarted(false)
353 JavaLoader::~JavaLoader()
356 if( m_StreamStarted
)
359 catch( std::exception
&e
) {
360 dout("Exception ignored in ~JavaLoader(): " << e
.what());
363 dout("Unknown exception in ~JavaLoader()");
367 ///////////////////////////////////////////////////////////////////////////////
371 ///////////////////////////////////////////////////////////////////////////////
374 void JavaLoader::OnOpen()
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
);
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
410 // 04 00 08 00 68 00 F8 07
411 // ^^^^^ : about size
413 // ^^ : size of packet header
416 // 00 00 0C 00 13 04 01 00 0A 00 00 00
418 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
419 // ^^^^^ ............. ^^^^^ : data (the file content)
420 // ^^^^^ : packet size
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());
474 void JavaLoader::LoadApp(std::istream
&input
)
476 uint32_t module_size
;
477 while( (module_size
= SeekNextCod(input
)) != 0 ) {
478 SendStream(input
, module_size
);
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
);
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
)
510 m_StreamStarted
= false;
512 if( packet
.Command() == SB_COMMAND_JL_RESET_REQUIRED
) {
513 m_socket
->ResetOnClose(true);
516 else if( packet
.Command() != SB_COMMAND_JL_ACK
&&
517 packet
.Command() != SB_COMMAND_JL_NOT_SUPPORTED
)
519 ThrowJLError("JavaLoader::StopStream", packet
.Command());
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
,
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);
570 dir
.push_back(entry
);
574 void JavaLoader::GetDir(JLPacket
&packet
,
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();
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.
616 // 04 00 08 00 6E 00 F8 07
617 // ^^^^^ : size + 4 bytes
619 // ^^^^^ : size of packet header
622 // 04 00 FC 07 DB 9D 95 2B 57 .... E6 FD
623 // ^^^^^ ............. ^^^^^ : data (the file content)
624 // ^^^^^ : packet size (0x07FC = 0x7F8 + 4)
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
)
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());
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
656 // 00000010: 00 00 00 00 ....
658 m_socket
->Receive(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
);
671 // 04 00 08 00 68 00 00 00
674 m_socket
->Packet(packet
);
676 // Read and parse the response
677 // 04 00 08 00 64 00 00 00
679 // 04 00 08 00 6e 00 f8 07
681 if( packet
.Command() == SB_COMMAND_JL_ACK
)
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();
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
);
709 unsigned char *buffer
= image
.GetBuffer(image
.GetSize() + bytereceived
);
710 memcpy(buffer
+ image
.GetSize(), pd
+ 4, bytereceived
);
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");
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
);
841 m_socket
->Packet(packet
);
843 if( packet
.Command() == SB_COMMAND_JL_ACK
)
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
,
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");
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
);
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
);
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
);
995 m_socket
->Packet(packet
);
997 if( packet
.Command() != SB_COMMAND_JL_ACK
) {
998 ThrowJLError("JavaLoader::WipeApps", packet
.Command());
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