Robert Menes | f83fc36 | 2008-09-27 16:37:16 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno and Frank Gevaerts |
| 11 | * |
| 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
| 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 21 | #include <stdio.h> |
| 22 | #include <stdlib.h> |
| 23 | #include <stdint.h> |
| 24 | #include <string.h> |
| 25 | #include <sys/types.h> |
| 26 | #include <sys/stat.h> |
| 27 | #include <fcntl.h> |
| 28 | #include <unistd.h> |
| 29 | #include <libgen.h> |
Bertrik Sikken | 79642ea | 2009-06-28 09:52:24 +0000 | [diff] [blame] | 30 | #include <arpa/inet.h> |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 31 | |
| 32 | #include <usb.h> |
| 33 | |
Frank Gevaerts | c487c01 | 2008-09-13 16:23:01 +0000 | [diff] [blame] | 34 | #define bswap_16(value) \ |
| 35 | ((((value) & 0xff) << 8) | ((value) >> 8)) |
| 36 | |
| 37 | #define bswap_32(value) \ |
| 38 | (((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \ |
| 39 | (uint32_t)bswap_16((uint16_t)((value) >> 16))) |
| 40 | |
| 41 | #define host_to_le32(_x) bswap_32(htonl(_x)) |
| 42 | #define host_to_le16(_x) bswap_16(htons(_x)) |
| 43 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 44 | void usage() |
| 45 | { |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 46 | fprintf(stderr, "usage: meizu_dfu m3 [SST39VF800.dfu] <M3.EBN>\n"); |
| 47 | fprintf(stderr, " meizu_dfu m6 [SST39VF800.dfu] <M6.EBN>\n"); |
| 48 | fprintf(stderr, " meizu_dfu m6sl [updateNAND_BE_070831.dfu] <M6SL.EBN>\n"); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 49 | exit(1); |
| 50 | } |
| 51 | |
| 52 | uint32_t crc32(char *data, int len, uint32_t poly, uint32_t init) |
| 53 | { |
| 54 | uint32_t crc_table[256]; |
| 55 | uint32_t crc, t; |
| 56 | int i, j; |
| 57 | |
| 58 | // generate the table |
| 59 | for (i = 0; i < 256; ++i) { |
| 60 | t = i; |
| 61 | for (j = 0; j < 8; ++j) |
| 62 | if (t & 1) |
| 63 | t = (t >> 1) ^ poly; |
| 64 | else |
| 65 | t >>= 1; |
| 66 | crc_table[i] = t; |
| 67 | } |
| 68 | |
| 69 | // calculate the crc |
| 70 | crc = init; |
| 71 | for (i = 0; i < len; ++i) |
| 72 | crc = (crc >> 8) ^ crc_table[(crc^data[i]) & 0xff]; |
| 73 | |
| 74 | return crc; |
| 75 | } |
| 76 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 77 | typedef struct { |
| 78 | char *name; |
| 79 | char *data; |
| 80 | int len; |
| 81 | } image_data_t; |
| 82 | |
| 83 | typedef struct { |
| 84 | int delay; |
| 85 | int pre_off; |
| 86 | uint32_t pre_sig; |
| 87 | uint16_t suf_dev; |
| 88 | uint16_t suf_prod; |
| 89 | uint16_t suf_ven; |
| 90 | uint16_t suf_dfu; |
| 91 | char suf_sig[3]; |
| 92 | uint8_t suf_len; |
| 93 | } image_attr_t; |
| 94 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 95 | #define BLOCK_SIZE 2048 |
| 96 | #define DFU_TIMEOUT 0xa000 |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 97 | #define DFU_CRC_POLY 0xedb88320 |
| 98 | #define DFU_INIT_CRC 0xffffffff |
| 99 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 100 | #define USB_VID_SAMSUNG 0x0419 |
Robert Menes | 063d37b | 2008-09-27 16:51:46 +0000 | [diff] [blame] | 101 | #define USB_PID_M6SL 0x0145 |
| 102 | #define USB_PID_M3_M6 0x0141 |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 103 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 104 | void init_img(image_data_t *img, const char *filename, image_attr_t *attr) |
| 105 | { |
| 106 | int fd, len, i, readlen; |
| 107 | struct stat statbuf; |
| 108 | char buf[BLOCK_SIZE]; |
| 109 | uint32_t dfu_crc; |
Frank Gevaerts | c487c01 | 2008-09-13 16:23:01 +0000 | [diff] [blame] | 110 | uint32_t le_len; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 111 | |
| 112 | printf("Reading %s...", filename); |
| 113 | |
Bertrik Sikken | 79642ea | 2009-06-28 09:52:24 +0000 | [diff] [blame] | 114 | if (stat(filename, &statbuf) < 0) { |
| 115 | printf("\nCould not stat file, exiting.\n"); |
| 116 | exit(1); |
| 117 | } |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 118 | len = statbuf.st_size; |
| 119 | |
| 120 | img->name = basename(strdup(filename)); |
| 121 | img->data = malloc(len + 16); |
| 122 | img->len = len + 16; |
| 123 | |
| 124 | fd = open(filename, O_RDONLY); |
| 125 | for (i = 0; i < len; i += BLOCK_SIZE) { |
| 126 | readlen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE; |
| 127 | read(fd, buf, readlen); |
| 128 | memcpy(img->data + i, buf, readlen); |
| 129 | } |
| 130 | close(fd); |
| 131 | |
Frank Gevaerts | c487c01 | 2008-09-13 16:23:01 +0000 | [diff] [blame] | 132 | le_len = host_to_le32(img->len); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 133 | // patch the data size in after the signature |
Frank Gevaerts | c487c01 | 2008-09-13 16:23:01 +0000 | [diff] [blame] | 134 | memcpy(img->data + attr->pre_off + 4, &le_len, 4); |
| 135 | |
| 136 | /* convert to little endian */ |
| 137 | attr->suf_dev = host_to_le16(attr->suf_dev); |
| 138 | attr->suf_prod = host_to_le16(attr->suf_prod); |
| 139 | attr->suf_ven = host_to_le16(attr->suf_ven); |
| 140 | attr->suf_dfu = host_to_le16(attr->suf_dfu); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 141 | |
| 142 | // append the suffix (excluding the checksum) |
| 143 | memcpy(img->data + len, &attr->suf_dev, 2); |
| 144 | memcpy(img->data + len + 2, &attr->suf_prod, 2); |
| 145 | memcpy(img->data + len + 4, &attr->suf_ven, 2); |
| 146 | memcpy(img->data + len + 6, &attr->suf_dfu, 2); |
| 147 | memcpy(img->data + len + 8, &attr->suf_sig, 3); |
| 148 | memcpy(img->data + len + 11, &attr->suf_len, 1); |
| 149 | |
Frank Gevaerts | c487c01 | 2008-09-13 16:23:01 +0000 | [diff] [blame] | 150 | dfu_crc = host_to_le32(crc32(img->data, len + 12, DFU_CRC_POLY, DFU_INIT_CRC)); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 151 | memcpy(img->data + len + 12, &dfu_crc, 4); |
| 152 | |
| 153 | #if 0 |
| 154 | FILE *f = fopen(img->name, "w"); |
| 155 | fwrite(img->data, len + 16, 1, f); |
| 156 | fclose(f); |
| 157 | #endif |
| 158 | |
| 159 | printf("OK\n"); |
| 160 | } |
| 161 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 162 | usb_dev_handle *usb_dev_open(uint16_t dfu_vid, uint16_t dfu_pid) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 163 | { |
| 164 | struct usb_bus *bus; |
| 165 | struct usb_device *dev; |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 166 | usb_dev_handle *device; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 167 | |
| 168 | printf("USB initialization..."); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 169 | |
| 170 | usb_init(); |
| 171 | usb_find_busses(); |
| 172 | usb_find_devices(); |
| 173 | |
| 174 | for (bus = usb_get_busses(); bus != NULL; bus = bus->next) |
| 175 | for (dev = bus->devices; dev != NULL; dev = dev->next) |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 176 | if (dev->descriptor.idVendor == dfu_vid |
| 177 | && dev->descriptor.idProduct == dfu_pid) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 178 | goto found; |
| 179 | |
| 180 | printf("\nNo device found, exiting.\n"); |
| 181 | exit(1); |
| 182 | |
| 183 | found: |
| 184 | printf(" Device found.\n"); |
| 185 | device = usb_open(dev); |
| 186 | usb_claim_interface(device, 0); |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 187 | return device; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 188 | } |
| 189 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 190 | void usb_mimic_windows(usb_dev_handle *device) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 191 | { |
| 192 | char data[1024]; |
| 193 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 194 | usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); |
| 195 | usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT); |
| 196 | usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x001b, DFU_TIMEOUT); |
| 197 | usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0040, DFU_TIMEOUT); |
| 198 | usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); |
| 199 | usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0009, DFU_TIMEOUT); |
| 200 | usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); |
| 201 | usb_control_msg(device, 0x80, 0x06, 0x0303, 0x0409, data, 0x00ff, DFU_TIMEOUT); |
| 202 | usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x00ff, DFU_TIMEOUT); |
| 203 | usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); |
| 204 | usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT); |
| 205 | usb_control_msg(device, 0x80, 0x06, 0x0300, 0x0000, data, 0x00ff, DFU_TIMEOUT); |
| 206 | usb_control_msg(device, 0x80, 0x06, 0x0302, 0x0409, data, 0x00ff, DFU_TIMEOUT); |
| 207 | usb_control_msg(device, 0x80, 0x06, 0x0100, 0x0000, data, 0x0012, DFU_TIMEOUT); |
| 208 | usb_control_msg(device, 0x80, 0x06, 0x0200, 0x0000, data, 0x0209, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 209 | } |
| 210 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 211 | void usb_dev_close(usb_dev_handle *device) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 212 | { |
| 213 | printf("Releasing interface..."); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 214 | |
| 215 | usb_release_interface(device, 0); |
| 216 | |
| 217 | printf(" OK\n"); |
| 218 | } |
| 219 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 220 | enum DFU_REQUEST { |
| 221 | DFU_DETACH = 0, |
| 222 | DFU_DOWNLOAD, |
| 223 | DFU_UPLOAD, |
| 224 | DFU_GETSTATUS, |
| 225 | DFU_CLRSTATUS, |
| 226 | DFU_GETSTATE, |
| 227 | DFU_ABORT |
| 228 | }; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 229 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 230 | void get_cpu(usb_dev_handle *device) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 231 | { |
| 232 | char data[64]; |
| 233 | int req_out_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
| 234 | int len; |
| 235 | |
| 236 | printf("GET CPU"); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 237 | |
| 238 | // check for "S5L8700 Rev.1" |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 239 | len = usb_control_msg(device, req_out_if, 0xff, 0x0002, 0, data, 0x003f, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 240 | if (len < 0) { |
| 241 | printf("\nError trying to get CPU model, exiting.\n"); |
| 242 | exit(1); |
| 243 | } |
| 244 | |
| 245 | memset(data + len, 0, 64 - len); |
| 246 | printf(", got: %s\n", data); |
| 247 | } |
| 248 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 249 | void send_file(usb_dev_handle *device, image_data_t *img) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 250 | { |
| 251 | char dfu_ret[6]; |
| 252 | char *data; |
| 253 | int req_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
| 254 | int req_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
| 255 | int len, idx, writelen, i; |
| 256 | |
| 257 | printf("Sending %s... ", img->name); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 258 | |
| 259 | len = img->len; |
| 260 | data = img->data; |
| 261 | |
| 262 | // loop for the file |
| 263 | for (i = 0, idx = 0; i < len; i += BLOCK_SIZE, ++idx) { |
| 264 | writelen = ((len - i) < BLOCK_SIZE) ? (len - i) : BLOCK_SIZE; |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 265 | usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, data + i, writelen, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 266 | dfu_ret[4] = 0x00; |
| 267 | while (dfu_ret[4] != 0x05) |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 268 | usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 269 | printf("#"); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 270 | } |
| 271 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 272 | usb_control_msg(device, req_out_if, DFU_DOWNLOAD, idx, 0, NULL, 0, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 273 | dfu_ret[4] = 0x00; |
| 274 | while (dfu_ret[4] != 0x07) |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 275 | usb_control_msg(device, req_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 276 | |
| 277 | printf(" OK\n"); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 278 | } |
| 279 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 280 | void clear_status(usb_dev_handle *device) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 281 | { |
| 282 | char dfu_ret[6]; |
| 283 | int usb_in_if = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
| 284 | int usb_out_if = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; |
| 285 | |
| 286 | printf("Clearing status..."); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 287 | |
| 288 | dfu_ret[4] = 0x00; |
| 289 | while (dfu_ret[4] != 0x08) |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 290 | usb_control_msg(device, usb_in_if, DFU_GETSTATUS, 0, 0, dfu_ret, 6, DFU_TIMEOUT); |
| 291 | usb_control_msg(device, usb_out_if, DFU_CLRSTATUS, 0, 0, NULL, 0, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 292 | |
| 293 | printf(" OK\n"); |
| 294 | } |
| 295 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 296 | void dfu_detach(usb_dev_handle *device) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 297 | { |
| 298 | char usb_ret[4]; |
| 299 | int usb_in_oth = USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_OTHER; |
| 300 | int usb_out_oth = USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER; |
| 301 | |
| 302 | printf("Detaching..."); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 303 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 304 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
| 305 | usb_control_msg(device, usb_out_oth, DFU_DOWNLOAD, 0x0010, 3, NULL, 0, DFU_TIMEOUT); |
| 306 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
| 307 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
| 308 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
| 309 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
| 310 | usb_control_msg(device, usb_in_oth, DFU_DETACH, 0x0000, 3, usb_ret, 4, DFU_TIMEOUT); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 311 | |
| 312 | printf(" OK\n"); |
| 313 | } |
| 314 | |
| 315 | void dfu_m3_m6(char *file1, char *file2) |
| 316 | { |
| 317 | image_data_t img1, img2; |
| 318 | image_attr_t attr1, attr2; |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 319 | usb_dev_handle *device; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 320 | |
| 321 | attr1.delay = 1000; |
| 322 | attr1.pre_off = 0x20; |
| 323 | attr1.pre_sig = 0x44465543; |
| 324 | attr1.suf_dev = 0x0100; |
| 325 | attr1.suf_prod = 0x0140; |
| 326 | attr1.suf_ven = 0x0419; |
| 327 | attr1.suf_dfu = 0x0100; |
| 328 | memcpy(attr1.suf_sig, "RON", 3); |
| 329 | attr1.suf_len = 0x10; |
| 330 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 331 | init_img(&img1, file1, &attr1); |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 332 | |
| 333 | if (file2) { |
| 334 | attr2.delay = 1000; |
| 335 | attr2.pre_off = 0x20; |
| 336 | attr2.pre_sig = 0x44465543; |
| 337 | attr2.suf_dev = 0x0100; |
| 338 | attr2.suf_prod = 0x0140; |
| 339 | attr2.suf_ven = 0x0419; |
| 340 | attr2.suf_dfu = 0x0100; |
| 341 | memcpy(attr2.suf_sig, "UFD", 3); |
| 342 | attr2.suf_len = 0x10; |
| 343 | |
| 344 | init_img(&img2, file2, &attr2); |
| 345 | } |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 346 | |
Frank Gevaerts | 903156d | 2008-09-01 08:56:54 +0000 | [diff] [blame] | 347 | device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M3_M6); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 348 | // usb_mimic_windows(); |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 349 | get_cpu(device); |
| 350 | get_cpu(device); |
| 351 | send_file(device, &img1); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 352 | |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 353 | if (file2) { |
| 354 | printf("Wait a sec (literally)..."); |
| 355 | sleep(1); |
| 356 | printf(" OK\n"); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 357 | |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 358 | clear_status(device); |
| 359 | get_cpu(device); |
| 360 | send_file(device, &img2); |
| 361 | dfu_detach(device); |
| 362 | } |
| 363 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 364 | usb_dev_close(device); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 365 | } |
| 366 | |
| 367 | void dfu_m6sl(char *file1, char *file2) |
| 368 | { |
| 369 | image_data_t img1, img2; |
| 370 | image_attr_t attr1, attr2; |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 371 | usb_dev_handle *device; |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 372 | |
| 373 | attr1.delay = 1000; |
| 374 | attr1.pre_off = 0x20; |
| 375 | attr1.pre_sig = 0x44465543; |
| 376 | attr1.suf_dev = 0x0100; |
| 377 | attr1.suf_prod = 0x0140; |
| 378 | attr1.suf_ven = 0x0419; |
| 379 | attr1.suf_dfu = 0x0100; |
| 380 | memcpy(attr1.suf_sig, "UFD", 3); |
| 381 | attr1.suf_len = 0x10; |
| 382 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 383 | init_img(&img1, file1, &attr1); |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 384 | |
| 385 | if (file2) { |
| 386 | attr2.delay = 1000; |
| 387 | attr2.pre_off = 0x20; |
| 388 | attr2.pre_sig = 0x44465543; |
| 389 | attr2.suf_dev = 0x0100; |
| 390 | attr2.suf_prod = 0x0140; |
| 391 | attr2.suf_ven = 0x0419; |
| 392 | attr2.suf_dfu = 0x0100; |
| 393 | memcpy(attr2.suf_sig, "UFD", 3); |
| 394 | attr2.suf_len = 0x10; |
| 395 | |
| 396 | init_img(&img2, file2, &attr2); |
| 397 | } |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 398 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 399 | device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL); |
| 400 | get_cpu(device); |
| 401 | get_cpu(device); |
| 402 | send_file(device, &img1); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 403 | |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 404 | if (file2) { |
| 405 | printf("Wait a sec (literally)..."); |
| 406 | sleep(1); |
| 407 | printf(" OK\n"); |
| 408 | usb_dev_close(device); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 409 | |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 410 | device = usb_dev_open(USB_VID_SAMSUNG, USB_PID_M6SL); |
| 411 | get_cpu(device); |
| 412 | get_cpu(device); |
| 413 | send_file(device, &img2); |
| 414 | dfu_detach(device); |
| 415 | } |
| 416 | |
Frank Gevaerts | 3409e9d | 2008-08-31 21:36:04 +0000 | [diff] [blame] | 417 | usb_dev_close(device); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 418 | } |
| 419 | |
| 420 | |
| 421 | int main(int argc, char **argv) |
| 422 | { |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 423 | if (argc < 3 || argc > 4) |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 424 | usage(); |
| 425 | |
Frank Gevaerts | 903156d | 2008-09-01 08:56:54 +0000 | [diff] [blame] | 426 | setvbuf(stdout, NULL, _IONBF, 0); |
| 427 | |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 428 | char *second_file = (argc == 4) ? argv[3] : NULL; |
| 429 | |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 430 | if (!strcmp(argv[1], "m3")) |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 431 | dfu_m3_m6(argv[2], second_file); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 432 | else if (!strcmp(argv[1], "m6")) |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 433 | dfu_m3_m6(argv[2], second_file); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 434 | else if (!strcmp(argv[1], "m6sl")) |
Rafaël Carré | 811c359 | 2010-06-08 23:04:17 +0000 | [diff] [blame] | 435 | dfu_m6sl(argv[2], second_file); |
Frank Gevaerts | e645ced | 2008-08-29 18:53:52 +0000 | [diff] [blame] | 436 | else |
| 437 | usage(); |
| 438 | |
| 439 | return 0; |
| 440 | } |
| 441 | |