blob: 59f4833d8379a5377c6cf118b9ca42b1a37a413e [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2000-2019 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Lenard Nagy
* version R1A
******************************************************************************/
#include "SerialPort.hh"
namespace SerialPortTypes {
SerialPort::SerialPort(const char *par_port_name)
: SerialPort_BASE(par_port_name)
{
//Set default values
speed = B9600; //9600 baud
blocking = 1; //set blocking
dataBits = CS8; //8 data bits
stopBit = ~CSTOPB; //1 stop bit
parity = 0; //parity: none
CRtoNL = false; // convert NL to CR: false
}
SerialPort::~SerialPort()
{
}
// Implementation of the external function <set_parameter>.
void set__port__parameter(const CHARSTRING& parameter_name, const CHARSTRING& parameter_value, SerialPort& serial_port) {
serial_port.set_parameter(parameter_name, parameter_value);
if (strcmp(parameter_name, "deviceFileName") == 0) {
const char* device_file_name = serial_port.get_device_file_name();
printf("Device File Name: %s\n", device_file_name);
}
}
char* SerialPort::get_device_file_name(){
return param_device_file;
}
void SerialPort::set_parameter(const char * parameter_name,
const char * parameter_value)
{
if (strcmp(parameter_name, "deviceFileName") == 0) {
param_device_file = (char*) malloc(strlen(parameter_value));
strcpy(param_device_file, parameter_value);
//printf("Parameter %s set to %s\n", parameter_name, param_device_file);
} else if (strcmp(parameter_name, "deviceSpeed") == 0) {
if (strcmp(parameter_value, "B0") == 0) {
speed = B0;
} else if (strcmp(parameter_value, "B50") == 0) {
speed = B50;
} else if (strcmp(parameter_value, "B75") == 0) {
speed = B75;
} else if (strcmp(parameter_value, "B75") == 0) {
speed = B75;
} else if (strcmp(parameter_value, "B110") == 0) {
speed = B110;
} else if (strcmp(parameter_value, "B134") == 0) {
speed = B134;
} else if (strcmp(parameter_value, "B150") == 0) {
speed = B150;
} else if (strcmp(parameter_value, "B200") == 0) {
speed = B200;
} else if (strcmp(parameter_value, "B300") == 0) {
speed = B300;
} else if (strcmp(parameter_value, "B600") == 0) {
speed = B600;
} else if (strcmp(parameter_value, "B1200") == 0) {
speed = B1200;
} else if (strcmp(parameter_value, "B1800") == 0) {
speed = B1800;
} else if (strcmp(parameter_value, "B2400") == 0) {
speed = B2400;
} else if (strcmp(parameter_value, "B4800") == 0) {
speed = B4800;
} else if (strcmp(parameter_value, "B9600") == 0) {
speed = B9600;
} else if (strcmp(parameter_value, "B19200") == 0) {
speed = B19200;
} else if (strcmp(parameter_value, "B38400") == 0) {
speed = B38400;
} else if (strcmp(parameter_value, "B57600") == 0) {
speed = B57600;
} else if (strcmp(parameter_value, "B115200") == 0) {
speed = B115200;
} else if (strcmp(parameter_value, "B230400") == 0) {
speed = B230400;
} else if (strcmp(parameter_value, "B460800") == 0) {
speed = B460800;
} else {
TTCN_error("Invalid %s value: %s\n", parameter_name, parameter_value);
}
//printf("Parameter %s set to %s (int: %u)\n", parameter_name, parameter_value, speed);
} else if (strcmp(parameter_name, "deviceParity") == 0) {
if (strcmp(parameter_value, "none") == 0) {
parity = 0;
} else if (strcmp(parameter_value, "odd") == 0) {
parity = PARENB|PARODD;
} else if (strcmp(parameter_value, "even") == 0) {
parity = PARENB;
} else if (strcmp(parameter_value, "mark") == 0) {
parity = PARENB|PARODD|CMSPAR;
} else if (strcmp(parameter_value, "space") == 0) {
parity = PARENB|CMSPAR;
} else {
TTCN_error("Invalid %s value: %s\n", parameter_name, parameter_value);
}
//printf("Parameter %s set to %s (int: %d)\n", parameter_name, parameter_value, parity);
} else if (strcmp(parameter_name, "deviceBlocking") == 0) {
if (strcmp(parameter_value, "no") == 0) {
blocking = 0;
} else if (strcmp(parameter_value, "yes") == 0) {
blocking = 1;
} else {
TTCN_error("Invalid %s value: %s\n", parameter_name, parameter_value);
}
//printf("Parameter %s set to %s (int: %d)\n", parameter_name, parameter_value, blocking);
} else if (strncmp(parameter_name, "EOLChar", 7) == 0) {
eolChars.push_back(parameter_value[0]);
//printf("Parameter %s set to %s (int: %d)\n", parameter_name, parameter_value, eolChars.back());
} else if (strcmp(parameter_name, "dataBits") == 0) {
if (strcmp(parameter_value, "5") == 0) {
dataBits = CS5;
} else if (strcmp(parameter_value, "6") == 0) {
dataBits = CS6;
} else if (strcmp(parameter_value, "7") == 0) {
dataBits = CS7;
} else if (strcmp(parameter_value, "8") == 0) {
dataBits = CS8;
} else {
TTCN_error("Invalid %s value: %s\n", parameter_name, parameter_value);
}
//printf("Parameter %s set to %s (int: %d, hex: 0x%0)\n", parameter_name, parameter_value, dataBits);
} else if (strcmp(parameter_name, "stopBit") == 0) {
if (strcmp(parameter_value, "1") == 0) {
stopBit = ~CSTOPB;
} else if (strcmp(parameter_value, "2") == 0) {
stopBit = CSTOPB;
} else {
TTCN_error("Invalid %s value: %s\n", parameter_name, parameter_value);
}
//printf("Parameter %s set to %s (int: %d, hex: 0x%0)\n", parameter_name, parameter_value, stopBit);
}else if (strcmp(parameter_name, "CRtoNL") == 0) {
if (strcmp(parameter_value, "no") == 0){
CRtoNL = false;
} else if (strcmp(parameter_value, "yes") == 0){
CRtoNL = true;
}
}
}
/*void SerialPort::Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error) {}*/
void SerialPort::Handle_Fd_Event_Error(int /*fd*/)
{
//printf("===ELNRNAG=== Message received e\n");
}
void SerialPort::Handle_Fd_Event_Writable(int fd)
{
//printf("Message received w\n");
Handle_Fd_Event_Readable(fd);
}
void SerialPort::Handle_Fd_Event_Readable(int fd)
{
//printf("Message received r\n");
char input_buffer[1];
char* pointer = input_buffer;
int read_bytes = read(fd, pointer, 1); //sizeof(input_buffer));
if (read_bytes > 0) {
//printf("Incoming: %s (%d)\n",input_buffer, input_buffer[0]);
if (ret_buffer.is_bound()) { //already bound, concatenate
//printf ("already bound, concatenate");
ret_buffer += input_buffer[0];
} else { //ret_buffer not bound, create new
//printf("ret_buffer not bound, create new");
ret_buffer = CHARSTRING(read_bytes, (const char*)pointer);
}
for(unsigned int i = 0; i < eolChars.size(); i++){
if (input_buffer[0] == eolChars.at(i)) { //EOL received, returning
//printf("EOL received, returning");
CHARSTRING ret_val = CHARSTRING(ret_buffer);
ret_buffer = CHARSTRING("");
incoming_message(ret_val);
}
}
}
}
/*void SerialPort::Handle_Timeout(double time_since_last_call) {}*/
void SerialPort::user_map(const char * system_port)
{
if (param_device_file != NULL && param_device_file[0] != '\0'){
device_fd = open(param_device_file, O_RDWR | O_NOCTTY | O_NDELAY);
if (device_fd == -1)
{
TTCN_error("Unable to open port %s", param_device_file);
} else {
set_interface_attribs (device_fd, speed, parity, dataBits, stopBit, CRtoNL);
set_blocking (device_fd, blocking);
Handler_Add_Fd_Read(device_fd);
ret_buffer = CHARSTRING("");
}
} else {
TTCN_error("No device file set in configuration file!");
}
}
void SerialPort::user_unmap(const char * /*system_port*/)
{
Handler_Remove_Fd_Read(device_fd);
close(device_fd);
free(param_device_file);
ret_buffer.clean_up();
}
void SerialPort::user_start()
{
}
void SerialPort::user_stop()
{
}
void SerialPort::outgoing_send(const CHARSTRING& send_par)
{
const char* data = (const char*)send_par;
if (data != NULL) {
long data_length = send_par.lengthof();
//printf("Sending message: %s\n", data);
int n = write(device_fd, data, data_length);
//printf("Sent message: %s\n", data);
if (n < data_length) {
TTCN_error("Error while sending data on port %s", param_device_file);
}
}
}
int SerialPort::set_interface_attribs (int fd, speed_t speed, int parity, int dataBits, int stopBit, bool CRtoNL)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
TTCN_error ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, 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
if(CRtoNL){
tty.c_iflag |= ICRNL;
//printf("now iflag: %u ",tty.c_iflag);
} else {
tty.c_iflag &= ~ICRNL;
//printf("iflag: %u ",tty.c_iflag);
}
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
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 (tcsetattr (fd, TCSANOW, &tty) != 0)
{
TTCN_error ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void SerialPort::set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
TTCN_error ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 0; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
TTCN_error ("error %d setting term attributes", errno);
}
} /* end of namespace */