Fix module loading
[ps4-sdk.git] / examples / usb / storage / source / main.c
blobdcbe5606439eef4da51b4142703bd08af158cff8
1 #include "ps4.h"
3 int netdbg_sock;
5 #define debug(...) \
6 do { \
7 char _debug_buffer[512]; \
8 int _dbg_size = sprintf(_debug_buffer, ##__VA_ARGS__); \
9 sceNetSend(netdbg_sock, _debug_buffer, _dbg_size, 0); \
10 } while(0)
13 /* Grabbed from libusb/examples/xusb.c */
15 #define ERR_EXIT(errcode) do { debug(" %i\n", errcode); return -1; } while (0)
16 #define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0);
17 #define B(x) (((x)!=0)?1:0)
18 #define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3])
20 #define RETRY_MAX 5
21 #define REQUEST_SENSE_LENGTH 0x12
22 #define INQUIRY_LENGTH 0x24
23 #define READ_CAPACITY_LENGTH 0x08
25 // Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications
26 #define BOMS_RESET 0xFF
27 #define BOMS_GET_MAX_LUN 0xFE
29 // Section 5.1: Command Block Wrapper (CBW)
30 struct command_block_wrapper {
31 uint8_t dCBWSignature[4];
32 uint32_t dCBWTag;
33 uint32_t dCBWDataTransferLength;
34 uint8_t bmCBWFlags;
35 uint8_t bCBWLUN;
36 uint8_t bCBWCBLength;
37 uint8_t CBWCB[16];
40 // Section 5.2: Command Status Wrapper (CSW)
41 struct command_status_wrapper {
42 uint8_t dCSWSignature[4];
43 uint32_t dCSWTag;
44 uint32_t dCSWDataResidue;
45 uint8_t bCSWStatus;
48 static uint8_t cdb_length[256] = {
49 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
50 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 0
51 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 1
52 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 2
53 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 3
54 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 4
55 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 5
56 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 6
57 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 7
58 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 8
59 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 9
60 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // A
61 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // B
62 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // C
63 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // D
64 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // E
65 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // F
68 static void display_buffer_hex(unsigned char *buffer, unsigned size)
70 unsigned i, j, k;
72 for (i=0; i<size; i+=16) {
73 debug("\n %08x ", i);
74 for(j=0,k=0; k<16; j++,k++) {
75 if (i+j < size) {
76 debug("%02x", buffer[i+j]);
77 } else {
78 debug(" ");
80 debug(" ");
82 debug(" ");
83 for(j=0,k=0; k<16; j++,k++) {
84 if (i+j < size) {
85 if ((buffer[i+j] < 32) || (buffer[i+j] > 126)) {
86 debug(".");
87 } else {
88 debug("%c", buffer[i+j]);
93 debug("\n" );
96 static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpoint, uint8_t lun,
97 uint8_t *cdb, uint8_t direction, int data_length, uint32_t *ret_tag)
99 static uint32_t tag = 1;
100 uint8_t cdb_len;
101 int i, r, size;
102 struct command_block_wrapper cbw;
104 if (cdb == NULL) {
105 return -1;
108 if (endpoint & LIBUSB_ENDPOINT_IN) {
109 debug("send_mass_storage_command: cannot send command on IN endpoint\n");
110 return -1;
113 cdb_len = cdb_length[cdb[0]];
114 if ((cdb_len == 0) || (cdb_len > sizeof(cbw.CBWCB))) {
115 debug("send_mass_storage_command: don't know how to handle this command (%02X, length %d)\n",
116 cdb[0], cdb_len);
117 return -1;
120 memset(&cbw, 0, sizeof(cbw));
121 cbw.dCBWSignature[0] = 'U';
122 cbw.dCBWSignature[1] = 'S';
123 cbw.dCBWSignature[2] = 'B';
124 cbw.dCBWSignature[3] = 'C';
125 *ret_tag = tag;
126 cbw.dCBWTag = tag++;
127 cbw.dCBWDataTransferLength = data_length;
128 cbw.bmCBWFlags = direction;
129 cbw.bCBWLUN = lun;
130 // Subclass is 1 or 6 => cdb_len
131 cbw.bCBWCBLength = cdb_len;
132 memcpy(cbw.CBWCB, cdb, cdb_len);
134 i = 0;
135 do {
136 // The transfer length must always be exactly 31 bytes.
137 r = sceUsbdBulkTransfer(handle, endpoint, (unsigned char*)&cbw, 31, &size, 1000);
138 if (r == LIBUSB_ERROR_PIPE) {
139 sceUsbdClearHalt(handle, endpoint);
141 i++;
142 } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
143 if (r != LIBUSB_SUCCESS) {
144 debug(" send_mass_storage_command\n");
145 return -1;
148 debug(" sent %d CDB bytes\n", cdb_len);
149 return 0;
153 static int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoint, uint32_t expected_tag)
155 int i, r, size;
156 struct command_status_wrapper csw;
158 // The device is allowed to STALL this transfer. If it does, you have to
159 // clear the stall and try again.
160 i = 0;
161 do {
162 r = sceUsbdBulkTransfer(handle, endpoint, (unsigned char*)&csw, 13, &size, 1000);
163 if (r == LIBUSB_ERROR_PIPE) {
164 sceUsbdClearHalt(handle, endpoint);
166 i++;
167 } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX));
168 if (r != LIBUSB_SUCCESS) {
169 debug(" get_mass_storage_status\n");
170 return -1;
172 if (size != 13) {
173 debug(" get_mass_storage_status: received %d bytes (expected 13)\n", size);
174 return -1;
176 if (csw.dCSWTag != expected_tag) {
177 debug(" get_mass_storage_status: mismatched tags (expected %08X, received %08X)\n",
178 expected_tag, csw.dCSWTag);
179 return -1;
181 // For this test, we ignore the dCSWSignature check for validity...
182 debug(" Mass Storage Status: %02X (%s)\n", csw.bCSWStatus, csw.bCSWStatus?"FAILED":"Success");
183 if (csw.dCSWTag != expected_tag)
184 return -1;
185 if (csw.bCSWStatus) {
186 // REQUEST SENSE is appropriate only if bCSWStatus is 1, meaning that the
187 // command failed somehow. Larger values (2 in particular) mean that
188 // the command couldn't be understood.
189 if (csw.bCSWStatus == 1)
190 return -2; // request Get Sense
191 else
192 return -1;
195 // In theory we also should check dCSWDataResidue. But lots of devices
196 // set it wrongly.
197 return 0;
200 static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
202 uint8_t cdb[16]; // SCSI Command Descriptor Block
203 uint8_t sense[18];
204 uint32_t expected_tag;
205 int size;
206 int rc;
208 // Request Sense
209 debug("Request Sense:\n");
210 memset(sense, 0, sizeof(sense));
211 memset(cdb, 0, sizeof(cdb));
212 cdb[0] = 0x03; // Request Sense
213 cdb[4] = REQUEST_SENSE_LENGTH;
215 send_mass_storage_command(handle, endpoint_out, 0, cdb, LIBUSB_ENDPOINT_IN, REQUEST_SENSE_LENGTH, &expected_tag);
216 rc = sceUsbdBulkTransfer(handle, endpoint_in, (unsigned char*)&sense, REQUEST_SENSE_LENGTH, &size, 1000);
217 if (rc < 0)
219 debug("sceUsbdBulkTransfer failed\n");
220 return;
222 debug(" received %d bytes\n", size);
224 if ((sense[0] != 0x70) && (sense[0] != 0x71)) {
225 debug(" ERROR No sense data\n");
226 } else {
227 debug(" ERROR Sense: %02X %02X %02X\n", sense[2]&0x0F, sense[12], sense[13]);
229 // Strictly speaking, the get_mass_storage_status() call should come
230 // before these debug() lines. If the status is nonzero then we must
231 // assume there's no data in the buffer. For xusb it doesn't matter.
232 get_mass_storage_status(handle, endpoint_in, expected_tag);
235 // Mass Storage device to test bulk transfers (non destructive test)
236 static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t endpoint_out)
238 int r, size;
239 uint8_t lun;
240 uint32_t expected_tag;
241 uint32_t i, max_lba, block_size;
242 double device_size;
243 uint8_t cdb[16]; // SCSI Command Descriptor Block
244 uint8_t buffer[64];
245 char vid[9], pid[9], rev[5];
246 unsigned char *data;
248 debug("Reading Max LUN:\n");
249 r = sceUsbdControlTransfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE,
250 BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000);
251 // Some devices send a STALL instead of the actual value.
252 // In such cases we should set lun to 0.
253 if (r == 0) {
254 lun = 0;
255 } else if (r < 0) {
256 debug(" Failed\n");
258 debug(" Max LUN = %d\n", lun);
260 // Send Inquiry
261 debug("Sending Inquiry:\n");
262 memset(buffer, 0, sizeof(buffer));
263 memset(cdb, 0, sizeof(cdb));
264 cdb[0] = 0x12; // Inquiry
265 cdb[4] = INQUIRY_LENGTH;
267 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, INQUIRY_LENGTH, &expected_tag);
268 CALL_CHECK(sceUsbdBulkTransfer(handle, endpoint_in, (unsigned char*)&buffer, INQUIRY_LENGTH, &size, 1000));
269 debug(" received %d bytes\n", size);
270 // The following strings are not zero terminated
271 for (i=0; i<8; i++) {
272 vid[i] = buffer[8+i];
273 pid[i] = buffer[16+i];
274 rev[i/2] = buffer[32+i/2]; // instead of another loop
276 vid[8] = 0;
277 pid[8] = 0;
278 rev[4] = 0;
279 debug(" VID:PID:REV \"%8s\":\"%8s\":\"%4s\"\n", vid, pid, rev);
280 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
281 get_sense(handle, endpoint_in, endpoint_out);
284 // Read capacity
285 debug("Reading Capacity:\n");
286 memset(buffer, 0, sizeof(buffer));
287 memset(cdb, 0, sizeof(cdb));
288 cdb[0] = 0x25; // Read Capacity
290 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, READ_CAPACITY_LENGTH, &expected_tag);
291 CALL_CHECK(sceUsbdBulkTransfer(handle, endpoint_in, (unsigned char*)&buffer, READ_CAPACITY_LENGTH, &size, 1000));
292 debug(" received %d bytes\n", size);
293 max_lba = be_to_int32(&buffer[0]);
294 block_size = be_to_int32(&buffer[4]);
295 device_size = ((double)(max_lba+1))*block_size/(1024*1024*1024);
296 debug(" Max LBA: %08X, Block Size: %08X (%.2f GB)\n", max_lba, block_size, device_size);
297 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
298 get_sense(handle, endpoint_in, endpoint_out);
301 // coverity[tainted_data]
302 data = (unsigned char*) calloc(1, block_size);
303 if (data == NULL) {
304 debug(" unable to allocate data buffer\n");
305 return -1;
308 // Send Read
309 debug("Attempting to read %d bytes:\n", block_size);
310 memset(cdb, 0, sizeof(cdb));
312 cdb[0] = 0x28; // Read(10)
313 cdb[8] = 0x01; // 1 block
315 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOINT_IN, block_size, &expected_tag);
316 sceUsbdBulkTransfer(handle, endpoint_in, data, block_size, &size, 5000);
317 debug(" READ: received %d bytes\n", size);
318 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) {
319 get_sense(handle, endpoint_in, endpoint_out);
320 } else {
321 display_buffer_hex(data, size);
323 free(data);
325 return 0;
328 int _main(void) {
329 // Load modules
330 initKernel();
332 initLibc();
333 initNetwork();
334 initUsb();
336 // Init netdebug
337 struct sockaddr_in server;
338 server.sin_len = sizeof(server);
339 server.sin_family = AF_INET;
340 server.sin_addr.s_addr = IP(192, 168, 0, 4);
341 server.sin_port = sceNetHtons(9023);
342 memset(server.sin_zero, 0, sizeof(server.sin_zero));
344 netdbg_sock = sceNetSocket("netdebug", AF_INET, SOCK_STREAM, 0);
345 sceNetConnect(netdbg_sock, (struct sockaddr *)&server, sizeof(server));
347 uint8_t endpoint_in = 0, endpoint_out = 0;
348 int usb_storage_found = 0;
349 unsigned short usb_stor_vid;
350 unsigned short usb_stor_pid;
352 // Read all USBs
353 libusb_device **list;
354 libusb_device_descriptor desc;
355 struct libusb_config_descriptor *config;
356 const struct libusb_interface *inter;
357 const struct libusb_interface_descriptor *interdesc;
358 const struct libusb_endpoint_descriptor *epdesc;
360 int ret = sceUsbdInit();
361 debug("sceUsbdInit %d\n", ret);
363 int count = sceUsbdGetDeviceList(&list);
364 debug("Device list count %d\n", count);
366 int i;
367 for(i = 0; i < count; i++) {
369 debug("Device %i\n", i);
371 ret = sceUsbdGetDeviceDescriptor(list[i], &desc);
372 debug(" Get device descriptor: %d\n", ret);
374 debug(" Device Class: 0x%02X\n", desc.bDeviceClass);
375 debug(" Vendor ID: 0x%04X\n", desc.idVendor);
376 debug(" Product ID: 0x%04X\n", desc.idProduct);
377 debug(" Number of possible configurations: %i\n", desc.bNumConfigurations);
379 ret = sceUsbdGetConfigDescriptor(list[i], 0, &config);
380 debug("\n Get config descriptor: %d\n", ret);
382 debug(" Number of interfaces: %i\n\n", config->bNumInterfaces);
384 int j;
385 for (j = 0; j < config->bNumInterfaces; j++) {
386 debug(" Interface %i\n", j);
387 inter = &config->interface[j];
389 debug(" Number of alternate settings: %i\n", inter->num_altsetting);
391 int k;
392 for (k = 0; k < inter->num_altsetting; k++) {
393 debug(" Interface %i\n", j);
394 interdesc = &inter->altsetting[j];
396 debug(" Interface Number: %i\n", interdesc->bInterfaceNumber);
397 debug(" Number of endpoints: %i\n", interdesc->bNumEndpoints);
399 if ( (interdesc->bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE)
400 && ( (interdesc->bInterfaceSubClass == 0x01)
401 || (interdesc->bInterfaceSubClass == 0x06) )
402 && (interdesc->bInterfaceProtocol == 0x50) ) {
403 usb_storage_found = 1;
404 usb_stor_vid = desc.idVendor;
405 usb_stor_pid = desc.idProduct;
408 int l;
409 for(l = 0; l < interdesc->bNumEndpoints; l++) {
410 debug(" Endpoint %i\n", l);
411 epdesc = &interdesc->endpoint[l];
413 debug(" Descriptor Type: 0x%02X\n", epdesc->bDescriptorType);
414 debug(" EP Address: 0x%02X\n", epdesc->bEndpointAddress);
415 debug(" EP Attributes: 0x%02X\n", epdesc->bmAttributes);
417 if ((epdesc->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) {
418 if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
419 if (!endpoint_in)
420 endpoint_in = epdesc->bEndpointAddress;
421 } else {
422 if (!endpoint_out)
423 endpoint_out = epdesc->bEndpointAddress;
430 sceUsbdFreeConfigDescriptor(config);
433 sceUsbdFreeDeviceList(list, 1);
435 if (usb_storage_found) {
436 libusb_device_handle *handle;
437 handle = sceUsbdOpenDeviceWithVidPid(usb_stor_vid, usb_stor_pid);
438 test_mass_storage(handle, endpoint_in, endpoint_out);
439 } else {
440 debug("USB storage not found.\n");
443 // Return to browser
444 sceUsbdExit();
445 sceNetSocketClose(netdbg_sock);
447 return 0;