Files
second-movement/filesystem/usb_msc_driver.c

156 lines
4.8 KiB
C

/*
* USB mass storage class driver that mimics littlefs to FAT12 file system.
*
* Copyright 2024, Hiroyuki OYAMA. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* - Neither the name of the copyright holder nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <tusb.h>
#include "mimic_fat.h"
#include "pins.h"
extern const struct lfs_config watch_lfs_cfg;
static bool ejected = false;
static bool is_initialized = false;
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
(void)lun;
if (!is_initialized) {
mimic_fat_init(&watch_lfs_cfg);
mimic_fat_update_usb_device_is_enabled(true);
mimic_fat_create_cache();
is_initialized = true;
}
const char vid[] = "littlefs";
const char pid[] = "Mass Storage";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
(void)lun;
return true;
}
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) {
(void)lun;
*block_count = mimic_fat_total_sector_size();
*block_size = DISK_SECTOR_SIZE;
printf("Block count: %lu\nBlock size: %d\n", *block_count, *block_size);
}
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
(void)lun;
(void)power_condition;
if (load_eject) {
if (start) {
// load disk storage
} else {
// unload disk storage
ejected = true;
}
}
return true;
}
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) {
(void)lun;
(void)offset;
mimic_fat_read(lun, lba, buffer, bufsize);
return (int32_t)bufsize;
}
bool tud_msc_is_writable_cb (uint8_t lun) {
(void) lun;
return false;
}
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) {
(void)offset;
mimic_fat_write(lun, lba, buffer, bufsize);
return bufsize;
}
int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) {
void const *response = NULL;
int32_t resplen = 0;
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0]) {
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
// negative means error -> tinyusb could stall and/or response with failed status
resplen = -1;
break;
}
// return resplen must not larger than bufsize
if (resplen > bufsize) resplen = bufsize;
if (response && (resplen > 0)) {
if(in_xfer) {
memcpy(buffer, response, (size_t) resplen);
} else {
; // SCSI output
}
}
return (int32_t)resplen;
}
void tud_mount_cb(void) {
printf("\e[45mmount\e[0m\n");
/*
* NOTE:
* This callback must be returned immediately. Time-consuming processing
* here will cause TinyUSB to PANIC `ep 0 in was already available`.
*/
is_initialized = false;
}
void tud_suspend_cb(bool remote_wakeup_en) {
(void)remote_wakeup_en;
printf("\e[45msuspend\e[0m\n");
mimic_fat_cleanup_cache();
mimic_fat_update_usb_device_is_enabled(false);
}