2 /// \file controller.cc
3 /// High level Barry API class
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.
23 #include "controller.h"
24 #include "controllerpriv.h"
27 #include "protostructs.h"
33 #define __DEBUG_MODE__
39 // Controller constructor
41 /// Constructor for the Controller class. Requires a valid ProbeResult
42 /// object to find the USB device to talk to.
44 /// \param[in] device One of the ProbeResult objects from the
46 /// \param[in] default_timeout Override Usb::Device's default timeout
48 Controller::Controller(const ProbeResult
&device
,
50 : m_priv(new PrivateControllerData(device
, default_timeout
))
52 dout(_("Controller: Using non-threaded sockets"));
57 // Controller constructor
59 /// Constructor for the Controller class. Requires a valid ProbeResult
60 /// object to find the USB device to talk to.
62 /// \param[in] device One of the ProbeResult objects from the
64 /// \param[in] queue Plugin router object for reading data
66 /// \param[in] default_timeout Override Usb::Device's default timeout
68 Controller::Controller(const ProbeResult
&device
,
69 SocketRoutingQueue
&queue
,
71 : m_priv(new PrivateControllerData(device
, queue
, default_timeout
))
73 dout(_("Controller: Using threaded socket router"));
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
)
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 ///////////////////////////////////////////////////////////////////////////////
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
)
134 Protocol::Packet packet
;
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
);
151 // No modeName given, use the default
155 strcpy(modeName
, "RIM Bypass");
159 strcpy(modeName
, "RIM Desktop");
163 strcpy(modeName
, "RIM_JavaLoader");
167 strcpy(modeName
, "RIM_JVMDebug");
171 strcpy(modeName
, "RIM_UsbSerData");
175 strcpy(modeName
, "RIM_UsbSerCtrl");
179 throw std::logic_error(_("Controller: No channel name given with RawChannel mode"));
183 throw std::logic_error(_("Controller: Invalid mode in SelectMode"));
188 // send mode command before we open, as a default socket is socket 0
189 Data
command(&packet
, btohs(packet
.size
));
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
);
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 ///////////////////////////////////////////////////////////////////////////////
232 bool Controller::HasQueue() const
234 return m_priv
->m_queue
!= NULL
;
237 SocketRoutingQueue
* Controller::GetQueue()
239 return m_priv
->m_queue
;
242 const ProbeResult
& Controller::GetProbeResult() const
244 return m_priv
->m_result
;