Renaming raw sockets to raw channels to follow device side API naming.
[barry.git] / tools / brawchannel.cc
blob94739bc8066ee883f0f5d27ca6d978bae46b6a65
1 ///
2 /// \file brawchannel.cc
3 ///
4 ///
6 /*
7 Copyright (C) 2010, RealVNC Ltd.
9 Some parts are inspired from bjavaloader.cc
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 See the GNU General Public License in the COPYING file at the
21 root directory of this project for more details.
25 #include <barry/barry.h>
26 #include <iostream>
27 #include <vector>
28 #include <string>
29 #include <cstring>
30 #include <cstdio>
31 #include <algorithm>
32 #include <getopt.h>
33 #include <fstream>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/types.h>
38 #include "i18n.h"
40 using namespace std;
41 using namespace Barry;
43 class StdoutWriter : public Barry::Mode::RawChannelDataCallback
45 public:
46 StdoutWriter(bool& keepGoing, bool verbose)
47 : m_continuePtr(&keepGoing)
48 , m_verbose(verbose)
53 void DataReceived(Data& data)
55 if (m_verbose)
57 std::cerr << "From BB: ";
58 data.DumpHex(std::cerr);
59 std::cerr << "\n";
62 size_t toWrite = data.GetSize();
63 size_t written = 0;
65 while (written < toWrite && *m_continuePtr)
67 ssize_t writtenThisTime = write(STDOUT_FILENO, &(data.GetData()[written]), toWrite - written);
68 if (m_verbose)
69 cerr << "Written " << writtenThisTime << " bytes over stdout\n";
70 std::fflush(stdout);
71 if (writtenThisTime < 0)
73 *m_continuePtr = false;
75 else
77 written += writtenThisTime;
82 private:
83 bool* m_continuePtr;
84 bool m_verbose;
87 void Usage()
89 int major, minor;
90 const char *Version = Barry::Version(major, minor);
92 cerr
93 << "brawchannel - Command line USB Blackberry raw channel interface\n"
94 << " Copyright 2010, RealVNC Ltd.\n"
95 << " Using: " << Version << "\n"
96 << "\n"
97 << "Usage:\n"
98 << "brawchannel [options] <channel name>\n"
99 << "\n"
100 << " -h This help\n"
101 << " -p pin PIN of device to talk with\n"
102 << " If only one device is plugged in, this flag is optional\n"
103 << " -P pass Simplistic method to specify device password\n"
104 << " -v Dump protocol data during operation\n"
105 << endl;
108 int main(int argc, char *argv[])
110 INIT_I18N(PACKAGE);
112 cout.sync_with_stdio(true); // leave this on, since libusb uses
113 // stdio for debug messages
115 try {
116 uint32_t pin = 0;
117 bool data_dump = false;
118 string password;
119 vector<string> params;
120 string busname;
121 string devname;
122 string iconvCharset;
123 Usb::EndpointPair epOverride;
125 // process command line options
126 for(;;) {
127 int cmd = getopt(argc, argv, "hp:P:v");
128 if( cmd == -1 )
129 break;
131 switch( cmd )
133 case 'p': // Blackberry PIN
134 pin = strtoul(optarg, NULL, 16);
135 break;
137 case 'P': // Device password
138 password = optarg;
139 break;
141 case 'v': // data dump on
142 data_dump = true;
143 break;
145 case 'h': // help
146 default:
147 Usage();
148 return 0;
152 argc -= optind;
153 argv += optind;
155 if( argc < 1 ) {
156 cerr << "Error: Missing raw channel name." << endl;
157 Usage();
158 return 1;
161 // Fetch command from remaining arguments
162 string channelName = argv[0];
163 argc --;
164 argv ++;
166 // Put the remaining arguments into an array
167 for (; argc > 0; argc --, argv ++) {
168 params.push_back(string(argv[0]));
171 // Initialize the barry library. Must be called before
172 // anything else.
173 Barry::Init(data_dump);
175 // Probe the USB bus for Blackberry devices and display.
176 // If user has specified a PIN, search for it in the
177 // available device list here as well
178 Barry::Probe probe;
179 int activeDevice = probe.FindActive(pin);
180 if( activeDevice == -1 ) {
181 cerr << "No device selected, or PIN not found" << endl;
182 return 1;
185 // Now start to read from cin and get ready to write
186 // to the BlackBerry.
187 if (data_dump)
188 std::cerr << "Connected to device, starting read/write\n";
190 bool running = true;
192 // Create the thing which will write onto stdout
193 StdoutWriter stdoutWriter(running, data_dump);
195 // Set up the BlackBerry gubbins
196 // Start a thread to handle any data arriving from
197 // the BlackBerry.
198 auto_ptr<SocketRoutingQueue> router;
199 router.reset(new SocketRoutingQueue);
200 router->SpinoffSimpleReadThread();
202 // Create our controller object
203 Barry::Controller con(probe.Get(activeDevice), *router);
204 Barry::Mode::RawChannel rawChannel(con, stdoutWriter);
207 // execute each mode that was turned on
209 rawChannel.Open(password.c_str(), channelName.c_str());
211 // We now have a thread running to read from the
212 // BB and write over stdout; in this thread we'll
213 // read from stdin and write to the BB.
214 unsigned char buf[Barry::Mode::RawChannel::MaximumPacketContentsSize];
215 while (running)
217 size_t haveRead = read(STDIN_FILENO, buf, sizeof(buf));
218 if (haveRead > 0)
220 Data toWrite(buf, haveRead);
221 if(data_dump)
223 std::cerr << "Sending " << haveRead << " bytes stdin->USB\n";
224 std::cerr << "To BB: ";
225 toWrite.DumpHex(std::cerr);
226 std::cerr << "\n";
228 rawChannel.Send(toWrite);
229 if(data_dump)
230 std::cerr << "Sent " << haveRead << " bytes stdin->USB\n";
232 else if (haveRead < 0 || !std::cin.good())
234 running = false;
238 catch( Usb::Error &ue) {
239 std::cerr << "Usb::Error caught: " << ue.what() << endl;
240 return 1;
242 catch( Barry::Error &se ) {
243 std::cerr << "Barry::Error caught: " << se.what() << endl;
244 return 1;
246 catch( std::exception &e ) {
247 std::cerr << "std::exception caught: " << e.what() << endl;
248 return 1;
251 return 0;