Last active
October 12, 2018 06:10
-
-
Save 0815fox/9ce9f19648ce2dc9b23b37dbbb9adab4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
compile & run: | |
gcc -lpthread epoll-playground.c && ./a.out | |
*/ | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <string.h> | |
#include <termios.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <sys/epoll.h> | |
#include <linux/loop.h> | |
#include <sys/ioctl.h> | |
#include <pthread.h> | |
static int getFreeLoopDevice(const char * backingfileName) { | |
int loopctlfd, loopfd, backingfile; | |
long devnr; | |
char loopname[4096]; | |
loopctlfd = open("/dev/loop-control", O_RDWR); | |
devnr = ioctl(loopctlfd, LOOP_CTL_GET_FREE); | |
close(loopctlfd); | |
return devnr; | |
sprintf(loopname, "/dev/loop%ld", devnr); | |
loopfd = open(loopname, O_RDWR); | |
backingfile = open(backingfileName, O_RDWR); | |
ioctl(loopfd, LOOP_SET_FD, backingfile); | |
return loopfd; | |
} | |
static int set_interface_attribs (int fd, int speed, int parity) { | |
struct termios tty; | |
memset (&tty, 0, sizeof tty); | |
if (tcgetattr (fd, &tty) != 0) { | |
fprintf (stderr, "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 | |
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); // 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) { | |
fprintf (stderr, "error %d from tcsetattr", errno); | |
return -1; | |
} | |
return 0; | |
} | |
void set_blocking (int fd, int should_block) { | |
struct termios tty; | |
memset (&tty, 0, sizeof tty); | |
if (tcgetattr (fd, &tty) != 0) | |
{ | |
fprintf (stderr, "error %d from tggetattr", errno); | |
return; | |
} | |
tty.c_cc[VMIN] = should_block ? 1 : 0; | |
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout | |
if (tcsetattr (fd, TCSANOW, &tty) != 0) | |
fprintf (stderr, "error %d setting term attributes", errno); | |
} | |
static void * uart_thread(void * handle) { | |
const int uartHandle = *(int*)handle; | |
char buffer[100]; | |
// the epoll stuff: | |
const int ePollFileDescriptor = epoll_create(1); | |
struct epoll_event ePollEvent; | |
ePollEvent.events = EPOLLIN; | |
ePollEvent.data.fd = uartHandle; | |
const int epoll_ctl_result = epoll_ctl(ePollFileDescriptor, EPOLL_CTL_ADD, uartHandle, &ePollEvent); | |
if (epoll_ctl_result) perror("epoll_ctl\n"); | |
for (;;) { | |
static struct epoll_event events[1] __attribute__((aligned(8))); | |
const int eventCount = epoll_wait(ePollFileDescriptor, events, 1, -1); | |
if (eventCount < 0) { | |
perror("epoll_wait\n"); | |
} else { | |
const int bytesRead = read(uartHandle, buffer, 99); | |
if (bytesRead >= 0) buffer[bytesRead] = 0; | |
else buffer[0] = 0; | |
fprintf(stderr, "Buffer: %s\nBytesread:%d\n", buffer, bytesRead); | |
} | |
} | |
} | |
int main (void) { | |
// working: | |
// char *portname = "/dev/ttyUSB0"; | |
// const int uartHandle = open (portname, O_RDWR | O_NOCTTY | O_SYNC); | |
// not working: | |
const int uartHandle = getFreeLoopDevice("/tmp/my-loop-back"); | |
if (uartHandle < 0) { | |
fprintf (stderr, "error %d opening: %s\n", errno, strerror (errno)); | |
return errno; | |
} | |
set_interface_attribs (uartHandle, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity) | |
set_blocking (uartHandle, 0); // set no blocking | |
// the pthread stuff: | |
pthread_t threadHandle; | |
const int pthread_create_result = pthread_create( &threadHandle, NULL, uart_thread, (void *) &uartHandle); | |
while (1) { | |
fprintf(stderr, "writing to uart\n"); | |
write(uartHandle, "hello!\n", 7); | |
sleep(10); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment