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