menu: added new Keywords tag to .desktop files
[barry.git] / src / controller.cc
blob9e5e2f131ce40bba335ab81491ef25204f27726e
1 ///
2 /// \file controller.cc
3 /// High level Barry API class
4 ///
6 /*
7 Copyright (C) 2005-2013, 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 "i18n.h"
23 #include "controller.h"
24 #include "controllerpriv.h"
25 #include "common.h"
26 #include "protocol.h"
27 #include "protostructs.h"
28 #include "data.h"
29 #include "endian.h"
30 #include "platform.h"
31 #include <string.h>
33 #define __DEBUG_MODE__
34 #include "debug.h"
36 namespace Barry {
39 // Controller constructor
41 /// Constructor for the Controller class. Requires a valid ProbeResult
42 /// object to find the USB device to talk to.
43 ///
44 /// \param[in] device One of the ProbeResult objects from the
45 /// Probe class.
46 /// \param[in] default_timeout Override Usb::Device's default timeout
47 ///
48 Controller::Controller(const ProbeResult &device,
49 int default_timeout)
50 : m_priv(new PrivateControllerData(device, default_timeout))
52 dout(_("Controller: Using non-threaded sockets"));
53 SetupUsb(device);
57 // Controller constructor
59 /// Constructor for the Controller class. Requires a valid ProbeResult
60 /// object to find the USB device to talk to.
61 ///
62 /// \param[in] device One of the ProbeResult objects from the
63 /// Probe class.
64 /// \param[in] queue Plugin router object for reading data
65 /// from sockets.
66 /// \param[in] default_timeout Override Usb::Device's default timeout
67 ///
68 Controller::Controller(const ProbeResult &device,
69 SocketRoutingQueue &queue,
70 int default_timeout)
71 : m_priv(new PrivateControllerData(device, queue, default_timeout))
73 dout(_("Controller: Using threaded socket router"));
75 SetupUsb(device);
77 // set the queue to use our device
78 queue.SetUsbDevice(&m_priv->m_dev, device.m_ep.write, device.m_ep.read);
81 void Controller::SetupUsb(const ProbeResult &device)
83 unsigned char cfg;
84 if( !m_priv->m_dev.GetConfiguration(cfg) )
85 throw Usb::Error(m_priv->m_dev.GetLastError(),
86 _("Controller: GetConfiguration failed"));
88 if( cfg != BLACKBERRY_CONFIGURATION || MUST_SET_CONFIGURATION ) {
89 if( !m_priv->m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
90 throw Usb::Error(m_priv->m_dev.GetLastError(),
91 _("Controller: SetConfiguration failed"));
94 m_priv->m_iface = new Usb::Interface(m_priv->m_dev, device.m_interface);
96 if( device.m_needSetAltInterface ) {
97 m_priv->m_iface->SetAltInterface(device.m_altsetting);
100 if( device.m_needClearHalt ) {
101 m_priv->m_dev.ClearHalt(device.m_ep.read);
102 m_priv->m_dev.ClearHalt(device.m_ep.write);
106 Controller::~Controller()
110 ///////////////////////////////////////////////////////////////////////////////
111 // protected members
114 // Tells device which mode is desired, and returns the suggested
115 // socket ID to use for that mode.
117 uint16_t Controller::SelectMode(ModeType mode)
119 return SelectMode(mode, NULL);
122 // Tells device which mode is desired, and returns the suggested
123 // socket ID to use for that mode.
125 // If explicitModeName is not NULL then it will be used as the mode name.
126 // Otherwise the default mode name for the given mode will be used.
127 // It should be a nul terminated string if it is provided.
129 // The RawChannel mode requires an explicitModeName to be specified.
131 uint16_t Controller::SelectMode(ModeType mode, const char *explicitModeName)
133 // select mode
134 Protocol::Packet packet;
135 packet.socket = 0;
136 packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
137 packet.command = SB_COMMAND_SELECT_MODE;
138 packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
139 packet.u.socket.sequence = 0; // updated by Socket::Send()
140 memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
142 char *modeName = (char *) packet.u.socket.u.mode.name;
144 if( explicitModeName ) {
145 if( strlen(explicitModeName) >= sizeof(packet.u.socket.u.mode.name) ) {
146 throw std::logic_error(_("Controller: explicit mode name too long"));
148 strcpy(modeName, explicitModeName);
150 else {
151 // No modeName given, use the default
152 switch( mode )
154 case Bypass:
155 strcpy(modeName, "RIM Bypass");
156 break;
158 case Desktop:
159 strcpy(modeName, "RIM Desktop");
160 break;
162 case JavaLoader:
163 strcpy(modeName, "RIM_JavaLoader");
164 break;
166 case JVMDebug:
167 strcpy(modeName, "RIM_JVMDebug");
168 break;
170 case UsbSerData:
171 strcpy(modeName, "RIM_UsbSerData");
172 break;
174 case UsbSerCtrl:
175 strcpy(modeName, "RIM_UsbSerCtrl");
176 break;
178 case RawChannel:
179 throw std::logic_error(_("Controller: No channel name given with RawChannel mode"));
180 break;
182 default:
183 throw std::logic_error(_("Controller: Invalid mode in SelectMode"));
184 break;
188 // send mode command before we open, as a default socket is socket 0
189 Data command(&packet, btohs(packet.size));
190 Data response;
192 try {
193 m_priv->m_zero.Send(command, response);
195 // get the data socket number
196 // indicates the socket number that
197 // should be used below in the Open() call
198 MAKE_PACKET(modepack, response);
199 if( modepack->command == SB_COMMAND_MODE_NOT_SELECTED ) {
200 throw Error(_("Controller: requested mode not supported"));
202 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
203 eeout(command, response);
204 throw Error(_("Controller: mode not selected"));
207 // return the socket that the device is expecting us to use
208 return btohs(modepack->u.socket.socket);
210 catch( Usb::Error & ) {
211 eout(_("Controller: error setting desktop mode"));
212 eeout(command, response);
213 throw;
218 // OpenSocket
220 /// Can be called multiple times, in case of password retries.
221 /// See also Mode::RetryPassword()
223 SocketHandle Controller::OpenSocket(uint16_t socket, const char *password)
225 return m_priv->m_zero.Open(socket, password);
229 // OpenSocket
231 /// Sets a data handler from the start of the socket being opened.
232 /// This avoids a race condition where data packets can be lost
233 /// from the device if they are received before the mode which owns
234 /// this socket calls Socket::RegisterInterest().
236 /// Can be called multiple times, in case of password retries.
237 /// See also Mode::RetryPassword()
239 SocketHandle Controller::OpenSocket(
240 SocketRoutingQueue::SocketDataHandlerPtr handler,
241 uint16_t socket, const char *password)
243 return m_priv->m_zero.Open(handler, socket, password);
247 ///////////////////////////////////////////////////////////////////////////////
248 // public API
250 bool Controller::HasQueue() const
252 return m_priv->m_queue != NULL;
255 SocketRoutingQueue* Controller::GetQueue()
257 return m_priv->m_queue;
260 const ProbeResult& Controller::GetProbeResult() const
262 return m_priv->m_result;
265 } // namespace Barry