Skip to content

Instantly share code, notes, and snippets.

@0815fox
Last active October 12, 2018 06:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0815fox/9ce9f19648ce2dc9b23b37dbbb9adab4 to your computer and use it in GitHub Desktop.
Save 0815fox/9ce9f19648ce2dc9b23b37dbbb9adab4 to your computer and use it in GitHub Desktop.
/*
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