/
device_crow.c
113 lines (94 loc) · 2.88 KB
/
device_crow.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.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);
}
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