Updated Debian binary package: manpages, ppp, warnings
[barry/pauldeden.git] / src / controller.cc
blob3cc98e54066fede14440e4d6c62d154a4adc35c3
1 ///
2 /// \file controller.cc
3 /// High level Barry API class
4 ///
6 /*
7 Copyright (C) 2005-2008, 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 "probe.h"
24 #include "common.h"
25 #include "protocol.h"
26 #include "protostructs.h"
27 #include "data.h"
28 #include "endian.h"
29 #include <string.h>
31 #define __DEBUG_MODE__
32 #include "debug.h"
34 namespace Barry {
37 // Controller constructor
39 /// Constructor for the Controller class. Requires a valid ProbeResult
40 /// object to find the USB device to talk to.
41 ///
42 /// \param[in] device One of the ProbeResult objects from the
43 /// Probe class.
44 ///
45 Controller::Controller(const ProbeResult &device)
46 : m_result(device)
47 , m_dev(device.m_dev)
48 , m_iface(0)
49 , m_pin(device.m_pin)
50 , m_zero(m_dev, device.m_ep.write, device.m_ep.read, device.m_zeroSocketSequence)
51 , m_queue(0)
53 dout("Controller: Using non-threaded sockets");
54 SetupUsb(device);
58 // Controller constructor
60 /// Constructor for the Controller class. Requires a valid ProbeResult
61 /// object to find the USB device to talk to.
62 ///
63 /// \param[in] device One of the ProbeResult objects from the
64 /// Probe class.
65 /// \param[in] queue Plugin router object for reading data
66 /// from sockets.
67 ///
68 Controller::Controller(const ProbeResult &device, SocketRoutingQueue &queue)
69 : m_result(device)
70 , m_dev(device.m_dev)
71 , m_iface(0)
72 , m_pin(device.m_pin)
73 , m_zero(queue, device.m_ep.write, device.m_zeroSocketSequence)
74 , m_queue(&queue)
76 dout("Controller: Using threaded socket router");
78 SetupUsb(device);
80 // set the queue to use our device
81 queue.SetUsbDevice(&m_dev, device.m_ep.write, device.m_ep.read);
84 void Controller::SetupUsb(const ProbeResult &device)
86 unsigned char cfg;
87 if( !m_dev.GetConfiguration(cfg) )
88 throw Usb::Error(m_dev.GetLastError(),
89 "Controller: GetConfiguration failed");
91 if( cfg != BLACKBERRY_CONFIGURATION ) {
92 if( !m_dev.SetConfiguration(BLACKBERRY_CONFIGURATION) )
93 throw Usb::Error(m_dev.GetLastError(),
94 "Controller: SetConfiguration failed");
97 m_iface = new Usb::Interface(m_dev, device.m_interface);
99 m_dev.ClearHalt(device.m_ep.read);
100 m_dev.ClearHalt(device.m_ep.write);
103 Controller::~Controller()
105 // // trap exceptions in the destructor
106 // try {
107 // // a non-default socket has been opened, close it
108 // m_socket.Close();
109 // }
110 // catch( std::runtime_error &re ) {
111 // // do nothing... log it?
112 // dout("Exception caught in ~Socket: " << re.what());
113 // }
115 // detach the router from our device
116 if( m_queue ) {
117 m_queue->ClearUsbDevice();
118 m_queue = 0;
121 // cleanup the interface
122 delete m_iface;
124 // this happens when for some reason the Desktop mode
125 // is not fully opened, but the device has already recommended
126 // a socket to open... in this case, reset the device
127 // in the hopes that on next open, it will be in a
128 // recognizable state.
130 // FIXME - this should not be necessary, and someday we
131 // we should figure out how to handle the "already open"
132 // response we get for the Desktop
134 // FIXME - halfOpen now seems to be handled in the Socket class...
135 // perhaps move this there if needed
138 if( m_halfOpen ) {
139 dout("Controller object destroyed in halfopen state, resetting device");
140 m_dev.Reset();
145 ///////////////////////////////////////////////////////////////////////////////
146 // protected members
149 // Tells device which mode is desired, and returns the suggested
150 // socket ID to use for that mode.
152 uint16_t Controller::SelectMode(ModeType mode)
154 // select mode
155 Protocol::Packet packet;
156 packet.socket = 0;
157 packet.size = htobs(SB_MODE_PACKET_COMMAND_SIZE);
158 packet.command = SB_COMMAND_SELECT_MODE;
159 packet.u.socket.socket = htobs(SB_MODE_REQUEST_SOCKET);
160 packet.u.socket.sequence = 0; // updated by Socket::Send()
161 memset(packet.u.socket.u.mode.name, 0, sizeof(packet.u.socket.u.mode.name));
163 char *modeName = (char *) packet.u.socket.u.mode.name;
164 switch( mode )
166 case Bypass:
167 strcpy(modeName, "RIM Bypass");
168 break;
170 case Desktop:
171 strcpy(modeName, "RIM Desktop");
172 break;
174 case JavaLoader:
175 strcpy(modeName, "RIM_JavaLoader");
176 break;
178 case UsbSerData:
179 strcpy(modeName, "RIM_UsbSerData");
180 break;
182 case UsbSerCtrl:
183 strcpy(modeName, "RIM_UsbSerCtrl");
184 break;
186 default:
187 throw std::logic_error("Controller: Invalid mode in SelectMode");
188 break;
191 // send mode command before we open, as a default socket is socket 0
192 Data command(&packet, btohs(packet.size));
193 Data response;
195 try {
196 m_zero.Send(command, response);
198 // get the data socket number
199 // indicates the socket number that
200 // should be used below in the Open() call
201 Protocol::CheckSize(response, SB_MODE_PACKET_RESPONSE_SIZE);
202 MAKE_PACKET(modepack, response);
203 if( modepack->command != SB_COMMAND_MODE_SELECTED ) {
204 eeout(command, response);
205 throw Error("Controller: mode not selected");
208 // return the socket that the device is expecting us to use
209 return btohs(modepack->u.socket.socket);
211 catch( Usb::Error & ) {
212 eout("Controller: error setting desktop mode");
213 eeout(command, response);
214 throw;
219 ///////////////////////////////////////////////////////////////////////////////
220 // public API
223 } // namespace Barry