summaryrefslogtreecommitdiff
path: root/utils/rk27utils/rkusbtool
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rk27utils/rkusbtool')
-rw-r--r--utils/rk27utils/rkusbtool/Makefile7
-rw-r--r--utils/rk27utils/rkusbtool/rkusbtool.c388
2 files changed, 395 insertions, 0 deletions
diff --git a/utils/rk27utils/rkusbtool/Makefile b/utils/rk27utils/rkusbtool/Makefile
new file mode 100644
index 0000000000..785a09a1f1
--- /dev/null
+++ b/utils/rk27utils/rkusbtool/Makefile
@@ -0,0 +1,7 @@
1all: rkusbtool
2
3rkusbtool: rkusbtool.c
4 gcc -g -std=c99 -o $@ -W -Wall -lusb-1.0 -I/usr/include/libusb-1.0/ $^
5
6clean:
7 rm -fr rkusbtool
diff --git a/utils/rk27utils/rkusbtool/rkusbtool.c b/utils/rk27utils/rkusbtool/rkusbtool.c
new file mode 100644
index 0000000000..06fb7e860c
--- /dev/null
+++ b/utils/rk27utils/rkusbtool/rkusbtool.c
@@ -0,0 +1,388 @@
1/* on ubuntu compile with gcc -W rkusbtool.c -o rkusbtool -lusb-1.0 -I/usr/include/libusb-1.0/ */
2#include <libusb.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6
7#define VERSION "v0.1"
8
9#define RETRY_MAX 5
10#define USB_TIMEOUT 512
11#define VENDORID 0x071b
12#define PRODUCTID 0x3203
13
14#define OUT_EP 0x01
15#define IN_EP 0x82
16
17#define CBW_SIGNATURE 0x43425355
18#define CSW_SIGNATURE 0x53425355
19#define SCSICMD_READ_12 0xa8
20
21/* rockchip specific commands */
22#define RK_CMD 0xe0
23#define RK_GET_VERSION 0xffffffff
24#define RK_SWITCH_ROCKUSB 0xfeffffff
25#define RK_CHECK_USB 0xfdffffff
26#define RK_OPEN_SYSDISK 0xfcffffff
27
28enum {
29 NONE = 0,
30 INFO = 1,
31 RKUSB = 2,
32 SYSDISK = 4,
33 CHECKUSB = 8
34};
35
36enum {
37 COMMAND_PASSED = 0,
38 COMMAND_FAILED = 1,
39 PHASE_ERROR = 2
40};
41
42struct CBWCB_t
43{
44 uint8_t cbCode;
45 uint8_t cbLun;
46 uint32_t LBA;
47 uint32_t cbLen;
48 uint8_t reseved;
49 uint8_t control;
50} __attribute__((__packed__));
51
52struct CBW_t
53{
54 uint32_t dCBWSignature;
55 uint32_t dCBWTag;
56 uint32_t dCBWDataTransferLength;
57 uint8_t bmCBWFlags;
58 uint8_t bCBWLUN;
59 uint8_t bCBWCBLength;
60 uint8_t CBWCB[16];
61} __attribute__((__packed__));
62
63struct CSW_t
64{
65 uint32_t dCSWSignature;
66 uint32_t dCSWTag;
67 uint32_t dCSWDataResidue;
68 uint8_t bCSWStatus;
69} __attribute__((__packed__));
70
71static int send_msc_cmd(libusb_device_handle *hdev, struct CBWCB_t *cbwcb, uint32_t data_len, uint32_t *reftag)
72{
73 struct CBW_t cbw;
74 int ret, repeat, transferred;
75 static uint32_t tag = 0xdaefbc01;
76
77 memset(&cbw, 0, sizeof(cbw));
78 cbw.dCBWSignature = CBW_SIGNATURE;
79 cbw.dCBWTag = tag++;
80 cbw.dCBWDataTransferLength = data_len;
81 cbw.bmCBWFlags = 0x80; /* device to host */
82 cbw.bCBWLUN = 0;
83 cbw.bCBWCBLength = sizeof(struct CBWCB_t);
84 memcpy(cbw.CBWCB, cbwcb, sizeof(struct CBWCB_t));
85
86 *reftag = cbw.dCBWTag;
87 do
88 {
89 /* transfer command to the device */
90 ret = libusb_bulk_transfer(hdev, OUT_EP, (unsigned char*)&cbw, 31, &transferred, USB_TIMEOUT);
91 if (ret == LIBUSB_ERROR_PIPE)
92 {
93 libusb_clear_halt(hdev, OUT_EP);
94 }
95 repeat++;
96 } while ((ret == LIBUSB_ERROR_PIPE) && (repeat < RETRY_MAX));
97
98 if (ret != LIBUSB_SUCCESS)
99 {
100 printf("error: command transfer error\n");
101 return -1;
102 }
103
104 return 0;
105}
106
107static int get_msc_csw(libusb_device_handle *hdev, uint32_t reftag)
108{
109 struct CSW_t csw;
110 int ret, repeat, transferred;
111
112 /* get CSW response from device */
113 repeat = 0;
114 do
115 {
116 ret = libusb_bulk_transfer(hdev, IN_EP, (unsigned char *)&csw, 13, &transferred, USB_TIMEOUT);
117 if (ret == LIBUSB_ERROR_PIPE)
118 {
119 libusb_clear_halt(hdev, IN_EP);
120 }
121 repeat++;
122 } while ((ret == LIBUSB_ERROR_PIPE) && (repeat < RETRY_MAX));
123
124 if (ret != LIBUSB_SUCCESS)
125 {
126 printf("error reading CSW\n");
127 return -3;
128 }
129
130 if (transferred != 13)
131 {
132 printf("error wrong size of CSW packet\n");
133 return -4;
134 }
135
136 if (csw.dCSWSignature != CSW_SIGNATURE)
137 {
138 printf("error: wrong CSW signature.\n");
139 return -5;
140 }
141
142 if (csw.dCSWTag != reftag)
143 {
144 printf("error: CSW dCSWTag mismatch\n");
145 return -6;
146 }
147
148 if (csw.bCSWStatus)
149 {
150 /* In case of CSW indicating error dump the content of the packet */
151 printf ("dCSWSignature: 0x%0x\n", csw.dCSWSignature);
152 printf ("dCSWTag: 0x%0x\n", csw.dCSWTag);
153 printf ("dCSWDataResidue: 0x%0x\n", csw.dCSWDataResidue);
154 printf ("bCSWStatus: 0x%0x\n", csw.bCSWStatus);
155 }
156
157 return csw.bCSWStatus;
158}
159
160static int rk_cmd(libusb_device_handle *hdev, uint32_t command, uint8_t *buf, uint8_t len)
161{
162 struct CBWCB_t cbwcb;
163 int ret, transferred;
164 uint32_t reftag;
165
166 /* enter command */
167 memset(&cbwcb, 0, sizeof(cbwcb));
168 cbwcb.cbCode = SCSICMD_READ_12;
169 cbwcb.cbLun = RK_CMD;
170 cbwcb.LBA = command; /* RK_GET_VERSION, RK_OPEN_SYSDISK, RK_SWITCH_ROCKUSB */
171 cbwcb.cbLen = len; /* size of transfer in response to this command */
172
173 ret = send_msc_cmd(hdev, &cbwcb, len, &reftag);
174
175 /* get the response */
176 if (len > 0)
177 {
178 ret = libusb_bulk_transfer(hdev, IN_EP, buf, len, &transferred, USB_TIMEOUT);
179 if (ret != LIBUSB_SUCCESS || transferred != len)
180 {
181 printf("error: reading response data failed\n");
182 return -2;
183 }
184 }
185
186 return get_msc_csw(hdev, reftag);
187}
188
189static int get_sense(libusb_device_handle *hdev)
190{
191 struct CBWCB_t cbwcb;
192 unsigned char sense[0x12];
193 int size, ret;
194 uint32_t reftag;
195
196 memset(&cbwcb, 0, sizeof(cbwcb));
197 cbwcb.cbCode = 0x03;
198 cbwcb.cbLun = 0;
199 cbwcb.LBA = 0;
200 cbwcb.cbLen = 0x12;
201
202 ret = send_msc_cmd(hdev, &cbwcb, 0x12, &reftag);
203 libusb_bulk_transfer(hdev, IN_EP, (unsigned char*)&sense, 0x12, &size, USB_TIMEOUT);
204
205 return get_msc_csw(hdev, reftag);
206}
207
208static void usage(void)
209{
210 printf("Usage: rkusbtool [options]\n");
211 printf("-h|--help This help message\n");
212 printf("-i|--info Get version string from the device\n");
213 printf("-d|--dfu Put device into DFU mode\n");
214 printf("-s|--sysdisk Open system disk\n");
215 printf("-c|--checkusb Check if dev is in System or Loader USB mode\n");
216}
217
218int main (int argc, char **argv)
219{
220 libusb_device_handle *hdev;
221 int ret;
222 int i = 0, action = NONE;
223 uint32_t ver[3];
224
225 if (argc < 2)
226 {
227 usage();
228 return 1;
229 }
230
231 /* print banner */
232 fprintf(stderr,"rkusbtool " VERSION "\n");
233 fprintf(stderr,"(C) Marcin Bukat 2011\n");
234 fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n");
235 fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
236
237 /* arguments handling */
238 while (i < argc)
239 {
240 if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--info")==0))
241 {
242 action |= INFO;
243 }
244 else if ((strcmp(argv[i],"-d")==0) || (strcmp(argv[i],"--dfu")==0))
245 {
246 action |= RKUSB;
247 }
248 else if ((strcmp(argv[i],"-s")==0) || (strcmp(argv[i],"--sysdisk")==0))
249 {
250 action |= SYSDISK;
251 }
252 else if ((strcmp(argv[i],"-c")==0) || (strcmp(argv[i],"--checkusb")==0))
253 {
254 action |= CHECKUSB;
255 }
256 else if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
257 {
258 usage();
259 return 0;
260 }
261 i++;
262 }
263
264 /* initialize libusb */
265 libusb_init(NULL);
266 /* usb_set_debug(2); */
267
268 hdev = libusb_open_device_with_vid_pid(NULL, VENDORID, PRODUCTID);
269 if (hdev == NULL)
270 {
271 printf("error: can't open device\n");
272 return -10;
273 }
274
275 ret = libusb_kernel_driver_active(hdev, 0);
276
277 if (ret < 0)
278 {
279 printf ("error checking kernel driver active\n");
280 libusb_close(hdev);
281 return -3;
282 }
283 else
284 {
285 if (ret)
286 libusb_detach_kernel_driver(hdev, 0);
287 }
288
289 ret = libusb_set_configuration(hdev, 1);
290 if (ret < 0)
291 {
292 printf("error: could not select configuration (1)\n");
293 libusb_close(hdev);
294 return -3;
295 }
296
297 ret = libusb_claim_interface(hdev, 0);
298 if (ret < 0)
299 {
300 printf("error: could not claim interface #0\n");
301 libusb_close(hdev);
302 return -11;
303 }
304
305 ret = libusb_set_interface_alt_setting(hdev, 0, 0);
306 if ( ret != LIBUSB_SUCCESS)
307 {
308 printf("error: could not set alt setting for interface #0\n");
309 libusb_close(hdev);
310 return -11;
311 }
312
313 /* BulkOnly reset */
314 //ret = libusb_control_transfer(hdev, 0x21, 0xff, 0, 0, NULL, 0, USB_TIMEOUT);
315
316 /* BulkOnly get max lun */
317 //ret = libusb_control_transfer(hdev, 0xa1, 0xfe, 0, 0, &maxlun, 1, USB_TIMEOUT);
318
319 /* Devices that do not support multiple LUNs may STALL this command. */
320 //if (ret == 0)
321 // maxlun = -1;
322
323 //printf("MAXLUN: %d\n", maxlun);
324
325 get_sense(hdev);
326
327 if (action & INFO)
328 {
329 ret = rk_cmd(hdev, RK_GET_VERSION, (uint8_t *)ver, 12);
330
331 if (ret)
332 {
333 printf("error sending RK_GET_VERSION command. Err 0x%0x\n", ret);
334 libusb_close(hdev);
335 return ret;
336 }
337
338 printf("Rockchip device info:\n");
339 printf("loader ver: %x.%x\n", (ver[0]>>16)&0xff, ver[0]&0xff);
340 printf("kernel ver: %x.%x\n", (ver[1]>>16)&0xff, ver[1]&0xff);
341 printf("sdk ver: %x.%x\n", (ver[2]>>16)&0xff, ver[2]&0xff);
342 }
343
344 if (action & CHECKUSB)
345 {
346 printf("Checking USB mode...\n");
347 ret = rk_cmd(hdev, RK_CHECK_USB, (uint8_t *)ver, 1);
348
349 //if (ret)
350 //{
351 // libusb_close(hdev);
352 // return ret;
353 //}
354
355 if (*(char *)ver)
356 printf("The device is in Loader USB mode\n");
357 else
358 printf("The device is in System USB mode\n");
359 }
360
361 if (action & SYSDISK)
362 {
363 printf("Opening system disk...\n");
364 ret = rk_cmd(hdev, RK_OPEN_SYSDISK, NULL, 0);
365
366 if (ret)
367 {
368 libusb_close(hdev);
369 return ret;
370 }
371 }
372
373 if (action & RKUSB)
374 {
375 printf("Switching into rk DFU mode...\n");
376 ret = rk_cmd(hdev, RK_SWITCH_ROCKUSB, NULL, 0);
377
378 if (ret)
379 {
380 libusb_close(hdev);
381 return ret;
382 }
383 }
384
385 libusb_close(hdev);
386 libusb_exit(NULL);
387 return 0;
388}