]> git.itanic.dy.fi Git - glucose/blob - contour-protocol.c
Added -format option (defaults to "clean"), added "raw" and "CSV" formats.
[glucose] / contour-protocol.c
1 /*
2  * Copyright (C) 2012 Timo Kokkonen <timo.t.kokkonen@iki.fi>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA
18  */
19
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <linux/types.h>
23 #include <linux/hiddev.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <time.h>
27
28 #include "hiddev.h"
29 #include "contour-protocol.h"
30 #include "utils.h"
31
32 #define MAX_MSGS        103
33
34 static int send_msg(const struct msg *msg, int fd, int usage_code)
35 {
36         int ret;
37         if (msg->direction != OUT) {
38                 trace(0, "Message direction is not OUT\n");
39                 exit(1);
40         }
41
42         usleep(30 * 1000);
43         trace(1, "Sending: ");
44         if (trace_level >= 3)
45                 print_hex(msg->data + 1, datalen(msg->data) - 1);
46         if (trace_level >= 2)
47                 print_ascii(msg->data + 1, datalen(msg->data) - 1);
48
49         ret = hiddev_write(msg->data, fd, usage_code);
50         if (ret)
51                 exit(1);
52
53         return 0;
54 }
55
56 static int send_msg_with_proggress_note(const struct msg *msg, int fd,
57                                         int usage_code)
58 {
59         static int msg_count;
60
61         if (trace_level < 1 && msg_count <= MAX_MSGS) {
62                 trace(0, "\r%d%%", msg_count * 100 / MAX_MSGS);
63                 fflush(stdout);
64         }
65
66         msg_count++;
67
68         return send_msg(msg, fd, usage_code);
69 }
70
71 static int read_and_verify(struct msg *msg, int fd)
72 {
73         unsigned char buf[64];
74         int ret, offset = 0;
75
76         while (offset < 64) {
77                 ret = hiddev_read(buf + offset, sizeof(buf) - offset, fd);
78
79                 if (ret < 0)
80                         goto err;
81
82                 offset += ret;
83         }
84
85         memcpy(msg->data, buf, sizeof(buf));
86         memset(&msg->data[sizeof(buf)], 0, sizeof(msg->data)-sizeof(buf));
87         trace(2, "Got data %d: ", datalen(buf));
88         if (trace_level >= 3)
89                 print_hex(buf, datalen(buf));
90         if (trace_level >= 2)
91                 print_ascii(buf, datalen(buf));
92 err:
93         return 0;
94 }
95
96 static int read_msgs(int fd)
97 {
98         struct msg msg;
99         while (1) {
100                 read_and_verify(&msg, fd);
101                 if (datalen(msg.data) <= 36)
102                         break;
103         }
104
105         return 0;
106 }
107
108 #define SET_FIRST_BYTE(byte)                                    \
109         do {                                                    \
110                 memset(&msg.data, 0, sizeof(msg.data));         \
111                 msg.data[4] = (byte);                           \
112                 j = 5;                                          \
113         } while (0)
114
115 #define SET_BYTE(idx, byte)                     \
116         do {                                    \
117                 msg.data[(idx) + 4] = (byte);   \
118                 j = (idx) + 1;                  \
119         } while (0)
120
121 #define SET_BYTES(byte) msg.data[j++] = (byte)
122
123 static int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
124 {
125         int j;
126         struct msg msg;
127         msg.direction = OUT;
128
129         usleep(100 * 1000);
130         SET_FIRST_BYTE(0x01);
131         SET_BYTES(0x04);
132         send_msg_with_proggress_note(&msg, fd, uc);
133         read_msgs(fd);
134
135         usleep(250 * 1000);
136         SET_BYTE(1, 0x15);
137         send_msg_with_proggress_note(&msg, fd, uc);
138         read_msgs(fd);
139
140         usleep(100 * 1000);
141         SET_BYTE(1, 0x05);
142         send_msg_with_proggress_note(&msg, fd, uc);
143         read_msgs(fd);
144
145         SET_FIRST_BYTE(0x02);
146         SET_BYTES(byte1);
147         SET_BYTES('|');
148         send_msg_with_proggress_note(&msg, fd, uc);
149         read_msgs(fd);
150
151         usleep(100 * 1000);
152         SET_BYTE(1, byte2);
153         send_msg_with_proggress_note(&msg, fd, uc);
154         read_msgs(fd);
155
156         return 0;
157 }
158
159 int contour_initialize(int fd, int uc)
160 {
161         int i, j;
162         struct msg msg;
163         msg.direction = OUT;
164
165         read_msgs(fd);
166         SET_FIRST_BYTE(0x01);
167         SET_BYTES(0x04);
168         send_msg_with_proggress_note(&msg, fd, uc);
169
170         usleep(100 * 1000);
171         SET_BYTE(1, 0x06);
172         send_msg_with_proggress_note(&msg, fd, uc);
173         read_msgs(fd);
174
175         SET_BYTE(1, 0x15);
176         for (i = 0; i < 6; i++) {
177                 usleep(100 * 1000);
178                 send_msg_with_proggress_note(&msg, fd, uc);
179                 read_msgs(fd);
180         }
181         usleep(1000 * 1000);
182         read_msgs(fd);
183         send_msg_with_proggress_note(&msg, fd, uc);
184         read_msgs(fd);
185
186         usleep(100 * 1000);
187         SET_BYTE(1, 0x05);
188         send_msg_with_proggress_note(&msg, fd, uc);
189         read_msgs(fd);
190
191         send_pattern(fd, uc, 'R', 'A');
192         send_pattern(fd, uc, 'R', 'C');
193         send_pattern(fd, uc, 'R', 'D');
194         send_pattern(fd, uc, 'R', 'G');
195         send_pattern(fd, uc, 'R', 'I');
196         send_pattern(fd, uc, 'R', 'M');
197         send_pattern(fd, uc, 'R', 'P');
198         send_pattern(fd, uc, 'R', 'R');
199         send_pattern(fd, uc, 'R', 'S');
200         send_pattern(fd, uc, 'R', 'T');
201         send_pattern(fd, uc, 'R', 'U');
202         send_pattern(fd, uc, 'R', 'V');
203         send_pattern(fd, uc, 'R', 'W');
204         send_pattern(fd, uc, 'R', 'X');
205         send_pattern(fd, uc, 'W', 'K');
206
207         usleep(100 * 1000);
208         SET_FIRST_BYTE(0x08);
209         SET_BYTES('O');
210         SET_BYTES('b');
211         SET_BYTES('p');
212         SET_BYTES('s');
213         SET_BYTES('e');
214         SET_BYTES('c');
215         SET_BYTES('3');
216         SET_BYTES('|');
217         send_msg_with_proggress_note(&msg, fd, uc);
218         read_msgs(fd);
219
220         usleep(410 * 1000);
221         SET_FIRST_BYTE(0x02);
222         SET_BYTES('R');
223         SET_BYTES('|');
224         send_msg_with_proggress_note(&msg, fd, uc);
225         read_msgs(fd);
226
227         usleep(100 * 1000);
228         SET_BYTE(1, 'Y');
229         send_msg_with_proggress_note(&msg, fd, uc);
230         read_msgs(fd);
231
232         usleep(100 * 1000);
233         SET_BYTE(1, 'W');
234         send_msg_with_proggress_note(&msg, fd, uc);
235         read_msgs(fd);
236
237         usleep(100 * 1000);
238         SET_BYTE(1, 'K');
239         send_msg_with_proggress_note(&msg, fd, uc);
240         read_msgs(fd);
241
242         usleep(100 * 1000);
243         SET_BYTE(1, 'C');
244         send_msg_with_proggress_note(&msg, fd, uc);
245         read_msgs(fd);
246
247         send_pattern(fd, uc, 'R', 'Z');
248
249         usleep(100 * 1000);
250         SET_FIRST_BYTE(0x01);
251         SET_BYTES(0x04);
252         send_msg_with_proggress_note(&msg, fd, uc);
253         read_msgs(fd);
254
255         usleep(100 * 1000);
256         SET_BYTE(1, 0x15);
257         send_msg_with_proggress_note(&msg, fd, uc);
258         read_msgs(fd);
259
260         usleep(100 * 1000);
261         SET_BYTE(1, 0x05);
262         send_msg_with_proggress_note(&msg, fd, uc);
263         read_msgs(fd);
264
265         usleep(100 * 1000);
266         SET_BYTE(1, 0x04);
267         send_msg_with_proggress_note(&msg, fd, uc);
268         read_msgs(fd);
269
270         usleep(100 * 1000);
271         send_msg_with_proggress_note(&msg, fd, uc);
272         read_msgs(fd);
273
274         usleep(100 * 1000);
275         SET_BYTE(1, 0x06);
276         send_msg_with_proggress_note(&msg, fd, uc);
277         read_msgs(fd);
278
279         usleep(100 * 1000);
280         send_msg_with_proggress_note(&msg, fd, uc);
281         read_msgs(fd);
282
283         usleep(100 * 1000);
284         send_msg_with_proggress_note(&msg, fd, uc);
285         read_msgs(fd);
286
287         usleep(100 * 1000);
288
289         trace(0, "\n");
290         return 0;
291 }
292
293 int contour_read_entry(int fd, int uc, struct msg *in)
294 {
295         struct msg msg;
296         int j;
297
298         msg.direction = OUT;
299         SET_FIRST_BYTE(0x01);
300         SET_BYTE(1, 0x06);
301         send_msg(&msg, fd, uc);
302
303         read_and_verify(in, fd);
304         return datalen(in->data);
305 }
306
307 int wait_for_device(int vendor, int product, int *usage_code)
308 {
309         int fd;
310
311         fd = hiddev_open_by_id(vendor, product, usage_code);
312
313         if (fd > 0)
314                 return fd;
315
316         trace(0,
317                "No suitable device found. Please plug in your glucose meter\n");
318         do {
319                 usleep(500 * 1000);
320                 fd = hiddev_open_by_id(vendor, product, usage_code);
321         } while(fd < 0);
322
323         usleep(2000 * 1000);
324
325         return fd;
326 }
327