blob: 69596c1accae5f27e05198a71542a7e18c6cca7b [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2017 Ericsson Telecom AB
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// Lenard Nagy
// version R2A
///////////////////////////////////////////////////////////////////////////////
#include "GPIO_Pin_Port.hh"
#include "Logger.hh"
#include <stdarg.h>
namespace GPIOPinPort {
static const char *gpio_dir = "/sys/class/gpio/";
static const char *export_file = "/sys/class/gpio/export";
static const char *unexport_file = "/sys/class/gpio/unexport";
//DEBUG
//const char *export_file = "/home/elnrnag/gpio/export";
//const char *unexport_file = "/home/elnrnag/gpio/unexport";
//DEBUG
static const string GPIO_DIRECTION_OUT = "out";
static const string GPIO_DIRECTION_IN = "in";
static const string GPIO_VALUE_HIGH = "1";
static const string GPIO_VALUE_LOW = "0";
static const string GPIO_EDGE_NONE = "none";
static const string GPIO_EDGE_BOTH = "both";
static const int NUMBER_OF_PINS = 26;
GPIO__Pin__Port::GPIO__Pin__Port(const char *par_port_name)
: GPIO__Pin__Port_BASE(par_port_name)
, debugAllowed(false) // debug disabled by default
{
}
GPIO__Pin__Port::~GPIO__Pin__Port()
{
}
void GPIO__Pin__Port::log_debug(const char *fmt, ...)
{
if (debugAllowed) {
// if (true) {
va_list ap;
va_start(ap, fmt);
TTCN_Logger::begin_event(TTCN_DEBUG);
TTCN_Logger::log_event("GPIO Test Port (%s): ", get_name());
TTCN_Logger::log_event_va_list(fmt, ap);
TTCN_Logger::end_event();
va_end(ap);
}
}
void GPIO__Pin__Port::set_parameter(const char *parameter_name,
const char *parameter_value)
{
if (!strcasecmp(parameter_name, "debug")) {
if (!strcasecmp(parameter_value,"YES")) {
debugAllowed = true;
}
}
}
/*void GPIO__Pin__Port::Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error) {}*/
void GPIO__Pin__Port::Handle_Fd_Event_Error(int fd)
{
Handle_Fd_Event_Readable(fd);
}
void GPIO__Pin__Port::Handle_Fd_Event_Writable(int /*fd*/)
{
}
void GPIO__Pin__Port::Handle_Fd_Event_Readable(int fd)
{
//unregister_fd_handler();
//set_edge_on_pin(GPIO_EDGE_NONE);
//log_debug("FileDescriptor: %d",fd);
GPIOPinPort::GPIO__PIN__VALUE ret_val;
if (get_value_of_pin() == GPIO_VALUE_HIGH) {
ret_val = GPIO__PIN__VALUE::HIGH;
} else {
ret_val = GPIO__PIN__VALUE::LOW;
}
if (ret_val != original_value) {
original_value = ret_val;
log_debug("Received value on %s: is %s", pin.c_str(),get_value_of_pin().c_str());
incoming_message(ret_val);
}
}
/*void GPIO__Pin__Port::Handle_Timeout(double time_since_last_call) {}*/
void GPIO__Pin__Port::user_map(const char * system_port)
{
if ((strlen(system_port) >= 5) && (strlen(system_port) <= 8)) {
char* str = (char*)malloc(strlen(system_port)+1);
strcpy(str, system_port);
removechars(str, '[');
removechars(str, ']');
pin.assign(str);
log_debug("length: %zd ",strlen(pin.c_str()));
pin_num.assign(str+4);
log_debug("Mapping %s ", pin.c_str());
export_pin();
} else {
TTCN_error("Invalid gpio pin name: %s\nThe port variable name in TTCN code MUST be \"gpio[2-27]\"\n", pin.c_str());
}
}
void GPIO__Pin__Port::user_unmap(const char * system_port)
{
unregister_fd_handler(fd_edge);
unexport_pin();
}
void GPIO__Pin__Port::user_start()
{
}
void GPIO__Pin__Port::user_stop()
{
}
void GPIO__Pin__Port::outgoing_send(const GPIO__PIN__DIRECTION& direction)
{
if (direction == GPIO__PIN__DIRECTION::IN) {
set_direction_of_pin(GPIO_DIRECTION_IN);
set_edge_on_pin(GPIO_EDGE_BOTH);
if (get_value_of_pin() == GPIO_VALUE_HIGH) {
original_value = GPIO__PIN__VALUE::HIGH;
} else {
original_value = GPIO__PIN__VALUE::LOW;
}
} else if (direction == GPIO__PIN__DIRECTION::OUT) {
set_edge_on_pin(GPIO_EDGE_NONE);
set_direction_of_pin(GPIO_DIRECTION_OUT);
} else {
//TODO: ERROR, must be set
}
}
void GPIO__Pin__Port::outgoing_send(const GPIO__PIN__VALUE& value)
{
if (value == GPIO__PIN__VALUE::LOW) {
set_value_of_pin(GPIO_VALUE_LOW);
} else if (value == GPIO__PIN__VALUE::HIGH) {
set_value_of_pin(GPIO_VALUE_HIGH);
} else {
TTCN_error("Value for %s must be set", pin.c_str());
}
}
void GPIO__Pin__Port::outgoing_send(const GPIO__PIN__STATUS& stat)
{
GPIO__PIN__STATUS status;
if (file_exists(get_pin_dir())){
status.is__exported() = true;
string direction = get_direction_of_pin();
if (0 == direction.compare(GPIO_DIRECTION_IN)) {
status.direction() = GPIO__PIN__DIRECTION::IN;
} else if (0 == direction.compare(GPIO_DIRECTION_OUT)) {
status.direction() = GPIO__PIN__DIRECTION::OUT;
} else {
TTCN_error("Invalid direction when reading direction of %s", pin.c_str());
}
string value = get_value_of_pin();
if (0 == value.compare(GPIO_VALUE_LOW)) {
status.val() = GPIO__PIN__VALUE::LOW;
} else if (0 == value.compare(GPIO_VALUE_HIGH)) {
status.val() = GPIO__PIN__VALUE::HIGH;
} else {
TTCN_error("Invalid value when reading value of %s ", pin.c_str());
}
} else {
status.is__exported() = false;
}
incoming_message(status);
}
//Utility functions
void GPIO__Pin__Port::export_pin() {
if (!file_exists(get_pin_dir().c_str())) {
log_debug("Exporting gpio%s (export file: %s) ",pin_num.c_str(), export_file);
ofstream exfile;
exfile.exceptions(ofstream::failbit | ofstream::badbit);
exfile.open (export_file);
exfile << pin_num.c_str();
} else {
log_debug("===WARNING=== %s was already exported!",pin.c_str());
}
}
void GPIO__Pin__Port::unexport_pin() {
log_debug("Unexporting gpio%s (export file: %s)", pin_num.c_str(), export_file);
ofstream unexfile;
unexfile.exceptions(ofstream::failbit | ofstream::badbit);
unexfile.open (unexport_file);
string pin_s(pin_num);
unexfile << pin_s.c_str();
}
void GPIO__Pin__Port::set_direction_of_pin(const string direction) {
string pin_direction_filename = get_pin_dir()+"/direction";
log_debug("Set direction of %s to %s", pin.c_str(), direction.c_str());
ofstream pin_direction_file;
pin_direction_file.exceptions(ofstream::failbit | ofstream::badbit);
pin_direction_file.open (pin_direction_filename.c_str());
pin_direction_file << direction.c_str();
pin_direction_file.close();
}
string GPIO__Pin__Port::get_direction_of_pin() {
string pin_direction_filename = get_pin_dir()+"/direction";
string line;
ifstream pin_direction_file;
pin_direction_file.exceptions(ifstream::failbit | ifstream::badbit);
pin_direction_file.open (pin_direction_filename.c_str());
getline(pin_direction_file,line);
pin_direction_file.close();
return line;
}
void GPIO__Pin__Port::set_value_of_pin(const string value) {
string pin_value_filename = get_pin_dir()+"/value";
log_debug("Set value of %s to %s ", pin.c_str(), value.c_str());
ofstream pin_value_file;
pin_value_file.exceptions(ofstream::failbit | ofstream::badbit);
pin_value_file.open (pin_value_filename.c_str());
pin_value_file << value.c_str();
pin_value_file.close();
}
string GPIO__Pin__Port::get_value_of_pin() {
string pin_value_filename = get_pin_dir()+"/value";
string line;
ifstream pin_value_file;
pin_value_file.exceptions(ifstream::failbit | ifstream::badbit);
pin_value_file.open (pin_value_filename.c_str());
getline(pin_value_file,line);
pin_value_file.close();
return line;
}
void GPIO__Pin__Port::set_edge_on_pin(const string edge) {
string pin_edge_filename = get_pin_dir()+"/edge";
log_debug("Set edge to \"%s\" on %s ", edge.c_str(),pin.c_str());
ofstream pin_edge_file;
pin_edge_file.exceptions(ofstream::failbit | ofstream::badbit);
pin_edge_file.open (pin_edge_filename.c_str());
pin_edge_file << edge.c_str();
pin_edge_file.close();
if (edge != GPIO_EDGE_NONE) {
int fd = open(pin_edge_filename.c_str(),O_RDONLY);
register_fd_handler(fd);
}
}
void GPIO__Pin__Port::register_fd_handler(int fd) {
if (fd > 0) {
Handler_Add_Fd_Read(fd);
fd_edge = fd;
}
}
void GPIO__Pin__Port::unregister_fd_handler(int fd) {
if (fd > 0) {
Handler_Remove_Fd_Read(fd);
close(fd);
fd_edge = -1;
}
}
string GPIO__Pin__Port::int2string(int i) {
string str;
stringstream ss;
ss << i;
ss >> str;
return str;
}
int GPIO__Pin__Port::string2int(const char* str) {
stringstream strValue;
strValue << str;
unsigned int intValue;
strValue >> intValue;
return intValue;
}
void GPIO__Pin__Port::removechars(char* s, char c) {
int writer = 0, reader = 0;
while (s[reader])
{
if (s[reader]!=c)
{
s[writer++] = s[reader];
}
reader++;
}
s[writer]=0;
}
bool GPIO__Pin__Port::file_exists (const std::string& name) {
return ( access( name.c_str(), F_OK ) != -1 );
}
string GPIO__Pin__Port::get_pin_dir() {
return string(gpio_dir)+pin;
}
} /* end of namespace */