1 /* on ubuntu compile with gcc -W rkusbtool.c -o rkusbtool -lusb-1.0 -I/usr/include/libusb-1.0/ */
10 #define USB_TIMEOUT 512
11 #define VENDORID 0x071b
12 #define PRODUCTID 0x3203
17 #define CBW_SIGNATURE 0x43425355
18 #define CSW_SIGNATURE 0x53425355
19 #define SCSICMD_READ_12 0xa8
21 /* rockchip specific commands */
23 #define RK_GET_VERSION 0xffffffff
24 #define RK_SWITCH_ROCKUSB 0xfeffffff
25 #define RK_CHECK_USB 0xfdffffff
26 #define RK_OPEN_SYSDISK 0xfcffffff
50 } __attribute__((__packed__
));
54 uint32_t dCBWSignature
;
56 uint32_t dCBWDataTransferLength
;
61 } __attribute__((__packed__
));
65 uint32_t dCSWSignature
;
67 uint32_t dCSWDataResidue
;
69 } __attribute__((__packed__
));
71 static int send_msc_cmd(libusb_device_handle
*hdev
, struct CBWCB_t
*cbwcb
, uint32_t data_len
, uint32_t *reftag
)
74 int ret
, repeat
, transferred
;
75 static uint32_t tag
= 0xdaefbc01;
77 memset(&cbw
, 0, sizeof(cbw
));
78 cbw
.dCBWSignature
= CBW_SIGNATURE
;
80 cbw
.dCBWDataTransferLength
= data_len
;
81 cbw
.bmCBWFlags
= 0x80; /* device to host */
83 cbw
.bCBWCBLength
= sizeof(struct CBWCB_t
);
84 memcpy(cbw
.CBWCB
, cbwcb
, sizeof(struct CBWCB_t
));
86 *reftag
= cbw
.dCBWTag
;
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
)
93 libusb_clear_halt(hdev
, OUT_EP
);
96 } while ((ret
== LIBUSB_ERROR_PIPE
) && (repeat
< RETRY_MAX
));
98 if (ret
!= LIBUSB_SUCCESS
)
100 printf("error: command transfer error\n");
107 static int get_msc_csw(libusb_device_handle
*hdev
, uint32_t reftag
)
110 int ret
, repeat
, transferred
;
112 /* get CSW response from device */
116 ret
= libusb_bulk_transfer(hdev
, IN_EP
, (unsigned char *)&csw
, 13, &transferred
, USB_TIMEOUT
);
117 if (ret
== LIBUSB_ERROR_PIPE
)
119 libusb_clear_halt(hdev
, IN_EP
);
122 } while ((ret
== LIBUSB_ERROR_PIPE
) && (repeat
< RETRY_MAX
));
124 if (ret
!= LIBUSB_SUCCESS
)
126 printf("error reading CSW\n");
130 if (transferred
!= 13)
132 printf("error wrong size of CSW packet\n");
136 if (csw
.dCSWSignature
!= CSW_SIGNATURE
)
138 printf("error: wrong CSW signature.\n");
142 if (csw
.dCSWTag
!= reftag
)
144 printf("error: CSW dCSWTag mismatch\n");
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
);
157 return csw
.bCSWStatus
;
160 static int rk_cmd(libusb_device_handle
*hdev
, uint32_t command
, uint8_t *buf
, uint8_t len
)
162 struct CBWCB_t cbwcb
;
163 int ret
, transferred
;
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 */
173 ret
= send_msc_cmd(hdev
, &cbwcb
, len
, &reftag
);
175 /* get the response */
178 ret
= libusb_bulk_transfer(hdev
, IN_EP
, buf
, len
, &transferred
, USB_TIMEOUT
);
179 if (ret
!= LIBUSB_SUCCESS
|| transferred
!= len
)
181 printf("error: reading response data failed\n");
186 return get_msc_csw(hdev
, reftag
);
189 static int get_sense(libusb_device_handle
*hdev
)
191 struct CBWCB_t cbwcb
;
192 unsigned char sense
[0x12];
196 memset(&cbwcb
, 0, sizeof(cbwcb
));
202 ret
= send_msc_cmd(hdev
, &cbwcb
, 0x12, &reftag
);
203 libusb_bulk_transfer(hdev
, IN_EP
, (unsigned char*)&sense
, 0x12, &size
, USB_TIMEOUT
);
205 return get_msc_csw(hdev
, reftag
);
208 static void usage(void)
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");
218 int main (int argc
, char **argv
)
220 libusb_device_handle
*hdev
;
222 int i
= 0, action
= NONE
;
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");
237 /* arguments handling */
240 if ((strcmp(argv
[i
],"-i")==0) || (strcmp(argv
[i
],"--info")==0))
244 else if ((strcmp(argv
[i
],"-d")==0) || (strcmp(argv
[i
],"--dfu")==0))
248 else if ((strcmp(argv
[i
],"-s")==0) || (strcmp(argv
[i
],"--sysdisk")==0))
252 else if ((strcmp(argv
[i
],"-c")==0) || (strcmp(argv
[i
],"--checkusb")==0))
256 else if ((strcmp(argv
[i
],"-h")==0) || (strcmp(argv
[i
],"--help")==0))
264 /* initialize libusb */
266 /* usb_set_debug(2); */
268 hdev
= libusb_open_device_with_vid_pid(NULL
, VENDORID
, PRODUCTID
);
271 printf("error: can't open device\n");
275 ret
= libusb_kernel_driver_active(hdev
, 0);
279 printf ("error checking kernel driver active\n");
286 libusb_detach_kernel_driver(hdev
, 0);
289 ret
= libusb_set_configuration(hdev
, 1);
292 printf("error: could not select configuration (1)\n");
297 ret
= libusb_claim_interface(hdev
, 0);
300 printf("error: could not claim interface #0\n");
305 ret
= libusb_set_interface_alt_setting(hdev
, 0, 0);
306 if ( ret
!= LIBUSB_SUCCESS
)
308 printf("error: could not set alt setting for interface #0\n");
314 //ret = libusb_control_transfer(hdev, 0x21, 0xff, 0, 0, NULL, 0, USB_TIMEOUT);
316 /* BulkOnly get max lun */
317 //ret = libusb_control_transfer(hdev, 0xa1, 0xfe, 0, 0, &maxlun, 1, USB_TIMEOUT);
319 /* Devices that do not support multiple LUNs may STALL this command. */
323 //printf("MAXLUN: %d\n", maxlun);
329 ret
= rk_cmd(hdev
, RK_GET_VERSION
, (uint8_t *)ver
, 12);
333 printf("error sending RK_GET_VERSION command. Err 0x%0x\n", ret
);
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);
344 if (action
& CHECKUSB
)
346 printf("Checking USB mode...\n");
347 ret
= rk_cmd(hdev
, RK_CHECK_USB
, (uint8_t *)ver
, 1);
351 // libusb_close(hdev);
356 printf("The device is in Loader USB mode\n");
358 printf("The device is in System USB mode\n");
361 if (action
& SYSDISK
)
363 printf("Opening system disk...\n");
364 ret
= rk_cmd(hdev
, RK_OPEN_SYSDISK
, NULL
, 0);
375 printf("Switching into rk DFU mode...\n");
376 ret
= rk_cmd(hdev
, RK_SWITCH_ROCKUSB
, NULL
, 0);