lib: added FifoArgs API, for use in passing command line args without command line
[barry.git] / tools / bjavaloader.cc
blob6ad59db28f4d8bc81f6e5a520a97da988a41155c
1 ///
2 /// \file bjavaloader.cc
3 ///
4 ///
6 /*
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 Some parts are inspired from btool.cc
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 <barry/barry.h>
27 #include <iostream>
28 #include <vector>
29 #include <string>
30 #include <cstring>
31 #include <algorithm>
32 #include <fstream>
33 #include <string.h>
34 #include <time.h>
35 #include "i18n.h"
37 #include "barrygetopt.h"
39 // supported javaloader commands
40 #define CMD_LIST "dir"
41 #define CMD_ERASE "erase"
42 #define CMD_LOAD "load"
43 #define CMD_SCREENSHOT "screenshot"
44 #define CMD_SETTIME "settime"
45 #define CMD_EVENTLOG "eventlog"
46 #define CMD_CLEAR_LOG "cleareventlog"
47 #define CMD_SAVE "save"
48 #define CMD_DEVICEINFO "deviceinfo"
49 #define CMD_WIPE "wipe"
50 #define CMD_LOGSTRACES "logstacktraces"
51 #define CMD_RESETFACTORY "resettofactory"
53 // time string format specifier and user friendly description
54 #define TIME_FMT "%Y-%m-%d %H:%M:%S"
55 #define TIME_FMT_EXAMPLE "yyyy-mm-dd HH:MM:SS"
57 using namespace std;
58 using namespace Barry;
60 void Usage()
62 int logical, major, minor;
63 const char *Version = Barry::Version(logical, major, minor);
65 cerr
66 << "bjavaloader - Command line USB Blackberry Java Loader\n"
67 << " Copyright 2008-2009, Nicolas VIVIEN.\n"
68 << " Copyright 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)\n"
69 << " Using: " << Version << "\n"
70 << "\n"
71 << " -A Save all modules found\n"
72 << " -a Wipe applications only\n"
73 << " -i Wipe filesystem only\n"
74 << " -f Force erase, if module is in use\n"
75 << " -h This help\n"
76 << " -s List sibling in module list\n"
77 << " -p pin PIN of device to talk with\n"
78 << " If only one device is plugged in, this flag is optional\n"
79 << " -P pass Simplistic method to specify device password\n"
80 << " -v Dump protocol data during operation\n"
81 << "\n"
82 << "commands\n"
83 << "\n"
84 << " " << CMD_LIST << " [-s]\n"
85 << " Lists modules on the handheld\n"
86 << "\n"
87 << " " << CMD_DEVICEINFO << "\n"
88 << " Provides information on the handheld\n"
89 << "\n"
90 << " " << CMD_LOAD << " <.cod file> ...\n"
91 << " Loads modules onto the handheld\n"
92 << "\n"
93 << " " << CMD_SAVE << " [-A] <module name> ...\n"
94 << " Retrieves modules from the handheld and writes to .cod file\n"
95 << " Note: will overwrite existing files!\n"
96 << "\n"
97 << " " << CMD_WIPE << " [-a | -i]\n"
98 << " Wipes the handheld\n"
99 << " Use Caution: Wiping filesystem will remove all data\n"
100 << " such as messages, contacts, etc.\n"
101 << " Wiping applications will remove all .cod files\n"
102 << " on the device, including OS .cod files.\n"
103 << "\n"
104 << " " << CMD_RESETFACTORY << "\n"
105 << " Reset IT policy to factory defaults\n"
106 << " Use Caution: Resetting IT policy to factory defaults will\n"
107 << " also perform a filesystem wipe which will remove\n"
108 << " all data such as messages, contacts, etc.\n"
109 << "\n"
110 << " " << CMD_ERASE << " [-f] <module name> ...\n"
111 << " Erase module from handheld\n"
112 << "\n"
113 << " " << CMD_EVENTLOG << "\n"
114 << " Retrieves the handheld event log\n"
115 << "\n"
116 << " " << CMD_CLEAR_LOG << "\n"
117 << " Clears the handheld event log\n"
118 << "\n"
119 << " " << CMD_LOGSTRACES << "\n"
120 << " Dump the stack traces for all threads to the event log\n"
121 << "\n"
122 << " " << CMD_SCREENSHOT << " <.bmp file>\n"
123 << " Make a screenshot of handheld\n"
124 << "\n"
125 << " " << CMD_SETTIME << " [" << TIME_FMT_EXAMPLE << "]\n"
126 << " Sets the time on the handheld to the current time\n"
127 << " Or the time specified as an argument to " << CMD_SETTIME << "\n"
128 << " If given as argument, current system timezone is assumed\n"
129 << endl;
133 class AutoClose
135 FILE *fp;
137 public:
138 AutoClose(FILE *fh) : fp(fh) {}
139 ~AutoClose()
141 fclose(fp);
145 void SetTime(Barry::Mode::JavaLoader *javaloader, const char *timestr)
147 time_t when;
149 if( timestr ) {
150 struct tm timeinfo;
151 memset(&timeinfo, 0, sizeof(timeinfo));
153 // parse time string
154 char *p = strptime(timestr, TIME_FMT, &timeinfo);
156 // NULL is return when strptime fails to match all of the format
157 // string, and returns a pointer to the NULL byte at the end of
158 // the input string on success
159 if( p == NULL || p != (timestr + strlen(timestr)) ) {
160 throw runtime_error(string("Unable to parse time string: ") + timestr);
163 when = mktime(&timeinfo);
164 } else { // time string is NULL, get current time
165 time(&when);
168 javaloader->SetTime(when);
171 void SendAppFile(Barry::Mode::JavaLoader *javaloader, const char *filename)
173 ifstream file(filename);
174 javaloader->LoadApp(file);
177 void GetScreenshot(Barry::Mode::JavaLoader *javaloader, const char *filename)
180 // Take a screenshot
181 // - info object contains the screenshot properties (width, height...)
182 // - image will be filled with the raw pixel screenshot data
183 JLScreenInfo info;
184 Data image;
185 javaloader->GetScreenshot(info, image);
188 // Convert to BMP format
189 Data bitmap(-1, GetTotalBitmapSize(info));
190 ScreenshotToBitmap(info, image, bitmap);
192 // Write BMP file
193 FILE *fp = fopen(filename, "wb");
194 if (fp == NULL) {
195 throw runtime_error(string("Can't open: ") + filename);
197 AutoClose ac(fp);
199 fwrite(bitmap.GetData(), bitmap.GetSize(), 1, fp);
202 void SaveModule(Barry::Mode::JavaLoader *javaloader, const char *filename)
204 string fname(filename), module;
206 size_t ext_index = fname.rfind(".cod");
207 if( ext_index != string::npos ) {
208 // filename contains .cod extension, strip it for module name
209 module = fname.substr(0, ext_index);
211 else {
212 // filename does not contain .cod extension, use it as module name
213 module = fname;
214 // append extension to file name
215 fname.append(".cod");
218 ofstream file(fname.c_str(), ios::binary | ios::trunc);
219 javaloader->Save(module.c_str(), file);
223 int main(int argc, char *argv[])
225 INIT_I18N(PACKAGE);
227 cout.sync_with_stdio(true); // leave this on, since libusb uses
228 // stdio for debug messages
230 try {
232 uint32_t pin = 0;
233 bool list_siblings = false,
234 force_erase = false,
235 data_dump = false,
236 all_modules = false,
237 wipe_apps = true,
238 wipe_fs = true;
239 string password;
240 vector<string> params;
241 string busname;
242 string devname;
243 string iconvCharset;
244 Usb::EndpointPair epOverride;
246 // process command line options
247 for(;;) {
248 int cmd = getopt(argc, argv, "Aaifhsp:P:v");
249 if( cmd == -1 )
250 break;
252 switch( cmd )
254 case 'p': // Blackberry PIN
255 pin = strtoul(optarg, NULL, 16);
256 break;
258 case 'P': // Device password
259 password = optarg;
260 break;
262 case 'f': // turn on 'force' mode for erase
263 force_erase = true;
264 break;
266 case 's': // turn on listing of sibling modules
267 list_siblings = true;
268 break;
270 case 'v': // data dump on
271 data_dump = true;
272 break;
274 case 'A': // save all modules
275 all_modules = true;
276 break;
278 case 'a': // wipe apps only
279 wipe_fs = false;
280 break;
282 case 'i': // wipe filesystem
283 wipe_apps = false;
284 break;
286 case 'h': // help
287 default:
288 Usage();
289 return 0;
293 argc -= optind;
294 argv += optind;
296 if( argc < 1 ) {
297 cerr << "missing command" << endl;
298 Usage();
299 return 1;
302 // Fetch command from remaining arguments
303 string cmd = argv[0];
304 argc --;
305 argv ++;
307 // Put the remaining arguments into an array
308 for (; argc > 0; argc --, argv ++) {
309 params.push_back(string(argv[0]));
312 // Initialize the barry library. Must be called before
313 // anything else.
314 Barry::Init(data_dump);
316 // Probe the USB bus for Blackberry devices and display.
317 // If user has specified a PIN, search for it in the
318 // available device list here as well
319 Barry::Probe probe;
320 int activeDevice = probe.FindActive(pin);
321 if( activeDevice == -1 ) {
322 cerr << "No device selected, or PIN not found" << endl;
323 return 1;
326 // Create our controller object
327 Barry::Controller con(probe.Get(activeDevice));
328 Barry::Mode::JavaLoader javaloader(con);
331 // execute each mode that was turned on
333 javaloader.Open(password.c_str());
334 javaloader.StartStream();
336 if( cmd == CMD_LIST ) {
337 JLDirectory dir;
338 javaloader.GetDirectory(dir, list_siblings);
339 cout << dir;
341 else if( cmd == CMD_LOAD ) {
342 if( params.size() == 0 ) {
343 cerr << "specify at least one .cod file to load" << endl;
344 Usage();
345 return 1;
348 vector<string>::iterator i = params.begin(), end = params.end();
349 for( ; i != end; ++i ) {
350 cout << "loading " << (*i) << "... ";
351 SendAppFile(&javaloader, (*i).c_str());
352 cout << "done." << endl;
355 else if( cmd == CMD_ERASE ) {
356 if( params.size() == 0 ) {
357 cerr << "specify at least one module to erase" << endl;
358 Usage();
359 return 1;
362 vector<string>::iterator i = params.begin(), end = params.end();
363 for( ; i != end; ++i ) {
364 cout << "erasing: " << (*i) << "... ";
365 if( force_erase )
366 javaloader.ForceErase((*i));
367 else
368 javaloader.Erase((*i));
369 cout << "done." << endl;
372 else if( cmd == CMD_SCREENSHOT ) {
373 if( params.size() == 0 ) {
374 cerr << "specify a .bmp filename" << endl;
375 Usage();
376 return 1;
379 GetScreenshot(&javaloader, params[0].c_str());
381 else if( cmd == CMD_SETTIME ) {
382 if( params.size() > 0 ) {
383 SetTime(&javaloader, params[0].c_str());
384 } else {
385 SetTime(&javaloader, NULL);
388 else if( cmd == CMD_EVENTLOG ) {
389 JLEventlog log;
390 javaloader.GetEventlog(log);
391 cout << log;
393 else if( cmd == CMD_CLEAR_LOG ) {
394 javaloader.ClearEventlog();
396 else if( cmd == CMD_LOGSTRACES ) {
397 javaloader.LogStackTraces();
399 else if( cmd == CMD_SAVE ) {
400 if( all_modules ) {
401 JLDirectory dir;
402 javaloader.GetDirectory(dir, false);
403 JLDirectory::BaseIterator i = dir.begin();
404 for( ; i != dir.end(); ++i ) {
405 cout << "saving: " << i->Name << "... ";
406 SaveModule(&javaloader,i->Name.c_str());
407 cout << "done." << endl;
410 else if( params.size() == 0 ) {
411 cerr << "specify at least one module to save" << endl;
412 Usage();
413 return 1;
415 else {
416 vector<string>::iterator i = params.begin(), end = params.end();
417 for( ; i != end; ++i ) {
418 cout << "saving: " << (*i) << "... ";
419 SaveModule(&javaloader, (*i).c_str());
420 cout << "done." << endl;
424 else if( cmd == CMD_DEVICEINFO ) {
425 JLDeviceInfo info;
426 javaloader.DeviceInfo(info);
427 cout << info;
429 else if( cmd == CMD_WIPE ) {
430 cout
431 << "Use Caution: Wiping filesystem will remove all data\n"
432 << " such as messages, contacts, etc.\n"
433 << " Wiping applications will remove all .cod files\n"
434 << " on the device, including OS .cod files.\n\n"
435 << "You have selected to wipe the filesystem of device '" << probe.Get(activeDevice).m_pin.Str() << "'\n"
436 << "Continue with wipe? (yes/no) ";
437 string confirm;
438 getline(cin, confirm);
439 if( confirm == "yes" ) {
440 javaloader.Wipe(wipe_apps, wipe_fs);
442 else {
443 cout << "Response of 'yes' not received, aborting." << endl;
446 else if( cmd == CMD_RESETFACTORY ) {
447 cout
448 << "Use Caution: Resetting IT policy to factory defaults will\n"
449 << " also perform a filesystem wipe which will remove\n"
450 << " all data such as messages, contacts, etc.\n\n"
451 << "You have selected to reset device '" << probe.Get(activeDevice).m_pin.Str() << "' to factory defaults\n"
452 << "Continue with wipe? (yes/no) ";
453 string confirm;
454 getline(cin, confirm);
455 if( confirm == "yes" ) {
456 javaloader.ResetToFactory();
458 else {
459 cout << "Response of 'yes' not received, aborting." << endl;
462 else {
463 cerr << "invalid command \"" << cmd << "\"" << endl;
464 Usage();
465 return 1;
468 // Stop
469 javaloader.StopStream();
472 catch( Usb::Error &ue) {
473 std::cout << endl; // flush any normal output first
474 std::cerr << "Usb::Error caught: " << ue.what() << endl;
475 return 1;
477 catch( Barry::Error &se ) {
478 std::cout << endl;
479 std::cerr << "Barry::Error caught: " << se.what() << endl;
480 return 1;
482 catch( std::exception &e ) {
483 std::cout << endl;
484 std::cerr << "std::exception caught: " << e.what() << endl;
485 return 1;
488 return 0;