Permalink
Cannot retrieve contributors at this time
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <linux/input.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| #include <termios.h> | |
| #include <unistd.h> | |
| #include "clocks/clock_crow.h" | |
| #include "device_crow.h" | |
| #include "events.h" | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wunused-result" | |
| #define TEST_NULL_AND_FREE(p) \ | |
| if ((p) != NULL) { \ | |
| free(p); \ | |
| } else { \ | |
| fprintf(stderr, "error: double free in device_crow.c\n"); \ | |
| } | |
| #define CROW_RETRIES 10 | |
| int dev_crow_init(void *self) { | |
| struct dev_crow *d = (struct dev_crow *)self; | |
| struct dev_common *base = (struct dev_common *)self; | |
| d->fd = open(d->base.path, O_RDWR | O_NOCTTY | O_SYNC); | |
| if (d->fd < 0) { | |
| fprintf(stderr, "failed to open crow device: %s\n", d->base.path); | |
| return -1; | |
| } | |
| tcgetattr(d->fd, &d->oldtio); | |
| // d->newtio.c_cflag = CROW_BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; | |
| d->newtio.c_cflag = CROW_BAUDRATE | CS8 | CLOCAL | CREAD; | |
| // d->newtio.c_iflag = IGNPAR | ICRNL; | |
| d->newtio.c_iflag &= ~(IXON | IXOFF | IXANY); | |
| d->newtio.c_oflag = 0; | |
| // d->newtio.c_lflag = ICANON; | |
| d->newtio.c_lflag = 0; | |
| d->newtio.c_cc[VMIN] = 0; | |
| d->newtio.c_cc[VTIME] = 5; | |
| tcflush(d->fd, TCIFLUSH); | |
| tcsetattr(d->fd, TCSANOW, &d->newtio); | |
| // check if modem is a crow | |
| char s[256]; | |
| read(d->fd, s, 255); // clear buffer | |
| write(d->fd, "^^i\n\0", 5); | |
| usleep(1000); | |
| int retry = 0; | |
| while (retry < CROW_RETRIES) { | |
| retry++; | |
| memset(s, 0, sizeof(s)); | |
| read(d->fd, s, 255); | |
| // fprintf(stderr,"crow init> %i %s",sizeof(s),s); | |
| if (strstr(s, "^^identity") != NULL) | |
| break; | |
| } | |
| if (retry >= CROW_RETRIES) { | |
| fprintf(stderr, ">> ttyACM found, but not a crow\n"); | |
| return -1; | |
| } | |
| base->start = &dev_crow_start; | |
| base->deinit = &dev_crow_deinit; | |
| return 0; | |
| } | |
| static void handle_event(void *dev, uint8_t id) { | |
| union event_data *ev = event_data_new(EVENT_CROW_EVENT); | |
| ev->crow_event.dev = dev; | |
| ev->crow_event.id = id; | |
| event_post(ev); | |
| struct dev_crow *d = (struct dev_crow *)dev; | |
| if (strstr(d->line, "^^change(1,1)")) { | |
| clock_crow_handle_clock(); | |
| } | |
| } | |
| void *dev_crow_start(void *self) { | |
| struct dev_crow *di = (struct dev_crow *)self; | |
| struct dev_common *base = (struct dev_common *)self; | |
| uint8_t len; | |
| while (1) { | |
| len = read(di->fd, di->line, 255); | |
| if (len > 0) { | |
| di->line[len] = 0; // add null to end of string | |
| if (len > 1) { | |
| // fprintf(stderr,"crow> %s", di->line); | |
| handle_event(self, base->id); | |
| } | |
| len = 0; | |
| } | |
| usleep(1000); // 1ms | |
| } | |
| return NULL; | |
| } | |
| void dev_crow_deinit(void *self) { | |
| struct dev_crow *di = (struct dev_crow *)self; | |
| tcsetattr(di->fd, TCSANOW, &di->oldtio); | |
| } | |
| void dev_crow_send(struct dev_crow *d, const char *line) { | |
| char s[256]; | |
| strcpy(s, line); | |
| strcat(s, "\n\0"); | |
| // fprintf(stderr,"crow_send: %s",line); | |
| write(d->fd, s, strlen(s)); | |
| } | |
| #pragma GCC diagnostic pop |