bwatch.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       bwatch.cc
00003 ///             Display a regularly updated video of the BlackBerry screen
00004 ///
00005 
00006 /*
00007     Copyright (C) 2011, Alberto Mattea
00008     Copyright (C) 2011-2012, Net Direct Inc. (http://www.netdirect.ca/)
00009 
00010     Some parts are inspired from bjavaloader
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00020 
00021     See the GNU General Public License in the COPYING file at the
00022     root directory of this project for more details.
00023 */
00024 
00025 
00026 #include <barry/barry.h>
00027 #include <iostream>
00028 #include <vector>
00029 #include <string>
00030 #include <cstring>
00031 #include <algorithm>
00032 #include <fstream>
00033 #include <string.h>
00034 #include <unistd.h>
00035 #include <SDL/SDL.h>
00036 
00037 using namespace std;
00038 using namespace Barry;
00039 
00040 void Usage()
00041 {
00042    int logical, major, minor;
00043    const char *Version = Barry::Version(logical, major, minor);
00044 
00045    cerr
00046    << "bwatch - View video of BlackBerry screenshots\n"
00047    << "         Copyright 2011, Alberto Mattea\n"
00048    << "         Copyright 2011-2012, Net Direct Inc. (http://www.netdirect.ca/)\n"
00049    << "         Using: " << Version << "\n"
00050    << "\n"
00051    << "   -d delay  Delay interval between screenshots, in milliseconds.\n"
00052    << "             The lower the value, the higher the load on the device.\n"
00053    << "             Default is 500ms.\n"
00054    << "   -p pin    PIN of device to talk with\n"
00055    << "             If only one device is plugged in, this flag is optional\n"
00056    << "   -P pass   Simplistic method to specify device password\n"
00057    << "   -v        Dump protocol data during operation\n"
00058    << endl;
00059 }
00060 
00061 int main(int argc, char *argv[])
00062 {
00063         try {
00064 
00065         cout.sync_with_stdio(true); // leave this on, since libusb uses stdio for debug messages
00066 
00067         uint32_t pin = 0;
00068         bool data_dump = false;
00069         string password;
00070         int delay = 500;        // default delay of 500 ms
00071 
00072         // process command line options
00073         for(;;) {
00074                 int cmd = getopt(argc, argv, "d:hp:P:v");
00075                 if( cmd == -1 )
00076                         break;
00077 
00078                 switch( cmd )
00079                 {
00080                 case 'd':       // delay interval in milliseconds
00081                         delay = atoi(optarg);
00082                         if( !delay ) {
00083                                 cerr << "Invalid interval value of '" << optarg << "'.  Defaulting to 500ms." << endl;
00084                                 delay = 500;
00085                         }
00086                         break;
00087 
00088                 case 'p':       // Blackberry PIN
00089                         pin = strtoul(optarg, NULL, 16);
00090                         break;
00091 
00092                 case 'P':       // Device password
00093                         password = optarg;
00094                         break;
00095 
00096                 case 'v':       // data dump on
00097                         data_dump = true;
00098                         break;
00099 
00100                 case 'h':       // help
00101                 default:
00102                         Usage();
00103                         return 0;
00104                 }
00105         }
00106 
00107         // Init SDL
00108         int sdl_width = -1, sdl_height = -1;
00109         SDL_Surface *screen = NULL;
00110         SDL_Event event;
00111         int keypress = 0;
00112         if( SDL_Init(SDL_INIT_VIDEO) < 0 )
00113                 return 1;
00114 
00115         // Initialize the barry library.  Must be called before
00116         // anything else.
00117         Barry::Init(data_dump);
00118 
00119         JLScreenInfo info;
00120         Data image, bitmap;
00121 
00122         // Probe the USB bus for Blackberry devices and display.
00123         // If user has specified a PIN, search for it in the
00124         // available device list here as well
00125         Barry::Probe probe;
00126         int activeDevice = probe.FindActive(pin);
00127         if( activeDevice == -1 ) {
00128                 cerr << "No device selected, or PIN not found" << endl;
00129                 return 1;
00130         }
00131 
00132         // Main loop
00133         cout << "Press a key to exit..." << endl;
00134         while( !keypress ) {
00135                 // Put this inside it's own block to avoid blocking the handheld
00136                 {
00137                         // Create our controller object
00138                         Barry::Controller con(probe.Get(activeDevice));
00139                         Barry::Mode::JavaLoader javaloader(con);
00140                         javaloader.Open(password.c_str());
00141                         javaloader.StartStream();
00142                         // Take a screenshot
00143                         //   - info object contains the screenshot properties
00144                         //     (width, height...)
00145                         //   - image will be filled with the raw pixel
00146                         //     screenshot data
00147                         javaloader.GetScreenshot(info, image);
00148                         javaloader.StopStream();
00149                 }
00150 
00151                 // Set the video mode according to the screenshot data
00152                 if( sdl_width != info.width || sdl_height != info.height ) {
00153                         sdl_width = info.width;
00154                         sdl_height = info.height;
00155                         if( !(screen = SDL_SetVideoMode(info.width, info.height, 0, SDL_HWSURFACE)) ) {
00156                                 SDL_Quit();
00157                                 return 1;
00158                         }
00159                         SDL_WM_SetCaption("Blackberry", 0);
00160                 }
00161 
00162                 // May want to tune this between 100 and 1000
00163                 SDL_Delay(500);
00164 
00165                 // Convert to 24-bit RGB
00166                 ScreenshotToRGB(info, image, bitmap, 0, 24, false);
00167 
00168                 // Do the blit
00169                 SDL_Surface *tmp;
00170                 tmp = SDL_CreateRGBSurfaceFrom((char*)bitmap.GetData(), info.width, info.height, 24, info.width*3, 0, 0, 0, 0);
00171                 SDL_BlitSurface(tmp, 0, screen, 0);
00172                 SDL_Flip(screen);
00173                 while(SDL_PollEvent(&event)) {
00174                         switch (event.type) {
00175                         case SDL_QUIT:
00176                                 keypress = 1;
00177                                 break;
00178                         case SDL_KEYDOWN:
00179                                 keypress = 1;
00180                                 break;
00181                         }
00182                 }
00183         }
00184 
00185         // Stop SDL
00186         SDL_Quit();
00187         return 0;
00188 
00189 
00190         }
00191         catch( Usb::Error &ue) {
00192                 std::cout << endl;      // flush any normal output first
00193                 std::cerr << "Usb::Error caught: " << ue.what() << endl;
00194                 return 1;
00195         }
00196         catch( Barry::Error &se ) {
00197                 std::cout << endl;
00198                 std::cerr << "Barry::Error caught: " << se.what() << endl;
00199                 return 1;
00200         }
00201         catch( std::exception &e ) {
00202                 std::cout << endl;
00203                 std::cerr << "std::exception caught: " << e.what() << endl;
00204                 return 1;
00205         }
00206 }
00207