]> git.itanic.dy.fi Git - glucose/blob - contour-protocol.c
Add copyright notices
[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         trace(2, "Got data %d: ", datalen(buf));
87         if (trace_level >= 3)
88                 print_hex(buf, datalen(buf));
89         if (trace_level >= 2)
90                 print_ascii(buf, datalen(buf));
91 err:
92         return 0;
93 }
94
95 static int read_msgs(int fd)
96 {
97         struct msg msg;
98         while (1) {
99                 read_and_verify(&msg, fd);
100                 if (datalen(msg.data) <= 36)
101                         break;
102         }
103
104         return 0;
105 }
106
107 #define SET_FIRST_BYTE(byte)                                    \
108         do {                                                    \
109                 memset(&msg.data, 0, sizeof(msg.data));         \
110                 msg.data[4] = (byte);                           \
111                 j = 5;                                          \
112         } while (0)
113
114 #define SET_BYTE(idx, byte)                     \
115         do {                                    \
116                 msg.data[(idx) + 4] = (byte);   \
117                 j = (idx) + 1;                  \
118         } while (0)
119
120 #define SET_BYTES(byte) msg.data[j++] = (byte)
121
122 static int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
123 {
124         int j;
125         struct msg msg;
126         msg.direction = OUT;
127
128         usleep(100 * 1000);
129         SET_FIRST_BYTE(0x01);
130         SET_BYTES(0x04);
131         send_msg_with_proggress_note(&msg, fd, uc);
132         read_msgs(fd);
133
134         usleep(250 * 1000);
135         SET_BYTE(1, 0x15);
136         send_msg_with_proggress_note(&msg, fd, uc);
137         read_msgs(fd);
138
139         usleep(100 * 1000);
140         SET_BYTE(1, 0x05);
141         send_msg_with_proggress_note(&msg, fd, uc);
142         read_msgs(fd);
143
144         SET_FIRST_BYTE(0x02);
145         SET_BYTES(byte1);
146         SET_BYTES('|');
147         send_msg_with_proggress_note(&msg, fd, uc);
148         read_msgs(fd);
149
150         usleep(100 * 1000);
151         SET_BYTE(1, byte2);
152         send_msg_with_proggress_note(&msg, fd, uc);
153         read_msgs(fd);
154
155         return 0;
156 }
157
158 int contour_initialize(int fd, int uc)
159 {
160         int i, j;
161         struct msg msg;
162         msg.direction = OUT;
163
164         read_msgs(fd);
165         SET_FIRST_BYTE(0x01);
166         SET_BYTES(0x04);
167         send_msg_with_proggress_note(&msg, fd, uc);
168
169         usleep(100 * 1000);
170         SET_BYTE(1, 0x06);
171         send_msg_with_proggress_note(&msg, fd, uc);
172         read_msgs(fd);
173
174         SET_BYTE(1, 0x15);
175         for (i = 0; i < 6; i++) {
176                 usleep(100 * 1000);
177                 send_msg_with_proggress_note(&msg, fd, uc);
178                 read_msgs(fd);
179         }
180         usleep(1000 * 1000);
181         read_msgs(fd);
182         send_msg_with_proggress_note(&msg, fd, uc);
183         read_msgs(fd);
184
185         usleep(100 * 1000);
186         SET_BYTE(1, 0x05);
187         send_msg_with_proggress_note(&msg, fd, uc);
188         read_msgs(fd);
189
190         send_pattern(fd, uc, 'R', 'A');
191         send_pattern(fd, uc, 'R', 'C');
192         send_pattern(fd, uc, 'R', 'D');
193         send_pattern(fd, uc, 'R', 'G');
194         send_pattern(fd, uc, 'R', 'I');
195         send_pattern(fd, uc, 'R', 'M');
196         send_pattern(fd, uc, 'R', 'P');
197         send_pattern(fd, uc, 'R', 'R');
198         send_pattern(fd, uc, 'R', 'S');
199         send_pattern(fd, uc, 'R', 'T');
200         send_pattern(fd, uc, 'R', 'U');
201         send_pattern(fd, uc, 'R', 'V');
202         send_pattern(fd, uc, 'R', 'W');
203         send_pattern(fd, uc, 'R', 'X');
204         send_pattern(fd, uc, 'W', 'K');
205
206         usleep(100 * 1000);
207         SET_FIRST_BYTE(0x08);
208         SET_BYTES('O');
209         SET_BYTES('b');
210         SET_BYTES('p');
211         SET_BYTES('s');
212         SET_BYTES('e');
213         SET_BYTES('c');
214         SET_BYTES('3');
215         SET_BYTES('|');
216         send_msg_with_proggress_note(&msg, fd, uc);
217         read_msgs(fd);
218
219         usleep(410 * 1000);
220         SET_FIRST_BYTE(0x02);
221         SET_BYTES('R');
222         SET_BYTES('|');
223         send_msg_with_proggress_note(&msg, fd, uc);
224         read_msgs(fd);
225
226         usleep(100 * 1000);
227         SET_BYTE(1, 'Y');
228         send_msg_with_proggress_note(&msg, fd, uc);
229         read_msgs(fd);
230
231         usleep(100 * 1000);
232         SET_BYTE(1, 'W');
233         send_msg_with_proggress_note(&msg, fd, uc);
234         read_msgs(fd);
235
236         usleep(100 * 1000);
237         SET_BYTE(1, 'K');
238         send_msg_with_proggress_note(&msg, fd, uc);
239         read_msgs(fd);
240
241         usleep(100 * 1000);
242         SET_BYTE(1, 'C');
243         send_msg_with_proggress_note(&msg, fd, uc);
244         read_msgs(fd);
245
246         send_pattern(fd, uc, 'R', 'Z');
247
248         usleep(100 * 1000);
249         SET_FIRST_BYTE(0x01);
250         SET_BYTES(0x04);
251         send_msg_with_proggress_note(&msg, fd, uc);
252         read_msgs(fd);
253
254         usleep(100 * 1000);
255         SET_BYTE(1, 0x15);
256         send_msg_with_proggress_note(&msg, fd, uc);
257         read_msgs(fd);
258
259         usleep(100 * 1000);
260         SET_BYTE(1, 0x05);
261         send_msg_with_proggress_note(&msg, fd, uc);
262         read_msgs(fd);
263
264         usleep(100 * 1000);
265         SET_BYTE(1, 0x04);
266         send_msg_with_proggress_note(&msg, fd, uc);
267         read_msgs(fd);
268
269         usleep(100 * 1000);
270         send_msg_with_proggress_note(&msg, fd, uc);
271         read_msgs(fd);
272
273         usleep(100 * 1000);
274         SET_BYTE(1, 0x06);
275         send_msg_with_proggress_note(&msg, fd, uc);
276         read_msgs(fd);
277
278         usleep(100 * 1000);
279         send_msg_with_proggress_note(&msg, fd, uc);
280         read_msgs(fd);
281
282         usleep(100 * 1000);
283         send_msg_with_proggress_note(&msg, fd, uc);
284         read_msgs(fd);
285
286         usleep(100 * 1000);
287
288         trace(0, "\n");
289         return 0;
290 }
291
292 int contour_read_entry(int fd, int uc, struct msg *in)
293 {
294         struct msg msg;
295         int j;
296
297         msg.direction = OUT;
298         SET_FIRST_BYTE(0x01);
299         SET_BYTE(1, 0x06);
300
301         send_msg(&msg, fd, uc);
302         read_and_verify(in, fd);
303
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