Added ppp/README
[barry/pauldeden.git] / src / m_serial.cc
bloba9f71096f11357016a3ac077eae638bae85acb3e
1 ///
2 /// \file m_serial.cc
3 /// Mode class for serial / GPRS modem mode
4 ///
6 #include "m_serial.h"
7 #include "controller.h"
8 #include "protostructs.h"
9 #include "endian.h"
10 #include "debug.h"
11 #include <stdexcept>
13 namespace Barry { namespace Mode {
15 //////////////////////////////////////////////////////////////////////////////
16 // Mode::Serial class
18 Serial::Serial( Controller &con,
19 DeviceDataCallback callback,
20 void *callback_context)
21 : m_con(con)
22 , m_ModeSocket(0)
23 , m_CtrlSocket(0)
24 , m_callback(callback)
25 , m_callback_context(callback_context)
27 if( !m_con.HasQueue() )
28 throw std::logic_error("A SocketRoutingQueue is required in the Controller class when using Mode::Serial.");
31 Serial::~Serial()
36 //////////////////////////////////////////////////////////////////////////////
37 // protected API / static functions
39 void Serial::DataCallback(void *context, Data *data)
41 ddout("Serial::DataCallback called");
43 Serial *ser = (Serial*) context;
45 if( data->GetSize() <= 4 )
46 return; // nothing to do
48 // call callback if available
49 if( ser->m_callback ) {
50 (*ser->m_callback)(ser->m_callback_context,
51 data->GetData() + 4,
52 data->GetSize() - 4);
54 // else {
55 // // append data to readCache
56 // FIXME;
57 // }
60 void Serial::CtrlCallback(void *context, Data *data)
62 // Serial *ser = (Serial*) context;
64 // just dump to stdout, and do nothing
65 ddout("CtrlCallback received:\n" << *data);
68 //////////////////////////////////////////////////////////////////////////////
69 // public API
71 void Serial::Open(const char *password)
73 if( m_ModeSocket ) {
74 m_data->Close();
75 m_data.reset();
76 m_ModeSocket = 0;
79 if( m_CtrlSocket ) {
80 m_ctrl->Close();
81 m_ctrl.reset();
82 m_CtrlSocket = 0;
85 m_ModeSocket = m_con.SelectMode(Controller::UsbSerData);
86 m_data = m_con.m_zero.Open(m_ModeSocket, password);
88 m_CtrlSocket = m_con.SelectMode(Controller::UsbSerCtrl);
89 m_ctrl = m_con.m_zero.Open(m_CtrlSocket, password);
91 // register callback for incoming data, for speed
92 m_data->RegisterInterest(DataCallback, this);
93 m_ctrl->RegisterInterest(CtrlCallback, this);
95 const unsigned char start[] =
96 { 0, 0, 0x0a, 0, 0x01, 0x01, 0xc2, 0x00, 0x40, 0x00 };
97 Data block(start, sizeof(start));
98 m_ctrl->Send(block);
102 // FIXME - if this behaviour is truly common between modes, create
103 // a common base class for this.
104 void Serial::RetryPassword(const char *password)
106 if( m_data.get() || m_ctrl.get() )
107 throw std::logic_error("Socket already open in Serial::RetryPassword");
109 m_data = m_con.m_zero.OpenDBSocket(m_ModeSocket, password);
110 m_ctrl = m_con.m_zero.OpenDBSocket(m_CtrlSocket, password);
112 // register callback for incoming data, for speed
113 m_data->RegisterInterest(DataCallback, this);
118 // can be called from separate thread
119 void Serial::SerialRead(Data &data, int timeout)
121 m_socket.Receive(data, timeout);
125 void Serial::Write(const Data &data, int timeout)
127 if( data.GetSize() <= 0 )
128 return; // nothing to do
130 if( !m_data.get() )
131 throw std::logic_error("Must call Open() before Write() in Mode::Serial");
133 // filter data for PPP, and prepend 4 bytes
134 Data &filtered = m_filter.Write(data, 4);
136 // setup header (only size needed, as socket will be set by socket class)
137 unsigned char *buf = filtered.GetBuffer();
138 MAKE_PACKETPTR_BUF(spack, buf);
139 spack->size = htobs(filtered.GetSize());
141 // send via appropriate socket
142 m_data->Send(filtered, timeout);
145 }} // namespace Barry::Mode