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:
+230
-51
@@ -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() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user