lib: fixed timeout mismatch behaviour between USB and Router
[barry.git] / src / m_serial.cc
blobfb18d3794f177d1f6fff81edeba44219eefff44c
1 ///
2 /// \file m_serial.cc
3 /// Mode class for serial / GPRS modem mode
4 ///
6 /*
7 Copyright (C) 2008-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 "m_serial.h"
23 #include "controller.h"
24 #include "protostructs.h"
25 #include "endian.h"
26 #include "debug.h"
27 #include <stdexcept>
29 namespace Barry { namespace Mode {
31 //////////////////////////////////////////////////////////////////////////////
32 // Mode::Serial class
34 Serial::Serial( Controller &con,
35 DeviceDataCallback callback,
36 void *callback_context)
37 : m_con(con)
38 , m_ModeSocket(0)
39 , m_CtrlSocket(0)
40 , m_callback(callback)
41 , m_callback_context(callback_context)
43 if( !m_con.HasQueue() )
44 throw std::logic_error("A SocketRoutingQueue is required in the Controller class when using Mode::Serial.");
47 Serial::~Serial()
52 //////////////////////////////////////////////////////////////////////////////
53 // protected API / static functions
55 void Serial::DataCallback(Serial &ser, Data *data)
57 ddout("Serial::DataCallback called");
59 if( data->GetSize() <= 4 )
60 return; // nothing to do
62 // call callback if available
63 if( ser.m_callback ) {
64 (*ser.m_callback)(ser.m_callback_context,
65 data->GetData() + 4,
66 data->GetSize() - 4);
68 // else {
69 // // append data to readCache
70 // FIXME;
71 // }
74 void Serial::CtrlCallback(Serial &ser, Data *data)
76 // just dump to stdout, and do nothing
77 ddout("CtrlCallback received:\n" << *data);
80 //////////////////////////////////////////////////////////////////////////////
81 // public API
83 void Serial::Open(const char *password)
85 if( m_ModeSocket ) {
86 m_data->Close();
87 m_data.reset();
88 m_ModeSocket = 0;
91 if( m_CtrlSocket ) {
92 m_ctrl->Close();
93 m_ctrl.reset();
94 m_CtrlSocket = 0;
97 m_ModeSocket = m_con.SelectMode(Controller::UsbSerData);
98 m_data = m_con.m_zero.Open(m_ModeSocket, password);
100 m_CtrlSocket = m_con.SelectMode(Controller::UsbSerCtrl);
101 m_ctrl = m_con.m_zero.Open(m_CtrlSocket, password);
103 // register callback for incoming data, for speed
104 SocketRoutingQueue::SocketDataHandlerPtr data_callback
105 (new SocketRoutingQueue::SimpleSocketDataHandler<Serial>(*this, DataCallback));
106 m_data->RegisterInterest(data_callback);
107 SocketRoutingQueue::SocketDataHandlerPtr ctrl_callback
108 (new SocketRoutingQueue::SimpleSocketDataHandler<Serial>(*this, CtrlCallback));
109 m_ctrl->RegisterInterest(ctrl_callback);
111 const unsigned char start[] =
112 { 0, 0, 0x0a, 0, 0x01, 0x01, 0xc2, 0x00, 0x40, 0x00 };
113 Data block(start, sizeof(start));
114 m_ctrl->Send(block);
117 void Serial::Close()
119 ddout("Serial:: Closing connection.");
123 // FIXME - if this behaviour is truly common between modes, create
124 // a common base class for this.
125 void Serial::RetryPassword(const char *password)
127 if( m_data.get() || m_ctrl.get() )
128 throw std::logic_error("Socket already open in Serial::RetryPassword");
130 m_data = m_con.m_zero.OpenDBSocket(m_ModeSocket, password);
131 m_ctrl = m_con.m_zero.OpenDBSocket(m_CtrlSocket, password);
133 // register callback for incoming data, for speed
134 m_data->RegisterInterest(DataCallback, this);
139 // can be called from separate thread
140 void Serial::SerialRead(Data &data, int timeout)
142 m_socket.Receive(data, timeout);
146 void Serial::Write(const Data &data, int timeout)
148 if( data.GetSize() <= 0 )
149 return; // nothing to do
151 if( !m_data.get() )
152 throw std::logic_error("Must call Open() before Write() in Mode::Serial");
154 // filter data for PPP, and prepend 4 bytes
155 Data &filtered = m_filter.Write(data, 4);
157 // setup header (only size needed, as socket will be set by socket class)
158 unsigned char *buf = filtered.GetBuffer();
159 MAKE_PACKETPTR_BUF(spack, buf);
160 spack->size = htobs(filtered.GetSize());
162 // send via appropriate socket
163 m_data->Send(filtered, timeout);
166 }} // namespace Barry::Mode