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