# 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-2011, 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 "probe.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_result(device)
    00050         , m_dev(device.m_dev, default_timeout)
    00051         , m_iface(0)
    00052         , m_pin(device.m_pin)
    00053         , m_zero(m_dev, device.m_ep.write, device.m_ep.read, device.m_zeroSocketSequence)
    00054         , m_queue(0)
    00055 {
    00056         dout("Controller: Using non-threaded sockets");
    00057         SetupUsb(device);
    00058 }
    00059
    00060 //
    00061 // Controller constructor
    00062 //
    00063 /// Constructor for the Controller class.  Requires a valid ProbeResult
    00064 /// object to find the USB device to talk to.
    00065 ///
    00066 /// \param[in]  device          One of the ProbeResult objects from the
    00067 ///                             Probe class.
    00068 /// \param[in]  queue           Plugin router object for reading data
    00069 ///                             from sockets.
    00070 /// \param[in]  default_timeout Override Usb::Device's default timeout
    00071 ///
    00072 Controller::Controller(const ProbeResult &device,
    00073                         SocketRoutingQueue &queue,
    00074                         int default_timeout)
    00075         : m_result(device)
    00076         , m_dev(device.m_dev, default_timeout)
    00077         , m_iface(0)
    00078         , m_pin(device.m_pin)
    00079         , m_zero(queue, device.m_ep.write, device.m_zeroSocketSequence)
    00080         , m_queue(&queue)
    00081 {
    00082         dout("Controller: Using threaded socket router");
    00083
    00084         SetupUsb(device);
    00085
    00086         // set the queue to use our device
    00087         queue.SetUsbDevice(&m_dev, device.m_ep.write, device.m_ep.read);
    00088 }
    00089
    00090 void Controller::SetupUsb(const ProbeResult &device)
    00091 {
    00092         unsigned char cfg;
    00093         if( !m_dev.GetConfiguration(cfg) )
    00094                 throw Usb::Error(m_dev.GetLastError(),
    00095                         "Controller: GetConfiguration failed");
    00096
    00097         if( cfg != BLACKBERRY_CONFIGURATION || MUST_SET_CONFIGURATION ) {
    00098                 if( !m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
    00099                         throw Usb::Error(m_dev.GetLastError(),
    00100                                 "Controller: SetConfiguration failed");
    00101         }
    00102
    00103         m_iface = new Usb::Interface(m_dev, device.m_interface);
    00104
    00105         if( device.m_needSetAltInterface ) {
    00106                 m_dev.SetAltInterface(device.m_interface);
    00107         }
    00108
    00109         if( device.m_needClearHalt ) {
    00110                 m_dev.ClearHalt(device.m_ep.read);
    00111                 m_dev.ClearHalt(device.m_ep.write);
    00112         }
    00113 }
    00114
    00115 Controller::~Controller()
    00116 {
    00117 //      // trap exceptions in the destructor
    00118 //      try {
    00119 //              // a non-default socket has been opened, close it
    00120 //              m_socket.Close();
    00121 //      }
    00122 //      catch( std::runtime_error &re ) {
    00123 //              // do nothing... log it?
    00124 //              dout("Exception caught in ~Socket: " << re.what());
    00125 //      }
    00126
    00127         // detach the router from our device
    00128         if( m_queue ) {
    00129                 m_queue->ClearUsbDevice();
    00130                 m_queue = 0;
    00131         }
    00132
    00133         // cleanup the interface
    00134         delete m_iface;
    00135
    00136         // this happens when for some reason the Desktop mode
    00137         // is not fully opened, but the device has already recommended
    00138         // a socket to open... in this case, reset the device
    00139         // in the hopes that on next open, it will be in a
    00140         // recognizable state.
    00141         //
    00142         // FIXME - this should not be necessary, and someday we
    00143         // we should figure out how to handle the "already open"
    00144         // response we get for the Desktop
    00145         //
    00146         // FIXME - halfOpen now seems to be handled in the Socket class...
    00147         // perhaps move this there if needed
    00148         //
    00149 /*
    00150         if( m_halfOpen ) {
    00151                 dout("Controller object destroyed in halfopen state, resetting device");
    00152                 m_dev.Reset();
    00153         }
    00154 */
    00155 }
    00156
    00157 ///////////////////////////////////////////////////////////////////////////////
    00158 // protected members
    00159
    00160 //
    00161 // Tells device which mode is desired, and returns the suggested
    00162 // socket ID to use for that mode.
    00163 //
    00164 uint16_t Controller::SelectMode(ModeType mode)
    00165 {
    00166         return SelectMode(mode, NULL);
    00167 }
    00168 //
    00169 // Tells device which mode is desired, and returns the suggested
    00170 // socket ID to use for that mode.
    00171 //
    00172 // If explicitModeName is not NULL then it will be used as the mode name.
    00173 // Otherwise the default mode name for the given mode will be used.
    00174 // It should be a nul terminated string if it is provided.
    00175 //
    00176 // The RawChannel mode requires an explicitModeName to be specified.
    00177 //
    00178 uint16_t Controller::SelectMode(ModeType mode, const char *explicitModeName)
    00179 {
    00180         // select mode
    00181         Protocol::Packet packet;
    00182         packet.socket = 0;
    00183         packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
    00184         packet.command = SB_COMMAND_SELECT_MODE;
    00185         packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
    00186         packet.u.socket.sequence = 0; // updated by Socket::Send()
    00187         memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
    00188
    00189         char *modeName = (char *) packet.u.socket.u.mode.name;
    00190
    00191         if( explicitModeName ) {
    00192                 if( strlen(explicitModeName) >= sizeof(packet.u.socket.u.mode.name) ) {
    00193                         throw std::logic_error("Controller: explicit mode name too long");
    00194                 }
    00195                 strcpy(modeName, explicitModeName);
    00196         }
    00197         else {
    00198                 // No modeName given, use the default
    00199                 switch( mode )
    00200                 {
    00201                 case Bypass:
    00202                         strcpy(modeName, "RIM Bypass");
    00203                         break;
    00204
    00205                 case Desktop:
    00206                         strcpy(modeName, "RIM Desktop");
    00207                         break;
    00208
    00209                 case JavaLoader:
    00210                         strcpy(modeName, "RIM_JavaLoader");
    00211                         break;
    00212
    00213                 case JVMDebug:
    00214                         strcpy(modeName, "RIM_JVMDebug");
    00215                         break;
    00216
    00217                 case UsbSerData:
    00218                         strcpy(modeName, "RIM_UsbSerData");
    00219                         break;
    00220
    00221                 case UsbSerCtrl:
    00222                         strcpy(modeName, "RIM_UsbSerCtrl");
    00223                         break;
    00224
    00225                 case RawChannel:
    00226                         throw std::logic_error("Controller: No channel name given with RawChannel mode");
    00227                         break;
    00228
    00229                 default:
    00230                         throw std::logic_error("Controller: Invalid mode in SelectMode");
    00231                         break;
    00232                 }
    00233         }
    00234
    00235         // send mode command before we open, as a default socket is socket 0
    00236         Data command(&packet, btohs(packet.size));
    00237         Data response;
    00238
    00239         try {
    00240                 m_zero.Send(command, response);
    00241
    00242                 // get the data socket number
    00243                 // indicates the socket number that
    00244                 // should be used below in the Open() call
    00245                 MAKE_PACKET(modepack, response);
    00246                 if( modepack->command == SB_COMMAND_MODE_NOT_SELECTED ) {
    00247                         throw Error("Controller: requested mode not supported");
    00248                 }
    00249                 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
    00250                         eeout(command, response);
    00251                         throw Error("Controller: mode not selected");
    00252                 }
    00253
    00254                 if( mode == Desktop ) {
    00255                         // On the BlackBerry Storm, I have to read a packet
    00256                         // after opening a socket. (only for Desktop mode)
    00257                         // Otherwise, barrybackup and opensync-plugin can crash (timeout)
    00258                         // I don't know why ! Maybe a bug on the handheld.
    00259                         m_zero.HideSequencePacket(false);
    00260                         m_zero.Receive(response);
    00261                         m_zero.HideSequencePacket(true);
    00262                 }
    00263                 // return the socket that the device is expecting us to use
    00264                 return btohs(modepack->u.socket.socket);
    00265         }
    00266         catch( Usb::Error & ) {
    00267                 eout("Controller: error setting desktop mode");
    00268                 eeout(command, response);
    00269                 throw;
    00270         }
    00271 }
    00272
    00273
    00274 ///////////////////////////////////////////////////////////////////////////////
    00275 // public API
    00276
    00277
    00278 } // namespace Barry
    00279