1/* 2 * Copyright (c) 2014, 2017 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __DEV_SERIAL_HH__ 41#define __DEV_SERIAL_HH__ 42 43#include "base/callback.hh" 44#include "sim/sim_object.hh" 45 46struct SerialDeviceParams; 47struct SerialNullDeviceParams; 48 49/** 50 * Base class for serial devices such as terminals. 51 * 52 * This class provides a unified interface that all serial (RS232 or 53 * similar) devices must implement. A device can be wired to exactly 54 * one host serial interface (serial port model). 55 * 56 * SerialDevices are passive devices that are <i>driven</i> by the 57 * serial interface using the writeData(c) (the interface sends a 58 * character) and readData() (the interface reads a character) 59 * methods. Serial devices need to override these methods to 60 * communicate with the host interface layer. 61 * 62 * To implement basic flow control, serial devices must implement the 63 * dataAvailable() method. This method returns true if a valid 64 * character can be read using the readData() method. When data 65 * becomes available, the serial device must call the 66 * notifyInterface() method to send a callback to the interface layer. 67 * 68 * To send a character (host to device), the interface layer calls 69 * writeData(char) to send a character to the serial device. 70 * 71 * To read a character (device to host), the interface layer calls 72 * dataAvailable() to determine if there is a character pending. If 73 * there is data available, it immediately calls readData() to get the 74 * character. The receive loop in the serial device typically looks 75 * like this: 76 * 77 * \code{.cc} 78 * while (device.dataAvailable()) { 79 * printf("%c", (int)device.readData()); 80 * } 81 * \endcode 82 * 83 * To avoid polling, the interface layer may register a data available 84 * callback using the regInterfaceCallback() method. The device uses 85 * this callback to notify the interface layer whenever there is new 86 * data pending. Note that devices will normally only notify the 87 * interface layer when there is a state transition in the 88 * device. E.g., the dataAvailable() transitions from false to 89 * true. This means that there can be multiple pending characters when 90 * the interface layer receives the callback. 91 */ 92class SerialDevice : public SimObject 93{ 94 public: 95 SerialDevice(const SerialDeviceParams *p); 96 ~SerialDevice(); 97 98 public: // Serial device API (UART->Device) 99 /** 100 * Register a data available callback into the host interface layer. 101 * 102 * Serial devices need to call the underlying host interface layer 103 * to inform it of state change such as pending data that can be 104 * read from the device by the interface layer using the readData() 105 * method. The interface layer may use this method to register a 106 * callback that informs it of pending data. 107 * 108 * @param c Callback instance from interface layer. 109 */ 110 void regInterfaceCallback(Callback *c); 111 112 /** 113 * Check if there is pending data from the serial device. 114 * 115 * @return true if there is data pending that can be read using 116 * the readData() method. 117 */ 118 virtual bool dataAvailable() const = 0; 119 120 /** 121 * Transmit a character from the host interface to the device. 122 * 123 * @param c Received data. 124 */ 125 virtual void writeData(uint8_t c) = 0; 126 127 /** 128 * Read a character from the device. 129 * 130 * @return Character from the device's output buffer, undefined if 131 * no data is pending. 132 */ 133 virtual uint8_t readData() = 0; 134 135 protected: 136 /** Notify the host interface of pending data. */ 137 void notifyInterface(); 138 139 private: 140 /** Currently regisxtered host interface layer callback */ 141 Callback *interfaceCallback; 142}; 143 144/** 145 * Dummy serial device that discards all data sent to it. 146 */ 147class SerialNullDevice : public SerialDevice 148{ 149 public: 150 SerialNullDevice(const SerialNullDeviceParams *p); 151 152 public: 153 bool dataAvailable() const override { return false; } 154 void writeData(uint8_t c) override {}; 155 uint8_t readData() override; 156}; 157 158#endif // __DEV_SERIAL_HH__ 159