]> git.itanic.dy.fi Git - glucose/blob - contour-protocol.c
contour-protocol: Replace bad macros with static functions
[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 static void set_first_msg_byte(struct msg *msg, int *idx, char byte)
109 {
110         memset(msg->data, 0, sizeof(msg->data));
111         msg->data[4] = (byte);
112
113         *idx = 5;
114 }
115
116 static void set_msg_byte(struct msg *msg, int *idx, int where, char byte)
117 {
118         msg->data[where + 4] = byte;
119         *idx = where + 1;
120 }
121
122 #define SET_BYTES(byte) msg.data[j++] = (byte)
123
124 static int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
125 {
126         int j;
127         struct msg msg;
128         msg.direction = OUT;
129
130         usleep(100 * 1000);
131         set_first_msg_byte(&msg, &j, 0x01);
132         SET_BYTES(0x04);
133         send_msg_with_proggress_note(&msg, fd, uc);
134         read_msgs(fd);
135
136         usleep(250 * 1000);
137         set_msg_byte(&msg, &j, 1, 0x15);
138         send_msg_with_proggress_note(&msg, fd, uc);
139         read_msgs(fd);
140
141         usleep(100 * 1000);
142         set_msg_byte(&msg, &j, 1, 0x05);
143         send_msg_with_proggress_note(&msg, fd, uc);
144         read_msgs(fd);
145
146         set_first_msg_byte(&msg, &j, 0x02);
147         SET_BYTES(byte1);
148         SET_BYTES('|');
149         send_msg_with_proggress_note(&msg, fd, uc);
150         read_msgs(fd);
151
152         usleep(100 * 1000);
153         set_msg_byte(&msg, &j, 1, byte2);
154         send_msg_with_proggress_note(&msg, fd, uc);
155         read_msgs(fd);
156
157         return 0;
158 }
159
160 int contour_initialize(int fd, int uc)
161 {
162         int i, j;
163         struct msg msg;
164         msg.direction = OUT;
165
166         read_msgs(fd);
167         set_first_msg_byte(&msg, &j, 0x01);
168         SET_BYTES(0x04);
169         send_msg_with_proggress_note(&msg, fd, uc);
170
171         usleep(100 * 1000);
172         set_msg_byte(&msg, &j, 1, 0x06);
173         send_msg_with_proggress_note(&msg, fd, uc);
174         read_msgs(fd);
175
176         set_msg_byte(&msg, &j, 1, 0x15);
177         for (i = 0; i < 6; i++) {
178                 usleep(100 * 1000);
179                 send_msg_with_proggress_note(&msg, fd, uc);
180                 read_msgs(fd);
181         }
182         usleep(1000 * 1000);
183         read_msgs(fd);
184         send_msg_with_proggress_note(&msg, fd, uc);
185         read_msgs(fd);
186
187         usleep(100 * 1000);
188         set_msg_byte(&msg, &j, 1, 0x05);
189         send_msg_with_proggress_note(&msg, fd, uc);
190         read_msgs(fd);
191
192         send_pattern(fd, uc, 'R', 'A');
193         send_pattern(fd, uc, 'R', 'C');
194         send_pattern(fd, uc, 'R', 'D');
195         send_pattern(fd, uc, 'R', 'G');
196         send_pattern(fd, uc, 'R', 'I');
197         send_pattern(fd, uc, 'R', 'M');
198         send_pattern(fd, uc, 'R', 'P');
199         send_pattern(fd, uc, 'R', 'R');
200         send_pattern(fd, uc, 'R', 'S');
201         send_pattern(fd, uc, 'R', 'T');
202         send_pattern(fd, uc, 'R', 'U');
203         send_pattern(fd, uc, 'R', 'V');
204         send_pattern(fd, uc, 'R', 'W');
205         send_pattern(fd, uc, 'R', 'X');
206         send_pattern(fd, uc, 'W', 'K');
207
208         usleep(100 * 1000);
209         set_first_msg_byte(&msg, &j, 0x08);
210         SET_BYTES('O');
211         SET_BYTES('b');
212         SET_BYTES('p');
213         SET_BYTES('s');
214         SET_BYTES('e');
215         SET_BYTES('c');
216         SET_BYTES('3');
217         SET_BYTES('|');
218         send_msg_with_proggress_note(&msg, fd, uc);
219         read_msgs(fd);
220
221         usleep(410 * 1000);
222         set_first_msg_byte(&msg, &j, 0x02);
223         SET_BYTES('R');
224         SET_BYTES('|');
225         send_msg_with_proggress_note(&msg, fd, uc);
226         read_msgs(fd);
227
228         usleep(100 * 1000);
229         set_msg_byte(&msg, &j, 1, 'Y');
230         send_msg_with_proggress_note(&msg, fd, uc);
231         read_msgs(fd);
232
233         usleep(100 * 1000);
234         set_msg_byte(&msg, &j, 1, 'W');
235         send_msg_with_proggress_note(&msg, fd, uc);
236         read_msgs(fd);
237
238         usleep(100 * 1000);
239         set_msg_byte(&msg, &j, 1, 'K');
240         send_msg_with_proggress_note(&msg, fd, uc);
241         read_msgs(fd);
242
243         usleep(100 * 1000);
244         set_msg_byte(&msg, &j, 1, 'C');
245         send_msg_with_proggress_note(&msg, fd, uc);
246         read_msgs(fd);
247
248         send_pattern(fd, uc, 'R', 'Z');
249
250         usleep(100 * 1000);
251         set_first_msg_byte(&msg, &j, 0x01);
252         SET_BYTES(0x04);
253         send_msg_with_proggress_note(&msg, fd, uc);
254         read_msgs(fd);
255
256         usleep(100 * 1000);
257         set_msg_byte(&msg, &j, 1, 0x15);
258         send_msg_with_proggress_note(&msg, fd, uc);
259         read_msgs(fd);
260
261         usleep(100 * 1000);
262         set_msg_byte(&msg, &j, 1, 0x05);
263         send_msg_with_proggress_note(&msg, fd, uc);
264         read_msgs(fd);
265
266         usleep(100 * 1000);
267         set_msg_byte(&msg, &j, 1, 0x04);
268         send_msg_with_proggress_note(&msg, fd, uc);
269         read_msgs(fd);
270
271         usleep(100 * 1000);
272         send_msg_with_proggress_note(&msg, fd, uc);
273         read_msgs(fd);
274
275         usleep(100 * 1000);
276         set_msg_byte(&msg, &j, 1, 0x06);
277         send_msg_with_proggress_note(&msg, fd, uc);
278         read_msgs(fd);
279
280         usleep(100 * 1000);
281         send_msg_with_proggress_note(&msg, fd, uc);
282         read_msgs(fd);
283
284         usleep(100 * 1000);
285         send_msg_with_proggress_note(&msg, fd, uc);
286         read_msgs(fd);
287
288         usleep(100 * 1000);
289
290         trace(0, "\n");
291         return 0;
292 }
293
294 int contour_read_entry(int fd, int uc, struct msg *in)
295 {
296         struct msg msg;
297         int j;
298
299         msg.direction = OUT;
300         set_first_msg_byte(&msg, &j, 0x01);
301         set_msg_byte(&msg, &j, 1, 0x06);
302         send_msg(&msg, fd, uc);
303
304         read_and_verify(in, fd);
305         return datalen(in->data);
306 }
307
308 int wait_for_device(int vendor, int product, int *usage_code)
309 {
310         int fd;
311
312         fd = hiddev_open_by_id(vendor, product, usage_code);
313
314         if (fd > 0)
315                 return fd;
316
317         trace(0,
318                "No suitable device found. Please plug in your glucose meter\n");
319         do {
320                 usleep(500 * 1000);
321                 fd = hiddev_open_by_id(vendor, product, usage_code);
322         } while(fd < 0);
323
324         usleep(2000 * 1000);
325
326         return fd;
327 }
328