522 lines
13 KiB
C
522 lines
13 KiB
C
#include "device/device.h"
|
||
#include "event/event.h"
|
||
#include "event/device_event.h"
|
||
#include "asm/sfc_norflash_api.h"
|
||
#include "fs/fs.h"
|
||
#include "system/init.h"
|
||
#include "sdio/sdmmc.h"
|
||
#include "generic/ascii.h"
|
||
#include "app_config.h"
|
||
|
||
#if TCFG_USB_SLAVE_ENABLE || TCFG_USB_HOST_ENABLE
|
||
#include "usb_stack.h"
|
||
#include "msd.h"
|
||
#include "device/hid.h"
|
||
#include "uac_audio.h"
|
||
#include "usb_host.h"
|
||
#include "audio.h"
|
||
#include "hid.h"
|
||
#include "adb.h"
|
||
#include "usbnet.h"
|
||
#endif
|
||
|
||
#ifdef CONFIG_JLFAT_ENABLE
|
||
#define FAT_FILE_SYSTEM_NAME "jlfat"
|
||
#else
|
||
#define FAT_FILE_SYSTEM_NAME "fat"
|
||
#endif
|
||
|
||
#ifndef FAT_CACHE_NUM
|
||
#define FAT_CACHE_NUM 32
|
||
#endif
|
||
|
||
enum {
|
||
SD_UNMOUNT = 0,
|
||
SD_MOUNT_SUSS,
|
||
SD_MOUNT_FAILD,
|
||
};
|
||
|
||
static u8 sd_mount[2];
|
||
static OS_MUTEX sd_mutex;
|
||
|
||
static int __sd_mutex_init()
|
||
{
|
||
return os_mutex_create(&sd_mutex);
|
||
}
|
||
early_initcall(__sd_mutex_init);
|
||
|
||
static int mount_sd_to_fs(const char *sd_name)
|
||
{
|
||
int err = 0;
|
||
u32 class = 0, capacity = 0, block_size = 0;
|
||
struct imount *mt;
|
||
int id = sd_name[2] - '0';
|
||
const char *dev = sd_name;
|
||
void *fd = NULL;
|
||
|
||
err = os_mutex_pend(&sd_mutex, 0);
|
||
if (err) {
|
||
return -EFAULT;
|
||
}
|
||
|
||
if (sd_mount[id] == SD_MOUNT_SUSS) {
|
||
goto __exit;
|
||
}
|
||
if (sd_mount[id] == SD_MOUNT_FAILD) {
|
||
err = -EFAULT;
|
||
goto __exit;
|
||
}
|
||
if (!dev_online(dev)) {
|
||
err = -EFAULT;
|
||
goto __exit;
|
||
}
|
||
|
||
#ifdef CONFIG_DMSDX_ENABLE
|
||
u8 i = 0;
|
||
char sub_dev_name[7] = {0};
|
||
char mount_path_name[16] = {0};
|
||
|
||
strcpy(sub_dev_name, dev);
|
||
strcpy(mount_path_name, id ? "storage/sd1" : "storage/sd0");
|
||
|
||
do {
|
||
sub_dev_name[strlen(dev)] = '.';
|
||
sub_dev_name[strlen(dev) + 1] = '0' + i;
|
||
fd = dev_open(sub_dev_name, 0);
|
||
if (fd) {
|
||
dev_close(fd);
|
||
mount_path_name[11] = '.';
|
||
mount_path_name[12] = '0' + i;
|
||
++i;
|
||
mt = mount(sub_dev_name, mount_path_name, FAT_FILE_SYSTEM_NAME, FAT_CACHE_NUM, NULL);
|
||
if (!mt) {
|
||
printf("%s mount %s %s fail, format...", sub_dev_name, mount_path_name, FAT_FILE_SYSTEM_NAME);
|
||
f_format(sub_dev_name, FAT_FILE_SYSTEM_NAME, 32 * 1024);
|
||
mt = mount(sub_dev_name, id ? "storage/sd1" : "storage/sd0", FAT_FILE_SYSTEM_NAME, FAT_CACHE_NUM, NULL);
|
||
} else {
|
||
printf("%s mount %s %s suss", sub_dev_name, mount_path_name, FAT_FILE_SYSTEM_NAME);
|
||
}
|
||
}
|
||
} while (fd != NULL && i < 10);
|
||
|
||
if (i == 0)
|
||
#endif
|
||
{
|
||
mt = mount(dev, id ? "storage/sd1" : "storage/sd0", FAT_FILE_SYSTEM_NAME, FAT_CACHE_NUM, NULL);
|
||
if (!mt) {
|
||
printf("mount %s fail\n", sd_name);
|
||
err = -EFAULT;
|
||
goto __err;
|
||
} else {
|
||
printf("mount %s suss\n", sd_name);
|
||
}
|
||
}
|
||
|
||
#if RCSP_MODE
|
||
if (mt) {
|
||
set_rcsp_mount_mt(&mt);
|
||
}
|
||
#endif
|
||
|
||
fd = dev_open(dev, 0);
|
||
if (!fd) {
|
||
err = -EFAULT;
|
||
goto __err;
|
||
}
|
||
|
||
dev_ioctl(fd, SD_IOCTL_GET_CLASS, (u32)&class);
|
||
if (class == SD_CLASS_10) {
|
||
log_i("%s card class: 10\n", sd_name);
|
||
} else {
|
||
log_w("%s card class: %d\n", sd_name, class * 2);
|
||
}
|
||
|
||
dev_close(fd);
|
||
|
||
__err:
|
||
sd_mount[id] = err ? SD_MOUNT_FAILD : SD_MOUNT_SUSS;
|
||
__exit:
|
||
os_mutex_post(&sd_mutex);
|
||
|
||
return err;
|
||
}
|
||
|
||
static void unmount_sd_to_fs(const char *sd_name)
|
||
{
|
||
int id = sd_name[2] - '0';
|
||
os_mutex_pend(&sd_mutex, 0);
|
||
#ifdef CONFIG_DMSDX_ENABLE
|
||
u8 i = 0;
|
||
char mount_path_name[16] = {0};
|
||
|
||
strcpy(mount_path_name, id ? "storage/sd1" : "storage/sd0");
|
||
mount_path_name[11] = '.';
|
||
|
||
while (1) {
|
||
mount_path_name[12] = '0' + i;
|
||
if (!fmount_exist(mount_path_name)) {
|
||
break;
|
||
}
|
||
unmount(mount_path_name);
|
||
printf("unmount %s", mount_path_name);
|
||
++i;
|
||
}
|
||
|
||
if (i == 0)
|
||
#endif
|
||
{
|
||
unmount(id ? "storage/sd1" : "storage/sd0");
|
||
}
|
||
sd_mount[id] = SD_UNMOUNT;
|
||
printf("unmount %s\n", sd_name);
|
||
os_mutex_post(&sd_mutex);
|
||
}
|
||
|
||
int storage_device_ready(void)
|
||
{
|
||
if (!dev_online(SDX_DEV)) {
|
||
return false;
|
||
}
|
||
if (SDX_DEV[2] - '0' < 2 && sd_mount[SDX_DEV[2] - '0'] == SD_UNMOUNT) {
|
||
mount_sd_to_fs(SDX_DEV);
|
||
}
|
||
|
||
return fmount_exist(CONFIG_STORAGE_PATH);
|
||
}
|
||
|
||
int sdcard_storage_device_ready(const char *sd_name)
|
||
{
|
||
int id = sd_name[2] - '0';
|
||
|
||
if (!dev_online(sd_name)) {
|
||
return false;
|
||
}
|
||
if (sd_mount[id] == SD_UNMOUNT) {
|
||
mount_sd_to_fs(sd_name);
|
||
}
|
||
|
||
return fmount_exist(id ? "storage/sd1" : "storage/sd0");
|
||
}
|
||
|
||
int sdcard_storage_device_format(const char *sd_name)
|
||
{
|
||
int err;
|
||
|
||
if (!sd_name || strlen(sd_name) != 3) {
|
||
return -EPERM;
|
||
}
|
||
|
||
unmount_sd_to_fs(sd_name);
|
||
|
||
err = f_format(sd_name, FAT_FILE_SYSTEM_NAME, 32 * 1024);
|
||
if (err == 0) {
|
||
mount_sd_to_fs(sd_name);
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
#ifdef CONFIG_DMSDX_ENABLE
|
||
int sdcard_storage_subdevice_format(const char *dev_name)
|
||
{
|
||
int err;
|
||
char sd_name[6] = {0};
|
||
|
||
if (!dev_name || strlen(dev_name) != 5) {
|
||
return -EPERM;
|
||
}
|
||
|
||
memcpy(sd_name, dev_name, 3);
|
||
|
||
unmount_sd_to_fs(sd_name);
|
||
|
||
err = f_format(dev_name, FAT_FILE_SYSTEM_NAME, 32 * 1024);
|
||
if (err == 0) {
|
||
mount_sd_to_fs(sd_name);
|
||
}
|
||
|
||
return err;
|
||
}
|
||
#endif
|
||
|
||
/*
|
||
* sd卡插拔事件处理
|
||
*/
|
||
static void sd_event_handler(struct device_event *event)
|
||
{
|
||
switch (event->event) {
|
||
case DEVICE_EVENT_IN:
|
||
printf("%s: in\n", (const char *)event->arg);
|
||
mount_sd_to_fs(event->arg);
|
||
break;
|
||
case DEVICE_EVENT_OUT:
|
||
printf("%s: out\n", (const char *)event->arg);
|
||
unmount_sd_to_fs(event->arg);
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
#if TCFG_UDISK_ENABLE
|
||
|
||
enum {
|
||
UDISK_UNMOUNT = 0,
|
||
UDISK_MOUNT_SUSS,
|
||
UDISK_MOUNT_FAILD,
|
||
};
|
||
|
||
static OS_MUTEX udisk_mutex;
|
||
static u8 udisk_mount[2];
|
||
static u8 udisk_online[2];
|
||
|
||
static int __udisk_mutex_init()
|
||
{
|
||
return os_mutex_create(&udisk_mutex);
|
||
}
|
||
early_initcall(__udisk_mutex_init);
|
||
|
||
static int mount_udisk_to_fs(int id)
|
||
{
|
||
int err = 0;
|
||
struct imount *mt;
|
||
u32 sta = 0;
|
||
const char *name = id ? "udisk1" : "udisk0";
|
||
|
||
err = os_mutex_pend(&udisk_mutex, 0);
|
||
if (err) {
|
||
return -EFAULT;
|
||
}
|
||
|
||
if (udisk_mount[id] == UDISK_MOUNT_SUSS) {
|
||
goto __exit;
|
||
}
|
||
if (udisk_mount[id] == UDISK_MOUNT_FAILD) {
|
||
err = -EFAULT;
|
||
goto __exit;
|
||
}
|
||
|
||
sta = dev_online(name);
|
||
if (!sta) {
|
||
err = -EFAULT;
|
||
goto __exit;
|
||
}
|
||
|
||
mt = mount(name, id ? "storage/udisk1" : "storage/udisk0", FAT_FILE_SYSTEM_NAME, FAT_CACHE_NUM, NULL);
|
||
if (!mt) {
|
||
printf("mount %s fail\n", name);
|
||
err = -EFAULT;
|
||
} else {
|
||
printf("mount %s suss\n", name);
|
||
}
|
||
|
||
__err:
|
||
udisk_mount[id] = err ? UDISK_MOUNT_FAILD : UDISK_MOUNT_SUSS;
|
||
__exit:
|
||
os_mutex_post(&udisk_mutex);
|
||
|
||
return err;
|
||
}
|
||
|
||
static void unmount_udisk_to_fs(int id)
|
||
{
|
||
os_mutex_pend(&udisk_mutex, 0);
|
||
unmount(id ? "storage/udisk1" : "storage/udisk0");
|
||
udisk_mount[id] = UDISK_UNMOUNT;
|
||
printf("unmount udisk%d\n", id);
|
||
os_mutex_post(&udisk_mutex);
|
||
}
|
||
|
||
int udisk_storage_device_ready(int id)
|
||
{
|
||
u32 sta = 0;
|
||
|
||
sta = dev_online(id ? "udisk1" : "udisk0");
|
||
if (!sta) {
|
||
return false;
|
||
}
|
||
if (udisk_mount[id] == UDISK_UNMOUNT) {
|
||
mount_udisk_to_fs(id);
|
||
}
|
||
return fmount_exist(id ? "storage/udisk1" : "storage/udisk0");
|
||
}
|
||
|
||
int udisk_storage_device_format(int id)
|
||
{
|
||
int err;
|
||
|
||
unmount_udisk_to_fs(id);
|
||
|
||
err = f_format(id ? "udisk1" : "udisk0", FAT_FILE_SYSTEM_NAME, 32 * 1024);
|
||
if (err == 0) {
|
||
mount_udisk_to_fs(id);
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
|
||
#endif
|
||
|
||
static u8 incharge;
|
||
|
||
int sys_power_is_charging(void)
|
||
{
|
||
return incharge;
|
||
}
|
||
|
||
static void otg_event_handler(struct device_event *event)
|
||
{
|
||
if (event->event == DEVICE_EVENT_IN) {
|
||
if (((const char *)event->value)[0] == 'h') {
|
||
int usb_id = ((const char *)event->value)[2] - '0';
|
||
log_i("usb%d connect, host mode\n", usb_id);
|
||
#if TCFG_UDISK_ENABLE || TCFG_HOST_AUDIO_ENABLE || TCFG_HOST_UVC_ENABLE || TCFG_HOST_WIRELESS_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_ADB_ENABLE
|
||
usb_host_mount(usb_id, MOUNT_RETRY, MOUNT_RESET, MOUNT_TIMEOUT);
|
||
#endif
|
||
} else if (((const char *)event->value)[0] == 'c') {
|
||
incharge = 1;
|
||
//插入充电,插入检测会有2秒延迟
|
||
}
|
||
} else if (event->event == DEVICE_EVENT_OUT) {
|
||
if (((const char *)event->value)[0] == 'h') {
|
||
int usb_id = ((const char *)event->value)[2] - '0';
|
||
log_i("usb%d disconnect, host mode\n", usb_id);
|
||
#if TCFG_UDISK_ENABLE || TCFG_HOST_AUDIO_ENABLE || TCFG_HOST_UVC_ENABLE || TCFG_HOST_WIRELESS_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_ADB_ENABLE
|
||
usb_host_unmount(usb_id);
|
||
#endif
|
||
} else if (((const char *)event->value)[0] == 'c') {
|
||
incharge = 0;
|
||
//拔出充电,拔出检测会有5秒延迟
|
||
}
|
||
}
|
||
}
|
||
|
||
#if TCFG_USB_HOST_ENABLE
|
||
static void usb_host_event_handler(struct device_event *event)
|
||
{
|
||
int usb_id;
|
||
|
||
if (event->event == DEVICE_EVENT_IN) {
|
||
usb_id = ((const char *)event->arg)[8] - '0';
|
||
log_i("usb host%d mount succ\n", usb_id);
|
||
#if TCFG_UDISK_ENABLE
|
||
if (!strncmp((const char *)event->value, "udisk", 5)) {
|
||
//上电发现U盘原本挂在USB则出现不进中断,无法挂载文件系统,U盘断电就解决
|
||
mount_udisk_to_fs(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HOST_UVC_ENABLE
|
||
extern int usb_host_video_init(const usb_dev usb_id, const u8 sub_id);
|
||
if (!strncmp((const char *)event->value, "uvc", 3)) {
|
||
usb_host_video_init(usb_id, usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HOST_AUDIO_ENABLE
|
||
if (!strncmp((const char *)event->value, "audio", 5)) {
|
||
usb_audio_start_process(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HID_HOST_ENABLE
|
||
if (!strncmp((const char *)event->value, "hid", 3)) {
|
||
hid_process(usb_id);
|
||
}
|
||
#endif
|
||
} else if (event->event == DEVICE_EVENT_OUT) {
|
||
usb_id = ((const char *)event->arg)[8] - '0';
|
||
log_i("usb host%d unmount\n", usb_id);
|
||
#if TCFG_UDISK_ENABLE
|
||
if (!strncmp((const char *)event->value, "udisk", 5)) {
|
||
unmount_udisk_to_fs(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HOST_UVC_ENABLE
|
||
extern int uvc_host_camera_out(u8 usb_id);
|
||
if (!strncmp((const char *)event->value, "uvc", 3)) {
|
||
uvc_host_camera_out(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HOST_AUDIO_ENABLE
|
||
if (!strncmp((const char *)event->value, "audio", 5)) {
|
||
usb_audio_stop_process(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HID_HOST_ENABLE
|
||
if (!strncmp((const char *)event->value, "hid", 3)) {
|
||
hid_stop_process(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_ADB_ENABLE
|
||
if (!strncmp((const char *)event->value, "adb", 3)) {
|
||
adb_stop_process(usb_id);
|
||
}
|
||
#endif
|
||
#if TCFG_HOST_WIRELESS_ENABLE
|
||
if (!strncmp((const char *)event->value, "wireless", 8)) {
|
||
usb_net_stop_process(usb_id);
|
||
}
|
||
if (!strncmp((const char *)event->value, "at_port", 7)) {
|
||
usb_net_at_port_stop_process(usb_id);
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static int device_event_handler(struct sys_event *e)
|
||
{
|
||
struct device_event *event = (struct device_event *)e->payload;
|
||
|
||
if (e->from == DEVICE_EVENT_FROM_OTG) {
|
||
#if TCFG_USB_SLAVE_ENABLE
|
||
extern int pc_device_event_handler(struct sys_event * e);
|
||
if (pc_device_event_handler(e)) {
|
||
return 1;
|
||
}
|
||
#endif
|
||
otg_event_handler(event);
|
||
} else if (e->from == DEVICE_EVENT_FROM_SD) {
|
||
sd_event_handler(event);
|
||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||
} else if (e->from == DEVICE_EVENT_FROM_UAC) {
|
||
extern int usb_audio_event_handler(struct device_event * event);
|
||
return usb_audio_event_handler(event);
|
||
#endif
|
||
#if TCFG_USB_HOST_ENABLE
|
||
} else if (e->from == DEVICE_EVENT_FROM_USB_HOST) {
|
||
usb_host_event_handler(event);
|
||
#endif
|
||
#if TCFG_EQ_ENABLE && TCFG_EQ_ONLINE_ENABLE && defined TCFG_COMM_TYPE && (TCFG_COMM_TYPE == TCFG_USB_COMM)
|
||
} else if (e->from == DEVICE_EVENT_FROM_CFG_TOOL) {
|
||
extern void usb_cdc_read_data_handler(struct device_event * event);
|
||
usb_cdc_read_data_handler(event);
|
||
#endif
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* 静态注册设备事件回调函数,优先级为0
|
||
*/
|
||
SYS_EVENT_STATIC_HANDLER_REGISTER(device_event) = {
|
||
.event_type = SYS_DEVICE_EVENT,
|
||
.prob_handler = device_event_handler,
|
||
.post_handler = NULL,
|
||
};
|
||
|
||
extern int sdfile_ext_init(const char *dev_name, u32 sdfile_ext_base_addr, u32 sdfile_ext_end_addr);
|
||
extern u32 boot_info_get_sfc_base_addr(void);
|
||
extern u32 ex_app_info_get_base_addr(void);
|
||
|
||
#ifdef CONFIG_SDFILE_EXT_ENABLE
|
||
void sdfile_ext_mount_init(void)
|
||
{
|
||
while (!dev_online(SDX_DEV)) {
|
||
os_time_dly(1);
|
||
}
|
||
|
||
/* sdfile_ext_init(SDX_DEV, boot_info_get_sfc_base_addr(), __FLASH_SIZE__); */
|
||
sdfile_ext_init(SDX_DEV, ex_app_info_get_base_addr(), CONFIG_SDNAND_HFS_LEN);
|
||
}
|
||
#endif
|