120 lines
2.7 KiB
C
120 lines
2.7 KiB
C
/*
|
|
* Copyright (c) 2022 HPMicro
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
*/
|
|
|
|
#include <rthw.h>
|
|
#include <rtdevice.h>
|
|
#include <rtdbg.h>
|
|
#include "tusb.h"
|
|
|
|
/* Definition of logic unit number for each drive */
|
|
#define LUN_USB (0U) /* lun 0 of usb drive */
|
|
|
|
static rt_ssize_t hpm_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
|
|
static rt_ssize_t hpm_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
|
|
rt_err_t hpm_usb_control(rt_device_t dev, int cmd, void *args);
|
|
|
|
rt_uint8_t usb_dev_addr;
|
|
|
|
static struct rt_device hpm_usb = {
|
|
.read = hpm_usb_read,
|
|
.write = hpm_usb_write,
|
|
.control = hpm_usb_control,
|
|
};
|
|
|
|
static bool usb_disk_wait_for_complete(uint8_t usb_addr)
|
|
{
|
|
#if CFG_TUSB_OS != OPT_OS_NONE
|
|
int32_t retry_cnt = 200;
|
|
#else
|
|
int32_t retry_cnt = 5000000;
|
|
#endif
|
|
|
|
while (!tuh_msc_idle(usb_addr) && retry_cnt--)
|
|
{
|
|
#if CFG_TUSB_OS != OPT_OS_NONE
|
|
osal_task_delay(5);
|
|
#else
|
|
tuh_task();
|
|
#endif
|
|
}
|
|
|
|
return retry_cnt > 0 ? true : false;
|
|
}
|
|
|
|
void hpm_usb_set_addr(uint8_t dev_addr)
|
|
{
|
|
usb_dev_addr = dev_addr;
|
|
}
|
|
|
|
static rt_ssize_t hpm_usb_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
|
{
|
|
rt_bool_t result;
|
|
|
|
result = tuh_msc_read10(usb_dev_addr, LUN_USB, buffer, pos, size, NULL);
|
|
|
|
if (result) {
|
|
result = usb_disk_wait_for_complete(usb_dev_addr);
|
|
}
|
|
|
|
return result ? size : 0;
|
|
}
|
|
|
|
static rt_ssize_t hpm_usb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
|
{
|
|
bool result;
|
|
|
|
result = tuh_msc_write10(usb_dev_addr, LUN_USB, buffer, pos, size, NULL);
|
|
|
|
if (result) {
|
|
result = usb_disk_wait_for_complete(usb_dev_addr);
|
|
}
|
|
|
|
return result ? size : 0;
|
|
}
|
|
|
|
rt_err_t hpm_usb_control(rt_device_t dev, int cmd, void *args)
|
|
{
|
|
rt_err_t ret = RT_EOK;
|
|
|
|
switch (cmd)
|
|
{
|
|
case RT_DEVICE_CTRL_BLK_GETGEOME:
|
|
struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args;
|
|
geometry->sector_count = tuh_msc_get_block_count(usb_dev_addr, LUN_USB);
|
|
geometry->bytes_per_sector = tuh_msc_get_block_size(usb_dev_addr, LUN_USB);
|
|
break;
|
|
case RT_DEVICE_CTRL_BLK_SYNC:
|
|
break;
|
|
case RT_DEVICE_CTRL_BLK_ERASE:
|
|
break;
|
|
|
|
default:
|
|
ret = RT_EINVAL;
|
|
break;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
int rt_hw_usb_init(void)
|
|
{
|
|
rt_err_t err = RT_EOK;
|
|
|
|
hpm_usb.type = RT_Device_Class_Block;
|
|
|
|
err = rt_device_register(&hpm_usb, "usb0", RT_DEVICE_FLAG_RDWR);
|
|
|
|
if (err != RT_EOK) {
|
|
LOG_E("rt device %s failed, status=%d\n", "usb", err);
|
|
return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
INIT_BOARD_EXPORT(rt_hw_usb_init);
|