summaryrefslogtreecommitdiff
path: root/fw-update.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-12-11 14:31:13 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-12-11 14:31:13 +0100
commitbb169127d8e87b32ea2c0a9d9d51fca015681a1f (patch)
tree5f65d9818206c3619aca9745b76ef45806c8cc50 /fw-update.c
downloadt650-dfu-bb169127d8e87b32ea2c0a9d9d51fca015681a1f.tar.gz
Add fw-update.c (from 6 April 2014)
Diffstat (limited to 'fw-update.c')
-rw-r--r--fw-update.c127
1 files changed, 127 insertions, 0 deletions
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 <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+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;
+}