From 5523c3effbe62e173d797b808bb5e29aeba4cf1a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ji=C5=99=C3=AD=20Mat=C4=9Bj=C3=A1k?= Date: Thu, 3 May 2018 10:25:44 +0200 Subject: [PATCH] gpio started --- Makefile | 5 +- mt_gpio.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mt_gpio.h | 33 ++++++++ 3 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 mt_gpio.c create mode 100644 mt_gpio.h diff --git a/Makefile b/Makefile index 8f12a1c..d19b094 100644 --- a/Makefile +++ b/Makefile @@ -6,11 +6,14 @@ mtrfid_LIBS = -lev -luFCoder-armhf mtserver_SRCS = signal_exit.c mt_server.c mtserver_LIBS = -lev -lwebsockets +mtgpio_SRCS = signal_exit.c mt_gpio.c +mtgpio_LIBS = -lev + mtaio_SRCS = signal_exit.c mt_rfid.c mt_server.c mt_aio.c mtaio_LIBS = -lev -luFCoder-armhf -lwebsockets mtaio_DEFS = -DNO_MAIN -all: mtrfid mtserver mtaio +all: mtrfid mtserver mtgpio mtaio .PHONY: clean diff --git a/mt_gpio.c b/mt_gpio.c new file mode 100644 index 0000000..3176d77 --- /dev/null +++ b/mt_gpio.c @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "mt_rfid.h" +#include "signal_exit.h" + +// shit to avoid constant repetition +#define CONCAT_AGAIN(A,B) A ## B +#define CONCAT(A,B) CONCAT_AGAIN(A,B) + +static int set_nonblock(int fd) +{ + int flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) { + perror("fcntl (get)"); + return -1; + } + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { + perror("fcntl (set)"); + return -1; + } + fprintf(stderr, "set %d non-blocking\n", fd); + return 0; +} + +static int set_rts(int fd, int level) +{ + int uart_status; + + if (ioctl(fd, TIOCMGET, &uart_status) == -1) { + perror("ioctl (TIOCMGET)"); + return -1; + } + + if (level) { + uart_status |= TIOCM_RTS; + } else { + uart_status &= ~TIOCM_RTS; + } + + if (ioctl(fd, TIOCMSET, &uart_status) == -1) { + perror("TIOCMSET"); + return -1; + } + + fprintf(stderr, "set %d rts %d\n", fd, level); + + return 0; +} + +static void set_baud_rate(int fd, int br) //TODO add some checking +{ + struct termios options; + + tcgetattr(fd, &options); + cfsetispeed(&options, br); + cfsetospeed(&options, br); + tcsetattr(fd, TCSANOW, &options); +} + +static int tty_open(const char *port, int br) +{ + + int fd = open(port, O_RDONLY | O_NOCTTY); + if (fd < 0) { + perror("open"); + return fd; + } else { + fprintf(stderr, "opened %s as %d\n", port, fd); + } + + set_nonblock(fd); + set_rts(fd, 0); //disable + set_baud_rate(fd, br); + usleep(1200000); //value by d-logic + tcflush(fd, TCIFLUSH); + + return fd; +} + +// really simple JSON helpers +#define JSON_START() dprintf(fd,"{") +#define JSON_NUM(NAME) dprintf(fd,"\"" #NAME "\":%d", NAME) //see the int? +#define JSON_NEXT() dprintf(fd,",") +#define JSON_STR(NAME) dprintf(fd,"\"" #NAME "\":\"%s\"", NAME) +#define JSON_END() dprintf(fd,"}\n") + +// print complete json +#define JSON_PRINT() do { \ + JSON_START(); \ + JSON_STR(type); \ + JSON_NEXT(); \ + JSON_NUM(card_type); \ + JSON_NEXT(); \ + JSON_NUM(sak); \ + JSON_NEXT(); \ + JSON_NUM(size); \ + JSON_NEXT(); \ + JSON_STR(uid); \ + JSON_END(); \ +} while (0) + +static void ufr_read(char *uid, int fd) +{ + static char *type = "rfid"; + + UFR_STATUS status; + uint8_t card_type; + uint8_t sak; //select acknowledge + uint8_t uid_bytes[10]; //uid as bytes + uint8_t size; + + status = GetDlogicCardType(&card_type); + if (status != UFR_OK) { + fprintf(stderr, "GetDlogicCardType: %s\n", UFR_Status2String(status)); + return; + } + + status = GetCardIdEx(&sak, uid_bytes, &size); + if (status != UFR_OK) { + fprintf(stderr, "GetCardIdEx: %s\n", UFR_Status2String(status)); + return; + } + + JSON_PRINT(); + +#ifdef UFR_BEEP + ReaderUISignal(0, 1); // no light, one beep +#endif +} + +#define UFR_ASYNC_SUFFIX 0 // keep it zero: separates uids, terminates strings + +static void ufr_cb(EV_P_ ev_io *w_, int revents) +{ + ev_io_ufr *w = (ev_io_ufr *)w_; + char uid; + + read(w->w.fd, &uid, 1); + *(w->uid++) = uid; + + if (uid == UFR_ASYNC_SUFFIX) { + //*(w->uid - 1) = 0; // no need if UFR_ASYNC_SUFFIX is 0 + w->uid = w->uid_data; + ufr_read(w->uid, w->fd); + } +} + +static int ufr_open(unsigned reader_type, char *port_name, + unsigned port_interface) +{ + UFR_STATUS status; + + fprintf(stderr, "uFCoder version: %s\n", GetDllVersionStr()); + + status = ReaderOpenEx(reader_type, port_name, port_interface, 0); + if (status != UFR_OK) { + fprintf(stderr, "ReaderOpenEx: %s\n", UFR_Status2String(status)); + return -1; + } + + fprintf(stderr, "%s\n", GetReaderDescription()); + + status = SetAsyncCardIdSendConfig( + 1, //enable send + 0, //disable prefix + 0, //prefix + UFR_ASYNC_SUFFIX, //suffix + 0, //disable send removed + UFR_ASYNC_BAUD_RATE + ); + fprintf(stderr, "SetAsyncCardIdSendConfig: %s\n", UFR_Status2String(status)); + if (status != UFR_OK) { + return -1; + } + + return 0; +} + +int mt_rfid_init(mt_rfid_t *self, struct ev_loop *loop, int fd) +{ + if (ufr_open(UFR_READER_TYPE, UFR_PORT_NAME, UFR_PORT_INTERFACE) == -1) { + return -1; + } + + int tty = tty_open(UFR_PORT_NAME, CONCAT(B, UFR_ASYNC_BAUD_RATE)); + if (tty < 0) { + return -2; + } + self->fd = tty; + + ev_io_ufr *w = &(self->w); + w->uid = w->uid_data; + w->fd = fd; + ev_io_init(&(w->w), ufr_cb, tty, EV_READ); + ev_io_start(loop, (ev_io *)w); + + return 0; +} + +void mt_rfid_deinit(mt_rfid_t *self) +{ + if (close(self->fd) == 0) { + fprintf(stderr, "closed %d\n", self->fd); + } else { + perror("close"); + } + + UFR_STATUS status = ReaderClose(); + fprintf(stderr, "ReaderClose: %s\n", UFR_Status2String(status)); +} + +#ifndef NO_MAIN +int main(int argc, char **argv) +{ + struct ev_loop *loop = EV_DEFAULT; + mt_rfid_t rfid; + + set_signal_exit(loop); + + if (mt_rfid_init(&rfid, loop, STDOUT_FILENO) != 0) { + return -1; + } + + ev_run(loop, 0); + + mt_rfid_deinit(&rfid); + + return 0; +} +#endif diff --git a/mt_gpio.h b/mt_gpio.h new file mode 100644 index 0000000..fad9390 --- /dev/null +++ b/mt_gpio.h @@ -0,0 +1,33 @@ +#ifndef MT_RFID_H +#define MT_RFID_H + +#include + +// reader open parameters, see uFR manual +#define UFR_READER_TYPE 1 // uFR type (1Mbps) +#define UFR_PORT_INTERFACE 1 // serial; auto->ftdi->FAIL +#define UFR_PORT_NAME "/dev/ttyUSB0" // reader device +#define UFR_ASYNC_BAUD_RATE 1000000 // 1Mbps, otherwise UFR_COMMUNICATION_BREAK + +#define UFR_BEEP // define this to annoy people + +typedef struct ev_io_ufr { + ev_io w; // fd watcher + char uid_data[24]; // store uid here (uid is 10 bytes max) + char *uid; // current position in uid_data + int fd; // PORT_NAME file descriptor +} ev_io_ufr; + +typedef struct mt_rfid_t { + ev_io_ufr w; // reader watcher + int fd; // print JSON output here +} mt_rfid_t; + +// connect to the reader, add self to loop and make it write to fd +// return 0 on success, negative number otherwise +int mt_rfid_init(mt_rfid_t *self, struct ev_loop *loop, int fd); + +// disconnect from reader +void mt_rfid_deinit(mt_rfid_t *self); + +#endif -- 2.39.2