controller.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       controller.cc
00003 ///             High level Barry API class
00004 ///
00005 
00006 /*
00007     Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "controller.h"
00023 #include "controllerpriv.h"
00024 #include "common.h"
00025 #include "protocol.h"
00026 #include "protostructs.h"
00027 #include "data.h"
00028 #include "endian.h"
00029 #include "platform.h"
00030 #include <string.h>
00031 
00032 #define __DEBUG_MODE__
00033 #include "debug.h"
00034 
00035 namespace Barry {
00036 
00037 //
00038 // Controller constructor
00039 //
00040 /// Constructor for the Controller class.  Requires a valid ProbeResult
00041 /// object to find the USB device to talk to.
00042 ///
00043 /// \param[in]  device          One of the ProbeResult objects from the
00044 ///                             Probe class.
00045 /// \param[in]  default_timeout Override Usb::Device's default timeout
00046 ///
00047 Controller::Controller(const ProbeResult &device,
00048                         int default_timeout)
00049         : m_priv(new PrivateControllerData(device, default_timeout))
00050 {
00051         dout("Controller: Using non-threaded sockets");
00052         SetupUsb(device);
00053 }
00054 
00055 //
00056 // Controller constructor
00057 //
00058 /// Constructor for the Controller class.  Requires a valid ProbeResult
00059 /// object to find the USB device to talk to.
00060 ///
00061 /// \param[in]  device          One of the ProbeResult objects from the
00062 ///                             Probe class.
00063 /// \param[in]  queue           Plugin router object for reading data
00064 ///                             from sockets.
00065 /// \param[in]  default_timeout Override Usb::Device's default timeout
00066 ///
00067 Controller::Controller(const ProbeResult &device,
00068                         SocketRoutingQueue &queue,
00069                         int default_timeout)
00070         : m_priv(new PrivateControllerData(device, queue, default_timeout))
00071 {
00072         dout("Controller: Using threaded socket router");
00073 
00074         SetupUsb(device);
00075 
00076         // set the queue to use our device
00077         queue.SetUsbDevice(&m_priv->m_dev, device.m_ep.write, device.m_ep.read);
00078 }
00079 
00080 void Controller::SetupUsb(const ProbeResult &device)
00081 {
00082         unsigned char cfg;
00083         if( !m_priv->m_dev.GetConfiguration(cfg) )
00084                 throw Usb::Error(m_priv->m_dev.GetLastError(),
00085                         "Controller: GetConfiguration failed");
00086 
00087         if( cfg != BLACKBERRY_CONFIGURATION || MUST_SET_CONFIGURATION ) {
00088                 if( !m_priv->m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
00089                         throw Usb::Error(m_priv->m_dev.GetLastError(),
00090                                 "Controller: SetConfiguration failed");
00091         }
00092 
00093         m_priv->m_iface = new Usb::Interface(m_priv->m_dev, device.m_interface);
00094 
00095         if( device.m_needSetAltInterface ) {
00096                 m_priv->m_iface->SetAltInterface(device.m_altsetting);
00097         }
00098 
00099         if( device.m_needClearHalt ) {
00100                 m_priv->m_dev.ClearHalt(device.m_ep.read);
00101                 m_priv->m_dev.ClearHalt(device.m_ep.write);
00102         }
00103 }
00104 
00105 Controller::~Controller()
00106 {
00107 }
00108 
00109 ///////////////////////////////////////////////////////////////////////////////
00110 // protected members
00111 
00112 //
00113 // Tells device which mode is desired, and returns the suggested
00114 // socket ID to use for that mode.
00115 //
00116 uint16_t Controller::SelectMode(ModeType mode)
00117 {
00118         return SelectMode(mode, NULL);
00119 }
00120 //
00121 // Tells device which mode is desired, and returns the suggested
00122 // socket ID to use for that mode.
00123 //
00124 // If explicitModeName is not NULL then it will be used as the mode name.
00125 // Otherwise the default mode name for the given mode will be used.
00126 // It should be a nul terminated string if it is provided.
00127 //
00128 // The RawChannel mode requires an explicitModeName to be specified.
00129 //
00130 uint16_t Controller::SelectMode(ModeType mode, const char *explicitModeName)
00131 {
00132         // select mode
00133         Protocol::Packet packet;
00134         packet.socket = 0;
00135         packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
00136         packet.command = SB_COMMAND_SELECT_MODE;
00137         packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
00138         packet.u.socket.sequence = 0; // updated by Socket::Send()
00139         memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
00140 
00141         char *modeName = (char *) packet.u.socket.u.mode.name;
00142 
00143         if( explicitModeName ) {
00144                 if( strlen(explicitModeName) >= sizeof(packet.u.socket.u.mode.name) ) {
00145                         throw std::logic_error("Controller: explicit mode name too long");
00146                 }
00147                 strcpy(modeName, explicitModeName);
00148         }
00149         else {
00150                 // No modeName given, use the default
00151                 switch( mode )
00152                 {
00153                 case Bypass:
00154                         strcpy(modeName, "RIM Bypass");
00155                         break;
00156 
00157                 case Desktop:
00158                         strcpy(modeName, "RIM Desktop");
00159                         break;
00160 
00161                 case JavaLoader:
00162                         strcpy(modeName, "RIM_JavaLoader");
00163                         break;
00164 
00165                 case JVMDebug:
00166                         strcpy(modeName, "RIM_JVMDebug");
00167                         break;
00168 
00169                 case UsbSerData:
00170                         strcpy(modeName, "RIM_UsbSerData");
00171                         break;
00172 
00173                 case UsbSerCtrl:
00174                         strcpy(modeName, "RIM_UsbSerCtrl");
00175                         break;
00176 
00177                 case RawChannel:
00178                         throw std::logic_error("Controller: No channel name given with RawChannel mode");
00179                         break;
00180 
00181                 default:
00182                         throw std::logic_error("Controller: Invalid mode in SelectMode");
00183                         break;
00184                 }
00185         }
00186 
00187         // send mode command before we open, as a default socket is socket 0
00188         Data command(&packet, btohs(packet.size));
00189         Data response;
00190 
00191         try {
00192                 m_priv->m_zero.Send(command, response);
00193 
00194                 // get the data socket number
00195                 // indicates the socket number that
00196                 // should be used below in the Open() call
00197                 MAKE_PACKET(modepack, response);
00198                 if( modepack->command == SB_COMMAND_MODE_NOT_SELECTED ) {
00199                         throw Error("Controller: requested mode not supported");
00200                 }
00201                 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
00202                         eeout(command, response);
00203                         throw Error("Controller: mode not selected");
00204                 }
00205 
00206                 // return the socket that the device is expecting us to use
00207                 return btohs(modepack->u.socket.socket);
00208         }
00209         catch( Usb::Error & ) {
00210                 eout("Controller: error setting desktop mode");
00211                 eeout(command, response);
00212                 throw;
00213         }
00214 }
00215 
00216 //
00217 // OpenSocket
00218 //
00219 /// Can be called multiple times, in case of password retries.
00220 /// See also Mode::RetryPassword()
00221 ///
00222 SocketHandle Controller::OpenSocket(uint16_t socket, const char *password)
00223 {
00224         return m_priv->m_zero.Open(socket, password);
00225 }
00226 
00227 
00228 ///////////////////////////////////////////////////////////////////////////////
00229 // public API
00230 
00231 bool Controller::HasQueue() const
00232 {
00233         return m_priv->m_queue;
00234 }
00235 
00236 SocketRoutingQueue* Controller::GetQueue()
00237 {
00238         return m_priv->m_queue;
00239 }
00240 
00241 const ProbeResult& Controller::GetProbeResult() const
00242 {
00243         return m_priv->m_result;
00244 }
00245 
00246 } // namespace Barry
00247