summaryrefslogtreecommitdiff
path: root/utils/e200rpatcher/e200rpatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/e200rpatcher/e200rpatcher.c')
-rw-r--r--utils/e200rpatcher/e200rpatcher.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/utils/e200rpatcher/e200rpatcher.c b/utils/e200rpatcher/e200rpatcher.c
new file mode 100644
index 0000000000..be09370997
--- /dev/null
+++ b/utils/e200rpatcher/e200rpatcher.c
@@ -0,0 +1,241 @@
1/***************************************************************************
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 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
22 *
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
25 *
26 ****************************************************************************/
27
28
29#include <stdio.h>
30#include <inttypes.h>
31#include <usb.h>
32#include <string.h>
33#include "stdbool.h"
34
35#include "bootimg.h"
36
37#define VERSION "0.2"
38
39/* USB IDs for Manufacturing Mode */
40#define E200R_VENDORID 0x0781
41#define E200R_PRODUCTID 0x0720
42
43#define E200R_BULK_TO 1
44#define TOUT 5000
45#define MAX_TRANSFER 64 /* Number of bytes to send in one write */
46
47#ifndef MAX
48#define MAX(a,b) (((a)>(b))?(a):(b))
49#endif
50
51static void put_int32le(uint32_t x, char* p)
52{
53 p[0] = x & 0xff;
54 p[1] = (x >> 8) & 0xff;
55 p[2] = (x >> 16) & 0xff;
56 p[3] = (x >> 24) & 0xff;
57}
58
59int upload_app(usb_dev_handle* dh)
60{
61 char buf[4];
62 int err;
63 int tosend;
64 char* p = (char*)bootimg;
65 int bytesleft = LEN_bootimg;
66
67 /* Write the data length */
68
69 put_int32le(LEN_bootimg, buf);
70
71 err = usb_bulk_write(dh, E200R_BULK_TO, buf, 4, TOUT);
72
73 if (err < 0)
74 {
75 fprintf(stderr,"[ERR] Error writing data length\n");
76 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
77 return -1;
78 }
79
80 /* Now send the data, MAX_TRANSFER bytes at a time. */
81
82 while (bytesleft > 0)
83 {
84 tosend = MAX(MAX_TRANSFER, bytesleft);
85
86 err = usb_bulk_write(dh, E200R_BULK_TO, p, tosend, TOUT);
87
88 if (err < 0)
89 {
90 fprintf(stderr,"[ERR] Error writing data\n");
91 fprintf(stderr,"[ERR] Bulk write error (%d, %s)\n", err, strerror(-err));
92 return -1;
93 }
94
95 p += tosend;
96 bytesleft -= tosend;
97 }
98
99 return 0;
100}
101
102
103/* The main function */
104
105void do_patching(void)
106{
107 struct usb_bus *busses;
108 struct usb_bus *bus;
109 struct usb_device *tmp_dev;
110 struct usb_device *dev = NULL;
111 usb_dev_handle *dh;
112 int err;
113
114 fprintf(stderr,"[INFO] Searching for E200R\n");
115
116 usb_init();
117
118 if(usb_find_busses() < 0) {
119 fprintf(stderr, "[ERR] Could not find any USB busses.\n");
120 return;
121 }
122
123 if (usb_find_devices() < 0) {
124 fprintf(stderr, "[ERR] USB devices not found(nor hubs!).\n");
125 return;
126 }
127
128 /* C calling convention, it's not nice to use global stuff */
129 busses = usb_get_busses();
130
131 for (bus = busses; bus; bus = bus->next) {
132 for (tmp_dev = bus->devices; tmp_dev; tmp_dev = tmp_dev->next) {
133 if (tmp_dev->descriptor.idVendor == E200R_VENDORID &&
134 tmp_dev->descriptor.idProduct == E200R_PRODUCTID ) {
135
136 dev = tmp_dev;
137 goto found;
138
139 }
140 }
141 }
142
143 if (dev == NULL) {
144 fprintf(stderr, "[ERR] E200R device not found.\n");
145 fprintf(stderr, "[ERR] Ensure your E200R is in manufacturing mode and run e200rpatcher again.\n");
146 return;
147 }
148
149found:
150 if ( (dh = usb_open(dev)) == NULL) {
151 fprintf(stderr,"[ERR] Unable to open E200R device.\n");
152 return;
153 }
154
155 err = usb_set_configuration(dh, 1);
156
157 if (err < 0) {
158 fprintf(stderr, "[ERR] usb_set_configuration failed (%d)\n", err);
159 usb_close(dh);
160 return;
161 }
162
163 /* "must be called" written in the libusb documentation */
164 err = usb_claim_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
165 if (err < 0) {
166 fprintf(stderr, "[ERR] Unable to claim interface (%d)\n", err);
167 usb_close(dh);
168 return;
169 }
170
171 fprintf(stderr,"[INFO] Found E200R, uploading patching application.\n");
172
173 /* Now we can transfer the application to the device. */
174
175 if (upload_app(dh) < 0)
176 {
177 fprintf(stderr,"[ERR] Upload of application failed.\n");
178 }
179 else
180 {
181 fprintf(stderr,"[INFO] Patching application uploaded successfully!\n");
182 }
183
184 /* release claimed interface */
185 usb_release_interface(dh, dev->config->interface->altsetting->bInterfaceNumber);
186
187 usb_close(dh);
188}
189void print_usage(void)
190{
191 fprintf(stderr,"Usage: e200rpatcher [options]\n");
192 fprintf(stderr,"Options:\n");
193 fprintf(stderr," -s, --silent\t\tDont display instructions\n");
194}
195
196int main(int argc, char* argv[])
197{
198 char input[4];
199 int silent = 0;
200 int i;
201
202 /* check args */
203 if ((argc > 1) && ((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0))) {
204 print_usage();
205 return 1;
206 }
207 for (i=1;i<argc;i++)
208 {
209 if (!strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s"))
210 silent = 1;
211 }
212
213 printf("e200rpatcher v" VERSION " - (C) 2007 Jonathan Gordon & Dave Chapman\n");
214 printf("This is free software; see the source for copying conditions. There is NO\n");
215 printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
216
217 if (!silent)
218 {
219 printf("Attach your E200R in \"manufacturing mode\" as follows:\n");
220 printf(" 1) Power-off your E200R\n");
221 printf(" 2) Turn ON the lock/hold switch\n");
222 printf(" 3) Press and hold the SELECT button and whilst it is held down,\n");
223 printf(" attach your E200R to your computer via USB\n");
224 printf(" 4) After attaching to USB, keep the SELECT button held for 10 seconds.\n");
225 printf("\n");
226 printf("NOTE: If your E200R starts in the normal Sansa firmware, you have\n");
227 printf(" failed to enter manufacturing mode and should try again at step 1).\n\n");
228
229 printf("[INFO] Press Enter to continue:");
230 fgets(input, 4, stdin);
231 }
232 do_patching();
233
234 if (!silent)
235 {
236 printf("[INFO] Press ENTER to exit: ");
237 fgets(input, 4, stdin);
238 }
239
240 return 0;
241}