lib: Fixing checking for incorrect return value in while loop.
[barry.git] / src / controller.cc
blob7f3cc4a55d893ddc41d62f31019dc754150530ae
1 ///
2 /// \file controller.cc
3 /// High level Barry API class
4 ///
6 /*
7 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "controller.h"
23 #include "controllerpriv.h"
24 #include "common.h"
25 #include "protocol.h"
26 #include "protostructs.h"
27 #include "data.h"
28 #include "endian.h"
29 #include "platform.h"
30 #include <string.h>
32 #define __DEBUG_MODE__
33 #include "debug.h"
35 namespace Barry {
38 // Controller constructor
40 /// Constructor for the Controller class. Requires a valid ProbeResult
41 /// object to find the USB device to talk to.
42 ///
43 /// \param[in] device One of the ProbeResult objects from the
44 /// Probe class.
45 /// \param[in] default_timeout Override Usb::Device's default timeout
46 ///
47 Controller::Controller(const ProbeResult &device,
48 int default_timeout)
49 : m_priv(new PrivateControllerData(device, default_timeout))
51 dout("Controller: Using non-threaded sockets");
52 SetupUsb(device);
56 // Controller constructor
58 /// Constructor for the Controller class. Requires a valid ProbeResult
59 /// object to find the USB device to talk to.
60 ///
61 /// \param[in] device One of the ProbeResult objects from the
62 /// Probe class.
63 /// \param[in] queue Plugin router object for reading data
64 /// from sockets.
65 /// \param[in] default_timeout Override Usb::Device's default timeout
66 ///
67 Controller::Controller(const ProbeResult &device,
68 SocketRoutingQueue &queue,
69 int default_timeout)
70 : m_priv(new PrivateControllerData(device, queue, default_timeout))
72 dout("Controller: Using threaded socket router");
74 SetupUsb(device);
76 // set the queue to use our device
77 queue.SetUsbDevice(&m_priv->m_dev, device.m_ep.write, device.m_ep.read);
80 void Controller::SetupUsb(const ProbeResult &device)
82 unsigned char cfg;
83 if( !m_priv->m_dev.GetConfiguration(cfg) )
84 throw Usb::Error(m_priv->m_dev.GetLastError(),
85 "Controller: GetConfiguration failed");
87 if( cfg != BLACKBERRY_CONFIGURATION || MUST_SET_CONFIGURATION ) {
88 if( !m_priv->m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
89 throw Usb::Error(m_priv->m_dev.GetLastError(),
90 "Controller: SetConfiguration failed");
93 m_priv->m_iface = new Usb::Interface(m_priv->m_dev, device.m_interface);
95 if( device.m_needSetAltInterface ) {
96 m_priv->m_iface->SetAltInterface(device.m_altsetting);
99 if( device.m_needClearHalt ) {
100 m_priv->m_dev.ClearHalt(device.m_ep.read);
101 m_priv->m_dev.ClearHalt(device.m_ep.write);
105 Controller::~Controller()
109 ///////////////////////////////////////////////////////////////////////////////
110 // protected members
113 // Tells device which mode is desired, and returns the suggested
114 // socket ID to use for that mode.
116 uint16_t Controller::SelectMode(ModeType mode)
118 return SelectMode(mode, NULL);
121 // Tells device which mode is desired, and returns the suggested
122 // socket ID to use for that mode.
124 // If explicitModeName is not NULL then it will be used as the mode name.
125 // Otherwise the default mode name for the given mode will be used.
126 // It should be a nul terminated string if it is provided.
128 // The RawChannel mode requires an explicitModeName to be specified.
130 uint16_t Controller::SelectMode(ModeType mode, const char *explicitModeName)
132 // select mode
133 Protocol::Packet packet;
134 packet.socket = 0;
135 packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
136 packet.command = SB_COMMAND_SELECT_MODE;
137 packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
138 packet.u.socket.sequence = 0; // updated by Socket::Send()
139 memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
141 char *modeName = (char *) packet.u.socket.u.mode.name;
143 if( explicitModeName ) {
144 if( strlen(explicitModeName) >= sizeof(packet.u.socket.u.mode.name) ) {
145 throw std::logic_error("Controller: explicit mode name too long");
147 strcpy(modeName, explicitModeName);
149 else {
150 // No modeName given, use the default
151 switch( mode )
153 case Bypass:
154 strcpy(modeName, "RIM Bypass");
155 break;
157 case Desktop:
158 strcpy(modeName, "RIM Desktop");
159 break;
161 case JavaLoader:
162 strcpy(modeName, "RIM_JavaLoader");
163 break;
165 case JVMDebug:
166 strcpy(modeName, "RIM_JVMDebug");
167 break;
169 case UsbSerData:
170 strcpy(modeName, "RIM_UsbSerData");
171 break;
173 case UsbSerCtrl:
174 strcpy(modeName, "RIM_UsbSerCtrl");
175 break;
177 case RawChannel:
178 throw std::logic_error("Controller: No channel name given with RawChannel mode");
179 break;
181 default:
182 throw std::logic_error("Controller: Invalid mode in SelectMode");
183 break;
187 // send mode command before we open, as a default socket is socket 0
188 Data command(&packet, btohs(packet.size));
189 Data response;
191 try {
192 m_priv->m_zero.Send(command, response);
194 // get the data socket number
195 // indicates the socket number that
196 // should be used below in the Open() call
197 MAKE_PACKET(modepack, response);
198 if( modepack->command == SB_COMMAND_MODE_NOT_SELECTED ) {
199 throw Error("Controller: requested mode not supported");
201 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
202 eeout(command, response);
203 throw Error("Controller: mode not selected");
206 // return the socket that the device is expecting us to use
207 return btohs(modepack->u.socket.socket);
209 catch( Usb::Error & ) {
210 eout("Controller: error setting desktop mode");
211 eeout(command, response);
212 throw;
217 // OpenSocket
219 /// Can be called multiple times, in case of password retries.
220 /// See also Mode::RetryPassword()
222 SocketHandle Controller::OpenSocket(uint16_t socket, const char *password)
224 return m_priv->m_zero.Open(socket, password);
228 ///////////////////////////////////////////////////////////////////////////////
229 // public API
231 bool Controller::HasQueue() const
233 return m_priv->m_queue;
236 SocketRoutingQueue* Controller::GetQueue()
238 return m_priv->m_queue;
241 const ProbeResult& Controller::GetProbeResult() const
243 return m_priv->m_result;
246 } // namespace Barry