# 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-2011, 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.m_zero.Open(m_ModeSocket, password);
    00099
    00100         m_CtrlSocket = m_con.SelectMode(Controller::UsbSerCtrl);
    00101         m_ctrl = m_con.m_zero.Open(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->RegisterInterest(data_callback);
    00107         SocketRoutingQueue::SocketDataHandlerPtr ctrl_callback
    00108                 (new SocketRoutingQueue::SimpleSocketDataHandler<Serial>(*this, CtrlCallback));
    00109         m_ctrl->RegisterInterest(ctrl_callback);
    00110
    00111         const unsigned char start[] =
    00112                 { 0, 0, 0x0a, 0, 0x01, 0x01, 0xc2, 0x00, 0x40, 0x00 };
    00113         Data block(start, sizeof(start));
    00114         m_ctrl->Send(block);
    00115 }
    00116
    00117 void Serial::Close()
    00118 {
    00119         ddout("Serial:: Closing connection.");
    00120 }
    00121
    00122 /*
    00123 // FIXME - if this behaviour is truly common between modes, create
    00124 // a common base class for this.
    00125 void Serial::RetryPassword(const char *password)
    00126 {
    00127         if( m_data.get() || m_ctrl.get() )
    00128                 throw std::logic_error("Socket already open in Serial::RetryPassword");
    00129
    00130         m_data = m_con.m_zero.OpenDBSocket(m_ModeSocket, password);
    00131         m_ctrl = m_con.m_zero.OpenDBSocket(m_CtrlSocket, password);
    00132
    00133         // register callback for incoming data, for speed
    00134         m_data->RegisterInterest(DataCallback, this);
    00135 }
    00136 */
    00137
    00138 /*
    00139 // can be called from separate thread
    00140 void Serial::SerialRead(Data &data, int timeout)
    00141 {
    00142         m_socket.Receive(data, timeout);
    00143 }
    00144 */
    00145
    00146 void Serial::Write(const Data &data, int timeout)
    00147 {
    00148         if( data.GetSize() <= 0 )
    00149                 return; // nothing to do
    00150
    00151         if( !m_data.get() )
    00152                 throw std::logic_error("Must call Open() before Write() in Mode::Serial");
    00153
    00154         // filter data for PPP, and prepend 4 bytes
    00155         Data &filtered = m_filter.Write(data, 4);
    00156
    00157         // setup header (only size needed, as socket will be set by socket class)
    00158         unsigned char *buf = filtered.GetBuffer();
    00159         MAKE_PACKETPTR_BUF(spack, buf);
    00160         spack->size = htobs(filtered.GetSize());
    00161
    00162         // send via appropriate socket
    00163         m_data->Send(filtered, timeout);
    00164 }
    00165
    00166 }} // namespace Barry::Mode
    00167