00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <barry/barry.h>
00026 #include <iostream>
00027 #include <vector>
00028 #include <string>
00029 #include <cstring>
00030 #include <cstdio>
00031 #include <cstdlib>
00032 #include <algorithm>
00033 #include <getopt.h>
00034 #include <fstream>
00035 #include <string.h>
00036 #include <sys/types.h>
00037 #include <sys/time.h>
00038 #include <unistd.h>
00039 #include <signal.h>
00040 #include <errno.h>
00041 #include <pthread.h>
00042
00043 #include "i18n.h"
00044 #include "platform.h"
00045
00046 using namespace std;
00047 using namespace Barry;
00048
00049
00050 #define READ_TIMEOUT_SECONDS 1
00051
00052 static volatile bool signalReceived = false;
00053
00054 static void signalHandler(int signum)
00055 {
00056 signalReceived = true;
00057 }
00058
00059 class CallbackHandler : public Barry::Mode::RawChannelDataCallback
00060 {
00061 private:
00062 volatile bool *m_continuePtr;
00063 bool m_verbose;
00064
00065 public:
00066 CallbackHandler(volatile bool &keepGoing, bool verbose)
00067 : m_continuePtr(&keepGoing)
00068 , m_verbose(verbose)
00069 {
00070 }
00071
00072
00073 public:
00074 virtual void DataReceived(Data &data);
00075 virtual void ChannelError(string msg);
00076 virtual void ChannelClose();
00077 };
00078
00079
00080 void CallbackHandler::DataReceived(Data &data)
00081 {
00082 if( m_verbose ) {
00083 cerr << "From BB: ";
00084 data.DumpHex(cerr);
00085 cerr << "\n";
00086 }
00087
00088 size_t toWrite = data.GetSize();
00089 size_t written = 0;
00090
00091 while( written < toWrite && *m_continuePtr ) {
00092 ssize_t writtenThisTime = write(STDOUT_FILENO, &(data.GetData()[written]), toWrite - written);
00093 if( m_verbose ) {
00094 cerr.setf(ios::dec, ios::basefield);
00095 cerr << "Written " << writtenThisTime << " bytes over stdout" << endl;
00096 }
00097 fflush(stdout);
00098 if( writtenThisTime < 0 ) {
00099 ChannelClose();
00100 }
00101 else {
00102 written += writtenThisTime;
00103 }
00104 }
00105 }
00106
00107 void CallbackHandler::ChannelError(string msg)
00108 {
00109 cerr << "CallbackHandler: Received error: " << msg << endl;
00110 ChannelClose();
00111 }
00112
00113 void CallbackHandler::ChannelClose()
00114 {
00115 *m_continuePtr = false;
00116 }
00117
00118 void Usage()
00119 {
00120 int major, minor;
00121 const char *Version = Barry::Version(major, minor);
00122
00123 cerr
00124 << "brawchannel - Command line USB Blackberry raw channel interface\n"
00125 << " Copyright 2010, RealVNC Ltd.\n"
00126 << " Using: " << Version << "\n"
00127 << "\n"
00128 << "Usage:\n"
00129 << "brawchannel [options] <channel name>\n"
00130 << "\n"
00131 << " -h This help\n"
00132 << " -p pin PIN of device to talk with\n"
00133 << " If only one device is plugged in, this flag is optional\n"
00134 << " -P pass Simplistic method to specify device password\n"
00135 << " -v Dump protocol data during operation\n"
00136 << " This will cause libusb output to appear on STDOUT unless\n"
00137 << " the environment variable USB_DEBUG is set to 0,1 or 2.\n"
00138 << endl;
00139 }
00140
00141
00142
00143
00144 class SignalRestorer
00145 {
00146 private:
00147 int m_signum;
00148 sighandler_t m_handler;
00149 public:
00150 SignalRestorer(int signum, sighandler_t handler)
00151 : m_signum(signum), m_handler(handler) {}
00152 ~SignalRestorer() { signal(m_signum, m_handler); }
00153 };
00154
00155 int main(int argc, char *argv[])
00156 {
00157 INIT_I18N(PACKAGE);
00158
00159
00160 sighandler_t oldSigHup = signal(SIGHUP, &signalHandler);
00161 sighandler_t oldSigTerm = signal(SIGTERM, &signalHandler);
00162 sighandler_t oldSigInt = signal(SIGINT, &signalHandler);
00163 sighandler_t oldSigQuit = signal(SIGQUIT, &signalHandler);
00164
00165 cerr.sync_with_stdio(true);
00166
00167
00168
00169
00170 unsigned char *buf = NULL;
00171 try {
00172 uint32_t pin = 0;
00173 bool data_dump = false;
00174 string password;
00175
00176
00177 for( ;; ) {
00178 int cmd = getopt(argc, argv, "hp:P:v");
00179 if( cmd == -1 ) {
00180 break;
00181 }
00182
00183 switch( cmd )
00184 {
00185 case 'p':
00186 pin = strtoul(optarg, NULL, 16);
00187 break;
00188
00189 case 'P':
00190 password = optarg;
00191 break;
00192
00193 case 'v':
00194 data_dump = true;
00195 break;
00196
00197 case 'h':
00198 default:
00199 Usage();
00200 return 0;
00201 }
00202 }
00203
00204 argc -= optind;
00205 argv += optind;
00206
00207 if( argc < 1 ) {
00208 cerr << "Error: Missing raw channel name." << endl;
00209 Usage();
00210 return 1;
00211 }
00212
00213 if( argc > 1 ) {
00214 cerr << "Error: Too many arguments." << endl;
00215 Usage();
00216 return 1;
00217 }
00218
00219
00220 string channelName = argv[0];
00221 argc --;
00222 argv ++;
00223
00224
00225 if( data_dump ) {
00226
00227
00228 char *val = getenv("USB_DEBUG");
00229 int parsedValue = -1;
00230 if( val ) {
00231 parsedValue = atoi(val);
00232 }
00233 if( parsedValue != 0 && parsedValue != 1 && parsedValue != 2 ) {
00234 cerr << "Warning: Protocol dump enabled without setting USB_DEBUG to 0, 1 or 2.\n"
00235 << " libusb might log to STDOUT and ruin data stream." << endl;
00236 }
00237 }
00238
00239
00240
00241 Barry::Init(data_dump, &cerr);
00242
00243
00244
00245
00246 Barry::Probe probe;
00247 int activeDevice = probe.FindActive(pin);
00248 if( activeDevice == -1 ) {
00249 cerr << "No device selected, or PIN not found" << endl;
00250 return 1;
00251 }
00252
00253
00254 if( data_dump ) {
00255 cerr << "Connected to device, starting read/write\n";
00256 }
00257
00258 volatile bool running = true;
00259
00260
00261
00262 CallbackHandler callbackHandler(running, data_dump);
00263
00264
00265
00266 auto_ptr<SocketRoutingQueue> router;
00267 router.reset(new SocketRoutingQueue());
00268 router->SpinoffSimpleReadThread();
00269
00270
00271 Barry::Controller con(probe.Get(activeDevice), *router);
00272
00273 Barry::Mode::RawChannel rawChannel(con, callbackHandler);
00274
00275
00276 rawChannel.Open(password.c_str(), channelName.c_str());
00277
00278
00279
00280
00281 const size_t bufSize = rawChannel.MaximumSendSize();
00282 buf = new unsigned char[bufSize];
00283 fd_set rfds;
00284 struct timeval tv;
00285 FD_ZERO(&rfds);
00286
00287
00288
00289
00290
00291
00292 SignalRestorer srh(SIGHUP, oldSigHup);
00293 SignalRestorer srt(SIGTERM, oldSigTerm);
00294 SignalRestorer sri(SIGINT, oldSigInt);
00295 SignalRestorer srq(SIGQUIT, oldSigQuit);
00296
00297 while( running && !signalReceived ) {
00298 FD_SET(STDIN_FILENO, &rfds);
00299 tv.tv_sec = READ_TIMEOUT_SECONDS;
00300 tv.tv_usec = 0;
00301
00302 int ret = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv);
00303 if( ret < 0 ) {
00304 cerr << "Select failed with errno: " << errno << endl;
00305 running = false;
00306 }
00307 else if ( ret && FD_ISSET(STDIN_FILENO, &rfds) ) {
00308 ssize_t haveRead = read(STDIN_FILENO, buf, bufSize);
00309 if( haveRead > 0 ) {
00310 Data toWrite(buf, haveRead);
00311 if( data_dump ) {
00312 cerr.setf(ios::dec, ios::basefield);
00313 cerr << "Sending " << haveRead << " bytes stdin->USB\n";
00314 cerr << "To BB: ";
00315 toWrite.DumpHex(cerr);
00316 cerr << "\n";
00317 }
00318 rawChannel.Send(toWrite);
00319 if( data_dump ) {
00320 cerr.setf(ios::dec, ios::basefield);
00321 cerr << "Sent " << haveRead << " bytes stdin->USB\n";
00322 }
00323 }
00324 else if( haveRead < 0 ) {
00325 running = false;
00326 }
00327 }
00328 }
00329 }
00330 catch( Usb::Error &ue ) {
00331 cerr << "Usb::Error caught: " << ue.what() << endl;
00332 return 1;
00333 }
00334 catch( Barry::Error &se ) {
00335 cerr << "Barry::Error caught: " << se.what() << endl;
00336 return 1;
00337 }
00338 catch( exception &e ) {
00339 cerr << "exception caught: " << e.what() << endl;
00340 return 1;
00341 }
00342
00343 delete[] buf;
00344
00345 return 0;
00346 }
00347