README.md
Rendering markdown...
#include <stdio.h>
#include <string.h>
#include "mass_storage.h"
#include "usb_device.h"
static inline void write_32LE(void *p, size_t offset, uint32_t value)
{
((uint8_t *)p)[offset] = (value) & 0x000000FF;
((uint8_t *)p)[offset + 1] = (value >> 8) & 0x000000FF;
((uint8_t *)p)[offset + 2] = (value >> 16) & 0x000000FF;
((uint8_t *)p)[offset + 3] = (value >> 24) & 0x000000FF;
}
static inline uint32_t read_32LE(const void *p, size_t offset)
{
uint32_t value;
value = ((uint8_t *)p)[offset];
value |= ((uint32_t)((uint8_t *)p)[offset + 1]) << 8;
value |= ((uint32_t)((uint8_t *)p)[offset + 2]) << 16;
value |= ((uint32_t)((uint8_t *)p)[offset + 3]) << 24;
return value;
}
static inline uint32_t read_32BE(const void *p, size_t offset)
{
uint32_t value;
value = ((uint32_t)((uint8_t *)p)[offset]) << 24;
value |= ((uint32_t)((uint8_t *)p)[offset + 1]) << 16;
value |= ((uint32_t)((uint8_t *)p)[offset + 2]) << 8;
value |= ((uint8_t *)p)[offset + 3];
return value;
}
static inline void write_32BE(void *p, size_t offset, uint32_t value)
{
((uint8_t *)p)[offset] = (value >> 24) & 0x000000FF;
((uint8_t *)p)[offset + 1] = (value >> 16) & 0x000000FF;
((uint8_t *)p)[offset + 2] = (value >> 8) & 0x000000FF;
((uint8_t *)p)[offset + 3] = (value) & 0x000000FF;
}
static inline void write_16BE(void *p, size_t offset, uint16_t value)
{
((uint8_t *)p)[offset] = (value >> 8) & 0x000000FF;
((uint8_t *)p)[offset + 1] = (value) & 0x000000FF;
}
int mass_storage_send_command(const void *command_block, size_t command_block_length, msc_dir_t direction, size_t transfer_length)
{
uint8_t cbw[31];
memset(cbw, 0, 31);
memcpy(cbw + 15, command_block, command_block_length);
write_32LE(cbw, 0, 0x43425355);
write_32LE(cbw, 4, 0x00000000);
write_32LE(cbw, 8, transfer_length);
cbw[12] = direction;
cbw[13] = 0;
cbw[14] = command_block_length;
return usb_bulk_write(cbw, 31);
}
int mass_storage_receive_status(size_t *residue)
{
uint8_t csw[13];
int result = usb_bulk_read(csw, 13);
if (result < 0) return result;
if (residue != NULL) *residue = read_32LE(csw, 8);
return csw[12];
}
int mass_storage_inquiry(void)
{
uint8_t cb[6];
memset(cb, 0, 6);
cb[0] = 0x12;
cb[4] = 36;
int result = mass_storage_send_command(cb, 6, MSC_DIR_D2H, 36);
if (result < 0) return result;
uint8_t data[36];
result = usb_bulk_read(data, 36);
if (result < 0) return result;
if (result != 36)
{
printf("INQUIRY command failed.\n");
}
else
{
char vendor[9], product[17], revision[5];
memcpy(vendor, data + 8, 8);
memcpy(product, data + 16, 16);
memcpy(revision, data + 32, 4);
vendor[8] = '\0';
product[16] = '\0';
revision[4] = '\0';
printf("Vendor = \"%s\", Product = \"%s\", Revision = \"%s\"\n", vendor, product, revision);
}
return mass_storage_receive_status(NULL);
}
int mass_storage_read(void *data, uint32_t sector, uint16_t count)
{
uint8_t cb[10];
memset(cb, 0, 10);
cb[0] = 0x28;
write_32BE(cb, 2, sector);
write_16BE(cb, 7, count);
int result = mass_storage_send_command(cb, 10, MSC_DIR_D2H, count * 512);
if (result < 0) return result;
result = usb_bulk_read(data, count * 512);
if (result < 0) return result;
return mass_storage_receive_status(NULL);
}
int mass_storage_write(const void *data, uint32_t sector, uint16_t count)
{
uint8_t cb[10];
memset(cb, 0, 10);
cb[0] = 0x2A;
write_32BE(cb, 2, sector);
write_16BE(cb, 7, count);
int result = mass_storage_send_command(cb, 10, MSC_DIR_H2D, count * 512);
if (result < 0) return result;
result = usb_bulk_write(data, count * 512);
if (result < 0) return result;
return mass_storage_receive_status(NULL);
}
int mass_storage_read_capacity(void)
{
uint8_t cb[10];
memset(cb, 0, 10);
cb[0] = 0x25;
int result = mass_storage_send_command(cb, 10, MSC_DIR_D2H, 8);
if (result < 0) return result;
uint8_t data[8];
result = usb_bulk_read(data, 8);
if (result < 0) return result;
printf("%u sectors (%u bytes each)\n", read_32BE(data, 0), read_32BE(data, 4));
return mass_storage_receive_status(NULL);
}
int mass_storage_test_unit_ready(void)
{
uint8_t cb[6];
memset(cb, 0, 6);
int result = mass_storage_send_command(cb, 6, MSC_DIR_D2H, 0);
if (result < 0) return result;
result = mass_storage_receive_status(NULL);
if (result == 0)
printf("Device ready\n");
else
printf("Device not ready\n");
return result;
}