]> git.itanic.dy.fi Git - glucose/blob - main.c
hiddev: Fix bug when matching incorrect device IDs
[glucose] / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <linux/types.h>
5 #include <linux/hiddev.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <time.h>
9
10 #include "hiddev.h"
11 #include "utils.h"
12 #include "options.h"
13
14 #define CONTOUR_USB_VENDOR_ID   0x1a79
15 #define CONTOUR_USB_PRODUCT_ID  0x6002
16
17 struct msg {
18         int direction;
19         unsigned char data[64];
20 };
21
22 enum direction {
23         IN = 666,
24         OUT,
25 };
26
27 int send_msg(const struct msg *msg, int fd, int usage_code)
28 {
29         int ret;
30
31         if (msg->direction != OUT) {
32                 trace(0, "Message direction is not OUT\n");
33                 exit(1);
34         }
35
36         usleep(30 * 1000);
37         trace(1, "Sending: ");
38         if (trace_level >= 3)
39                 print_hex(msg->data + 1, datalen(msg->data) - 1);
40         if (trace_level >= 2)
41                 print_ascii(msg->data + 1, datalen(msg->data) - 1);
42
43         ret = hiddev_write(msg->data, fd, usage_code);
44         if (ret)
45                 exit(1);
46
47         return 0;
48 }
49
50 int read_and_verify(struct msg *msg, int fd)
51 {
52         unsigned char buf[64];
53         int ret, offset = 0;
54
55         while (offset < 64) {
56                 ret = hiddev_read(buf + offset, sizeof(buf) - offset, fd);
57
58                 if (ret < 0)
59                         goto err;
60
61                 offset += ret;
62         }
63
64         memcpy(msg->data, buf, sizeof(buf));
65         trace(2, "Got data %d: ", datalen(buf));
66         if (trace_level >= 3)
67                 print_hex(buf, datalen(buf));
68         if (trace_level >= 2)
69                 print_ascii(buf, datalen(buf));
70 err:
71         return 0;
72 }
73
74 int read_msgs(int fd)
75 {
76         struct msg msg;
77         while (1) {
78                 read_and_verify(&msg, fd);
79                 if (datalen(msg.data) <= 36)
80                         break;
81         }
82
83         return 0;
84 }
85
86 #define SET_FIRST_BYTE(byte)                                    \
87         do {                                                    \
88                 memset(&msg.data, 0, sizeof(msg.data));         \
89                 msg.data[4] = (byte);                           \
90                 j = 5;                                          \
91         } while (0)
92
93 #define SET_BYTE(idx, byte)                     \
94         do {                                    \
95                 msg.data[(idx) + 4] = (byte);   \
96                 j = (idx) + 1;                  \
97         } while (0)
98
99 #define SET_BYTES(byte) msg.data[j++] = (byte)
100
101 int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
102 {
103         int j;
104         struct msg msg;
105         msg.direction = OUT;
106
107         usleep(100 * 1000);
108         SET_FIRST_BYTE(0x01);
109         SET_BYTES(0x04);
110         send_msg(&msg, fd, uc);
111         read_msgs(fd);
112
113         usleep(250 * 1000);
114         SET_BYTE(1, 0x15);
115         send_msg(&msg, fd, uc);
116         read_msgs(fd);
117
118         usleep(100 * 1000);
119         SET_BYTE(1, 0x05);
120         send_msg(&msg, fd, uc);
121         read_msgs(fd);
122
123         SET_FIRST_BYTE(0x02);
124         SET_BYTES(byte1);
125         SET_BYTES('|');
126         send_msg(&msg, fd, uc);
127         read_msgs(fd);
128
129         usleep(100 * 1000);
130         SET_BYTE(1, byte2);
131         send_msg(&msg, fd, uc);
132         read_msgs(fd);
133
134         return 0;
135 }
136
137 int communicate(int fd, int uc)
138 {
139         int i, j;
140         struct msg msg, in;
141         msg.direction = OUT;
142
143         read_msgs(fd);
144         SET_FIRST_BYTE(0x01);
145         SET_BYTES(0x04);
146         send_msg(&msg, fd, uc);
147
148         usleep(100 * 1000);
149         SET_BYTE(1, 0x06);
150         send_msg(&msg, fd, uc);
151         read_msgs(fd);
152
153         SET_BYTE(1, 0x15);
154         for (i = 0; i < 6; i++) {
155                 usleep(100 * 1000);
156                 send_msg(&msg, fd, uc);
157                 read_msgs(fd);
158         }
159         usleep(1000 * 1000);
160         read_msgs(fd);
161         send_msg(&msg, fd, uc);
162         read_msgs(fd);
163
164         usleep(100 * 1000);
165         SET_BYTE(1, 0x05);
166         send_msg(&msg, fd, uc);
167         read_msgs(fd);
168
169         send_pattern(fd, uc, 'R', 'A');
170         send_pattern(fd, uc, 'R', 'C');
171         send_pattern(fd, uc, 'R', 'D');
172         send_pattern(fd, uc, 'R', 'G');
173         send_pattern(fd, uc, 'R', 'I');
174         send_pattern(fd, uc, 'R', 'M');
175         send_pattern(fd, uc, 'R', 'P');
176         send_pattern(fd, uc, 'R', 'R');
177         send_pattern(fd, uc, 'R', 'S');
178         send_pattern(fd, uc, 'R', 'T');
179         send_pattern(fd, uc, 'R', 'U');
180         send_pattern(fd, uc, 'R', 'V');
181         send_pattern(fd, uc, 'R', 'W');
182         send_pattern(fd, uc, 'R', 'X');
183         send_pattern(fd, uc, 'W', 'K');
184
185         usleep(100 * 1000);
186         SET_FIRST_BYTE(0x08);
187         SET_BYTES('O');
188         SET_BYTES('b');
189         SET_BYTES('p');
190         SET_BYTES('s');
191         SET_BYTES('e');
192         SET_BYTES('c');
193         SET_BYTES('3');
194         SET_BYTES('|');
195         send_msg(&msg, fd, uc);
196         read_msgs(fd);
197
198         usleep(410 * 1000);
199         SET_FIRST_BYTE(0x02);
200         SET_BYTES('R');
201         SET_BYTES('|');
202         send_msg(&msg, fd, uc);
203         read_msgs(fd);
204
205         usleep(100 * 1000);
206         SET_BYTE(1, 'Y');
207         send_msg(&msg, fd, uc);
208         read_msgs(fd);
209
210         usleep(100 * 1000);
211         SET_BYTE(1, 'W');
212         send_msg(&msg, fd, uc);
213         read_msgs(fd);
214
215         usleep(100 * 1000);
216         SET_BYTE(1, 'K');
217         send_msg(&msg, fd, uc);
218         read_msgs(fd);
219
220         usleep(100 * 1000);
221         SET_BYTE(1, 'C');
222         send_msg(&msg, fd, uc);
223         read_msgs(fd);
224
225         send_pattern(fd, uc, 'R', 'Z');
226
227         usleep(100 * 1000);
228         SET_FIRST_BYTE(0x01);
229         SET_BYTES(0x04);
230         send_msg(&msg, fd, uc);
231         read_msgs(fd);
232
233         usleep(100 * 1000);
234         SET_BYTE(1, 0x15);
235         send_msg(&msg, fd, uc);
236         read_msgs(fd);
237
238         usleep(100 * 1000);
239         SET_BYTE(1, 0x05);
240         send_msg(&msg, fd, uc);
241         read_msgs(fd);
242
243         usleep(100 * 1000);
244         SET_BYTE(1, 0x04);
245         send_msg(&msg, fd, uc);
246         read_msgs(fd);
247
248         usleep(100 * 1000);
249         send_msg(&msg, fd, uc);
250         read_msgs(fd);
251
252         usleep(100 * 1000);
253         SET_BYTE(1, 0x06);
254         send_msg(&msg, fd, uc);
255         read_msgs(fd);
256
257         usleep(100 * 1000);
258         send_msg(&msg, fd, uc);
259         read_msgs(fd);
260
261         usleep(100 * 1000);
262         send_msg(&msg, fd, uc);
263         read_msgs(fd);
264
265         trace(0, "Glucose readings:\n");
266         usleep(100 * 1000);
267         do {
268                 send_msg(&msg, fd, uc);
269                 read_and_verify(&in, fd);
270                 print_ascii(in.data, datalen(in.data));
271         } while (datalen(in.data) > 45);
272
273         return 0;
274 }
275
276 int main(int argc, char *argv[])
277 {
278         int fd, usage_code;
279         struct user_options opts;
280
281         read_args(argc, argv, &opts);
282         trace_level = opts.trace_level;
283
284         if (opts.usbdev == NULL)
285                 fd = hiddev_open_by_id(CONTOUR_USB_PRODUCT_ID,
286                                 CONTOUR_USB_VENDOR_ID, &usage_code);
287         else
288                 fd = hiddev_open(opts.usbdev, &usage_code);
289         if (fd < 0)
290                 return 1;
291
292         communicate(fd, usage_code);
293
294         return 0;
295 }