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