2 * Copyright © 2016 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 static uint32_t dfu_crc;
30 static FILE *dfu_file;
31 static int dfu_failed;
34 static uint32_t update_crc(uint32_t crc, uint8_t byte)
40 for (j = 0; j < 8; j++) {
42 crc = (crc >> 1) ^ (0xEDB88320 & mask);
47 static void dfu_init(FILE *file)
55 static int dfu_fini(void)
57 if (fflush(dfu_file) == EOF) {
68 static void dfu_8(uint8_t byte) {
69 if (putc(byte, dfu_file) == EOF) {
75 dfu_crc = update_crc(dfu_crc, byte);
78 static void dfu_pad(int len) {
83 static void dfu_string(char *string) {
86 while ((c = *string++))
90 static void dfu_string_pad(char *string, int len) {
93 while ((c = *string++)) {
100 static void dfu_block(uint8_t *bytes, int len) {
105 static void dfu_lsb16(uint16_t value) {
110 static void dfu_lsb32(uint32_t value) {
117 static uint32_t dfu_image_size(struct ao_hex_image *image) {
118 return 8 + image->length;
121 static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[])
126 for (i = 0; i < num_image; i++)
127 size += dfu_image_size(&images[i]);
131 static void dfu_image(struct ao_hex_image *image)
133 dfu_lsb32(image->address);
134 dfu_lsb32(image->length);
135 dfu_block(image->data, image->length);
138 static void dfu_target(char *name, int num_image, struct ao_hex_image images[])
140 uint32_t images_size = dfu_images_size(num_image, images);
143 dfu_string("Target");
148 dfu_string_pad(name, 255);
154 dfu_lsb32(images_size);
155 dfu_lsb32(num_image);
156 for (i = 0; i < num_image; i++)
157 dfu_image(&images[i]);
160 static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[])
162 return 274 + dfu_images_size(num_image, images);
166 dfu_size(int num_image, struct ao_hex_image images[])
169 size += 11; /* DFU Prefix */
171 size += dfu_target_size(num_image, images);
177 ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[])
181 total_size = dfu_size(num_image, images);
185 dfu_string(DFU_SIGNATURE);
187 dfu_lsb32(total_size);
190 dfu_target("ST...", num_image, images);
193 dfu_lsb16(info->bcdDevice);
194 dfu_lsb16(info->idProduct);
195 dfu_lsb16(info->idVendor);
196 dfu_lsb16(DFU_SPEC_VERSION);