267 lines
7.2 KiB
C++
267 lines
7.2 KiB
C++
|
||
#include "SerialPort.h"
|
||
#include "LpUtil.h"
|
||
using namespace std;
|
||
|
||
Serial::Serial():
|
||
portNo(""),
|
||
connected(false)
|
||
{
|
||
}
|
||
|
||
Serial::~Serial()
|
||
{
|
||
//Check if we are connected before trying to disconnect
|
||
close();
|
||
}
|
||
|
||
bool Serial::open(std::string portno, int baudrate)
|
||
{
|
||
if (isConnected())
|
||
close();
|
||
|
||
createUsbDeviceMap();
|
||
|
||
map<string, string>::iterator iter = usbDeviceMap.find(portno);
|
||
if (iter != usbDeviceMap.end())
|
||
{
|
||
portno = iter->second;
|
||
}
|
||
|
||
fd = ::open (portno.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
|
||
if (fd < 0)
|
||
{
|
||
log.e(TAG, "Error opening %s: Err %d %s\n", portno.c_str(), errno, strerror (errno));
|
||
return false;
|
||
}
|
||
|
||
if (set_interface_attribs (fd, baudrate, 0) == -1)
|
||
{
|
||
log.e(TAG, "Error configuring serial attributes");
|
||
return false;
|
||
}
|
||
|
||
//tcflush(fd,TCIOFLUSH);
|
||
portNo = portno;
|
||
this->connected = true;
|
||
return true;
|
||
}
|
||
|
||
|
||
bool Serial::close()
|
||
{
|
||
if (this->connected)
|
||
{
|
||
//We're no longer connected
|
||
this->connected = false;
|
||
|
||
//tcflush(fd,TCIOFLUSH);
|
||
//Close the serial handler
|
||
::close(fd);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
int Serial::readData(unsigned char *buffer, unsigned int nbChar)
|
||
{
|
||
if (!isConnected())
|
||
return 0;
|
||
|
||
int bytes_avail;
|
||
ioctl(fd, FIONREAD, &bytes_avail);
|
||
|
||
if (bytes_avail > INCOMING_DATA_MAX_LENGTH) {
|
||
log.d(TAG, "Warning: Buffer overflow: %d\n", bytes_avail);
|
||
bytes_avail = INCOMING_DATA_MAX_LENGTH;
|
||
} else if (bytes_avail > nbChar)
|
||
bytes_avail = nbChar;
|
||
|
||
int n = ::read(fd, buffer, bytes_avail);//sizeof(rxBuffer)); // read up to 100 characters if ready to read
|
||
|
||
return n;
|
||
}
|
||
|
||
void Serial::setMode(int mode)
|
||
{
|
||
usbMode = mode;
|
||
}
|
||
|
||
int Serial::getMode(void)
|
||
{
|
||
return usbMode;
|
||
}
|
||
|
||
bool Serial::writeData(unsigned char *buffer, unsigned int nbChar)
|
||
{
|
||
if (!isConnected())
|
||
{
|
||
log.e(TAG, "Error: dongle not connected\n");
|
||
return false;
|
||
}
|
||
int ret;
|
||
ret = ::write(fd, buffer, nbChar); // send 7 character greeting
|
||
return true;
|
||
}
|
||
|
||
bool Serial::isConnected()
|
||
{
|
||
//Simply return the connection status
|
||
return this->connected;
|
||
}
|
||
|
||
|
||
int Serial::set_interface_attribs (int fd, int speed, int parity)
|
||
{
|
||
/*
|
||
struct termios2 tty;
|
||
|
||
|
||
if (ioctl(fd, TCGETS2, &tty) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
tty.c_cflag &= ~CBAUD;
|
||
tty.c_cflag |= BOTHER;
|
||
tty.c_ispeed = speed;
|
||
tty.c_ospeed = speed;
|
||
|
||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
||
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
||
// as \000 chars
|
||
tty.c_iflag &= ~IGNBRK; // disable break processing
|
||
tty.c_lflag = 0; // no signaling chars, no echo,
|
||
// no canonical processing
|
||
tty.c_oflag = 0; // no remapping, no delays
|
||
tty.c_cc[VMIN] = 0; // read doesn't block
|
||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||
|
||
tty.c_iflag &= ~(IXON | IXOFF | IXANY |INLCR | IGNCR | ICRNL); //enable xon
|
||
tty.c_iflag |=IXOFF;
|
||
|
||
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
||
// enable reading
|
||
|
||
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
|
||
tty.c_cflag |= parity;
|
||
tty.c_cflag &= ~CSTOPB;
|
||
tty.c_cflag &= ~CRTSCTS;
|
||
|
||
if (ioctl(fd, TCSETS2, &tty) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
*/
|
||
|
||
struct termios2 config;
|
||
|
||
if (ioctl(fd, TCGETS2, &config) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
config.c_cflag &= ~CBAUD;
|
||
config.c_cflag |= BOTHER;
|
||
config.c_ispeed = speed;
|
||
config.c_ospeed = speed;
|
||
|
||
|
||
config.c_iflag &= ~(IGNBRK | IXANY | INLCR | IGNCR | ICRNL);
|
||
config.c_iflag &= ~IXON; // disable XON/XOFF flow control (output)
|
||
config.c_iflag &= ~IXOFF; // disable XON/XOFF flow control (input)
|
||
config.c_cflag &= ~CRTSCTS; // disable RTS flow control
|
||
config.c_lflag = 0;
|
||
config.c_oflag = 0;
|
||
config.c_cflag &= ~CSIZE;
|
||
config.c_cflag |= CS8; // 8-bit chars
|
||
config.c_cflag |= CLOCAL; // ignore modem controls
|
||
config.c_cflag |= CREAD; // enable reading
|
||
config.c_cflag &= ~(PARENB | PARODD); // disable parity
|
||
config.c_cflag &= ~CSTOPB; // one stop bit
|
||
config.c_cc[VMIN] = 0; // read doesn´t block
|
||
config.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||
|
||
config.c_cflag |= parity;
|
||
|
||
if (ioctl(fd, TCSETS2, &config) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
struct termios2 config;
|
||
|
||
if (ioctl(fd, TCGETS2, &config) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
config.c_iflag &= ~(IGNBRK | IXANY | INLCR | IGNCR | ICRNL);
|
||
config.c_iflag &= ~IXON; // disable XON/XOFF flow control (output)
|
||
config.c_iflag &= ~IXOFF; // disable XON/XOFF flow control (input)
|
||
config.c_cflag &= ~CRTSCTS; // disable RTS flow control
|
||
config.c_lflag = 0;
|
||
config.c_oflag = 0;
|
||
config.c_cflag &= ~CSIZE;
|
||
config.c_cflag |= CS8; // 8-bit chars
|
||
config.c_cflag |= CLOCAL; // ignore modem controls
|
||
config.c_cflag |= CREAD; // enable reading
|
||
config.c_cflag &= ~(PARENB | PARODD); // disable parity
|
||
config.c_cflag &= ~CSTOPB; // one stop bit
|
||
config.c_cc[VMIN] = 0; // read doesn´t block
|
||
config.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||
|
||
|
||
if (ioctl(fd, TCSETS2, &config) < 0)
|
||
{
|
||
return -1;
|
||
}
|
||
*/
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void Serial::createUsbDeviceMap()
|
||
{
|
||
struct udev *udev;
|
||
struct udev_device *dev;
|
||
struct udev_enumerate *enumerate;
|
||
struct udev_list_entry *list, *node;
|
||
const char *path;
|
||
|
||
usbDeviceMap.clear();
|
||
udev = udev_new();
|
||
if (!udev)
|
||
{
|
||
printf("can not create udev");
|
||
}
|
||
|
||
enumerate = udev_enumerate_new(udev);
|
||
udev_enumerate_add_match_subsystem(enumerate, "tty");
|
||
udev_enumerate_scan_devices(enumerate);
|
||
|
||
list = udev_enumerate_get_list_entry(enumerate);
|
||
udev_list_entry_foreach(node, list)
|
||
{
|
||
path = udev_list_entry_get_name(node);
|
||
dev = udev_device_new_from_syspath(udev, path);
|
||
|
||
|
||
if (udev_device_get_property_value(dev, "ID_SERIAL_SHORT") &&
|
||
udev_device_get_property_value(dev, "DEVNAME"))
|
||
{
|
||
string serialID(udev_device_get_property_value(dev, "ID_SERIAL_SHORT"));
|
||
string devName(udev_device_get_property_value(dev, "DEVNAME"));
|
||
|
||
string vendorId(udev_device_get_property_value(dev, "ID_VENDOR_ID"));
|
||
string productId(udev_device_get_property_value(dev, "ID_MODEL_ID"));
|
||
|
||
// Check device usb is CP2102
|
||
if (vendorId=="10c4" && (productId=="ea60" || productId == "ea61" ))
|
||
usbDeviceMap.insert(pair<string, string>(serialID, devName));
|
||
}
|
||
udev_device_unref(dev);
|
||
}
|
||
}
|
||
|