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-2009, 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 <string.h>
00030 
00031 #define __DEBUG_MODE__
00032 #include "debug.h"
00033 
00034 namespace Barry {
00035 
00036 //
00037 // Controller constructor
00038 //
00039 /// Constructor for the Controller class.  Requires a valid ProbeResult
00040 /// object to find the USB device to talk to.
00041 ///
00042 /// \param[in]  device          One of the ProbeResult objects from the
00043 ///                             Probe class.
00044 ///
00045 Controller::Controller(const ProbeResult &device)
00046         : m_result(device)
00047         , m_dev(device.m_dev)
00048         , m_iface(0)
00049         , m_pin(device.m_pin)
00050         , m_zero(m_dev, device.m_ep.write, device.m_ep.read, device.m_zeroSocketSequence)
00051         , m_queue(0)
00052 {
00053         dout("Controller: Using non-threaded sockets");
00054         SetupUsb(device);
00055 }
00056 
00057 //
00058 // Controller constructor
00059 //
00060 /// Constructor for the Controller class.  Requires a valid ProbeResult
00061 /// object to find the USB device to talk to.
00062 ///
00063 /// \param[in]  device          One of the ProbeResult objects from the
00064 ///                             Probe class.
00065 /// \param[in]  queue           Plugin router object for reading data
00066 ///                             from sockets.
00067 ///
00068 Controller::Controller(const ProbeResult &device, SocketRoutingQueue &queue)
00069         : m_result(device)
00070         , m_dev(device.m_dev)
00071         , m_iface(0)
00072         , m_pin(device.m_pin)
00073         , m_zero(queue, device.m_ep.write, device.m_zeroSocketSequence)
00074         , m_queue(&queue)
00075 {
00076         dout("Controller: Using threaded socket router");
00077 
00078         SetupUsb(device);
00079 
00080         // set the queue to use our device
00081         queue.SetUsbDevice(&m_dev, device.m_ep.write, device.m_ep.read);
00082 }
00083 
00084 void Controller::SetupUsb(const ProbeResult &device)
00085 {
00086         unsigned char cfg;
00087         if( !m_dev.GetConfiguration(cfg) )
00088                 throw Usb::Error(m_dev.GetLastError(),
00089                         "Controller: GetConfiguration failed");
00090 
00091         if( cfg != BLACKBERRY_CONFIGURATION ) {
00092                 if( !m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
00093                         throw Usb::Error(m_dev.GetLastError(),
00094                                 "Controller: SetConfiguration failed");
00095         }
00096 
00097         m_iface = new Usb::Interface(m_dev, device.m_interface);
00098 
00099         m_dev.ClearHalt(device.m_ep.read);
00100         m_dev.ClearHalt(device.m_ep.write);
00101 }
00102 
00103 Controller::~Controller()
00104 {
00105 //      // trap exceptions in the destructor
00106 //      try {
00107 //              // a non-default socket has been opened, close it
00108 //              m_socket.Close();
00109 //      }
00110 //      catch( std::runtime_error &re ) {
00111 //              // do nothing... log it?
00112 //              dout("Exception caught in ~Socket: " << re.what());
00113 //      }
00114 
00115         // detach the router from our device
00116         if( m_queue ) {
00117                 m_queue->ClearUsbDevice();
00118                 m_queue = 0;
00119         }
00120 
00121         // cleanup the interface
00122         delete m_iface;
00123 
00124         // this happens when for some reason the Desktop mode
00125         // is not fully opened, but the device has already recommended
00126         // a socket to open... in this case, reset the device
00127         // in the hopes that on next open, it will be in a
00128         // recognizable state.
00129         //
00130         // FIXME - this should not be necessary, and someday we
00131         // we should figure out how to handle the "already open"
00132         // response we get for the Desktop
00133         //
00134         // FIXME - halfOpen now seems to be handled in the Socket class...
00135         // perhaps move this there if needed
00136         //
00137 /*
00138         if( m_halfOpen ) {
00139                 dout("Controller object destroyed in halfopen state, resetting device");
00140                 m_dev.Reset();
00141         }
00142 */
00143 }
00144 
00145 ///////////////////////////////////////////////////////////////////////////////
00146 // protected members
00147 
00148 //
00149 // Tells device which mode is desired, and returns the suggested
00150 // socket ID to use for that mode.
00151 //
00152 uint16_t Controller::SelectMode(ModeType mode)
00153 {
00154         // select mode
00155         Protocol::Packet packet;
00156         packet.socket = 0;
00157         packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
00158         packet.command = SB_COMMAND_SELECT_MODE;
00159         packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
00160         packet.u.socket.sequence = 0; // updated by Socket::Send()
00161         memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
00162 
00163         char *modeName = (char *) packet.u.socket.u.mode.name;
00164         switch( mode )
00165         {
00166         case Bypass:
00167                 strcpy(modeName, "RIM Bypass");
00168                 break;
00169 
00170         case Desktop:
00171                 strcpy(modeName, "RIM Desktop");
00172                 break;
00173 
00174         case JavaLoader:
00175                 strcpy(modeName, "RIM_JavaLoader");
00176                 break;
00177 
00178         case UsbSerData:
00179                 strcpy(modeName, "RIM_UsbSerData");
00180                 break;
00181 
00182         case UsbSerCtrl:
00183                 strcpy(modeName, "RIM_UsbSerCtrl");
00184                 break;
00185 
00186         default:
00187                 throw std::logic_error("Controller: Invalid mode in SelectMode");
00188                 break;
00189         }
00190 
00191         // send mode command before we open, as a default socket is socket 0
00192         Data command(&packet, btohs(packet.size));
00193         Data response;
00194 
00195         try {
00196                 m_zero.Send(command, response);
00197 
00198                 // get the data socket number
00199                 // indicates the socket number that
00200                 // should be used below in the Open() call
00201                 Protocol::CheckSize(response, SB_MODE_PACKET_RESPONSE_SIZE);
00202                 MAKE_PACKET(modepack, response);
00203                 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
00204                         eeout(command, response);
00205                         throw Error("Controller: mode not selected");
00206                 }
00207 
00208                 // return the socket that the device is expecting us to use
00209                 return btohs(modepack->u.socket.socket);
00210         }
00211         catch( Usb::Error & ) {
00212                 eout("Controller: error setting desktop mode");
00213                 eeout(command, response);
00214                 throw;
00215         }
00216 }
00217 
00218 
00219 ///////////////////////////////////////////////////////////////////////////////
00220 // public API
00221 
00222 
00223 } // namespace Barry
00224 

Generated on Mon Jan 12 10:51:12 2009 for Barry by  doxygen 1.5.7.1