1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Amaury Pouly
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
28 #define MIN(a,b) ((a) < (b) ? (a) : (b))
31 void put32le(uint8_t *buf
, uint32_t i
)
34 *buf
++ = (i
>> 8) & 0xff;
35 *buf
++ = (i
>> 16) & 0xff;
36 *buf
++ = (i
>> 24) & 0xff;
39 void put32be(uint8_t *buf
, uint32_t i
)
41 *buf
++ = (i
>> 24) & 0xff;
42 *buf
++ = (i
>> 16) & 0xff;
43 *buf
++ = (i
>> 8) & 0xff;
58 enum dev_type_t dev_type
;
61 struct dev_info_t g_dev_info
[] =
63 {0x066f, 0x3780, 1024, HID_DEVICE
}, /* i.MX233 / STMP3780 */
64 {0x066f, 0x3770, 48, HID_DEVICE
}, /* STMP3770 */
65 {0x15A2, 0x004F, 1024, HID_DEVICE
}, /* i.MX28 */
66 {0x066f, 0x3600, 4096, RECOVERY_DEVICE
}, /* STMP36xx */
69 int send_hid(libusb_device_handle
*dev
, int xfer_size
, uint8_t *data
, int size
, int nr_xfers
)
71 libusb_detach_kernel_driver(dev
, 0);
72 libusb_detach_kernel_driver(dev
, 4);
74 libusb_claim_interface(dev
, 0);
75 libusb_claim_interface(dev
, 4);
77 uint8_t *xfer_buf
= malloc(1 + xfer_size
);
78 uint8_t *p
= xfer_buf
;
80 *p
++ = 0x01; /* Report id */
82 /* Command block wrapper */
83 *p
++ = 'B'; /* Signature */
87 put32le(p
, 0x1); /* Tag */
89 put32le(p
, size
); /* Payload size */
91 *p
++ = 0; /* Flags (host to device) */
92 p
+= 2; /* Reserved */
94 /* Command descriptor block */
95 *p
++ = 0x02; /* Firmware download */
96 put32be(p
, size
); /* Download size */
98 int ret
= libusb_control_transfer(dev
,
99 LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
, 0x9, 0x201, 0,
100 xfer_buf
, xfer_size
+ 1, 1000);
103 printf("transfer error at init step\n");
107 for(int i
= 0; i
< nr_xfers
; i
++)
110 memcpy(&xfer_buf
[1], &data
[i
* xfer_size
], xfer_size
);
112 ret
= libusb_control_transfer(dev
,
113 LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
,
114 0x9, 0x202, 0, xfer_buf
, xfer_size
+ 1, 1000);
117 printf("transfer error at send step %d\n", i
);
123 ret
= libusb_interrupt_transfer(dev
, 0x81, xfer_buf
, xfer_size
, &recv_size
,
127 printf("transfer error at final stage\n");
134 int send_recovery(libusb_device_handle
*dev
, int xfer_size
, uint8_t *data
, int size
, int nr_xfers
)
137 // there should be no kernel driver attached but in doubt...
138 libusb_detach_kernel_driver(dev
, 0);
139 libusb_claim_interface(dev
, 0);
145 int len
= MIN(size
- sent
, xfer_size
);
146 int ret
= libusb_bulk_transfer(dev
, 1, data
+ sent
, len
, &xfered
, 1000);
149 printf("transfer error at send offset %d\n", sent
);
154 printf("empty transfer at step offset %d\n", sent
);
162 int main(int argc
, char **argv
)
166 printf("usage: %s <xfer size> <file>\n", argv
[0]);
167 printf("If <xfer size> is set to zero, the preferred one is used.\n");
172 int xfer_size
= strtol(argv
[1], &end
, 0);
173 if(end
!= (argv
[1] + strlen(argv
[1])))
175 printf("Invalid transfer size !\n");
179 libusb_device_handle
*dev
;
183 libusb_set_debug(NULL
, 3);
186 for(i
= 0; i
< sizeof(g_dev_info
) / sizeof(g_dev_info
[0]); i
++)
188 dev
= libusb_open_device_with_vid_pid(NULL
,
189 g_dev_info
[i
].vendor_id
, g_dev_info
[i
].product_id
);
193 xfer_size
= g_dev_info
[i
].xfer_size
;
194 printf("Found a match for %04x:%04x\n",
195 g_dev_info
[i
].vendor_id
, g_dev_info
[i
].product_id
);
200 printf("Cannot open device\n");
204 FILE *f
= fopen(argv
[2], "r");
207 perror("cannot open file");
210 fseek(f
, 0, SEEK_END
);
211 size_t size
= ftell(f
);
212 fseek(f
, 0, SEEK_SET
);
214 printf("Transfer size: %d\n", xfer_size
);
215 int nr_xfers
= (size
+ xfer_size
- 1) / xfer_size
;
216 uint8_t *file_buf
= malloc(nr_xfers
* xfer_size
);
217 memset(file_buf
, 0xff, nr_xfers
* xfer_size
); // pad with 0xff
218 if(fread(file_buf
, size
, 1, f
) != 1)
220 perror("read error");
226 switch(g_dev_info
[i
].dev_type
)
229 send_hid(dev
, xfer_size
, file_buf
, size
, nr_xfers
);
231 case RECOVERY_DEVICE
:
232 send_recovery(dev
, xfer_size
, file_buf
, size
, nr_xfers
);
235 printf("unknown device type\n");