]> git.itanic.dy.fi Git - glucose/commitdiff
Initial commit
authorTimo Kokkonen <kaapeli@itanic.dy.fi>
Wed, 27 Apr 2011 15:25:49 +0000 (18:25 +0300)
committerTimo Kokkonen <kaapeli@itanic.dy.fi>
Wed, 27 Apr 2011 15:51:52 +0000 (18:51 +0300)
This version is extremely slow and prints huge amounts of verbose
debug messages. But it is able to import the glucose readings from the
device.

Signed-off-by: Timo Kokkonen <kaapeli@itanic.dy.fi>
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a80905b
--- /dev/null
@@ -0,0 +1,6 @@
+*.o
+*~
+\#*#
+.*.o.d
+glucose
+TAGS
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..c5f7cb7
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+CC = gcc
+LD = ld
+CFLAGS = -Wall -O2 -g
+
+GLUCOSE_OBJS = main.o
+
+ALL_OBJS = $(GLUCOSE_OBJS)
+ALL_DEBS = $(shell echo " "$(ALL_OBJS) | sed -e "s,[^ ]*\.a,,g" -e     \
+       "s,\([^ ]*\)/\([^ /]*\)\.o,\1/.\2.o.d,g" -e "s, \([^            \
+       /]*\)\.o, .\1.o.d,g" )
+
+ifeq ($(V),1)
+       Q               =
+       QUIET_CC        =
+       QUIET_LINK      =
+else
+       Q               = @
+       QUIET_CC        = @echo "       CC " $@;
+       QUIET_LINK      = @echo "     LINK " $@;
+endif
+
+all: glucose
+
+glucose: $(GLUCOSE_OBJS)
+       $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $^
+
+clean:
+       rm -vf glucose *~ *.o .*.d
+
+.c.o:
+       $(QUIET_CC)$(CC) -MMD -MF .$@.d $(CFLAGS) -c $< -o $@
+       $(Q)cp .$@.d .$@.P; \
+            sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
+                -e '/^$$/ d' -e 's/$$/ :/' < .$@.d >> .$@.P; \
+            mv .$@.P .$@.d
+
+TAGS:
+       @echo -e "\tTAGS\t"
+       @etags *.[ch]
+
+.PHONY: all clean TAGS
+
+-include $(ALL_DEBS)
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..a842a68
--- /dev/null
+++ b/main.c
@@ -0,0 +1,422 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/hiddev.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#define PRINT_FIELD(field) printf(#field ": %04x\n", field)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define READ_BUFFER_LENGTH 64
+
+struct msg {
+       int direction;
+       unsigned char data[64];
+};
+
+enum direction {
+       IN = 666,
+       OUT,
+};
+
+static int is_printable(const unsigned char c)
+{
+       return c >= 0x20 && c < 0x80;
+}
+
+static int datalen(const unsigned char *data)
+{
+       int i, len;
+
+       for (i = 0, len = 0; i < 64; i++)
+               if (data[i])
+                       len = i;
+
+       return len + 1;
+}
+
+static void print_hex(const unsigned char *data, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               printf("0x%02x ", data[i]);
+
+       printf("\n");
+}
+
+static void print_ascii(const unsigned char *data, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               printf("%c", is_printable(data[i]) ? data[i] : '.');
+
+       printf("\n");
+}
+
+int hid_read(unsigned char *data, int bufsize, int fd)
+{
+       struct hiddev_event readBuffer[READ_BUFFER_LENGTH];
+       int ret, n, i;
+
+       ret = read(fd, readBuffer, sizeof(readBuffer));
+       if (ret < 0)
+               return ret;
+
+       n = ret / sizeof(readBuffer[0]);
+       for (i = 0; i < n && i < bufsize; i++)
+               data[i] = readBuffer[i].value;
+       return n;
+}
+
+
+int hid_write(const unsigned char data[64], int fd , int usage_code)
+{
+       int rc = 0, uindex, error;
+
+       struct hiddev_usage_ref uref;
+       struct hiddev_report_info rinfo;
+
+       uref.report_id = *data++;
+       uref.report_type = HID_REPORT_TYPE_OUTPUT;
+       uref.field_index = 0;
+
+       uref.usage_code = usage_code;
+
+       for (uindex = 0; uindex < 63; uindex++) {
+               uref.usage_index = uindex;
+               uref.value = *data++;
+
+               rc = ioctl(fd, HIDIOCSUSAGE, &uref);
+               if (rc != 0)
+                       goto err;
+       }
+
+       rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
+       rinfo.report_id =  0x0;
+       rinfo.num_fields = 1;
+
+       rc = ioctl(fd, HIDIOCSREPORT, &rinfo);
+       if (rc != 0)
+               goto err2;
+
+       return 0;
+err2:
+       printf("HIDIOCSREPORT\n");
+err:
+       error = errno;
+       printf("Error in IOCTL: %s\n", strerror(error));
+
+       return rc;
+}
+
+int get_usagecode(int fd)
+{
+       struct hiddev_usage_ref uref;
+       int rc, error;
+
+       uref.report_type = HID_REPORT_TYPE_OUTPUT;
+       uref.report_id = 0x0;
+       uref.field_index = 0;
+       uref.usage_index = 0;
+
+       rc = ioctl(fd, HIDIOCGUCODE, &uref);
+       if (rc < 0) {
+               error = errno;
+               printf("Error gettin usage code: %s\n", strerror(error));
+               return rc;
+       }
+
+       return uref.usage_code;
+}
+
+int hiddev_open(const char *device_path, int *usage_code)
+{
+       struct hiddev_devinfo device_info;
+       struct hiddev_report_info rinfo;
+       int ret, error;
+       int fd;
+       fd = ret = open(device_path, O_RDWR);
+
+       if (fd < 0)
+               goto err;
+
+
+       rinfo.report_type = HID_REPORT_TYPE_OUTPUT;
+       rinfo.report_id = HID_REPORT_ID_FIRST;
+       ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
+       if (ret < 0)
+               goto err;
+
+       PRINT_FIELD(rinfo.report_type);
+       PRINT_FIELD(rinfo.report_id);
+       PRINT_FIELD(rinfo.num_fields);
+
+       *usage_code = get_usagecode(fd);
+
+       if (*usage_code < 0)
+               return -8;
+
+       ret = ioctl(fd, HIDIOCGDEVINFO, &device_info);
+
+       if (ret < 0)
+               goto err;
+
+       PRINT_FIELD(device_info.bustype);
+       PRINT_FIELD(device_info.busnum);
+       PRINT_FIELD(device_info.devnum);
+       PRINT_FIELD(device_info.ifnum);
+       PRINT_FIELD(device_info.vendor);
+       PRINT_FIELD(device_info.product);
+       PRINT_FIELD(device_info.version);
+       PRINT_FIELD(device_info.num_applications);
+
+       return fd;
+
+err:
+       error = errno;
+       printf("Error opening device %s: %s\n", device_path, strerror(error));
+       return ret;
+}
+
+int send_msg(const struct msg *msg, int fd, int usage_code)
+{
+       int ret;
+
+       if (msg->direction != OUT) {
+               printf("Message direction is not OUT\n");
+               exit(1);
+       }
+
+       usleep(1000 * 1000);
+       printf("Sending: ");
+       print_hex(msg->data + 1, datalen(msg->data) - 1);
+       print_ascii(msg->data + 1, datalen(msg->data) - 1);
+
+       ret = hid_write(msg->data, fd, usage_code);
+       if (ret)
+               exit(1);
+
+       return 0;
+}
+
+int read_and_verify(struct msg *msg, int fd)
+{
+       unsigned char buf[64];
+       int ret, offset = 0;
+
+       while (offset < 64) {
+               ret = hid_read(buf + offset, sizeof(buf) - offset, fd);
+
+               if (ret < 0)
+                       goto err;
+
+               offset += ret;
+       }
+
+       memcpy(msg->data, buf, sizeof(buf));
+       printf("Got data %d: ", datalen(buf));
+//     print_hex(buf, datalen(buf));
+       print_ascii(buf, datalen(buf));
+err:
+       return 0;
+}
+
+int read_msgs(int fd)
+{
+       struct msg msg;
+       while (1) {
+               read_and_verify(&msg, fd);
+               if (datalen(msg.data) <= 36)
+                       break;
+       }
+
+       return 0;
+}
+
+#define SET_FIRST_BYTE(byte)                                   \
+       do {                                                    \
+               memset(&msg.data, 0, sizeof(msg.data));         \
+               msg.data[4] = (byte);                           \
+               j = 5;                                          \
+       } while (0)
+
+#define SET_BYTE(idx, byte)                    \
+       do {                                    \
+               msg.data[(idx) + 4] = (byte);   \
+               j = (idx) + 1;                  \
+       } while (0)
+
+#define SET_BYTES(byte) msg.data[j++] = (byte)
+
+int send_pattern(int fd, int uc, unsigned char byte1, unsigned char byte2)
+{
+       int j;
+       struct msg msg;
+       msg.direction = OUT;
+
+       SET_FIRST_BYTE(0x01);
+       SET_BYTES(0x04);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x15);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x05);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_FIRST_BYTE(0x02);
+       SET_BYTES(byte1);
+       SET_BYTES('|');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, byte2);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       return 0;
+}
+
+int communicate(int fd, int uc)
+{
+       int i, j;
+       struct msg msg, in;
+       msg.direction = OUT;
+
+       read_msgs(fd);
+       SET_FIRST_BYTE(0x01);
+       SET_BYTES(0x04);
+       send_msg(&msg, fd, uc);
+
+       usleep(100 * 1000);
+       SET_BYTE(1, 0x06);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x15);
+       for (i = 0; i < 6; i++) {
+               send_msg(&msg, fd, uc);
+               read_msgs(fd);
+       }
+       usleep(1000 * 1000);
+       read_msgs(fd);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x05);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       send_pattern(fd, uc, 'R', 'A');
+       send_pattern(fd, uc, 'R', 'C');
+       send_pattern(fd, uc, 'R', 'D');
+       send_pattern(fd, uc, 'R', 'G');
+       send_pattern(fd, uc, 'R', 'I');
+       send_pattern(fd, uc, 'R', 'M');
+       send_pattern(fd, uc, 'R', 'P');
+       send_pattern(fd, uc, 'R', 'R');
+       send_pattern(fd, uc, 'R', 'S');
+       send_pattern(fd, uc, 'R', 'T');
+       send_pattern(fd, uc, 'R', 'U');
+       send_pattern(fd, uc, 'R', 'V');
+       send_pattern(fd, uc, 'R', 'W');
+       send_pattern(fd, uc, 'R', 'X');
+       send_pattern(fd, uc, 'W', 'K');
+
+       SET_FIRST_BYTE(0x08);
+       SET_BYTES('O');
+       SET_BYTES('b');
+       SET_BYTES('p');
+       SET_BYTES('s');
+       SET_BYTES('e');
+       SET_BYTES('c');
+       SET_BYTES('3');
+       SET_BYTES('|');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_FIRST_BYTE(0x02);
+       SET_BYTES('R');
+       SET_BYTES('|');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 'Y');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 'W');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 'K');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 'C');
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       send_pattern(fd, uc, 'R', 'Z');
+
+       SET_FIRST_BYTE(0x01);
+       SET_BYTES(0x04);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x15);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x05);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x04);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       SET_BYTE(1, 0x06);
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       send_msg(&msg, fd, uc);
+       read_msgs(fd);
+
+       do {
+               send_msg(&msg, fd, uc);
+               read_and_verify(&in, fd);
+       } while (datalen(in.data) > 45);
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       int fd, usage_code;
+
+       fd = hiddev_open(argv[1], &usage_code);
+       if (fd < 0)
+               return 1;
+
+       communicate(fd, usage_code);
+
+       return 0;
+}