2 /// \file controller.cc
3 /// High level Barry API class
7 Copyright (C) 2005-2010, 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"
26 #include "protostructs.h"
31 #define __DEBUG_MODE__
37 // Controller constructor
39 /// Constructor for the Controller class. Requires a valid ProbeResult
40 /// object to find the USB device to talk to.
42 /// \param[in] device One of the ProbeResult objects from the
44 /// \param[in] default_timeout Override Usb::Device's default timeout
46 Controller::Controller(const ProbeResult
&device
,
49 , m_dev(device
.m_dev
, default_timeout
)
52 , m_zero(m_dev
, device
.m_ep
.write
, device
.m_ep
.read
, device
.m_zeroSocketSequence
)
55 dout("Controller: Using non-threaded sockets");
60 // Controller constructor
62 /// Constructor for the Controller class. Requires a valid ProbeResult
63 /// object to find the USB device to talk to.
65 /// \param[in] device One of the ProbeResult objects from the
67 /// \param[in] queue Plugin router object for reading data
69 /// \param[in] default_timeout Override Usb::Device's default timeout
71 Controller::Controller(const ProbeResult
&device
,
72 SocketRoutingQueue
&queue
,
75 , m_dev(device
.m_dev
, default_timeout
)
78 , m_zero(queue
, device
.m_ep
.write
, device
.m_zeroSocketSequence
)
81 dout("Controller: Using threaded socket router");
85 // set the queue to use our device
86 queue
.SetUsbDevice(&m_dev
, device
.m_ep
.write
, device
.m_ep
.read
);
89 void Controller::SetupUsb(const ProbeResult
&device
)
92 if( !m_dev
.GetConfiguration(cfg
) )
93 throw Usb::Error(m_dev
.GetLastError(),
94 "Controller: GetConfiguration failed");
96 if( cfg
!= BLACKBERRY_CONFIGURATION
) {
97 if( !m_dev
.SetConfiguration(BLACKBERRY_CONFIGURATION
) )
98 throw Usb::Error(m_dev
.GetLastError(),
99 "Controller: SetConfiguration failed");
102 m_iface
= new Usb::Interface(m_dev
, device
.m_interface
);
104 if( device
.m_needClearHalt
) {
105 m_dev
.ClearHalt(device
.m_ep
.read
);
106 m_dev
.ClearHalt(device
.m_ep
.write
);
110 Controller::~Controller()
112 // // trap exceptions in the destructor
114 // // a non-default socket has been opened, close it
117 // catch( std::runtime_error &re ) {
118 // // do nothing... log it?
119 // dout("Exception caught in ~Socket: " << re.what());
122 // detach the router from our device
124 m_queue
->ClearUsbDevice();
128 // cleanup the interface
131 // this happens when for some reason the Desktop mode
132 // is not fully opened, but the device has already recommended
133 // a socket to open... in this case, reset the device
134 // in the hopes that on next open, it will be in a
135 // recognizable state.
137 // FIXME - this should not be necessary, and someday we
138 // we should figure out how to handle the "already open"
139 // response we get for the Desktop
141 // FIXME - halfOpen now seems to be handled in the Socket class...
142 // perhaps move this there if needed
146 dout("Controller object destroyed in halfopen state, resetting device");
152 ///////////////////////////////////////////////////////////////////////////////
156 // Tells device which mode is desired, and returns the suggested
157 // socket ID to use for that mode.
159 uint16_t Controller::SelectMode(ModeType mode
)
161 return SelectMode(mode
, NULL
);
164 // Tells device which mode is desired, and returns the suggested
165 // socket ID to use for that mode.
167 // If explicitModeName is not NULL then it will be used as the mode name.
168 // Otherwise the default mode name for the given mode will be used.
169 // It should be a nul terminated string if it is provided.
171 // The RawChannel mode requires an explicitModeName to be specified.
173 uint16_t Controller::SelectMode(ModeType mode
, const char *explicitModeName
)
176 Protocol::Packet packet
;
178 packet
.size
= htobs(SB_MODE_PACKET_COMMAND_SIZE
);
179 packet
.command
= SB_COMMAND_SELECT_MODE
;
180 packet
.u
.socket
.socket
= htobs(SB_MODE_REQUEST_SOCKET
);
181 packet
.u
.socket
.sequence
= 0; // updated by Socket::Send()
182 memset(packet
.u
.socket
.u
.mode
.name
, 0, sizeof(packet
.u
.socket
.u
.mode
.name
));
184 char *modeName
= (char *) packet
.u
.socket
.u
.mode
.name
;
186 if( explicitModeName
) {
187 if( strlen(explicitModeName
) >= sizeof(packet
.u
.socket
.u
.mode
.name
) ) {
188 throw std::logic_error("Controller: explicit mode name too long");
190 strcpy(modeName
, explicitModeName
);
193 // No modeName given, use the default
197 strcpy(modeName
, "RIM Bypass");
201 strcpy(modeName
, "RIM Desktop");
205 strcpy(modeName
, "RIM_JavaLoader");
209 strcpy(modeName
, "RIM_JVMDebug");
213 strcpy(modeName
, "RIM_UsbSerData");
217 strcpy(modeName
, "RIM_UsbSerCtrl");
221 throw std::logic_error("Controller: No channel name given with RawChannel mode");
225 throw std::logic_error("Controller: Invalid mode in SelectMode");
230 // send mode command before we open, as a default socket is socket 0
231 Data
command(&packet
, btohs(packet
.size
));
235 m_zero
.Send(command
, response
);
237 // get the data socket number
238 // indicates the socket number that
239 // should be used below in the Open() call
240 MAKE_PACKET(modepack
, response
);
241 if( modepack
->command
== SB_COMMAND_MODE_NOT_SELECTED
) {
242 throw Error("Controller: requested mode not supported");
244 if( modepack
->command
!= SB_COMMAND_MODE_SELECTED
) {
245 eeout(command
, response
);
246 throw Error("Controller: mode not selected");
249 if( mode
== Desktop
) {
250 // On the BlackBerry Storm, I have to read a packet
251 // after opening a socket. (only for Desktop mode)
252 // Otherwise, barrybackup and opensync-plugin can crash (timeout)
253 // I don't know why ! Maybe a bug on the handheld.
254 m_zero
.HideSequencePacket(false);
255 m_zero
.Receive(response
);
256 m_zero
.HideSequencePacket(true);
258 // return the socket that the device is expecting us to use
259 return btohs(modepack
->u
.socket
.socket
);
261 catch( Usb::Error
& ) {
262 eout("Controller: error setting desktop mode");
263 eeout(command
, response
);
269 ///////////////////////////////////////////////////////////////////////////////