2 * Boiler System Bus Interface Daemon
4 * (c) 2020 Martin Mares <mj@ucw.cz>
17 static struct libusb_context *usb_ctxt;
18 static struct libusb_device_handle *devh;
20 typedef unsigned char byte;
22 typedef unsigned int uint;
24 #include "../firmware/interface.h"
26 static void die(const char *msg, ...)
31 vfprintf(stderr, msg, args);
37 static void usb_error(const char *msg, ...)
41 vfprintf(stderr, msg, args);
51 static void open_device(void)
54 libusb_device **devlist;
55 ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist);
57 die("Cannot enumerate USB devices: error %d", (int) devn);
59 for (ssize_t i=0; i<devn; i++) {
60 struct libusb_device_descriptor desc;
61 libusb_device *dev = devlist[i];
62 if (!libusb_get_device_descriptor(dev, &desc)) {
63 if (desc.idVendor == BSB_USB_VENDOR && desc.idProduct == BSB_USB_PRODUCT) {
64 fprintf(stderr, "Found device at usb%d.%d\n", libusb_get_bus_number(dev), libusb_get_device_address(dev));
66 if (err = libusb_open(dev, &devh)) {
67 usb_error("Cannot open device: error %d", err);
70 libusb_reset_device(devh);
71 if (err = libusb_claim_interface(devh, 0)) {
72 usb_error("Cannot claim interface: error %d", err);
82 libusb_free_device_list(devlist, 1);
85 static inline uint get_u32_le(byte *p)
87 return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
90 static const char * const stat_names[] = {
96 static void show_stats(byte *resp, uint len)
99 for (uint i=0; 4*i + 3 < (uint) len; i++)
100 printf(" %s=%u", (i < sizeof(stat_names) / sizeof(stat_names[0]) ? stat_names[i] : "?"), get_u32_le(resp+4*i));
106 static void show_packet(byte *pkt, uint len)
108 time_t now = time(NULL);
109 struct tm *tm = localtime(&now);
111 strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", tm);
112 printf("%s ", timebuf);
115 printf("ERROR: Received empty frame!\n");
119 byte status = *pkt++;
123 printf("ERROR: Transmit status: %u\n", status);
128 printf(": [%d]", status);
129 for (uint i=0; i<len; i++)
130 printf(" %02x", pkt[i]);
134 printf("%02x -> %02x: ", pkt[BF_SRC] ^ 0x80, pkt[BF_DEST]);
139 printf("INFO %04x:%04x =", (pkt[5]<<8) | pkt[6], (pkt[7]<<8) | pkt[8]);
140 for (uint i=9; i<len; i++)
141 printf(" %02x", pkt[i]);
145 printf("GET %04x:%04x\n", (pkt[6]<<8) | pkt[5], (pkt[7]<<8) | pkt[8]);
148 printf("RET %04x:%04x =", (pkt[5]<<8) | pkt[6], (pkt[7]<<8) | pkt[8]);
149 for (uint i=9; i<len; i++)
150 printf(" %02x", pkt[i]);
154 printf("??? type=%02x\n", pkt[4]);
163 if (err = libusb_init(&usb_ctxt))
164 die("Cannot initialize libusb: error %d", err);
165 // libusb_set_debug(usb_ctxt, 3);
168 time_t now = time(NULL);
169 time_t last_stats = 0;
170 time_t last_query = now;
176 fprintf(stderr, "Waiting for device to appear...\n");
184 if (last_stats + 60 < now) {
185 if ((received = libusb_control_transfer(devh, 0xc0, 0x00, 0, 0, resp, sizeof(resp), 1000)) < 0) {
186 usb_error("Receive failed: error %d", received);
190 show_stats(resp, received);
194 if (last_query + 10 < now) {
195 byte pkt[] = { 0xdc, 0xc2, 0x00, 0x0b, 0x06, 0x3d, 0x2e, 0x11, 0x25, 0x00, 0x00 };
196 if (err = libusb_bulk_transfer(devh, 0x01, pkt, sizeof(pkt), &received, 2000)) {
197 printf("Send failed: error %d\n", err);
198 // usb_error("Receive failed: error %d", received);
201 // printf("Send OK: %d bytes\n", received);
206 if (err = libusb_interrupt_transfer(devh, 0x82, resp, 64, &received, 1000)) {
207 if (err != LIBUSB_ERROR_TIMEOUT)
208 usb_error("Receive failed: error %d", err);
212 show_packet(resp, received);