BSerialPort, not very much tested. Written by Jack Burton.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2225 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper
2002-12-11 22:01:42 +00:00
parent 6db844ad4e
commit 27a24b9f61
+230 -51
View File
@@ -1,164 +1,251 @@
/* /*
* Copyright 2002, Marcus Overhagen. All rights reserved. * Copyright 2002, Jack Burton.
* Copyright 2002, Marcus Overhagen.
* All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#include <Directory.h>
#include <Entry.h>
#include <List.h>
#include <SerialPort.h> #include <SerialPort.h>
#include <errno.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#define SERIAL_DIR "/dev/ports"
BSerialPort::BSerialPort() BSerialPort::BSerialPort()
: ffd(-1),
fBaudRate(B_19200_BPS),
fDataBits(B_DATA_BITS_8),
fStopBits(B_STOP_BIT_1),
fParityMode(B_NO_PARITY),
fFlow(B_HARDWARE_CONTROL),
fTimeout(B_INFINITE_TIMEOUT),
fBlocking(true),
_fDevices(new BList)
{ {
ScanDevices();
} }
BSerialPort::~BSerialPort() BSerialPort::~BSerialPort()
{ {
if (ffd > 0)
close(ffd);
for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
free(_fDevices->ItemAt(count));
delete _fDevices;
} }
status_t status_t
BSerialPort::Open(const char *portName) BSerialPort::Open(const char *portName)
{ {
return B_ERROR; char buf[64];
//TODO: Check if portName is a valid name
sprintf(buf, SERIAL_DIR"/%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
if (ffd > 0)
DriverControl(); //Setup the port
return (ffd < 0) ? ffd : B_OK;
} }
void void
BSerialPort::Close(void) BSerialPort::Close(void)
{ {
if (ffd > 0)
close(ffd);
ffd = -1;
} }
ssize_t ssize_t
BSerialPort::Read(void *buf, BSerialPort::Read(void *buf, size_t count)
size_t count)
{ {
return 0; if (ffd < 0) // We have no open port
return B_FILE_ERROR;
return read(ffd, buf, count);
} }
ssize_t ssize_t
BSerialPort::Write(const void *buf, BSerialPort::Write(const void *buf, size_t count)
size_t count)
{ {
return 0; if (ffd < 0) // We have no open port
return B_FILE_ERROR;
return write(ffd, buf, count);
} }
void void
BSerialPort::SetBlocking(bool Blocking) BSerialPort::SetBlocking(bool Blocking)
{ {
fBlocking = Blocking;
DriverControl();
} }
status_t status_t
BSerialPort::SetTimeout(bigtime_t microSeconds) BSerialPort::SetTimeout(bigtime_t microSeconds)
{ {
return B_ERROR; status_t err = B_BAD_VALUE;
if (microSeconds == B_INFINITE_TIMEOUT || microSeconds <= 25000000)
{
fTimeout = microSeconds;
DriverControl();
err = B_OK;
}
return err;
} }
status_t status_t
BSerialPort::SetDataRate(data_rate bitsPerSecond) BSerialPort::SetDataRate(data_rate bitsPerSecond)
{ {
return B_ERROR; fBaudRate = bitsPerSecond;
return DriverControl();
} }
data_rate data_rate
BSerialPort::DataRate(void) BSerialPort::DataRate(void)
{ {
return B_0_BPS; return fBaudRate;
} }
void void
BSerialPort::SetDataBits(data_bits numBits) BSerialPort::SetDataBits(data_bits numBits)
{ {
fDataBits = numBits;
DriverControl();
} }
data_bits data_bits
BSerialPort::DataBits(void) BSerialPort::DataBits(void)
{ {
return B_DATA_BITS_8; return fDataBits;
} }
void void
BSerialPort::SetStopBits(stop_bits numBits) BSerialPort::SetStopBits(stop_bits numBits)
{ {
fStopBits = numBits;
DriverControl();
} }
stop_bits stop_bits
BSerialPort::StopBits(void) BSerialPort::StopBits(void)
{ {
return B_STOP_BITS_1; return fStopBits;
} }
void void
BSerialPort::SetParityMode(parity_mode which) BSerialPort::SetParityMode(parity_mode which)
{ {
fParityMode = which;
DriverControl();
} }
parity_mode parity_mode
BSerialPort::ParityMode(void) BSerialPort::ParityMode(void)
{ {
return B_NO_PARITY; return fParityMode;
} }
void void
BSerialPort::ClearInput(void) BSerialPort::ClearInput(void)
{ {
tcflush(ffd, TCIFLUSH);
} }
void void
BSerialPort::ClearOutput(void) BSerialPort::ClearOutput(void)
{ {
tcflush(ffd, TCOFLUSH);
} }
void void
BSerialPort::SetFlowControl(uint32 method) BSerialPort::SetFlowControl(uint32 method)
{ {
fFlow = method;
DriverControl();
} }
uint32 uint32
BSerialPort::FlowControl(void) BSerialPort::FlowControl(void)
{ {
return 0; return fFlow;
} }
status_t status_t
BSerialPort::SetDTR(bool asserted) BSerialPort::SetDTR(bool asserted)
{ {
return B_ERROR; status_t status = ioctl(ffd, TCSETDTR, &asserted);
return (status > 0) ? status : errno;
} }
status_t status_t
BSerialPort::SetRTS(bool asserted) BSerialPort::SetRTS(bool asserted)
{ {
return B_ERROR; status_t status = ioctl(ffd, TCSETRTS, &asserted);
return (status > 0) ? status : errno;
} }
status_t status_t
BSerialPort::NumCharsAvailable(int32 *wait_until_this_many) BSerialPort::NumCharsAvailable(int32 *wait_until_this_many)
{ {
return B_ERROR; //No help from the BeBook...
if (ffd < 0)
return B_ERROR;
return B_OK;
} }
bool bool
BSerialPort::IsCTS(void) BSerialPort::IsCTS(void)
{ {
unsigned int bits = ioctl(ffd, TCGETBITS, 0);
if (bits & TCGB_CTS)
return true;
return false; return false;
} }
@@ -166,6 +253,11 @@ BSerialPort::IsCTS(void)
bool bool
BSerialPort::IsDSR(void) BSerialPort::IsDSR(void)
{ {
unsigned int bits = ioctl(ffd, TCGETBITS, 0);
if (bits & TCGB_DSR)
return true;
return false; return false;
} }
@@ -173,6 +265,11 @@ BSerialPort::IsDSR(void)
bool bool
BSerialPort::IsRI(void) BSerialPort::IsRI(void)
{ {
unsigned int bits = ioctl(ffd, TCGETBITS, 0);
if (bits & TCGB_RI)
return true;
return false; return false;
} }
@@ -180,6 +277,11 @@ BSerialPort::IsRI(void)
bool bool
BSerialPort::IsDCD(void) BSerialPort::IsDCD(void)
{ {
unsigned int bits = ioctl(ffd, TCGETBITS, 0);
if (bits & TCGB_DCD)
return true;
return false; return false;
} }
@@ -187,60 +289,137 @@ BSerialPort::IsDCD(void)
ssize_t ssize_t
BSerialPort::WaitForInput(void) BSerialPort::WaitForInput(void)
{ {
return 0; int size;
int err = ioctl(ffd, TCWAITEVENT, &size, sizeof(size));
return (err < B_OK) ? errno : size;
} }
int32 int32
BSerialPort::CountDevices() BSerialPort::CountDevices()
{ {
return 0; int32 count = 0;
if (_fDevices != NULL)
count = _fDevices->CountItems();
return count;
} }
status_t status_t
BSerialPort::GetDeviceName(int32 n, BSerialPort::GetDeviceName(int32 n, char *name, size_t bufSize)
char *name,
size_t bufSize)
{ {
return B_ERROR; status_t result = B_ERROR;
char *dev = NULL;
if (_fDevices != NULL)
dev = static_cast<char*>(_fDevices->ItemAt(n));
if (dev != NULL && name != NULL) {
strncpy(name, dev, bufSize);
result = B_OK;
}
return result;
} }
// Private or Reserved
void void
BSerialPort::ScanDevices() BSerialPort::ScanDevices()
{ {
} BEntry entry;
BDirectory dir(SERIAL_DIR);
char buf[B_OS_NAME_LENGTH];
void
BSerialPort::_ReservedSerialPort1() //First, we empty the list
{ for (int32 count = _fDevices->CountItems() - 1; count >= 0; count--)
} free(_fDevices->ItemAt(count));
_fDevices->MakeEmpty();
void
BSerialPort::_ReservedSerialPort2() //Then, add the devices to the list
{ while (dir.GetNextEntry(&entry) == B_OK)
} {
entry.GetName(buf);
_fDevices->AddItem(strdup(buf));
void };
BSerialPort::_ReservedSerialPort3()
{
}
void
BSerialPort::_ReservedSerialPort4()
{
} }
int int
BSerialPort::DriverControl() BSerialPort::DriverControl()
{ {
return 0; struct termio termioControl;
int err;
if (ffd < 0)
return B_NO_INIT;
//Load the current settings
err = ioctl(ffd, TCGETA, &termioControl);
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);
//Set the flags to the wanted values
if (fFlow & B_HARDWARE_CONTROL)
termioControl.c_cflag |= CRTSCTS;
if (fFlow & B_SOFTWARE_CONTROL)
termioControl.c_iflag |= (IXON | IXOFF);
if (fStopBits & B_STOP_BITS_2)
termioControl.c_cflag |= CSTOPB; // We want 2 stop bits
if (fDataBits == B_DATA_BITS_8)
termioControl.c_cflag |= CS8; // We want 8 data bits
//Ok, set the parity now
if (fParityMode != B_NO_PARITY)
{
termioControl.c_cflag |= PARENB; //Enable parity
if (fParityMode == B_ODD_PARITY)
termioControl.c_cflag |= PARODD; //Select odd parity
}
//Set the baud rate
termioControl.c_cflag |= (fBaudRate & CBAUD);
//Set the timeout
if (fBlocking)
{
if (fTimeout == B_INFINITE_TIMEOUT)
{
termioControl.c_cc[VTIME] = 0;
termioControl.c_cc[VMIN] = 1;
}
else if (fTimeout == 0)
termioControl.c_cc[VMIN] = 0;
else
{
int t = fTimeout / 100000;
termioControl.c_cc[VTIME] = (t == 0) ? 1 : t;
termioControl.c_cc[VMIN] = 1;
}
} else
termioControl.c_cc[VMIN] = 0;
//Ok, finished. Now tell the driver what we decided
err = ioctl(ffd, TCSETA, &termioControl);
return err > 0 ? err : errno;
} }
//FBC
void BSerialPort::_ReservedSerialPort1() {}
void BSerialPort::_ReservedSerialPort2() {}
void BSerialPort::_ReservedSerialPort3() {}
void BSerialPort::_ReservedSerialPort4() {}