]> mj.ucw.cz Git - home-hw.git/blob - bsb/daemon/burrow-bsb.c
BSB: Firmware handles replies
[home-hw.git] / bsb / daemon / burrow-bsb.c
1 /*
2  *      Boiler System Bus Interface Daemon
3  *
4  *      (c) 2020 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <time.h>
13 #include <unistd.h>
14
15 #include <libusb.h>
16
17 static struct libusb_context *usb_ctxt;
18 static struct libusb_device_handle *devh;
19
20 typedef unsigned char byte;
21 typedef uint32_t u32;
22 typedef unsigned int uint;
23
24 #include "../firmware/interface.h"
25
26 static void die(const char *msg, ...)
27 {
28         va_list args;
29         va_start(args, msg);
30
31         vfprintf(stderr, msg, args);
32         fputc('\n', stderr);
33
34         exit(1);
35 }
36
37 static void usb_error(const char *msg, ...)
38 {
39         va_list args;
40         va_start(args, msg);
41         vfprintf(stderr, msg, args);
42         fputc('\n', stderr);
43         va_end(args);
44
45         if (devh) {
46                 libusb_close(devh);
47                 devh = NULL;
48         }
49 }
50
51 static void open_device(void)
52 {
53         int err;
54         libusb_device **devlist;
55         ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist);
56         if (devn < 0)
57                 die("Cannot enumerate USB devices: error %d", (int) devn);
58
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));
65
66                                 if (err = libusb_open(dev, &devh)) {
67                                         usb_error("Cannot open device: error %d", err);
68                                         goto out;
69                                 }
70                                 libusb_reset_device(devh);
71                                 if (err = libusb_claim_interface(devh, 0)) {
72                                         usb_error("Cannot claim interface: error %d", err);
73                                         goto out;
74                                 }
75
76                                 goto out;
77                         }
78                 }
79         }
80
81 out:
82         libusb_free_device_list(devlist, 1);
83 }
84
85 static inline uint get_u32_le(byte *p)
86 {
87         return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
88 }
89
90 static const char * const stat_names[] = {
91 #define P(x) #x,
92         BSB_STATS
93 #undef P
94 };
95
96 static void show_stats(byte *resp, uint len)
97 {
98         printf("# Stats:");
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));
101         printf("\n");
102
103         fflush(stdout);
104 }
105
106 static void show_packet(byte *pkt, uint len)
107 {
108         if (!len) {
109                 printf("ERROR: Received empty frame!\n");
110                 return;
111         }
112
113         byte status = *pkt++;
114         len--;
115
116         if (!len) {
117                 printf("Transmit status: %u\n", status);
118                 return;
119         }
120
121 #if 1
122         printf(": [%d]", status);
123         for (uint i=0; i<len; i++)
124                 printf(" %02x", pkt[i]);
125         putchar('\n');
126 #endif
127
128         printf("%02x -> %02x: ", pkt[BF_SRC] ^ 0x80, pkt[BF_DEST]);
129         if (status)
130                 printf("[REPLY] ");
131         switch (pkt[4]) {
132                 case 2:
133                         printf("INFO %04x:%04x =", (pkt[5]<<8) | pkt[6], (pkt[7]<<8) | pkt[8]);
134                         for (uint i=9; i<len; i++)
135                                 printf(" %02x", pkt[i]);
136                         putchar('\n');
137                         break;
138                 case 6:
139                         printf("GET %04x:%04x\n", (pkt[6]<<8) | pkt[5], (pkt[7]<<8) | pkt[8]);
140                         break;
141                 case 7:
142                         printf("RET %04x:%04x =", (pkt[5]<<8) | pkt[6], (pkt[7]<<8) | pkt[8]);
143                         for (uint i=9; i<len; i++)
144                                 printf(" %02x", pkt[i]);
145                         putchar('\n');
146                         break;
147                 default:
148                         printf("??? type=%02x\n", pkt[4]);
149         }
150
151         fflush(stdout);
152 }
153
154 int main(void)
155 {
156         int err;
157         if (err = libusb_init(&usb_ctxt))
158                 die("Cannot initialize libusb: error %d", err);
159         // libusb_set_debug(usb_ctxt, 3);
160         open_device();
161
162         time_t now = time(NULL);
163         time_t last_stats = 0;
164         time_t last_query = now;
165         int received;
166         byte resp[64];
167
168         for (;;) {
169                 if (!devh) {
170                         fprintf(stderr, "Waiting for device to appear...\n");
171                         while (!devh) {
172                                 sleep(5);
173                                 open_device();
174                         }
175                 }
176
177                 now = time(NULL);
178                 if (last_stats + 60 < now) {
179                         if ((received = libusb_control_transfer(devh, 0xc0, 0x00, 0, 0, resp, sizeof(resp), 1000)) < 0) {
180                                 usb_error("Receive failed: error %d", received);
181                                 continue;
182                         }
183
184                         show_stats(resp, received);
185                         last_stats = now;
186                 }
187
188                 if (last_query + 10 < now) {
189                         byte pkt[] = { 0xdc, 0xc2, 0x00, 0x0b, 0x06, 0x3d, 0x2e, 0x11, 0x25, 0x00, 0x00 };
190                         if (err = libusb_bulk_transfer(devh, 0x01, pkt, sizeof(pkt), &received, 2000)) {
191                                 printf("Send failed: error %d\n", err);
192                                 // usb_error("Receive failed: error %d", received);
193                                 // continue;
194                         } else {
195                                 printf("Send OK: %d bytes\n", received);
196                         }
197                         last_query = now;
198                 }
199
200 #if 0
201                 if (err = libusb_bulk_transfer(devh, 0x81, resp, 64, &received, 2000)) {
202                         usb_error("Receive failed: error %d", err);
203                         continue;
204                 }
205
206                 printf("Received %d bytes\n", received);
207                 if (received < 4) {
208                         usb_error("Receive failed: unexpected response size %d", received);
209                         continue;
210                 }
211
212                 printf("-> %02x%02x%02x%02x\n", resp[0], resp[1], resp[2], resp[3]);
213 #endif
214
215                 if (err = libusb_interrupt_transfer(devh, 0x82, resp, 64, &received, 1000)) {
216                         if (err != LIBUSB_ERROR_TIMEOUT)
217                                 usb_error("Receive failed: error %d", err);
218                         continue;
219                 }
220
221                 show_packet(resp, received);
222         }
223 }