From bb169127d8e87b32ea2c0a9d9d51fca015681a1f Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Thu, 11 Dec 2014 14:31:13 +0100 Subject: Add fw-update.c (from 6 April 2014) --- fw-update.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 fw-update.c (limited to 'fw-update.c') diff --git a/fw-update.c b/fw-update.c new file mode 100644 index 0000000..5b70219 --- /dev/null +++ b/fw-update.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include +#include + +size_t read_fw(const char *filename, uint8_t **fw_buf) { + int fw_fd, r; + size_t read_bytes = 0; + size_t bufsize = 0; + const size_t blocksize = 1024; + + fw_fd = open(filename, O_RDONLY); + if (fw_fd < 0) { + perror(filename); + return 0; + } + + *fw_buf = NULL; + do { + if (bufsize - read_bytes < blocksize) { + bufsize += blocksize; + *fw_buf = realloc(*fw_buf, bufsize); + if (fw_buf == NULL) { + perror("realloc"); + abort(); + } + } + + r = read(fw_fd, *fw_buf + read_bytes, bufsize - read_bytes); + if (r > 0) + read_bytes += r; + } while (r > 0); + + if (r < 0) + perror("read"); + if (read_bytes == 0) + fprintf(stderr, "Warning: no data is read\n"); + + close(fw_fd); + + if (r < 0 || read_bytes == 0) { + free(*fw_buf); + *fw_buf = NULL; + return 0; + } + + return read_bytes; +} + +typedef struct { + uint8_t report_id; + uint8_t device_index; + uint8_t addr; + union { + uint8_t params[3]; + uint8_t params_l[16]; + }; +} HidppReport; + +int fw_update(int fd, uint8_t device_index, uint8_t *fw, size_t fw_len) { + HidppReport report; + report.report_id = 0x10; + report.device_index = device_index; + report.addr = 0xE2; + report.params[0]; + +// TODO: refactor ltunify to allow re-using its feature discovery functionality. + // TODO: [ix feat] find HID++ version, confirm >= 0x0200 + // TODO: [ix feat] discover DFU feature + // TODO: print: ask user to restart device + // TODO: [ix notif] wait for device connect + // TODO: [ix feat req] send "DFU" to DFU feature + // TODO: [ix feat resp] confirm DFU enablement + // TODO: [ff SHORT_REG req] write "LT" ix to f0 + // TODO: [DJ ix notif resp] Link-loss notif (0x42) + // TODO: [ff SHORT_REG resp] write must be succesful + // TODO: [ff SHORT_REG] read f0 and confirm it says LT ix + // TODO: [ix 82 E2] send magic packet (+verify) + // TODO: [ix 82 E2] send firmware (+check toggle) + // TODO: [ix 82 E2] send verify (+check toggle) + // TODO: [ff SHORT_REG req] send "XIT + // TODO: [ix notif] expect re-connection (0x41, proto 5) + // TODO: (optional): ask user to restart device, confirm notif + // TODO: print: success + + return 1; +} + +int main(int argc, char **argv) { + uint8_t *fw = NULL; + size_t fw_len; + int hid_fd = -1; + int r = 0; + uint8_t device_index; + + if (argc <= 3) { + fprintf(stderr, "Usage: %s /dev/hidrawX device_index flash-file\n", argv[0]); + return 1; + } + + device_index = atoi(argv[2]); + if (!(device_index >= 1 && device_index <= 6)) { + fprintf(stderr, "device_index must be between 1 and 6 (inclusive)\n"); + return 1; + } + + if ((fw_len = read_fw(argv[3], &fw)) == 0) { + return 1; + } + + printf("Firmware size: %zu\n", fw_len); + + hid_fd = open(argv[1], O_RDWR); + if (hid_fd >= 0) { + r = fw_update(hid_fd, device_index, fw, fw_len); + } else { + perror(argv[1]); + r = 1; + } + + if (hid_fd >= 0) + close(hid_fd); + free(fw); + return r; +} -- cgit v1.2.1