]> git.itanic.dy.fi Git - glucose/blob - main.c
Initial commit
[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(1000 * 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         SET_FIRST_BYTE(0x01);
266         SET_BYTES(0x04);
267         send_msg(&msg, fd, uc);
268         read_msgs(fd);
269
270         SET_BYTE(1, 0x15);
271         send_msg(&msg, fd, uc);
272         read_msgs(fd);
273
274         SET_BYTE(1, 0x05);
275         send_msg(&msg, fd, uc);
276         read_msgs(fd);
277
278         SET_FIRST_BYTE(0x02);
279         SET_BYTES(byte1);
280         SET_BYTES('|');
281         send_msg(&msg, fd, uc);
282         read_msgs(fd);
283
284         SET_BYTE(1, byte2);
285         send_msg(&msg, fd, uc);
286         read_msgs(fd);
287
288         return 0;
289 }
290
291 int communicate(int fd, int uc)
292 {
293         int i, j;
294         struct msg msg, in;
295         msg.direction = OUT;
296
297         read_msgs(fd);
298         SET_FIRST_BYTE(0x01);
299         SET_BYTES(0x04);
300         send_msg(&msg, fd, uc);
301
302         usleep(100 * 1000);
303         SET_BYTE(1, 0x06);
304         send_msg(&msg, fd, uc);
305         read_msgs(fd);
306
307         SET_BYTE(1, 0x15);
308         for (i = 0; i < 6; i++) {
309                 send_msg(&msg, fd, uc);
310                 read_msgs(fd);
311         }
312         usleep(1000 * 1000);
313         read_msgs(fd);
314         send_msg(&msg, fd, uc);
315         read_msgs(fd);
316
317         SET_BYTE(1, 0x05);
318         send_msg(&msg, fd, uc);
319         read_msgs(fd);
320
321         send_pattern(fd, uc, 'R', 'A');
322         send_pattern(fd, uc, 'R', 'C');
323         send_pattern(fd, uc, 'R', 'D');
324         send_pattern(fd, uc, 'R', 'G');
325         send_pattern(fd, uc, 'R', 'I');
326         send_pattern(fd, uc, 'R', 'M');
327         send_pattern(fd, uc, 'R', 'P');
328         send_pattern(fd, uc, 'R', 'R');
329         send_pattern(fd, uc, 'R', 'S');
330         send_pattern(fd, uc, 'R', 'T');
331         send_pattern(fd, uc, 'R', 'U');
332         send_pattern(fd, uc, 'R', 'V');
333         send_pattern(fd, uc, 'R', 'W');
334         send_pattern(fd, uc, 'R', 'X');
335         send_pattern(fd, uc, 'W', 'K');
336
337         SET_FIRST_BYTE(0x08);
338         SET_BYTES('O');
339         SET_BYTES('b');
340         SET_BYTES('p');
341         SET_BYTES('s');
342         SET_BYTES('e');
343         SET_BYTES('c');
344         SET_BYTES('3');
345         SET_BYTES('|');
346         send_msg(&msg, fd, uc);
347         read_msgs(fd);
348
349         SET_FIRST_BYTE(0x02);
350         SET_BYTES('R');
351         SET_BYTES('|');
352         send_msg(&msg, fd, uc);
353         read_msgs(fd);
354
355         SET_BYTE(1, 'Y');
356         send_msg(&msg, fd, uc);
357         read_msgs(fd);
358
359         SET_BYTE(1, 'W');
360         send_msg(&msg, fd, uc);
361         read_msgs(fd);
362
363         SET_BYTE(1, 'K');
364         send_msg(&msg, fd, uc);
365         read_msgs(fd);
366
367         SET_BYTE(1, 'C');
368         send_msg(&msg, fd, uc);
369         read_msgs(fd);
370
371         send_pattern(fd, uc, 'R', 'Z');
372
373         SET_FIRST_BYTE(0x01);
374         SET_BYTES(0x04);
375         send_msg(&msg, fd, uc);
376         read_msgs(fd);
377
378         SET_BYTE(1, 0x15);
379         send_msg(&msg, fd, uc);
380         read_msgs(fd);
381
382         SET_BYTE(1, 0x05);
383         send_msg(&msg, fd, uc);
384         read_msgs(fd);
385
386         SET_BYTE(1, 0x04);
387         send_msg(&msg, fd, uc);
388         read_msgs(fd);
389
390         send_msg(&msg, fd, uc);
391         read_msgs(fd);
392
393         SET_BYTE(1, 0x06);
394         send_msg(&msg, fd, uc);
395         read_msgs(fd);
396
397         send_msg(&msg, fd, uc);
398         read_msgs(fd);
399
400         send_msg(&msg, fd, uc);
401         read_msgs(fd);
402
403         do {
404                 send_msg(&msg, fd, uc);
405                 read_and_verify(&in, fd);
406         } while (datalen(in.data) > 45);
407
408         return 0;
409 }
410
411 int main(int argc, char *argv[])
412 {
413         int fd, usage_code;
414
415         fd = hiddev_open(argv[1], &usage_code);
416         if (fd < 0)
417                 return 1;
418
419         communicate(fd, usage_code);
420
421         return 0;
422 }