m_serial.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       m_serial.cc
00003 ///             Mode class for serial / GPRS modem mode
00004 ///
00005 
00006 /*
00007     Copyright (C) 2008-2012, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "m_serial.h"
00023 #include "controller.h"
00024 #include "protostructs.h"
00025 #include "endian.h"
00026 #include "debug.h"
00027 #include <stdexcept>
00028 
00029 namespace Barry { namespace Mode {
00030 
00031 //////////////////////////////////////////////////////////////////////////////
00032 // Mode::Serial class
00033 
00034 Serial::Serial( Controller &con,
00035                 DeviceDataCallback callback,
00036                 void *callback_context)
00037         : m_con(con)
00038         , m_ModeSocket(0)
00039         , m_CtrlSocket(0)
00040         , m_callback(callback)
00041         , m_callback_context(callback_context)
00042 {
00043         if( !m_con.HasQueue() )
00044                 throw std::logic_error("A SocketRoutingQueue is required in the Controller class when using Mode::Serial.");
00045 }
00046 
00047 Serial::~Serial()
00048 {
00049 }
00050 
00051 
00052 //////////////////////////////////////////////////////////////////////////////
00053 // protected API / static functions
00054 
00055 void Serial::DataCallback(Serial &ser, Data *data)
00056 {
00057         ddout("Serial::DataCallback called");
00058 
00059         if( data->GetSize() <= 4 )
00060                 return; // nothing to do
00061 
00062         // call callback if available
00063         if( ser.m_callback ) {
00064                 (*ser.m_callback)(ser.m_callback_context,
00065                         data->GetData() + 4,
00066                         data->GetSize() - 4);
00067         }
00068 //      else {
00069 //              // append data to readCache
00070 //              FIXME;
00071 //      }
00072 }
00073 
00074 void Serial::CtrlCallback(Serial &ser, Data *data)
00075 {
00076         // just dump to stdout, and do nothing
00077         ddout("CtrlCallback received:\n" << *data);
00078 }
00079 
00080 //////////////////////////////////////////////////////////////////////////////
00081 // public API
00082 
00083 void Serial::Open(const char *password)
00084 {
00085         if( m_ModeSocket ) {
00086                 m_data->Close();
00087                 m_data.reset();
00088                 m_ModeSocket = 0;
00089         }
00090 
00091         if( m_CtrlSocket ) {
00092                 m_ctrl->Close();
00093                 m_ctrl.reset();
00094                 m_CtrlSocket = 0;
00095         }
00096 
00097         m_ModeSocket = m_con.SelectMode(Controller::UsbSerData);
00098         m_data = m_con.OpenSocket(m_ModeSocket, password);
00099 
00100         m_CtrlSocket = m_con.SelectMode(Controller::UsbSerCtrl);
00101         m_ctrl = m_con.OpenSocket(m_CtrlSocket, password);
00102 
00103         // register callback for incoming data, for speed
00104         SocketRoutingQueue::SocketDataHandlerPtr data_callback
00105                 (new SocketRoutingQueue::SimpleSocketDataHandler<Serial>(*this, DataCallback));
00106         m_data->UnregisterInterest();
00107         m_data->RegisterInterest(data_callback);
00108         SocketRoutingQueue::SocketDataHandlerPtr ctrl_callback
00109                 (new SocketRoutingQueue::SimpleSocketDataHandler<Serial>(*this, CtrlCallback));
00110         m_ctrl->UnregisterInterest();
00111         m_ctrl->RegisterInterest(ctrl_callback);
00112 
00113         const unsigned char start[] =
00114                 { 0, 0, 0x0a, 0, 0x01, 0x01, 0xc2, 0x00, 0x40, 0x00 };
00115         Data block(start, sizeof(start));
00116         m_ctrl->RawSend(block);
00117 }
00118 
00119 void Serial::Close()
00120 {
00121         ddout("Serial:: Closing connection.");
00122 }
00123 
00124 /*
00125 // FIXME - if this behaviour is truly common between modes, create
00126 // a common base class for this.
00127 void Serial::RetryPassword(const char *password)
00128 {
00129         if( m_data.get() || m_ctrl.get() )
00130                 throw std::logic_error("Socket already open in Serial::RetryPassword");
00131 
00132         m_data = m_con.m_zero.OpenDBSocket(m_ModeSocket, password);
00133         m_ctrl = m_con.m_zero.OpenDBSocket(m_CtrlSocket, password);
00134 
00135         // register callback for incoming data, for speed
00136         m_data->UnregisterInterest();
00137         m_data->RegisterInterest(DataCallback, this);
00138 }
00139 */
00140 
00141 /*
00142 // can be called from separate thread
00143 void Serial::SerialRead(Data &data, int timeout)
00144 {
00145         m_socket.Receive(data, timeout);
00146 }
00147 */
00148 
00149 void Serial::Write(const Data &data, int timeout)
00150 {
00151         if( data.GetSize() <= 0 )
00152                 return; // nothing to do
00153 
00154         if( !m_data.get() )
00155                 throw std::logic_error("Must call Open() before Write() in Mode::Serial");
00156 
00157         // filter data for PPP, and prepend 4 bytes
00158         Data &filtered = m_filter.Write(data, 4);
00159 
00160         // setup header (only size needed, as socket will be set by socket class)
00161         unsigned char *buf = filtered.GetBuffer();
00162         MAKE_PACKETPTR_BUF(spack, buf);
00163         spack->size = htobs(filtered.GetSize());
00164 
00165         // send via appropriate socket
00166         m_data->RawSend(filtered, timeout);
00167 }
00168 
00169 }} // namespace Barry::Mode
00170