From e0e9c5ac9f88b80baf8735fb394869bf32c067e8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ji=C5=99=C3=AD=20Mat=C4=9Bj=C3=A1k?= Date: Tue, 24 Apr 2018 17:24:25 +0200 Subject: [PATCH] async uid + libev --- mt_rfid.c | 275 ++++++++++++++++++++++++++++++++++++++---------------- mt_rfid.h | 27 ++---- 2 files changed, 204 insertions(+), 98 deletions(-) diff --git a/mt_rfid.c b/mt_rfid.c index 3d4ab3b..a16dffb 100644 --- a/mt_rfid.c +++ b/mt_rfid.c @@ -6,116 +6,231 @@ #include #include #include -#include -#include +#include +#include +#include + +#include +#include #include "mt_rfid.h" -#include "uFCoder.h" -// really simple JSON helpers -#define JSON_NUM(NAME) printf("\"" #NAME "\": %d", NAME) -#define JSON_STR(NAME) printf("\"" #NAME "\": \"%s\"", NAME) -#define JSON_START() printf("{\n") -#define JSON_NEXT() printf(",\n") -#define JSON_END() printf("\n}\n") +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 non-blocking\n"); + return 0; +} + +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 rts %d\n", level); + + return 0; +} + +void set_baud_rate(int fd, int br) { + struct termios options; + + tcgetattr(fd, &options); + cfsetispeed(&options, br); + cfsetospeed(&options, br); + tcsetattr(fd, TCSANOW, &options); +} + +int tty_open(const char *port, int baud_rate) { + + 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); + set_baud_rate(fd, baud_rate); + usleep(1200000); //value by d-logic + tcflush(fd, TCIFLUSH); + + return fd; +} -static mt_rfid_t ufr = {READER_TYPE, PORT_NAME, PORT_INTERFACE, 0, 1}; +typedef struct ev_io_ufr { + ev_io w; + char uid_data[24]; + char *uid; +} ev_io_ufr; -static void signal_exit(int sig) +static void sigint_cb(EV_P_ ev_signal *w, int revents) { - ufr.run = 0; - fprintf(stderr, "signal %d, terminating\n", sig); + ev_break (EV_A_ EVBREAK_ALL); } -void *mt_rfid_run(void *ptr) +static void ufr_read(char *uid) { - mt_rfid_t *self = (mt_rfid_t *)ptr; UFR_STATUS status; - uint8_t card_type; uint8_t sak; //select acknowledge - uint8_t uid_num[10]; //uid as bytes + uint8_t uid_bytes[10]; //uid as bytes uint8_t uid_size; - char uid[24]; //uid as a string - fprintf(stderr, "uFCoder library version: %s\n", GetDllVersionStr()); + status = GetDlogicCardType(&card_type); + if (status != UFR_OK) { + fprintf(stderr, "GetDlogicCardType: %s\n", UFR_Status2String(status)); + return; + } - status = ReaderOpenEx(self->reader_type, self->port_name, self->port_interface, 0); + status = GetCardIdEx(&sak, uid_bytes, &uid_size); if (status != UFR_OK) { - fprintf(stderr, "ReaderOpenEx: %s\n", UFR_Status2String(status)); - return NULL; + fprintf(stderr, "GetCardIdEx: %s\n", UFR_Status2String(status)); + return; } - fputs(GetReaderDescription(), stderr); - - while (self->run) { - status = GetDlogicCardType(&card_type); - if (status != UFR_OK) { - if (status != UFR_NO_CARD) { - fprintf(stderr, "GetDlogicCardType: %s\n", UFR_Status2String(status)); - } - usleep(10000); - continue; - } - - status = GetCardIdEx(&sak, uid_num, &uid_size); - if (status != UFR_OK) { - if (status != UFR_NO_CARD) { - fprintf(stderr, "GetCardIdEx: %s\n", UFR_Status2String(status)); - } - usleep(10000); - continue; - } - - for (uint8_t i = 0; i < uid_size; i++) { - sprintf(&uid[2*i], "%02x", uid_num[i]); - } - - JSON_START(); - JSON_NUM(card_type); JSON_NEXT(); - JSON_NUM(sak); JSON_NEXT(); - JSON_NUM(uid_size); JSON_NEXT(); - JSON_STR(uid); JSON_END(); - - if (self->beep) { - ReaderUISignal(0, 1); - } - - usleep(500000); + JSON_START(); + JSON_NUM(card_type); JSON_NEXT(); + JSON_NUM(sak); JSON_NEXT(); + JSON_NUM(uid_size); JSON_NEXT(); + JSON_STR(uid); JSON_END(); + + ReaderUISignal(0, 1); +} + +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 == ASYNC_SUFFIX) { + //*(w->uid - 1) = 0; + w->uid = w->uid_data; + ufr_read(w->uid); } - status = ReaderClose(); - fprintf(stderr, "ReaderClose: %s\n", UFR_Status2String(status)); + //for one-shot events, one must manually stop the watcher with its corresponding stop function. + //ev_io_stop (EV_A_ w); - return NULL; + //this causes all nested ev_run's to stop iterating + //ev_break (EV_A_ EVBREAK_ALL); } -int main(int argc, char **argv) +ev_io_ufr ufr_watcher; +ev_signal int_watcher, term_watcher; + +int libev_run(int fd) +{ + struct ev_loop *loop = EV_DEFAULT; + + ufr_watcher.uid = ufr_watcher.uid_data; + ev_io_init (&(ufr_watcher.w), ufr_cb, fd, EV_READ); + ev_io_start (loop, (ev_io *)&ufr_watcher); + + ev_signal_init (&int_watcher, sigint_cb, SIGINT); + ev_signal_start (loop, &int_watcher); + ev_signal_init (&term_watcher, sigint_cb, SIGTERM); + ev_signal_start (loop, &term_watcher); + + ev_run (loop, 0); + + return 0; +} + +int ufr_open(unsigned reader_type, char *port_name, unsigned port_interface) { - pthread_t t; - char c; - - while ((c = getopt(argc, argv, "p:bh")) != -1) { - switch (c) { - case 'p': - ufr.port_name = optarg; - break; - case 'b': - ufr.beep = 1; - break; - } + 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 + ASYNC_SUFFIX, //suffix + 0, //disable send removed + ASYNC_BAUD_RATE + ); + fprintf(stderr, "SetAsyncCardIdSendConfig: %s\n", UFR_Status2String(status)); + if (status != UFR_OK) { + return -1; } - // avoid sigaction for windows compatibility - signal(SIGINT, signal_exit); - signal(SIGTERM, signal_exit); + return 0; +} - if (pthread_create(&t, NULL, mt_rfid_run, (void *)&ufr)) { - perror("pthread_create"); +int main(int argc, char **argv) +{ + if (ufr_open(READER_TYPE, PORT_NAME, PORT_INTERFACE) == -1) { return -1; } - pthread_join(t, NULL); + int fd = tty_open(PORT_NAME, BASYNC_BAUD_RATE); + if (fd < 0) { + return -2; + } + + libev_run(fd); + + close(fd); + fprintf(stderr, "closed %d\n", fd); + + UFR_STATUS status; + status = ReaderClose(); + fprintf(stderr, "ReaderClose: %s\n", UFR_Status2String(status)); return 0; } + +/* other tty options + //Enable the receiver and set local mode... + options.c_cflag |= (CLOCAL | CREAD); + + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_cflag &= ~CRTSCTS; + options.c_lflag |= (ICANON | ECHO | ECHOE); + //Disable XON/XOFF both i/p and o/p + options.c_iflag &= ~(IXON | IXOFF | IXANY); + //Non Cannon mode + options.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); + + options.c_oflag |= OPOST; +*/ + diff --git a/mt_rfid.h b/mt_rfid.h index 60c4515..5d95960 100644 --- a/mt_rfid.h +++ b/mt_rfid.h @@ -20,26 +20,17 @@ typedef struct { // macros for convenience #define READER_TYPE 1 // uFR type (1Mbps) #define PORT_INTERFACE 1 // serial -#ifndef PORT_NAME #define PORT_NAME "/dev/ttyUSB0" -#endif - -// poll the uFR reader and print JSON formatted card info to stdout. -// run it directly or using pthreads. -void *mt_rfid_run(void *ptr); - -//example -/* - -pthread_t t; -mt_rfid_t ufr = {READER_TYPE, PORT_NAME, PORT_INTERFACE, 0, 1}; -if (!pthread_create(&t, NULL, mt_rfid_run, (void *)&ufr)) { - getchar(); - ufr.run = 0; - pthread_join(t, NULL); -} +#define ASYNC_SUFFIX 0 +#define ASYNC_BAUD_RATE 1000000 +#define BASYNC_BAUD_RATE B1000000 -*/ +// really simple JSON helpers +#define JSON_NUM(NAME) printf("\"" #NAME "\": %d", NAME) +#define JSON_STR(NAME) printf("\"" #NAME "\": \"%s\"", NAME) +#define JSON_START() printf("{\n") +#define JSON_NEXT() printf(",\n") +#define JSON_END() printf("\n}\n") #endif -- 2.39.2