doubao_chat/apps/common/usb/device/ram_disk_circle.c

675 lines
30 KiB
C

#include "os/os_api.h"
#include "spinlock.h"
#include "device/device.h"
#include "app_config.h"
#include "usb/usb_phy.h"
#include "server/audio_server.h"
#include "server/server_core.h"
/*
使用方法
1、在app_config.h使用USB从机的MASSSTORAGE_CLASS功能
2、在版籍board_xxx.c声明:extern const struct device_operations ram_disk_dev_ops;
3、在版籍board_xxx.c添加
在REGISTER_DEVICES(device_table) = {
//数组中添加
{"vir_udisk", &ram_disk_dev_ops, NULL},
*/
#if TCFG_VIR_UDISK_ENABLE
//模拟2GByte U盘的配置
#define BLOCK_SIZE 512u
#define CLUSTER_SIZE 0x4000u
#define BLOCK_NUM (2 * 1024 * 1024 * 1024u / BLOCK_SIZE)
#define RESERVED_SECTOR_SIZE 0x1806u
#define TOTAL_SECTOR_SIZE 0x3fe800u
#define FAT_TABLE_SECTOR_SIZE 0x3fdu
#define BSP_VOL_ID 0x4cfc8d04u
#define FILE_START_CLUSTER 6
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
#define FILE_SIZE 0x25800000ull
/* #define FILE_SIZE 0x12c00000u */
#define FILE_NUM 3
#else
#define FILE_SIZE 0
#define FILE_NUM 0
#endif
#define DATE_TIME_YEAR 2022u
#define DATE_TIME_MONTH 2u
#define DATE_TIME_DAY 14u
#define DATE_TIME_HOUR 13u
#define DATE_TIME_MINUTE 14u
#define DATE_TIME_SEC 0u
#define DATE_TIME (((((DATE_TIME_YEAR - 1980) << 9) | (DATE_TIME_MONTH << 5) | DATE_TIME_DAY) << 16) | (DATE_TIME_HOUR << 11) | (DATE_TIME_MINUTE << 5) | (DATE_TIME_SEC / 2))
#define TOTAL_FILE_SIZE (FILE_SIZE * FILE_NUM + FILE_START_CLUSTER * CLUSTER_SIZE)
#define FAT_TABLE1_OFFSET (RESERVED_SECTOR_SIZE * BLOCK_SIZE)
#define FAT_TABLE2_OFFSET ((RESERVED_SECTOR_SIZE + FAT_TABLE_SECTOR_SIZE) * BLOCK_SIZE)
#define ROOT_TABLE_OFFSET ((RESERVED_SECTOR_SIZE + FAT_TABLE_SECTOR_SIZE * 2) * BLOCK_SIZE)
#define FILE_START_OFFSET ((RESERVED_SECTOR_SIZE + FAT_TABLE_SECTOR_SIZE * 2) * BLOCK_SIZE + CLUSTER_SIZE * 4)
static u8 ram_disk_online;
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
static struct {
const char *file_name; //暂时只支持短文件名8+3规则
u32 file_size; //需要对齐到簇大小
} file_inf[FILE_NUM] = {
{"MUSIC1.WAV", FILE_SIZE},
{"MUSIC2.MP3", FILE_SIZE},
{"MUSIC3.WAV", FILE_SIZE},
};
#endif
static const unsigned char WIN_FAT32_HEAD[] = {
0xEB, 0x58, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x20, LOBYTE(RESERVED_SECTOR_SIZE), HIBYTE(RESERVED_SECTOR_SIZE), //offset:14-15 保留扇区数目
0x02, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x80, 0x00, 0x00, 0x00, //offset:28-31 FAT区前隐藏扇区数
DW1BYTE(TOTAL_SECTOR_SIZE), DW2BYTE(TOTAL_SECTOR_SIZE), DW3BYTE(TOTAL_SECTOR_SIZE), DW4BYTE(TOTAL_SECTOR_SIZE), DW1BYTE(FAT_TABLE_SECTOR_SIZE), DW2BYTE(FAT_TABLE_SECTOR_SIZE), DW3BYTE(FAT_TABLE_SECTOR_SIZE), DW4BYTE(FAT_TABLE_SECTOR_SIZE), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, //offset:32-35 该卷总扇区数 offset:36-39 一个FAT表扇区数
0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x29, DW1BYTE(BSP_VOL_ID), DW2BYTE(BSP_VOL_ID), DW3BYTE(BSP_VOL_ID), DW4BYTE(BSP_VOL_ID), 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20, //offset:67-70 BS volID
0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0x33, 0xC9, 0x8E, 0xD1, 0xBC, 0xF4,
0x7B, 0x8E, 0xC1, 0x8E, 0xD9, 0xBD, 0x00, 0x7C, 0x88, 0x56, 0x40, 0x88, 0x4E, 0x02, 0x8A, 0x56,
0x40, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x72, 0x10, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x0A,
0xF6, 0xC1, 0x01, 0x74, 0x05, 0xFE, 0x46, 0x02, 0xEB, 0x2D, 0x8A, 0x56, 0x40, 0xB4, 0x08, 0xCD,
0x13, 0x73, 0x05, 0xB9, 0xFF, 0xFF, 0x8A, 0xF1, 0x66, 0x0F, 0xB6, 0xC6, 0x40, 0x66, 0x0F, 0xB6,
0xD1, 0x80, 0xE2, 0x3F, 0xF7, 0xE2, 0x86, 0xCD, 0xC0, 0xED, 0x06, 0x41, 0x66, 0x0F, 0xB7, 0xC9,
0x66, 0xF7, 0xE1, 0x66, 0x89, 0x46, 0xF8, 0x83, 0x7E, 0x16, 0x00, 0x75, 0x39, 0x83, 0x7E, 0x2A,
0x00, 0x77, 0x33, 0x66, 0x8B, 0x46, 0x1C, 0x66, 0x83, 0xC0, 0x0C, 0xBB, 0x00, 0x80, 0xB9, 0x01,
0x00, 0xE8, 0x2C, 0x00, 0xE9, 0xA8, 0x03, 0xA1, 0xF8, 0x7D, 0x80, 0xC4, 0x7C, 0x8B, 0xF0, 0xAC,
0x84, 0xC0, 0x74, 0x17, 0x3C, 0xFF, 0x74, 0x09, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB,
0xEE, 0xA1, 0xFA, 0x7D, 0xEB, 0xE4, 0xA1, 0x7D, 0x80, 0xEB, 0xDF, 0x98, 0xCD, 0x16, 0xCD, 0x19,
0x66, 0x60, 0x80, 0x7E, 0x02, 0x00, 0x0F, 0x84, 0x20, 0x00, 0x66, 0x6A, 0x00, 0x66, 0x50, 0x06,
0x53, 0x66, 0x68, 0x10, 0x00, 0x01, 0x00, 0xB4, 0x42, 0x8A, 0x56, 0x40, 0x8B, 0xF4, 0xCD, 0x13,
0x66, 0x58, 0x66, 0x58, 0x66, 0x58, 0x66, 0x58, 0xEB, 0x33, 0x66, 0x3B, 0x46, 0xF8, 0x72, 0x03,
0xF9, 0xEB, 0x2A, 0x66, 0x33, 0xD2, 0x66, 0x0F, 0xB7, 0x4E, 0x18, 0x66, 0xF7, 0xF1, 0xFE, 0xC2,
0x8A, 0xCA, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xF7, 0x76, 0x1A, 0x86, 0xD6, 0x8A, 0x56,
0x40, 0x8A, 0xE8, 0xC0, 0xE4, 0x06, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0xCD, 0x13, 0x66, 0x61, 0x0F,
0x82, 0x74, 0xFF, 0x81, 0xC3, 0x00, 0x02, 0x66, 0x40, 0x49, 0x75, 0x94, 0xC3, 0x42, 0x4F, 0x4F,
0x54, 0x4D, 0x47, 0x52, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A, 0x44, 0x69,
0x73, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73,
0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74,
0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x01, 0xB9, 0x01, 0x00, 0x00, 0x55, 0xAA,
};
static const unsigned char WIN_FAT32_HEAD1[] = {
0x00, 0x00, 0x00, 0x00, 0x72, 0x72, 0x41, 0x61, 0x3A, 0x1D, 0x01, 0x00, 0x08, 0xE1, 0x00, 0x00, //offset:9-15 上一个读写簇号缓存
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA,
};
static const unsigned char WIN_FAT32_HEAD2[] = {
0x00, 0x00, 0x00, 0x00, 0x72, 0x72, 0x41, 0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA,
};
static const unsigned char WIN_FAT32_HEAD3[] = {
0x0D, 0x0A, 0x41, 0x6E, 0x20, 0x6F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x73,
0x79, 0x73, 0x74, 0x65, 0x6D, 0x20, 0x77, 0x61, 0x73, 0x6E, 0x27, 0x74, 0x20, 0x66, 0x6F, 0x75,
0x6E, 0x64, 0x2E, 0x20, 0x54, 0x72, 0x79, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65,
0x63, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x73,
0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6F, 0x6E, 0x27, 0x74, 0x0D, 0x0A, 0x63, 0x6F, 0x6E,
0x74, 0x61, 0x69, 0x6E, 0x20, 0x61, 0x6E, 0x20, 0x6F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6E,
0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x2E, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x66,
0x0F, 0xB6, 0x46, 0x10, 0x66, 0x8B, 0x4E, 0x24, 0x66, 0xF7, 0xE1, 0x66, 0x03, 0x46, 0x1C, 0x66,
0x0F, 0xB7, 0x56, 0x0E, 0x66, 0x03, 0xC2, 0x66, 0x89, 0x46, 0xFC, 0x66, 0xC7, 0x46, 0xF4, 0xFF,
0xFF, 0xFF, 0xFF, 0x66, 0x8B, 0x46, 0x2C, 0x66, 0x83, 0xF8, 0x02, 0x0F, 0x82, 0x47, 0xFC, 0x66,
0x3D, 0xF8, 0xFF, 0xFF, 0x0F, 0x0F, 0x83, 0x3D, 0xFC, 0x66, 0x50, 0x66, 0x83, 0xE8, 0x02, 0x66,
0x0F, 0xB6, 0x5E, 0x0D, 0x8B, 0xF3, 0x66, 0xF7, 0xE3, 0x66, 0x03, 0x46, 0xFC, 0xBB, 0x00, 0x82,
0x8B, 0xFB, 0xB9, 0x01, 0x00, 0xE8, 0x28, 0xFC, 0x38, 0x2D, 0x74, 0x1E, 0xB1, 0x0B, 0x56, 0xBE,
0x6D, 0x7D, 0xF3, 0xA6, 0x5E, 0x74, 0x1B, 0x03, 0xF9, 0x83, 0xC7, 0x15, 0x3B, 0xFB, 0x72, 0xE8,
0x4E, 0x75, 0xDA, 0x66, 0x58, 0xE8, 0x65, 0x00, 0x72, 0xBF, 0x83, 0xC4, 0x04, 0xE9, 0xF6, 0xFB,
0x00, 0x20, 0x83, 0xC4, 0x04, 0x8B, 0x75, 0x09, 0x8B, 0x7D, 0x0F, 0x8B, 0xC6, 0x66, 0xC1, 0xE0,
0x10, 0x8B, 0xC7, 0x66, 0x83, 0xF8, 0x02, 0x0F, 0x82, 0xDB, 0xFB, 0x66, 0x3D, 0xF8, 0xFF, 0xFF,
0x0F, 0x0F, 0x83, 0xD1, 0xFB, 0x66, 0x50, 0x66, 0x83, 0xE8, 0x02, 0x66, 0x0F, 0xB6, 0x4E, 0x0D,
0x66, 0xF7, 0xE1, 0x66, 0x03, 0x46, 0xFC, 0xBB, 0x00, 0x00, 0x06, 0x8E, 0x06, 0x00, 0x81, 0xE8,
0xBE, 0xFB, 0x07, 0x66, 0x58, 0xC1, 0xEB, 0x04, 0x01, 0x1E, 0x00, 0x81, 0xE8, 0x0E, 0x00, 0x0F,
0x83, 0x02, 0x00, 0x72, 0xD0, 0x8A, 0x56, 0x40, 0xEA, 0x00, 0x00, 0x00, 0x20, 0x66, 0xC1, 0xE0,
0x02, 0xE8, 0x11, 0x00, 0x26, 0x66, 0x8B, 0x01, 0x66, 0x25, 0xFF, 0xFF, 0xFF, 0x0F, 0x66, 0x3D,
0xF8, 0xFF, 0xFF, 0x0F, 0xC3, 0xBF, 0x00, 0x7E, 0x66, 0x0F, 0xB7, 0x4E, 0x0B, 0x66, 0x33, 0xD2,
0x66, 0xF7, 0xF1, 0x66, 0x3B, 0x46, 0xF4, 0x74, 0x3A, 0x66, 0x89, 0x46, 0xF4, 0x66, 0x03, 0x46,
0x1C, 0x66, 0x0F, 0xB7, 0x4E, 0x0E, 0x66, 0x03, 0xC1, 0x66, 0x0F, 0xB7, 0x5E, 0x28, 0x83, 0xE3,
0x0F, 0x74, 0x16, 0x3A, 0x5E, 0x10, 0x0F, 0x83, 0x4C, 0xFB, 0x52, 0x66, 0x8B, 0xC8, 0x66, 0x8B,
0x46, 0x24, 0x66, 0xF7, 0xE3, 0x66, 0x03, 0xC1, 0x5A, 0x52, 0x8B, 0xDF, 0xB9, 0x01, 0x00, 0xE8,
0x3E, 0xFB, 0x5A, 0x8B, 0xDA, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA,
};
static const unsigned char WIN_FAT32_FAT_TABLE_HEAD[] = {
0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F,
0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F,
};
static const unsigned char WIN_FAT32_ROOT_TABLE_HEAD[] = {
0x4A, 0x4c, 0x2D, 0x55, 0x44, 0x49, 0x53, 0x4B, 0x20, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, //u盘名称
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x0F, 0x00, 0x72, 0x72, 0x00,
0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00, 0x00,
0x01, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x0F, 0x00, 0x72, 0x6D, 0x00,
0x20, 0x00, 0x56, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x75, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x65, 0x00,
0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x7E, 0x31, 0x20, 0x20, 0x20, 0x16, 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME),
DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char WIN_FAT32_SYSTEM_VOLUME_INF_HEAD[] = {
0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME),
DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME),
DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x42, 0x74, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xCE, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x01, 0x57, 0x00, 0x50, 0x00, 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x0F, 0x00, 0xCE, 0x74, 0x00,
0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x73, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x64, 0x00, 0x61, 0x00,
0x57, 0x50, 0x53, 0x45, 0x54, 0x54, 0x7E, 0x31, 0x44, 0x41, 0x54, 0x20, 0x00, 0x01, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME),
DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x04, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x42, 0x47, 0x00, 0x75, 0x00, 0x69, 0x00, 0x64, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x01, 0x49, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x65, 0x00, 0x78, 0x00, 0x0F, 0x00, 0xFF, 0x65, 0x00,
0x72, 0x00, 0x56, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x75, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x65, 0x00,
0x49, 0x4E, 0x44, 0x45, 0x58, 0x45, 0x7E, 0x31, 0x20, 0x20, 0x20, 0x20, 0x00, 0x02, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME),
DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x00, 0x00, DW1BYTE(DATE_TIME), DW2BYTE(DATE_TIME), DW3BYTE(DATE_TIME), DW4BYTE(DATE_TIME), 0x05, 0x00, 0x4C, 0x00, 0x00, 0x00,
};
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
static const unsigned char WAV_INF_HEAD[44] = {
0x52, 0x49, 0x46, 0x46, DW1BYTE(FILE_SIZE - 8), DW2BYTE(FILE_SIZE - 8), DW3BYTE(FILE_SIZE - 8), DW4BYTE(FILE_SIZE - 8), 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, DW1BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE), DW2BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE), DW3BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE), DW4BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE), DW1BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE * 4), DW2BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE * 4), DW3BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE * 4), DW4BYTE(TCFG_USER_VIRTUAL_PLAY_SAMPLERATE * 4),
0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, DW1BYTE(FILE_SIZE - 44), DW2BYTE(FILE_SIZE - 44), DW3BYTE(FILE_SIZE - 44), DW4BYTE(FILE_SIZE - 44),
};
struct user_virtual_vfs_handle {
volatile u8 open;
volatile u8 reading;
volatile u8 wait_stop;
spinlock_t lock;
OS_SEM sem;
OS_SEM rd_sem;
void *audio_enc;
struct audio_cbuf_t *virtual;
cbuffer_t cbuf;
void *buf;
};
static struct user_virtual_vfs_handle user_virtual_vfs_handle;
#define ufs (&user_virtual_vfs_handle)
#define USER_VIRTUAL_AUDIO_CBUF_SIZE (1024 * 4)
static int user_virtual_vfs_fwrite(void *file, void *data, u32 len)
{
cbuffer_t *cbuf = (cbuffer_t *)file;
while (ufs->open) {
if (cbuf_write(cbuf, data, len) == len) {
os_sem_set(&ufs->rd_sem, 0);
os_sem_post(&ufs->rd_sem);
break;
}
os_sem_pend(&ufs->sem, 0);
}
return len;
}
static int user_virtual_vfs_fclose(void *file)
{
return 0;
}
static const struct audio_vfs_ops user_virtual_vfs_ops = {
.fwrite = user_virtual_vfs_fwrite,
.fclose = user_virtual_vfs_fclose,
};
static int mp3_read_input(u8 *buf, u32 len)
{
u32 rlen = 0;
do {
spin_lock(&ufs->lock);
if (!ufs->open || !ufs->virtual || ufs->wait_stop) {
ufs->reading = 0;
spin_unlock(&ufs->lock);
memset(buf, 0, len);
return len;
}
ufs->reading = 1;
spin_unlock(&ufs->lock);
rlen = cbuf_read(ufs->virtual->cbuf, buf, len);
if (rlen == len) {
break;
}
if (ufs->virtual->end) {
ufs->virtual->end = 2;
os_sem_post(ufs->virtual->wr_sem);
ufs->reading = 0;
return 0;
}
if (!ufs->virtual->state || 0 != os_sem_pend(ufs->virtual->rd_sem, 5)) {
rlen = len;
break;
}
} while (!rlen);
os_sem_post(ufs->virtual->wr_sem);
ufs->reading = 0;
return rlen;
}
void set_user_virtual_play_hdl(void *virtual)
{
spin_lock(&ufs->lock);
ufs->wait_stop = virtual ? 0 : 1;
while (ufs->reading) {
spin_unlock(&ufs->lock);
if (!virtual && ufs->virtual && ufs->virtual->rd_sem) {
os_sem_post(ufs->virtual->rd_sem);
}
os_time_dly(1);
spin_lock(&ufs->lock);
}
ufs->virtual = virtual;
spin_unlock(&ufs->lock);
}
int user_virtual_play_read_data(void *buf, u32 len)
{
u32 rlen = 0;
u32 data_size;
if (ufs->audio_enc) {
while (rlen < len) {
data_size = cbuf_get_data_size(&ufs->cbuf);
if (data_size > 0) {
rlen += cbuf_read(&ufs->cbuf, (u8 *)buf + rlen, data_size > len - rlen ? len - rlen : data_size);
os_sem_set(&ufs->sem, 0);
os_sem_post(&ufs->sem);
}
if (rlen < len) {
os_sem_pend(&ufs->rd_sem, 0);
}
}
} else {
do {
spin_lock(&ufs->lock);
if (!ufs->virtual || ufs->wait_stop) {
ufs->reading = 0;
spin_unlock(&ufs->lock);
memset(buf, 0, len);
return 0;
}
ufs->reading = 1;
spin_unlock(&ufs->lock);
rlen = cbuf_read(ufs->virtual->cbuf, buf, len);
if (rlen == len) {
break;
}
if (ufs->virtual->end) {
ufs->virtual->end = 2;
break;
}
if (!ufs->virtual->state || 0 != os_sem_pend(ufs->virtual->rd_sem, 5)) {
break;
}
} while (!rlen);
os_sem_post(ufs->virtual->wr_sem);
ufs->reading = 0;
}
return rlen;
}
int check_user_virtual_audio_if_running(void)
{
return ram_disk_online;
}
void *get_user_virtual_audio_server(void)
{
return ufs->audio_enc;
}
int virtual_mp3_encoder_init(void)
{
union audio_req req = {0};
printf("audio udisk virtual audio server open \n");
os_sem_create(&ufs->sem, 0);
os_sem_create(&ufs->rd_sem, 0);
ufs->buf = malloc(USER_VIRTUAL_AUDIO_CBUF_SIZE);
if (!ufs->buf) {
return -1;
}
ufs->audio_enc = server_open("audio_server", "enc");
if (!ufs->audio_enc) {
free(ufs->buf);
ufs->buf = NULL;
return -1;
}
cbuf_init(&ufs->cbuf, ufs->buf, USER_VIRTUAL_AUDIO_CBUF_SIZE);
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = 2;
req.enc.frame_size = 512;
req.enc.output_buf_len = 2 * req.enc.frame_size;
req.enc.format = "mp3";
req.enc.sample_source = "virtual";
req.enc.read_input = mp3_read_input;
req.enc.vfs_ops = &user_virtual_vfs_ops;
req.enc.file = (FILE *)&ufs->cbuf;
req.enc.vir_data_wait = 1;
req.enc.delay_ms = 50;
/* req.enc.no_auto_start = 1; */
req.enc.bitrate = 128000;//64000;
req.enc.sample_rate = TCFG_USER_VIRTUAL_PLAY_SAMPLERATE;
ufs->open = 1;
return server_request(ufs->audio_enc, AUDIO_REQ_ENC, &req);
}
int virtual_mp3_encoder_close(void)
{
union audio_req req = {0};
printf("audio udisk virtual audio server close \n");
ufs->open = 0;
os_sem_set(&ufs->sem, 0);
os_sem_post(&ufs->sem);
if (ufs->audio_enc) {
req.enc.cmd = AUDIO_ENC_CLOSE;
server_request(ufs->audio_enc, AUDIO_REQ_ENC, &req);
server_close(ufs->audio_enc);
ufs->audio_enc = NULL;
}
if (ufs->buf) {
cbuf_clear(&ufs->cbuf);
free(ufs->buf);
ufs->buf = NULL;
}
return 0;
}
void virtual_mp3_encoder_reset_cbuf(void)
{
if (ufs->buf) {
cbuf_clear(&ufs->cbuf);
os_sem_post(&ufs->sem);
}
}
#endif
/* static u8 ram_disk_buf[RAM_DISK_SIZE] ALIGNE(4); */
static struct device ram_disk_dev;
static int ram_disk_dev_init(const struct dev_node *node, void *arg)
{
printf("ram_disk_dev_init\n");
return 0;
}
static int ram_disk_dev_open(const char *name, struct device **device, void *arg)
{
*device = &ram_disk_dev;
(*device)->private_data = NULL;
ram_disk_online = 1;
return 0;
}
static int ram_disk_dev_close(struct device *device)
{
ram_disk_online = 0;
return 0;
}
static int ram_disk_dev_read(struct device *device, void *buf, u32 len, u32 offset)
{
int i = 0;
u32 wlen = 0;
u8 *data = (u8 *)buf;
len *= BLOCK_SIZE;
offset *= BLOCK_SIZE;
u8 has_read = 0;
while (len > wlen) {
if (offset < FAT_TABLE1_OFFSET) {
//引导扇区
if (offset == 0 || offset == 0xc00) {
memcpy(data + wlen, WIN_FAT32_HEAD, sizeof(WIN_FAT32_HEAD));
} else if (offset == 0x200) {
memset(data + wlen, 0x00, BLOCK_SIZE);
memcpy(data + wlen, "RRaA", 4);
memcpy(data + wlen + 0x1e0, WIN_FAT32_HEAD1, sizeof(WIN_FAT32_HEAD1));
} else if (offset == 0xc00 + 0x200) {
memset(data + wlen, 0x00, BLOCK_SIZE);
memcpy(data + wlen, "RRaA", 4);
memcpy(data + wlen + 0x1e0, WIN_FAT32_HEAD2, sizeof(WIN_FAT32_HEAD2));
} else if (offset == 0x200 * 2 || offset == 0xc00 + 0x200 * 2) {
memset(data + wlen, 0x00, BLOCK_SIZE);
data[wlen + 0x200 - 2] = 0x55;
data[wlen + 0x200 - 1] = 0xAA;
} else if (offset == 0x1800) {
memcpy(data + wlen, WIN_FAT32_HEAD3, 0x200);
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
} else if (offset >= FAT_TABLE1_OFFSET && offset < FAT_TABLE2_OFFSET) {
//FAT表1
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
if (offset + BLOCK_SIZE < FAT_TABLE1_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE)) {
for (i = 0; i < BLOCK_SIZE / 4; ++i) {
*((int *)(data + wlen) + i) = (offset - FAT_TABLE1_OFFSET) / 4 + i + 1;
}
if (offset == FAT_TABLE1_OFFSET) {
memcpy(data + wlen, WIN_FAT32_FAT_TABLE_HEAD, sizeof(WIN_FAT32_FAT_TABLE_HEAD));
}
} else if (offset < FAT_TABLE1_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE)) {
memset(data + wlen, 0, BLOCK_SIZE);
for (i = 0; i < (FAT_TABLE1_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE) - offset) / 4; ++i) {
*((int *)(data + wlen) + i) = (offset - FAT_TABLE1_OFFSET) / 4 + i + 1;
}
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
for (u32 j = 0, start_clust = FILE_START_CLUSTER; j < ARRAY_SIZE(file_inf); ++j) {
int end_offset = FAT_TABLE1_OFFSET + (start_clust + file_inf[j].file_size / CLUSTER_SIZE) * 4;
if (end_offset - (int)offset >= 0 && end_offset - (int)offset < BLOCK_SIZE) {
*((int *)(data + wlen) + (end_offset - offset) / 4 - 1) = 0xfffffff;
}
start_clust += file_inf[j].file_size / CLUSTER_SIZE;
}
#else
if (offset == FAT_TABLE1_OFFSET) {
memcpy(data + wlen, WIN_FAT32_FAT_TABLE_HEAD, sizeof(WIN_FAT32_FAT_TABLE_HEAD));
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
#endif
} else if (offset >= FAT_TABLE2_OFFSET && offset < ROOT_TABLE_OFFSET) {
//FAT表2
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
if (offset + BLOCK_SIZE < FAT_TABLE2_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE)) {
for (i = 0; i < BLOCK_SIZE / 4; ++i) {
*((int *)(data + wlen) + i) = (offset - FAT_TABLE2_OFFSET) / 4 + i + 1;
}
if (offset == FAT_TABLE2_OFFSET) {
memcpy(data + wlen, WIN_FAT32_FAT_TABLE_HEAD, sizeof(WIN_FAT32_FAT_TABLE_HEAD));
}
} else if (offset < FAT_TABLE2_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE)) {
memset(data + wlen, 0, BLOCK_SIZE);
for (i = 0; i < (FAT_TABLE2_OFFSET + (TOTAL_FILE_SIZE * 4 / CLUSTER_SIZE) - offset) / 4; ++i) {
*((int *)(data + wlen) + i) = (offset - FAT_TABLE2_OFFSET) / 4 + i + 1;
}
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
for (u32 j = 0, start_clust = FILE_START_CLUSTER; j < ARRAY_SIZE(file_inf); ++j) {
int end_offset = FAT_TABLE2_OFFSET + (start_clust + file_inf[j].file_size / CLUSTER_SIZE) * 4;
if (end_offset - (int)offset >= 0 && end_offset - (int)offset < BLOCK_SIZE) {
*((int *)(data + wlen) + (end_offset - offset) / 4 - 1) = 0xfffffff;
}
start_clust += file_inf[j].file_size / CLUSTER_SIZE;
}
#else
if (offset == FAT_TABLE2_OFFSET) {
memcpy(data + wlen, WIN_FAT32_FAT_TABLE_HEAD, sizeof(WIN_FAT32_FAT_TABLE_HEAD));
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
#endif
} else if (offset == ROOT_TABLE_OFFSET) {
//根目录
memset(data + wlen, 0, BLOCK_SIZE);
memcpy(data + wlen, WIN_FAT32_ROOT_TABLE_HEAD, sizeof(WIN_FAT32_ROOT_TABLE_HEAD));
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
for (u32 i = 0, start_clust = FILE_START_CLUSTER; i < ARRAY_SIZE(file_inf); ++i) {
const char *p = strchr(file_inf[i].file_name, '.');
if (p) {
memcpy(data + wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20, file_inf[i].file_name, p - file_inf[i].file_name);
if (p - file_inf[i].file_name < 8) {
memset(data + wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + (p - file_inf[i].file_name), 0x20, 8 - (p - file_inf[i].file_name));
}
memcpy(data + wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 8, p + 1, strlen(p + 1));
}
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 11] = 0x20;
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 12] = 0x18;
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 13] = i;
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 14] = DW1BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 15] = DW2BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 16] = DW3BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 17] = DW4BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 18] = DW3BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 19] = DW4BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 20] = DW3BYTE(start_clust);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 21] = DW4BYTE(start_clust);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 22] = DW1BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 23] = DW2BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 24] = DW3BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 25] = DW4BYTE(DATE_TIME);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 26] = DW1BYTE(start_clust);
data[wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 27] = DW2BYTE(start_clust);
memcpy(data + wlen + sizeof(WIN_FAT32_ROOT_TABLE_HEAD) + i * 0x20 + 28, &file_inf[i].file_size, sizeof(file_inf[i].file_size));
start_clust += file_inf[i].file_size / CLUSTER_SIZE;
}
#endif
} else if (offset == ROOT_TABLE_OFFSET + CLUSTER_SIZE) {
//system volume information
memset(data + wlen, 0, BLOCK_SIZE);
memcpy(data + wlen, WIN_FAT32_SYSTEM_VOLUME_INF_HEAD, sizeof(WIN_FAT32_SYSTEM_VOLUME_INF_HEAD));
} else if (offset == ROOT_TABLE_OFFSET + CLUSTER_SIZE * 2) {
//WPSettings.dat
memset(data + wlen, 0, BLOCK_SIZE);
} else if (offset == ROOT_TABLE_OFFSET + CLUSTER_SIZE * 3) {
//IndexerVolumeGuid
memset(data + wlen, 0, BLOCK_SIZE);
#if TCFG_USER_VIRTUAL_PLAY_ENABLE
} else if (offset >= FILE_START_OFFSET && offset < FILE_START_OFFSET + FILE_SIZE * FILE_NUM) {
for (u32 i = 0, start_file_offset = FILE_START_OFFSET; i < ARRAY_SIZE(file_inf); ++i) {
//用户数据在此读取
if (offset == start_file_offset) {
if (ufs->audio_enc) {
virtual_mp3_encoder_close();
}
if (strstr(file_inf[i].file_name, ".WAV")) {
memcpy(data + wlen, WAV_INF_HEAD, sizeof(WAV_INF_HEAD));
user_virtual_play_read_data(data + wlen + sizeof(WAV_INF_HEAD), BLOCK_SIZE - sizeof(WAV_INF_HEAD));
has_read = 1;
break;
} else if (strstr(file_inf[i].file_name, ".MP3")) {
virtual_mp3_encoder_init();
}
}
start_file_offset += file_inf[i].file_size;
}
if (!has_read) {
user_virtual_play_read_data(data + wlen, BLOCK_SIZE);
}
#endif
} else {
memset(data + wlen, 0, BLOCK_SIZE);
}
wlen += BLOCK_SIZE;
offset += BLOCK_SIZE;
len -= BLOCK_SIZE;
}
return wlen / BLOCK_SIZE;
}
static int ram_disk_dev_write(struct device *device, void *buf, u32 len, u32 offset)
{
#if TCFG_VIR_UPDATE_ENABLE
int ram_disk_update(const u8 * buf, const u32 len, const u32 offset);
ram_disk_update(buf, len, offset);
#endif
return len;
}
static int ram_disk_dev_ioctl(struct device *device, u32 cmd, u32 arg)
{
switch (cmd) {
case IOCTL_GET_ID:
*((int *)arg) = 0;
break;
case IOCTL_GET_BLOCK_NUMBER:
*((int *)arg) = BLOCK_NUM;
break;
case IOCTL_GET_SECTOR_SIZE:
*((int *)arg) = TOTAL_SECTOR_SIZE;
break;
case IOCTL_GET_BLOCK_SIZE:
*((int *)arg) = BLOCK_SIZE;
break;
case IOCTL_GET_CAPACITY:
*((int *)arg) = BLOCK_NUM * BLOCK_SIZE;
break;
case IOCTL_GET_STATUS:
*((int *)arg) = 1;
break;
default:
break;
}
return 0;
}
const struct device_operations ram_disk_dev_ops = {
.init = ram_disk_dev_init,
.open = ram_disk_dev_open,
.read = ram_disk_dev_read,
.write = ram_disk_dev_write,
.ioctl = ram_disk_dev_ioctl,
.close = ram_disk_dev_close,
};
#endif