From d376996084f802412eb6d793ac67c6da05408977 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 21 Jan 2003 19:34:45 +0000 Subject: [PATCH] Added doxygen style comments. Fixed a bug in open() return value. The class still doesn't work as it should. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2526 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/device/SerialPort.cpp | 298 ++++++++++++++++++++++----------- 1 file changed, 202 insertions(+), 96 deletions(-) diff --git a/src/kits/device/SerialPort.cpp b/src/kits/device/SerialPort.cpp index e0d87c4960..334d3a53f2 100644 --- a/src/kits/device/SerialPort.cpp +++ b/src/kits/device/SerialPort.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2002, Jack Burton. + * Copyright 2002, Stefano Ceccherini. * Copyright 2002, Marcus Overhagen. * All rights reserved. * Distributed under the terms of the MIT License. @@ -21,20 +21,19 @@ /* The directory where the serial driver publishes its devices */ #define SERIAL_DIR "/dev/ports" - -/* Creates and initializes a BSerialPort object, */ -/* query the driver, and builds a list of available */ -/* serial ports. */ - -/* The BSerialPort object is initialized to these */ -/* values: */ -/* 19200 BPS, */ -/* 8 Data Bits, */ -/* 1 Stop Bit, */ -/* No Parity, */ -/* Hardware Flow Control, */ -/* Infinite Timeout */ -/* and Blocking mode. */ +/*! \brief Creates and initializes a BSerialPort object. + + Query the driver, and builds a list of the available + serial ports. + The BSerialPort object is initialized to these values: + - \c B_19200_BPS + - \c B_DATA_BITS_8 + - \c B_STOP_BIT_1 + - \c B_NO_PARITY + - \c B_HARDWARE_CONTROL + - \c B_INFINITE_TIMEOUT + - Blocking mode +*/ BSerialPort::BSerialPort() : ffd(-1), fBaudRate(B_19200_BPS), @@ -50,7 +49,9 @@ BSerialPort::BSerialPort() } -/* Closes the port, if it's open, and deletes the devices list */ +/*! \brief Frees the resources associated with the object. + Closes the port, if it's open, and deletes the devices list. +*/ BSerialPort::~BSerialPort() { if (ffd > 0) @@ -63,28 +64,42 @@ BSerialPort::~BSerialPort() } -/* Opens a serial port. @param a valid port name */ +/*! \brief Opens a serial port. + \param portName A valid port name + (i.e."/dev/ports/serial2", "serial2", ...) + \return + - A positive number if the serialport has been succesfully opened. + - An errorcode (negative integer) if not. +*/ status_t BSerialPort::Open(const char *portName) { char buf[64]; - //TODO: Check if portName is a valid name - sprintf(buf, SERIAL_DIR"/%s", portName); - + if (portName == NULL) + return B_BAD_VALUE; // Heheee, we won't crash + + if (portName[0] != '/') + sprintf(buf, SERIAL_DIR"/%s", portName); + else + // A name like "/dev/ports/serial2" was passed + sprintf(buf, "%s", portName); + if (ffd > 0) //If this port is already open, close it close(ffd); - - ffd = open(buf, O_RDWR|O_NONBLOCK); //R5 seem to use this mask + + // We want "open()" to return immediately + ffd = open(buf, O_RDWR|O_NONBLOCK); if (ffd > 0) DriverControl(); //Setup the port - - return (ffd < 0) ? ffd : B_OK; + + return (ffd > 0) ? ffd : errno; } -/* Closes the port */ +/*! \brief Closes the port. +*/ void BSerialPort::Close(void) { @@ -94,33 +109,36 @@ BSerialPort::Close(void) } -/* Read some data from the serial port. */ -/* @param the buffer where to transfer the data */ -/* @param how many bytes to read */ +/*! \brief Reads some bytes from the serial port. + \param buf The buffer where to copy the data. + \param count The maximum amount of bytes to read. + \return The amount of data read. +*/ ssize_t BSerialPort::Read(void *buf, size_t count) { - if (ffd < 0) // We have no open port - return B_FILE_ERROR; + ssize_t err = read(ffd, buf, count); - return read(ffd, buf, count); + return (err >= 0) ? err : errno; } -/* Write some data to the serial port. */ -/* @param the buffer from which transfer the data */ -/* @param how many bytes to write */ +/*! \brief Writes some bytes to the serial port. + \param buf The buffer which copy the data from. + \param count The amount of bytes to write. +*/ ssize_t BSerialPort::Write(const void *buf, size_t count) { - if (ffd < 0) // We have no open port - return B_FILE_ERROR; - - return write(ffd, buf, count); + ssize_t err = write(ffd, buf, count); + + return (err >= 0) ? err : errno; } -/* Set blocking mode */ +/*! \brief Set blocking mode + \param Blocking If true, enables the blocking mode. If false, disables it. +*/ void BSerialPort::SetBlocking(bool Blocking) { @@ -129,8 +147,13 @@ BSerialPort::SetBlocking(bool Blocking) } -/* Set the timeout for the port */ -/* Valid values: B_INFINITE_TIMEOUT or any value between 0 and 25000000 */ +/*! \brief Set the timeout for the port. + \param microSeconds The timeout for the port. + Valid values are: + - \c B_INFINITE_TIMEOUT + - Any value between 0 and 25,000,000, but remember that the granularity + of the serial driver is 100,000 microseconds. +*/ status_t BSerialPort::SetTimeout(bigtime_t microSeconds) { @@ -146,7 +169,33 @@ BSerialPort::SetTimeout(bigtime_t microSeconds) } -/* Set the data rate (Baud rate) for the port */ +/*! \brief Set the Baud rate for the port. + \param bitsPerSeconds The baud rate. + Valid values: + - \c B_0_BPS + - \c B_50_BPS + - \c B_75_BPS + - \c B_110_BPS + - \c B_134_BPS + - \c B_150_BPS + - \c B_200_BPS + - \c B_300_BPS + - \c B_600_BPS + - \c B_1200_BPS + - \c B_1800_BPS + - \c B_2400_BPS + - \c B_4800_BPS + - \c B_9600_BPS + - \c B_19200_BPS + - \c B_38400_BPS + - \c B_57600_BPS + - \c B_115200_BPS + - \c B_230400_BPS + - \c B_31250_BPS + \return + - \c B_OK if all goes fine, + - an error code if something goes wrong. +*/ status_t BSerialPort::SetDataRate(data_rate bitsPerSecond) { @@ -156,7 +205,10 @@ BSerialPort::SetDataRate(data_rate bitsPerSecond) } -/* Get the data rate (Baud Rate) */ +/*! \brief Get the current Baud Rate. + \return The current Baud Rate. +*/ + data_rate BSerialPort::DataRate(void) { @@ -173,7 +225,9 @@ BSerialPort::SetDataBits(data_bits numBits) } -/* Get the data bits */ +/*! \brief Get the current data bits. + \return The current data bits. +*/ data_bits BSerialPort::DataBits(void) { @@ -181,7 +235,12 @@ BSerialPort::DataBits(void) } -/* Set the stop bits (1 or 2) */ +/*! \brief Set the stop bits. + \param numBits The number of stop bits + Valid values: + - \c B_STOP_BITS_1 (or \c B_STOP_BIT_1) + - \c B_STOP_BITS_2 +*/ void BSerialPort::SetStopBits(stop_bits numBits) { @@ -190,7 +249,9 @@ BSerialPort::SetStopBits(stop_bits numBits) } -/* Get the stop bits */ +/*! \brief Get the current stop bits. + \return The current stop bits. +*/ stop_bits BSerialPort::StopBits(void) { @@ -198,7 +259,13 @@ BSerialPort::StopBits(void) } -/* Set the parity mode (ODD, PAIR, or NONE) */ +/*! \brief Set the parity mode. + \param which The parity mode to set. + Valid values: + - \c B_ODD_PARITY + - \c B_EVEN_PARITY + - \c B_NO_PARITY +*/ void BSerialPort::SetParityMode(parity_mode which) { @@ -207,7 +274,9 @@ BSerialPort::SetParityMode(parity_mode which) } -/* Get the parity mode */ +/*! \brief Get the parity mode. + \return The current parity mode. +*/ parity_mode BSerialPort::ParityMode(void) { @@ -215,7 +284,8 @@ BSerialPort::ParityMode(void) } -/* Clear the input buffer */ +/*! \brief Clear the input buffer. +*/ void BSerialPort::ClearInput(void) { @@ -223,7 +293,8 @@ BSerialPort::ClearInput(void) } -/* Clear the output buffer */ +/*! \brief Clear the output buffer. +*/ void BSerialPort::ClearOutput(void) { @@ -231,7 +302,13 @@ BSerialPort::ClearOutput(void) } -/* Set the flow control (HARDWARE, SOFTWARE, or NONE) */ +/*! \brief Set the flow control + \param method The type of flow control. + Valid values: + - \c B_HARDWARE_CONTROL + - \c B_SOFTWARE_CONTROL + - \c B_NOFLOW_CONTROL +*/ void BSerialPort::SetFlowControl(uint32 method) { @@ -240,7 +317,9 @@ BSerialPort::SetFlowControl(uint32 method) } -/* Get the flow control */ +/*! \brief Returns the selected flow control. + \return The flow control for the current open port. +*/ uint32 BSerialPort::FlowControl(void) { @@ -268,8 +347,11 @@ BSerialPort::SetRTS(bool asserted) } -/* See how many chars are queued on the serial port, */ -/* waiting to be read */ +/*! \brief See how many chars are queued on the serial port. + \param wait_until_this_many A pointer to an int32 where you want + that value stored. + \return ? +*/ status_t BSerialPort::NumCharsAvailable(int32 *wait_until_this_many) { @@ -282,7 +364,9 @@ BSerialPort::NumCharsAvailable(int32 *wait_until_this_many) } -/* See if CTS is set */ +/*! \brief See if the Clear to Send pin is asserted. + \return true if CTS is asserted, false if not. +*/ bool BSerialPort::IsCTS(void) { @@ -295,7 +379,9 @@ BSerialPort::IsCTS(void) } -/* See if DSR is set */ +/*! \brief See if the Data Set Ready pin is asserted. + \return true if DSR is asserted, false if not. +*/ bool BSerialPort::IsDSR(void) { @@ -308,7 +394,9 @@ BSerialPort::IsDSR(void) } -/* See if RI is set */ +/*! \brief See if the Ring Indicator pin is asserted. + \return true if RI is asserted, false if not. +*/ bool BSerialPort::IsRI(void) { @@ -321,7 +409,9 @@ BSerialPort::IsRI(void) } -/* See if DCD is set */ +/*! \brief See if the Data Carrier Detect pin is asserted. + \return true if DCD is asserted, false if not. +*/ bool BSerialPort::IsDCD(void) { @@ -334,10 +424,12 @@ BSerialPort::IsDCD(void) } -/* Wait until there's something to read from the serial port. */ -/* If no data is ready, it will always block, ignoring the */ -/* value of SetBlocking(); however, it respects the timeout */ -/* set by SetTimeout(). */ +/*! \brief Wait until there's something to read from the serial port. + If no data is ready, it will always block, ignoring the + value of SetBlocking(); however, it respects the timeout + set by SetTimeout(). + \return The number of bytes available to be read. +*/ ssize_t BSerialPort::WaitForInput(void) { @@ -348,7 +440,10 @@ BSerialPort::WaitForInput(void) } -/* Returns the number of available Serial Ports. */ +/*! \brief Count the number of available Serial Ports. + \return An integer which represents the number of available + serial ports. +*/ int32 BSerialPort::CountDevices() { @@ -361,11 +456,14 @@ BSerialPort::CountDevices() } -/* Get the device name for the given device.*/ -/* The first parameter is the number of the device */ -/* you want to know the name, the second is the buffer */ -/* where you want to store the name, and the third is */ -/* the length of that buffer. */ +/*! \brief Get the device name for the given device. + \param n Number of the device you want to know the name of. + \param name The buffer where you want to store the name. + \param bufSize The size of the buffer. + \return + - \c B_ERROR if something goes wrong + - \c B_OK if all goes fine. +*/ status_t BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize) { @@ -375,7 +473,8 @@ BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize) if (_fDevices != NULL) dev = static_cast(_fDevices->ItemAt(n)); - if (dev != NULL && name != NULL) { + if (dev != NULL && name != NULL) + { strncpy(name, dev, bufSize); result = B_OK; } @@ -385,8 +484,10 @@ BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize) /* Private or Reserved */ -/* Query the serial driver about the available devices, */ -/* and build a list of them. */ +/*! \brief Build a list of available serial ports. + Query the serial driver about the available devices, + and build a list of them. +*/ void BSerialPort::ScanDevices() { @@ -407,75 +508,80 @@ BSerialPort::ScanDevices() } -/* Send the options to the serial driver. */ -/* Returns B_OK if all goes fine, an error code */ -/* if something goes wrong. */ +/*! \brief Send the selected options to the serial driver. + \return + - \c B_OK if all goes fine, + - an error code if something goes wrong. +*/ int BSerialPort::DriverControl() { - struct termio termioControl; + struct termio options; int err; if (ffd < 0) return B_NO_INIT; //Load the current settings - err = ioctl(ffd, TCGETA, &termioControl); + err = tcgetattr(ffd, &options); if (err < 0) return errno; // Reset all flags - termioControl.c_cflag &= ~(CRTSCTS | CSIZE | CBAUD | CSTOPB | PARODD | PARENB); - termioControl.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK); - termioControl.c_lflag &= ~(ECHO | ECHONL | ISIG | ICANON); + options.c_cflag &= ~(CRTSCTS | CSIZE | CBAUD | CSTOPB | PARODD | PARENB); + options.c_iflag &= ~(IXON | IXOFF | IXANY | INPCK); + options.c_lflag &= ~(ECHO | ECHONL | ISIG | ICANON); //Set the flags to the wanted values if (fFlow & B_HARDWARE_CONTROL) - termioControl.c_cflag |= CRTSCTS; + options.c_cflag |= CRTSCTS; if (fFlow & B_SOFTWARE_CONTROL) - termioControl.c_iflag |= (IXON | IXOFF); + options.c_iflag |= (IXON | IXOFF); if (fStopBits & B_STOP_BITS_2) - termioControl.c_cflag |= CSTOPB; // We want 2 stop bits + options.c_cflag |= CSTOPB; // Set 2 stop bits - if (fDataBits == B_DATA_BITS_8) - termioControl.c_cflag |= CS8; // We want 8 data bits + if (fDataBits & B_DATA_BITS_8) + options.c_cflag |= CS8; // Set 8 data bits //Ok, set the parity now if (fParityMode != B_NO_PARITY) { - termioControl.c_cflag |= PARENB; //Enable parity + options.c_cflag |= PARENB; //Enable parity if (fParityMode == B_ODD_PARITY) - termioControl.c_cflag |= PARODD; //Select odd parity + options.c_cflag |= PARODD; //Select odd parity } //Set the baud rate - termioControl.c_cflag |= (fBaudRate & CBAUD); + cfsetispeed(&options, fBaudRate); + cfsetospeed(&options, fBaudRate); + + //options.c_cflag |= (fBaudRate & CBAUD); //Set the timeout if (fBlocking) { if (fTimeout == B_INFINITE_TIMEOUT) { - termioControl.c_cc[VTIME] = 0; - termioControl.c_cc[VMIN] = 1; + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 1; } else if (fTimeout == 0) - termioControl.c_cc[VMIN] = 0; + options.c_cc[VMIN] = 0; else { - int t = fTimeout / 100000; - termioControl.c_cc[VTIME] = (t == 0) ? 1 : t; - termioControl.c_cc[VMIN] = 1; + int timeout = fTimeout / 100000; + options.c_cc[VTIME] = (timeout == 0) ? 1 : timeout; + options.c_cc[VMIN] = 1; } } else - termioControl.c_cc[VMIN] = 0; + options.c_cc[VMIN] = 0; //Ok, finished. Now tell the driver what we decided - err = ioctl(ffd, TCSETA, &termioControl); + err = tcsetattr(ffd, TCSANOW, &options); - return err > 0 ? err : errno; + return (err > 0) ? err : errno; }