675 lines
30 KiB
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
|
|
|