blob: bdc8da69fe61e54ea5d501b4ec476ad73e9213c7 [file] [log] [blame]
Dave Chapmandd998b72007-09-09 13:30:40 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Dave Chapman
11 *
12 * USB code based on ifp-line - http://ifp-driver.sourceforge.net
13 *
14 * ifp-line is (C) Pavel Kriz, Jun Yamishiro and Joe Roback and
15 * licensed under the GPL (v2)
16 *
17 *
18 * All files in this archive are subject to the GNU General Public License.
19 * See the file COPYING in the source tree root for full license agreement.
20 *
21 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
22 * KIND, either express or implied.
23 *
24 ****************************************************************************/
25
26
27#include <stdio.h>
28#include <inttypes.h>
29#include <usb.h>
Barry Wardell79244b22007-09-12 00:03:17 +000030#include <string.h>
Jonathan Gordon7929b032007-09-16 00:30:10 +000031#include "stdbool.h"
Dave Chapmandd998b72007-09-09 13:30:40 +000032
33#include "bootimg.h"
34
Barry Wardellfd52fd72007-11-20 23:37:22 +000035#define VERSION "0.2"
Dave Chapmandd998b72007-09-09 13:30:40 +000036
37/* USB IDs for Manufacturing Mode */
38#define E200R_VENDORID 0x0781
39#define E200R_PRODUCTID 0x0720
40
41#define E200R_BULK_TO 1
42#define TOUT 5000
43#define MAX_TRANSFER 64 /* Number of bytes to send in one write */
44
45#ifndef MAX
46#define MAX(a,b) (((a)>(b))?(a):(b))
47#endif
48
49static void put_int32le(uint32_t x, char* p)
50{
51 p[0] = x & 0xff;
52 p[1] = (x >> 8) & 0xff;
53 p[2] = (x >> 16) & 0xff;
54 p[3] = (x >> 24) & 0xff;
55}
56
57int upload_app(usb_dev_handle* dh)
58{
59 char buf[4];
60 int err;
61 int tosend;
62 char* p = (char*)bootimg;
63 int bytesleft = LEN_bootimg;
64
65 /* Write the data length */
66
67 put_int32le(LEN_bootimg, buf);
68
69 err = usb_bulk_write(dh, E200R_BULK_TO, buf, 4, TOUT);
70
71 if (err < 0)
72 {
73 fprintf(stderr,"[ERR] Error writing data length\n");
Barry Wardell79244b22007-09-12 00:03:17 +000074 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
Dave Chapmandd998b72007-09-09 13:30:40 +000075 return -1;
76 }
77
78 /* Now send the data, MAX_TRANSFER bytes at a time. */
79
80 while (bytesleft > 0)
81 {
82 tosend = MAX(MAX_TRANSFER, bytesleft);
83
84 err = usb_bulk_write(dh, E200R_BULK_TO, p, tosend, TOUT);
85
86 if (err < 0)
87 {
88 fprintf(stderr,"[ERR] Error writing data\n");
Barry Wardell79244b22007-09-12 00:03:17 +000089 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
Dave Chapmandd998b72007-09-09 13:30:40 +000090 return -1;
91 }
92
93 p += tosend;
94 bytesleft -= tosend;
95 }
96
97 return 0;
98}
99
100
101/* The main function */
102
103void do_patching(void)
104{
105 struct usb_bus *busses;
106 struct usb_bus *bus;
107 struct usb_device *tmp_dev;
108 struct usb_device *dev = NULL;
109 usb_dev_handle *dh;
Dave Chapman7e0ed6b2007-09-15 22:47:42 +0000110 int err;
Dave Chapmandd998b72007-09-09 13:30:40 +0000111
112 fprintf(stderr,"[INFO] Searching for E200R\n");
113
114 usb_init();
115
116 if(usb_find_busses() < 0) {
117 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
118 return;
119 }
120
121 if (usb_find_devices() < 0) {
122 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
123 return;
124 }
125
126 /* C calling convention, it's not nice to use global stuff */
127 busses = usb_get_busses();
128
Dave Chapmandd998b72007-09-09 13:30:40 +0000129 for (bus = busses; bus; bus = bus->next) {
130 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) {
131 if (tmp_dev->descriptor.idVendor == E200R_VENDORID &&
132 tmp_dev->descriptor.idProduct == E200R_PRODUCTID ) {
133
134 dev = tmp_dev;
135 goto found;
136
137 }
138 }
139 }
140
141 if (dev == NULL) {
142 fprintf(stderr, "[ERR] E200R device not found.\n");
143 fprintf(stderr, "[ERR] Ensure your E200R is in manufacturing mode and run e200rpatcher again.\n");
144 return;
145 }
146
147found:
148 if ( (dh = usb_open(dev)) == NULL) {
149 fprintf(stderr,"[ERR] Unable to open E200R device.\n");
150 return;
151 }
152
Dave Chapman7e0ed6b2007-09-15 22:47:42 +0000153 err = usb_set_configuration(dh, 1);
154
155 if (err < 0) {
156 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
Dave Chapmandd998b72007-09-09 13:30:40 +0000157 usb_close(dh);
158 return;
159 }
160
Dave Chapman7e0ed6b2007-09-15 22:47:42 +0000161 /* "must be called" written in the libusb documentation */
162 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
163 if (err < 0) {
164 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
165 usb_close(dh);
166 return;
167 }
Dave Chapmandd998b72007-09-09 13:30:40 +0000168
Dave Chapmana619d062007-09-14 19:01:57 +0000169 fprintf(stderr,"[INFO] Found E200R, uploading patching application.\n");
Dave Chapmandd998b72007-09-09 13:30:40 +0000170
171 /* Now we can transfer the application to the device. */
172
173 if (upload_app(dh) < 0)
174 {
175 fprintf(stderr,"[ERR] Upload of application failed.\n");
176 }
177 else
178 {
179 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n");
180 }
181
182 /* release claimed interface */
183 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
184
185 usb_close(dh);
186}
Jonathan Gordon7929b032007-09-16 00:30:10 +0000187void print_usage(void)
188{
189 fprintf(stderr,"Usage: e200rpatcher [options]\n");
190 fprintf(stderr,"Options:\n");
191 fprintf(stderr," -s, --silent\t\tDont display instructions\n");
192}
Dave Chapmandd998b72007-09-09 13:30:40 +0000193
194int main(int argc, char* argv[])
195{
196 char input[4];
Jonathan Gordon7929b032007-09-16 00:30:10 +0000197 int silent = 0;
198 int i;
199
200 /* check args */
201 if ((argc > 1) && ((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0))) {
202 print_usage();
203 return 1;
204 }
205 for (i=1;i<argc;i++)
206 {
207 if (!strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s"))
208 silent = 1;
209 }
Dave Chapmandd998b72007-09-09 13:30:40 +0000210
211 printf("e200rpatcher v" VERSION " - (C) 2007 Jonathan Gordon & Dave Chapman\n");
212 printf("This is free software; see the source for copying conditions. There is NO\n");
213 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
214
Jonathan Gordon7929b032007-09-16 00:30:10 +0000215 if (!silent)
216 {
217 printf("Attach your E200R in \"manufacturing mode\" as follows:\n");
218 printf(" 1) Power-off your E200R\n");
219 printf(" 2) Turn ON the lock/hold switch\n");
220 printf(" 3) Press and hold the SELECT button and whilst it is held down,\n");
221 printf(" attach your E200R to your computer via USB\n");
222 printf(" 4) After attaching to USB, keep the SELECT button held for 10 seconds.\n");
223 printf("\n");
224 printf("NOTE: If your E200R starts in the normal Sansa firmware, you have\n");
225 printf(" failed to enter manufacturing mode and should try again at step 1).\n\n");
226
227 printf("[INFO] Press Enter to continue:");
228 fgets(input, 4, stdin);
229 }
Dave Chapmandd998b72007-09-09 13:30:40 +0000230 do_patching();
231
Jonathan Gordon7929b032007-09-16 00:30:10 +0000232 if (!silent)
233 {
234 printf("[INFO] Press ENTER to exit: ");
235 fgets(input, 4, stdin);
236 }
Dave Chapmandd998b72007-09-09 13:30:40 +0000237
238 return 0;
239}