2 /// \file bjavaloader.cc
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 <barry/cod.h>
37 #include <sys/types.h>
40 // supported javaloader commands
41 #define CMD_LIST "dir"
42 #define CMD_LOAD "load"
43 #define CMD_SETTIME "settime"
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"
50 using namespace Barry
;
55 const char *Version
= Barry::Version(major
, minor
);
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"
64 << " -s List sibling in module list\n"
65 << " -p pin PIN of device to talk with\n"
66 << " If only one device is plugged in, this flag is optional\n"
67 << " -P pass Simplistic method to specify device password\n"
68 << " -v Dump protocol data during operation\n"
72 << " " << CMD_LIST
<< endl
73 << " Lists modules on the handheld\n"
75 << " " << CMD_LOAD
<< " <.cod file> ...\n"
76 << " Loads modules onto the handheld\n"
78 << " " << CMD_SETTIME
<< " [" << TIME_FMT_EXAMPLE
<< "]\n"
79 << " Sets the time on the handheld to the current time\n"
80 << " Or the time specified as an argument to " << CMD_SETTIME
<< "\n"
81 << " If given as argument, current system timezone is assumed\n"
91 AutoClose(FILE *fh
) : fp(fh
) {}
98 void SetTime(Barry::Mode::JavaLoader
*javaloader
, const char *timestr
)
106 char *p
= strptime(timestr
, TIME_FMT
, &timeinfo
);
108 // NULL is return when strptime fails to match all of the format
109 // string, and returns a pointer to the NULL byte at the end of
110 // the input string on success
111 if( p
== NULL
|| p
!= (timestr
+ strlen(timestr
)) ) {
112 throw runtime_error(string("Unable to parse time string: ") + timestr
);
115 when
= mktime(&timeinfo
);
116 } else { // time string is NULL, get current time
120 javaloader
->SetTime(when
);
123 void SendAppFile(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
129 codfile_header_t header
;
138 if (stat(filename
, &sb
) == -1) {
139 throw runtime_error(string("Can't stat: ") + filename
);
142 filesize
= sb
.st_size
;
143 if( (unsigned long)filesize
> (size_t)-1 ) {
144 throw runtime_error("Filesize larger than max fread()... contact Barry developers.");
148 fp
= fopen(filename
, "rb");
151 throw runtime_error(string("Can't open: ") + filename
);
158 n
= fread(&header
, sizeof(codfile_header_t
), 1, fp
);
163 // Is a COD file packed (a big COD file) ?
164 if (header
.type
== 0x4B50) {
165 if (header
.size1
!= header
.size2
)
168 skip
= header
.strsize
+ header
.strfree
;
170 if( fseek(fp
, skip
, SEEK_CUR
) != 0 ) {
171 throw runtime_error("Can't skip COD header");
174 // this is a one-time program, so allocate and
175 // don't worry about freeing
176 data
= (char *) realloc(data
, header
.size1
* sizeof(char));
178 n
= fread(data
, sizeof(char), header
.size1
, fp
);
179 if( n
!= header
.size1
) {
180 throw runtime_error("Can't read packed COD header");
183 javaloader
->SendStream(data
, (int) header
.size1
);
185 // Is a simple COD file (a small COD file) ?
186 else if (header
.type
== 0xC0DE) {
189 data
= (char *) malloc(filesize
* sizeof(char));
191 n
= fread(data
, sizeof(char), filesize
, fp
);
192 if( (off_t
) n
!= filesize
) {
193 throw runtime_error("Can't read COD data");
197 javaloader
->SendStream(data
, filesize
);
203 int main(int argc
, char *argv
[])
205 cout
.sync_with_stdio(true); // leave this on, since libusb uses
206 // stdio for debug messages
211 bool list_siblings
= false,
214 vector
<string
> params
;
218 Usb::EndpointPair epOverride
;
220 // process command line options
222 int cmd
= getopt(argc
, argv
, "hsp:P:v");
228 case 'p': // Blackberry PIN
229 pin
= strtoul(optarg
, NULL
, 16);
232 case 'P': // Device password
236 case 's': // turn on listing of sibling modules
237 list_siblings
= true;
240 case 'v': // data dump on
255 cerr
<< "missing command" << endl
;
260 // Fetch command from remaining arguments
261 string cmd
= argv
[0];
265 // Put the remaining arguments into an array
266 for (; argc
> 0; argc
--, argv
++) {
267 params
.push_back(string(argv
[0]));
270 // Initialize the barry library. Must be called before
272 Barry::Init(data_dump
);
274 // Probe the USB bus for Blackberry devices and display.
275 // If user has specified a PIN, search for it in the
276 // available device list here as well
278 int activeDevice
= probe
.FindActive(pin
);
279 if( activeDevice
== -1 ) {
280 cerr
<< "No device selected, or PIN not found" << endl
;
284 // Create our controller object
285 Barry::Controller
con(probe
.Get(activeDevice
));
286 Barry::Mode::JavaLoader
javaloader(con
);
289 // execute each mode that was turned on
291 javaloader
.Open(password
.c_str());
292 javaloader
.StartStream();
294 if( cmd
== CMD_LIST
) {
296 javaloader
.GetDirectory(dir
, list_siblings
);
298 } else if( cmd
== CMD_LOAD
) {
299 if( params
.size() == 0 ) {
300 cerr
<< "specify at least one .cod file to load" << endl
;
305 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
306 for( ; i
!= end
; ++i
) {
307 cout
<< "loading " << (*i
) << "... ";
308 SendAppFile(&javaloader
, (*i
).c_str());
309 cout
<< "done." << endl
;
311 } else if( cmd
== CMD_SETTIME
) {
312 if( params
.size() > 0 ) {
313 SetTime(&javaloader
, params
[0].c_str());
315 SetTime(&javaloader
, NULL
);
318 cerr
<< "invalid command \"" << cmd
<< "\"" << endl
;
324 javaloader
.StopStream();
327 catch( Usb::Error
&ue
) {
328 std::cerr
<< "Usb::Error caught: " << ue
.what() << endl
;
331 catch( Barry::Error
&se
) {
332 std::cerr
<< "Barry::Error caught: " << se
.what() << endl
;
335 catch( std::exception
&e
) {
336 std::cerr
<< "std::exception caught: " << e
.what() << endl
;