1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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;
}
|