]> git.itanic.dy.fi Git - glucose/blob - main.c
Significantly reduce the delays between messages
[glucose] / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <sys/ioctl.h>
6 #include <linux/types.h>
7 #include <linux/hiddev.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <time.h>
11
12 #define PRINT_FIELD(field) printf(#field ": %04x\n", field)
13
14 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
15
16 #define READ_BUFFER_LENGTH 64
17
18 struct msg {
19         int direction;
20         unsigned char data[64];
21 };
22
23 enum direction {
24         IN = 666,
25         OUT,
26 };
27
28 static int is_printable(const unsigned char c)
29 {
30         return c >= 0x20 && c < 0x80;
31 }
32
33 static int datalen(const unsigned char *data)
34 {
35         int i, len;
36
37         for (i = 0, len = 0; i < 64; i++)
38                 if (data[i])
39                         len = i;
40
41         return len + 1;
42 }
43
44 static void print_hex(const unsigned char *data, int len)
45 {
46         int i;
47
48         for (i = 0; i < len; i++)
49                 printf("0x%02x ", data[i]);
50
51         printf("\n");
52 }
53
54 static void print_ascii(const unsigned char *data, int len)
55 {
56         int i;
57
58         for (i = 0; i < len; i++)
59                 printf("%c", is_printable(data[i]) ? data[i] : '.');
60
61         printf("\n");
62 }
63
64 int hid_read(unsigned char *data, int bufsize, int fd)
65 {
66         struct hiddev_event readBuffer[READ_BUFFER_LENGTH];
67         int ret, n, i;
68
69         ret = read(fd, readBuffer, sizeof(readBuffer));
70         if (ret < 0)
71                 return ret;
72
73         n = ret / sizeof(readBuffer[0]);
74         for (i = 0; i < n && i < bufsize; i++)
75                 data[i] = readBuffer[i].value;
76         return n;
77 }
78
79
80 int hid_write(const unsigned char data[64], int fd , int usage_code)
81 {
82         int rc = 0, uindex, error;
83
84         struct hiddev_usage_ref uref;
85         struct hiddev_report_info rinfo;
86
87         uref.report_id = *data++;
88         uref.report_type = HID_REPORT_TYPE_OUTPUT;
89         uref.field_index = 0;
90
91         uref.usage_code = usage_code;
92
93         for (uindex = 0; uindex < 63; uindex++) {
94                 uref.usage_index = uindex;
95                 uref.value = *data++;
96
97                 rc = ioctl(fd, HIDIOCSUSAGE, &uref);
98                 if (rc != 0)
99                         goto err;
100         }
101
102         rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
103         rinfo.report_id =  0x0;
104         rinfo.num_fields = 1;
105
106         rc = ioctl(fd, HIDIOCSREPORT, &rinfo);
107         if (rc != 0)
108                 goto err2;
109
110         return 0;
111 err2:
112         printf("HIDIOCSREPORT\n");
113 err:
114         error = errno;
115         printf("Error in IOCTL: %s\n", strerror(error));
116
117         return rc;
118 }
119
120 int get_usagecode(int fd)
121 {
122         struct hiddev_usage_ref uref;
123         int rc, error;
124
125         uref.report_type = HID_REPORT_TYPE_OUTPUT;
126         uref.report_id = 0x0;
127         uref.field_index = 0;
128         uref.usage_index = 0;
129
130         rc = ioctl(fd, HIDIOCGUCODE, &uref);
131         if (rc < 0) {
132                 error = errno;
133                 printf("Error gettin usage code: %s\n", strerror(error));
134                 return rc;
135         }
136
137         return uref.usage_code;
138 }
139
140 int hiddev_open(const char *device_path, int *usage_code)
141 {
142         struct hiddev_devinfo device_info;
143         struct hiddev_report_info rinfo;
144         int ret, error;
145         int fd;
146         fd = ret = open(device_path, O_RDWR);
147
148         if (fd < 0)
149                 goto err;
150
151
152         rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
153         rinfo.report_id = HID_REPORT_ID_FIRST;
154         ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
155         if (ret < 0)
156                 goto err;
157
158         PRINT_FIELD(rinfo.report_type);
159         PRINT_FIELD(rinfo.report_id);
160         PRINT_FIELD(rinfo.num_fields);
161
162         *usage_code = get_usagecode(fd);
163
164         if (*usage_code < 0)
165                 return -8;
166
167         ret = ioctl(fd, HIDIOCGDEVINFO, &device_info);
168
169         if (ret < 0)
170                 goto err;
171
172         PRINT_FIELD(device_info.bustype);
173         PRINT_FIELD(device_info.busnum);
174         PRINT_FIELD(device_info.devnum);
175         PRINT_FIELD(device_info.ifnum);
176         PRINT_FIELD(device_info.vendor);
177         PRINT_FIELD(device_info.product);
178         PRINT_FIELD(device_info.version);
179         PRINT_FIELD(device_info.num_applications);
180
181         return fd;
182
183 err:
184         error = errno;
185         printf("Error opening device %s: %s\n", device_path, strerror(error));
186         return ret;
187 }
188
189 int send_msg(const struct msg *msg, int fd, int usage_code)
190 {
191         int ret;
192
193         if (msg->direction != OUT) {
194                 printf("Message direction is not OUT\n");
195                 exit(1);
196         }
197
198         usleep(30 * 1000);
199         printf("Sending: ");
200         print_hex(msg->data + 1, datalen(msg->data) - 1);
201         print_ascii(msg->data + 1, datalen(msg->data) - 1);
202
203         ret = hid_write(msg->data, fd, usage_code);
204         if (ret)
205                 exit(1);
206
207         return 0;
208 }
209
210 int read_and_verify(struct msg *msg, int fd)
211 {
212         unsigned char buf[64];
213         int ret, offset = 0;
214
215         while (offset < 64) {
216                 ret = hid_read(buf + offset, sizeof(buf) - offset, fd);
217
218                 if (ret < 0)
219                         goto err;
220
221                 offset += ret;
222         }
223
224         memcpy(msg->data, buf, sizeof(buf));
225         printf("Got data %d: ", datalen(buf));
226 //      print_hex(buf, datalen(buf));
227         print_ascii(buf, datalen(buf));
228 err:
229         return 0;
230 }
231
232 int read_msgs(int fd)
233 {
234         struct msg msg;
235         while (1) {
236                 read_and_verify(&msg, fd);
237                 if (datalen(msg.data) <= 36)
238                         break;
239         }
240
241         return 0;
242 }
243
244 #define SET_FIRST_BYTE(byte)                                    \
245         do {                                                    \
246                 memset(&msg.data, 0, sizeof(msg.data));         \
247                 msg.data[4] = (byte);                           \
248                 j = 5;                                          \
249         } while (0)
250
251 #define SET_BYTE(idx, byte)                     \
252         do {                                    \
253                 msg.data[(idx) + 4] = (byte);   \
254                 j = (idx) + 1;                  \
255         } while (0)
256
257 #define SET_BYTES(byte) msg.data[j++] = (byte)
258
259 int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
260 {
261         int j;
262         struct msg msg;
263         msg.direction = OUT;
264
265         usleep(100 * 1000);
266         SET_FIRST_BYTE(0x01);
267         SET_BYTES(0x04);
268         send_msg(&msg, fd, uc);
269         read_msgs(fd);
270
271         usleep(250 * 1000);
272         SET_BYTE(1, 0x15);
273         send_msg(&msg, fd, uc);
274         read_msgs(fd);
275
276         usleep(100 * 1000);
277         SET_BYTE(1, 0x05);
278         send_msg(&msg, fd, uc);
279         read_msgs(fd);
280
281         SET_FIRST_BYTE(0x02);
282         SET_BYTES(byte1);
283         SET_BYTES('|');
284         send_msg(&msg, fd, uc);
285         read_msgs(fd);
286
287         usleep(100 * 1000);
288         SET_BYTE(1, byte2);
289         send_msg(&msg, fd, uc);
290         read_msgs(fd);
291
292         return 0;
293 }
294
295 int communicate(int fd, int uc)
296 {
297         int i, j;
298         struct msg msg, in;
299         msg.direction = OUT;
300
301         read_msgs(fd);
302         SET_FIRST_BYTE(0x01);
303         SET_BYTES(0x04);
304         send_msg(&msg, fd, uc);
305
306         usleep(100 * 1000);
307         SET_BYTE(1, 0x06);
308         send_msg(&msg, fd, uc);
309         read_msgs(fd);
310
311         SET_BYTE(1, 0x15);
312         for (i = 0; i < 6; i++) {
313                 usleep(100 * 1000);
314                 send_msg(&msg, fd, uc);
315                 read_msgs(fd);
316         }
317         usleep(1000 * 1000);
318         read_msgs(fd);
319         send_msg(&msg, fd, uc);
320         read_msgs(fd);
321
322         usleep(100 * 1000);
323         SET_BYTE(1, 0x05);
324         send_msg(&msg, fd, uc);
325         read_msgs(fd);
326
327         send_pattern(fd, uc, 'R', 'A');
328         send_pattern(fd, uc, 'R', 'C');
329         send_pattern(fd, uc, 'R', 'D');
330         send_pattern(fd, uc, 'R', 'G');
331         send_pattern(fd, uc, 'R', 'I');
332         send_pattern(fd, uc, 'R', 'M');
333         send_pattern(fd, uc, 'R', 'P');
334         send_pattern(fd, uc, 'R', 'R');
335         send_pattern(fd, uc, 'R', 'S');
336         send_pattern(fd, uc, 'R', 'T');
337         send_pattern(fd, uc, 'R', 'U');
338         send_pattern(fd, uc, 'R', 'V');
339         send_pattern(fd, uc, 'R', 'W');
340         send_pattern(fd, uc, 'R', 'X');
341         send_pattern(fd, uc, 'W', 'K');
342
343         usleep(100 * 1000);
344         SET_FIRST_BYTE(0x08);
345         SET_BYTES('O');
346         SET_BYTES('b');
347         SET_BYTES('p');
348         SET_BYTES('s');
349         SET_BYTES('e');
350         SET_BYTES('c');
351         SET_BYTES('3');
352         SET_BYTES('|');
353         send_msg(&msg, fd, uc);
354         read_msgs(fd);
355
356         usleep(410 * 1000);
357         SET_FIRST_BYTE(0x02);
358         SET_BYTES('R');
359         SET_BYTES('|');
360         send_msg(&msg, fd, uc);
361         read_msgs(fd);
362
363         usleep(100 * 1000);
364         SET_BYTE(1, 'Y');
365         send_msg(&msg, fd, uc);
366         read_msgs(fd);
367
368         usleep(100 * 1000);
369         SET_BYTE(1, 'W');
370         send_msg(&msg, fd, uc);
371         read_msgs(fd);
372
373         usleep(100 * 1000);
374         SET_BYTE(1, 'K');
375         send_msg(&msg, fd, uc);
376         read_msgs(fd);
377
378         usleep(100 * 1000);
379         SET_BYTE(1, 'C');
380         send_msg(&msg, fd, uc);
381         read_msgs(fd);
382
383         send_pattern(fd, uc, 'R', 'Z');
384
385         usleep(100 * 1000);
386         SET_FIRST_BYTE(0x01);
387         SET_BYTES(0x04);
388         send_msg(&msg, fd, uc);
389         read_msgs(fd);
390
391         usleep(100 * 1000);
392         SET_BYTE(1, 0x15);
393         send_msg(&msg, fd, uc);
394         read_msgs(fd);
395
396         usleep(100 * 1000);
397         SET_BYTE(1, 0x05);
398         send_msg(&msg, fd, uc);
399         read_msgs(fd);
400
401         usleep(100 * 1000);
402         SET_BYTE(1, 0x04);
403         send_msg(&msg, fd, uc);
404         read_msgs(fd);
405
406         usleep(100 * 1000);
407         send_msg(&msg, fd, uc);
408         read_msgs(fd);
409
410         usleep(100 * 1000);
411         SET_BYTE(1, 0x06);
412         send_msg(&msg, fd, uc);
413         read_msgs(fd);
414
415         usleep(100 * 1000);
416         send_msg(&msg, fd, uc);
417         read_msgs(fd);
418
419         usleep(100 * 1000);
420         send_msg(&msg, fd, uc);
421         read_msgs(fd);
422
423         usleep(100 * 1000);
424         do {
425                 send_msg(&msg, fd, uc);
426                 read_and_verify(&in, fd);
427         } while (datalen(in.data) > 45);
428
429         return 0;
430 }
431
432 int main(int argc, char *argv[])
433 {
434         int fd, usage_code;
435
436         fd = hiddev_open(argv[1], &usage_code);
437         if (fd < 0)
438                 return 1;
439
440         communicate(fd, usage_code);
441
442         return 0;
443 }