Clarified bjavaloader save behaviour
[barry.git] / tools / bjavaloader.cc
blob2d000a2458a6927a5f004737a2a6818f272c32cf
1 ///
2 /// \file bjavaloader.cc
3 ///
4 ///
6 /*
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2005-2009, 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 <getopt.h>
33 #include <fstream>
35 // supported javaloader commands
36 #define CMD_LIST "dir"
37 #define CMD_ERASE "erase"
38 #define CMD_LOAD "load"
39 #define CMD_SCREENSHOT "screenshot"
40 #define CMD_SETTIME "settime"
41 #define CMD_EVENTLOG "eventlog"
42 #define CMD_CLEAR_LOG "cleareventlog"
43 #define CMD_SAVE "save"
45 // time string format specifier and user friendly description
46 #define TIME_FMT "%Y-%m-%d %H:%M:%S"
47 #define TIME_FMT_EXAMPLE "yyyy-mm-dd HH:MM:SS"
49 using namespace std;
50 using namespace Barry;
52 void Usage()
54 int major, minor;
55 const char *Version = Barry::Version(major, minor);
57 cerr
58 << "bjavaloader - Command line USB Blackberry Java Loader\n"
59 << " Copyright 2008-2009, Nicolas VIVIEN.\n"
60 << " Copyright 2005-2009, Net Direct Inc. (http://www.netdirect.ca/)\n"
61 << " Using: " << Version << "\n"
62 << "\n"
63 << " -f Force erase, if module is in use\n"
64 << " -h This help\n"
65 << " -s List sibling in module list\n"
66 << " -p pin PIN of device to talk with\n"
67 << " If only one device is plugged in, this flag is optional\n"
68 << " -P pass Simplistic method to specify device password\n"
69 << " -v Dump protocol data during operation\n"
70 << "\n"
71 << "commands\n"
72 << "\n"
73 << " " << CMD_LIST << " [-s]\n"
74 << " Lists modules on the handheld\n"
75 << "\n"
76 << " " << CMD_LOAD << " <.cod file> ...\n"
77 << " Loads modules onto the handheld\n"
78 << "\n"
79 << " " << CMD_SAVE << " <module name> ...\n"
80 << " Retrieves modules from the handheld and writes to .cod file\n"
81 << " Note: will overwrite existing files!\n"
82 << "\n"
83 << " " << CMD_ERASE << " [-f] <module name> ...\n"
84 << " Erase module from handheld\n"
85 << "\n"
86 << " " << CMD_EVENTLOG << "\n"
87 << " Retrives the handheld event log\n"
88 << "\n"
89 << " " << CMD_CLEAR_LOG << "\n"
90 << " Clears the handheld event log\n"
91 << "\n"
92 << " " << CMD_SCREENSHOT << " <.bmp file>\n"
93 << " Make a screenshot of handheld\n"
94 << "\n"
95 << " " << CMD_SETTIME << " [" << TIME_FMT_EXAMPLE << "]\n"
96 << " Sets the time on the handheld to the current time\n"
97 << " Or the time specified as an argument to " << CMD_SETTIME << "\n"
98 << " If given as argument, current system timezone is assumed\n"
99 << endl;
103 class AutoClose
105 FILE *fp;
107 public:
108 AutoClose(FILE *fh) : fp(fh) {}
109 ~AutoClose()
111 fclose(fp);
115 void SetTime(Barry::Mode::JavaLoader *javaloader, const char *timestr)
117 time_t when;
119 if( timestr ) {
120 struct tm timeinfo;
122 // parse time string
123 char *p = strptime(timestr, TIME_FMT, &timeinfo);
125 // NULL is return when strptime fails to match all of the format
126 // string, and returns a pointer to the NULL byte at the end of
127 // the input string on success
128 if( p == NULL || p != (timestr + strlen(timestr)) ) {
129 throw runtime_error(string("Unable to parse time string: ") + timestr);
132 when = mktime(&timeinfo);
133 } else { // time string is NULL, get current time
134 time(&when);
137 javaloader->SetTime(when);
140 void SendAppFile(Barry::Mode::JavaLoader *javaloader, const char *filename)
142 ifstream file(filename);
143 javaloader->LoadApp(file);
146 void GetScreenshot(Barry::Mode::JavaLoader *javaloader, const char *filename)
149 // Take a screenshot
150 // - info object contains the screenshot properties (width, height...)
151 // - image will be filled with the raw pixel screenshot data
152 JLScreenInfo info;
153 Data image;
154 javaloader->GetScreenshot(info, image);
157 // Convert to BMP format
158 Data bitmap(-1, GetTotalBitmapSize(info));
159 ScreenshotToBitmap(info, image, bitmap);
161 // Write BMP file
162 FILE *fp = fopen(filename, "wb");
163 if (fp == NULL) {
164 throw runtime_error(string("Can't open: ") + filename);
166 AutoClose ac(fp);
168 fwrite(bitmap.GetData(), bitmap.GetSize(), 1, fp);
171 void SaveModule(Barry::Mode::JavaLoader *javaloader, const char *filename)
173 string fname(filename), module;
175 size_t ext_index = fname.rfind(".cod");
176 if( ext_index != string::npos ) {
177 // filename contains .cod extension, strip it for module name
178 module = fname.substr(0, ext_index);
180 else {
181 // filename does not contain .cod extension, use it as module name
182 module = fname;
183 // append extension to file name
184 fname.append(".cod");
187 ofstream file(fname.c_str(), ios::binary | ios::trunc);
188 javaloader->Save(module.c_str(), file);
192 int main(int argc, char *argv[])
194 cout.sync_with_stdio(true); // leave this on, since libusb uses
195 // stdio for debug messages
197 try {
199 uint32_t pin = 0;
200 bool list_siblings = false,
201 force_erase = false,
202 data_dump = false;
203 string password;
204 vector<string> params;
205 string busname;
206 string devname;
207 string iconvCharset;
208 Usb::EndpointPair epOverride;
210 // process command line options
211 for(;;) {
212 int cmd = getopt(argc, argv, "fhsp:P:v");
213 if( cmd == -1 )
214 break;
216 switch( cmd )
218 case 'p': // Blackberry PIN
219 pin = strtoul(optarg, NULL, 16);
220 break;
222 case 'P': // Device password
223 password = optarg;
224 break;
226 case 'f': // turn on 'force' mode for erase
227 force_erase = true;
228 break;
230 case 's': // turn on listing of sibling modules
231 list_siblings = true;
232 break;
234 case 'v': // data dump on
235 data_dump = true;
236 break;
238 case 'h': // help
239 default:
240 Usage();
241 return 0;
245 argc -= optind;
246 argv += optind;
248 if( argc < 1 ) {
249 cerr << "missing command" << endl;
250 Usage();
251 return 1;
254 // Fetch command from remaining arguments
255 string cmd = argv[0];
256 argc --;
257 argv ++;
259 // Put the remaining arguments into an array
260 for (; argc > 0; argc --, argv ++) {
261 params.push_back(string(argv[0]));
264 // Initialize the barry library. Must be called before
265 // anything else.
266 Barry::Init(data_dump);
268 // Probe the USB bus for Blackberry devices and display.
269 // If user has specified a PIN, search for it in the
270 // available device list here as well
271 Barry::Probe probe;
272 int activeDevice = probe.FindActive(pin);
273 if( activeDevice == -1 ) {
274 cerr << "No device selected, or PIN not found" << endl;
275 return 1;
278 // Create our controller object
279 Barry::Controller con(probe.Get(activeDevice));
280 Barry::Mode::JavaLoader javaloader(con);
283 // execute each mode that was turned on
285 javaloader.Open(password.c_str());
286 javaloader.StartStream();
288 if( cmd == CMD_LIST ) {
289 JLDirectory dir;
290 javaloader.GetDirectory(dir, list_siblings);
291 cout << dir;
293 else if( cmd == CMD_LOAD ) {
294 if( params.size() == 0 ) {
295 cerr << "specify at least one .cod file to load" << endl;
296 Usage();
297 return 1;
300 vector<string>::iterator i = params.begin(), end = params.end();
301 for( ; i != end; ++i ) {
302 cout << "loading " << (*i) << "... ";
303 SendAppFile(&javaloader, (*i).c_str());
304 cout << "done." << endl;
307 else if( cmd == CMD_ERASE ) {
308 if( params.size() == 0 ) {
309 cerr << "specify at least one module to erase" << endl;
310 Usage();
311 return 1;
314 vector<string>::iterator i = params.begin(), end = params.end();
315 for( ; i != end; ++i ) {
316 cout << "erasing: " << (*i) << "... ";
317 if( force_erase )
318 javaloader.ForceErase((*i));
319 else
320 javaloader.Erase((*i));
321 cout << "done." << endl;
324 else if( cmd == CMD_SCREENSHOT ) {
325 if( params.size() == 0 ) {
326 cerr << "specify a .bmp filename" << endl;
327 Usage();
328 return 1;
331 GetScreenshot(&javaloader, params[0].c_str());
333 else if( cmd == CMD_SETTIME ) {
334 if( params.size() > 0 ) {
335 SetTime(&javaloader, params[0].c_str());
336 } else {
337 SetTime(&javaloader, NULL);
340 else if( cmd == CMD_EVENTLOG ) {
341 JLEventlog log;
342 javaloader.GetEventlog(log);
343 cout << log;
345 else if( cmd == CMD_CLEAR_LOG ) {
346 javaloader.ClearEventlog();
348 else if( cmd == CMD_SAVE ) {
349 if( params.size() == 0 ) {
350 cerr << "specify at least one module to save" << endl;
351 Usage();
352 return 1;
355 vector<string>::iterator i = params.begin(), end = params.end();
356 for( ; i != end; ++i ) {
357 cout << "saving: " << (*i) << "... ";
358 SaveModule(&javaloader, (*i).c_str());
359 cout << "done." << endl;
362 else {
363 cerr << "invalid command \"" << cmd << "\"" << endl;
364 Usage();
365 return 1;
368 // Stop
369 javaloader.StopStream();
372 catch( Usb::Error &ue) {
373 std::cout << endl; // flush any normal output first
374 std::cerr << "Usb::Error caught: " << ue.what() << endl;
375 return 1;
377 catch( Barry::Error &se ) {
378 std::cout << endl;
379 std::cerr << "Barry::Error caught: " << se.what() << endl;
380 return 1;
382 catch( std::exception &e ) {
383 std::cout << endl;
384 std::cerr << "std::exception caught: " << e.what() << endl;
385 return 1;
388 return 0;