mirror of
https://github.com/Martin-P/OpenV2G.git
synced 2024-11-18 12:53:58 +00:00
- changed Tool Chain Editor from 'MinGW GCC' to 'Linux GCC'
- added test/network_expample_1 --> TCP-Server for EVSE git-svn-id: https://svn.code.sf.net/p/openv2g/code/trunk@21 d9f2db14-54d0-4bde-b00c-16405c910529
This commit is contained in:
parent
350a915582
commit
3e4a8426d8
7 changed files with 1399 additions and 1020 deletions
138
.project
138
.project
|
@ -1,69 +1,69 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<projectDescription>
|
<projectDescription>
|
||||||
<name>OpenV2G</name>
|
<name>OpenV2G</name>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
<projects>
|
<projects>
|
||||||
</projects>
|
</projects>
|
||||||
<buildSpec>
|
<buildSpec>
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||||
<triggers>clean,full,incremental,</triggers>
|
<triggers>clean,full,incremental,</triggers>
|
||||||
<arguments>
|
<arguments>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>?name?</key>
|
<key>?name?</key>
|
||||||
<value></value>
|
<value></value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.append_environment</key>
|
<key>org.eclipse.cdt.make.core.append_environment</key>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
||||||
<value></value>
|
<value></value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
||||||
<value>make</value>
|
<value>make</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.buildLocation</key>
|
<key>org.eclipse.cdt.make.core.buildLocation</key>
|
||||||
<value>${workspace_loc:/OpenV2G/Debug}</value>
|
<value>${workspace_loc:/OpenV2G/Debug}</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.contents</key>
|
<key>org.eclipse.cdt.make.core.contents</key>
|
||||||
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
|
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
|
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
|
||||||
<value>false</value>
|
<value>false</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
|
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
|
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.stopOnError</key>
|
<key>org.eclipse.cdt.make.core.stopOnError</key>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary>
|
<dictionary>
|
||||||
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
|
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
|
||||||
<value>true</value>
|
<value>true</value>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</arguments>
|
</arguments>
|
||||||
</buildCommand>
|
</buildCommand>
|
||||||
<buildCommand>
|
<buildCommand>
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||||
<arguments>
|
<arguments>
|
||||||
</arguments>
|
</arguments>
|
||||||
</buildCommand>
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
</projectDescription>
|
</projectDescription>
|
||||||
|
|
|
@ -37,5 +37,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
/* V2G client / service example scenario */
|
/* V2G client / service example scenario */
|
||||||
return main_service(argc, argv);
|
return main_service(argc, argv);
|
||||||
|
|
||||||
|
/* network example 1 */
|
||||||
|
/* return main_network_1(argc, argv); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,5 +30,6 @@
|
||||||
|
|
||||||
int main_codec(int argc, char *argv[]);
|
int main_codec(int argc, char *argv[]);
|
||||||
int main_service(int argc, char *argv[]);
|
int main_service(int argc, char *argv[]);
|
||||||
|
int main_network_1(int argc, char *argv[]);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
140
src/test/network_example1/main_network_1.c
Normal file
140
src/test/network_example1/main_network_1.c
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 INSYS Microelectronics GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* @author mlauterbach
|
||||||
|
* @version 0.0.1
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define EVSE 1
|
||||||
|
#define PEV 2
|
||||||
|
|
||||||
|
static char *help_string =
|
||||||
|
"%s: Valid parameters are:\n"
|
||||||
|
" -v - print the program version and exit\n"
|
||||||
|
" -d - daemonize this process\n"
|
||||||
|
" -m<x> - mode of application with x=1 EVSE or x=2 PEV\n"
|
||||||
|
" -h - help\n";
|
||||||
|
|
||||||
|
extern void run_evse(unsigned int port);
|
||||||
|
extern void run_pev(unsigned int port);
|
||||||
|
|
||||||
|
|
||||||
|
static void arg_error(char *name)
|
||||||
|
{
|
||||||
|
fprintf(stderr, help_string, name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main_network_1(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd0, fd1, fd2;
|
||||||
|
int i, pid;
|
||||||
|
int daemonize = 0;
|
||||||
|
int mode = -1;
|
||||||
|
unsigned int port = 7259; /* TODO port is fix, should be configurable */
|
||||||
|
|
||||||
|
/* check arguments */
|
||||||
|
if(argc == 1)
|
||||||
|
arg_error("too few parameters");
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
if ((argv[i][0] != '-') || (strlen(argv[i]) > 3)) {
|
||||||
|
fprintf(stderr, "Invalid argument: '%s'\n", argv[i]);
|
||||||
|
arg_error(argv[0]);
|
||||||
|
}
|
||||||
|
switch (argv[i][1]) {
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
daemonize = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
mode = atoi(&argv[i][2]);
|
||||||
|
if(mode != EVSE && mode != PEV) {
|
||||||
|
fprintf(stderr, "Invalid option: '%s'\n", argv[i]);
|
||||||
|
arg_error(argv[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h' :
|
||||||
|
fprintf(stdout, help_string, argv[0]);
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
printf("%s Example 1: 0.0.1\n", argv[0]);
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Invalid option: '%s'\n", argv[i]);
|
||||||
|
arg_error(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemonize) {
|
||||||
|
if ((pid = fork()) > 0) {
|
||||||
|
exit(0);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
printf("Error forking first fork\n");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
/* setsid() is necessary if we really want to demonize */
|
||||||
|
if(setsid() == -1)
|
||||||
|
printf("Error setsid()\n");
|
||||||
|
/* Second fork to really deamonize me. */
|
||||||
|
if ((pid = fork()) > 0) {
|
||||||
|
exit(0);
|
||||||
|
} else if (pid < 0) {
|
||||||
|
printf("Error forking second fork\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* change working directory to root so we won't prevent file systems
|
||||||
|
* from being unmounted.
|
||||||
|
*/
|
||||||
|
if(chdir("/") < 0) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
/* Attach file descriptors 0, 1, and 2 to /dev/null */
|
||||||
|
fd0 = open("/dev/null", O_RDWR);
|
||||||
|
fd1 = dup(0);
|
||||||
|
fd2 = dup(0);
|
||||||
|
}else {
|
||||||
|
printf("+++Start EVSE/PEV Example+++\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == EVSE) {
|
||||||
|
printf("+++Start EVSE on port: %i+++\n\n", port);
|
||||||
|
run_evse(port);
|
||||||
|
|
||||||
|
}else if (mode == PEV) {
|
||||||
|
printf("+++Start PEV to port: %i+++\n\n", port);
|
||||||
|
run_pev(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("+++Terminate EV2SE Example+++\n\n");
|
||||||
|
return 0;
|
||||||
|
}
|
214
src/test/network_example1/run_evse.c
Normal file
214
src/test/network_example1/run_evse.c
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 INSYS Microelectronics GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* @author mlauterbach
|
||||||
|
* @version 0.0.1
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
fd_set master_fd; /* master fd list */
|
||||||
|
fd_set read_fds; /* tmp fd list for select() */
|
||||||
|
int fdmax; /* maximum file descriptor number */
|
||||||
|
int listen_fd; /* file descriptor for TCP-Server */
|
||||||
|
int pev_fd; /* file descriptor to PEV */
|
||||||
|
|
||||||
|
|
||||||
|
static void close_server(void)
|
||||||
|
{
|
||||||
|
if(listen_fd == -1)
|
||||||
|
return;
|
||||||
|
tcflush(listen_fd, TCIOFLUSH);
|
||||||
|
FD_CLR(listen_fd, &master_fd);
|
||||||
|
close(listen_fd);
|
||||||
|
listen_fd = -1;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void init_server(void)
|
||||||
|
{
|
||||||
|
listen_fd = -1;
|
||||||
|
pev_fd = -1;
|
||||||
|
FD_ZERO(&master_fd);
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cleanup_server(void)
|
||||||
|
{
|
||||||
|
close_server();
|
||||||
|
if(pev_fd != -1) {
|
||||||
|
close(pev_fd);
|
||||||
|
pev_fd = -1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int start_server(unsigned int port)
|
||||||
|
{
|
||||||
|
|
||||||
|
int yes = 1;
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *ai;
|
||||||
|
char str_port[10];
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof hints);
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
|
||||||
|
sprintf(str_port, "%d", port);
|
||||||
|
if ((getaddrinfo(NULL, str_port, &hints, &ai)) != 0) {
|
||||||
|
printf("ERROR: Could not get address info for the TCP listener: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
listen_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); /* create the socket */
|
||||||
|
if (listen_fd < 0) {
|
||||||
|
printf("ERROR: Creation of TCP listen socket failed: %s\n", strerror(errno));
|
||||||
|
listen_fd = -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); /* just some options */
|
||||||
|
if (bind(listen_fd, ai->ai_addr, ai->ai_addrlen) < 0) { /* now we bind it to the port */
|
||||||
|
printf("ERROR: Binding TCP listen socket failed: %s\n", strerror(errno));
|
||||||
|
close(listen_fd);
|
||||||
|
listen_fd = -1;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
freeaddrinfo(ai);
|
||||||
|
|
||||||
|
if (listen(listen_fd, 10) == -1) { /* and put the socket in listen-mode */
|
||||||
|
printf("ERROR: Listening on TCP listen socket failed: %s\n", strerror(errno));
|
||||||
|
close(listen_fd);
|
||||||
|
listen_fd = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_SET(listen_fd, &master_fd);
|
||||||
|
if(listen_fd > fdmax)
|
||||||
|
fdmax = listen_fd;
|
||||||
|
|
||||||
|
printf("DEBUG: TCP-Server fd:%i\n", listen_fd);
|
||||||
|
return listen_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int accept_connection(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct sockaddr_in remoteaddr;
|
||||||
|
socklen_t addrlen = sizeof remoteaddr;
|
||||||
|
|
||||||
|
pev_fd = accept(listen_fd, (struct sockaddr *) &remoteaddr, &addrlen);
|
||||||
|
if (pev_fd == -1) {
|
||||||
|
printf("ERROR: Could not accept on TCP listen socket: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_SET(pev_fd, &master_fd);
|
||||||
|
if (pev_fd > fdmax) {
|
||||||
|
fdmax = pev_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("PEV arrived .................... ;-)\n");
|
||||||
|
close_server();
|
||||||
|
return pev_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int handle_tcp_data(void)
|
||||||
|
{
|
||||||
|
ssize_t read_bytes;
|
||||||
|
uint8_t buffer[512];
|
||||||
|
|
||||||
|
read_bytes = read(pev_fd, buffer, sizeof(buffer)); /* get data from PEV */
|
||||||
|
if(read_bytes < 1) {
|
||||||
|
if(errno != EAGAIN) {
|
||||||
|
if(errno == EBADF)
|
||||||
|
printf("ERROR: Reading from TCP failed: connection is gone\n");
|
||||||
|
else
|
||||||
|
printf("ERROR: Reading from TCP failed: %d: %s\n", errno, strerror(errno));
|
||||||
|
printf("INFO: PEV gone\n");
|
||||||
|
close(pev_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("INFO: number of bytes from PEV: %i\n", read_bytes);
|
||||||
|
|
||||||
|
/* TODO give data to DoIP/EXI Parser and send response to PEV, if a complete EXI msg. was received */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void run_evse(unsigned int port)
|
||||||
|
{
|
||||||
|
int sel;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
init_server();
|
||||||
|
|
||||||
|
listen_fd = start_server(port);
|
||||||
|
if (listen_fd == -1) {
|
||||||
|
printf("ERROR: open_server failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 100000;
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
read_fds = master_fd;
|
||||||
|
|
||||||
|
sel = select(fdmax + 1, &read_fds, NULL, NULL, &tv);
|
||||||
|
if(sel > 0) {
|
||||||
|
if (FD_ISSET(listen_fd, &read_fds))
|
||||||
|
accept_connection();
|
||||||
|
if (FD_ISSET(pev_fd, &read_fds))
|
||||||
|
if(handle_tcp_data() == -1) { /* PEV gone */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else if (sel == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_server();
|
||||||
|
return;
|
||||||
|
}
|
30
src/test/network_example1/run_pev.c
Normal file
30
src/test/network_example1/run_pev.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 INSYS Microelectronics GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
*
|
||||||
|
* @author mlauterbach
|
||||||
|
* @version 0.0.1
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
void run_pev(unsigned int port)
|
||||||
|
{
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return;
|
||||||
|
}
|
Loading…
Reference in a new issue