提交 adc63f2c 编写于 作者: wuyangyong's avatar wuyangyong

update elmfat to R0.08b

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1336 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 a8ba93e9
FatFs Module Source Files R0.07e (C)ChaN, 2009
FatFs Module Source Files R0.08b (C)ChaN, 2011
FILES
......@@ -7,7 +7,6 @@ FILES
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c Skeleton of low level disk I/O module.
integer.h Alternative type definitions for integer variables.
option Optional external functions.
......@@ -24,7 +23,7 @@ AGREEMENTS
small embedded systems. This is a free software and is opened for education,
research and commercial developments under license policy of following trems.
Copyright (C) 2009, ChaN, all right reserved.
Copyright (C) 2011, ChaN, all right reserved.
* The FatFs module is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
......@@ -103,8 +102,26 @@ REVISION HISTORY
Added f_chdrive().
Added proper case conversion for extended characters.
Nov 03,'2009 R0.07e Separated out configuration options from ff.h to ffconf.h.
Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h.
Added a configuration option, _LFN_UNICODE.
Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
Fixed name matching error on the 13 char boundary.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed fname member in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
Fixed f_mkfs() creates wrong FAT32 volume.
Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Ignores duplicated directory separators in given path names.
......@@ -8,7 +8,7 @@
#include <dfs_fs.h>
#include <dfs_def.h>
static rt_device_t disk[_DRIVES] = {0};
static rt_device_t disk[_VOLUMES] = {0};
static int elm_result_to_dfs(FRESULT result)
{
......@@ -48,7 +48,7 @@ static int elm_result_to_dfs(FRESULT result)
case FR_MKFS_ABORTED:
status = -DFS_STATUS_EINVAL;
break;
default:
status = -1;
break;
......@@ -64,14 +64,14 @@ int dfs_elm_mount(struct dfs_filesystem* fs, unsigned long rwflag, const void* d
rt_uint32_t index;
/* handle RT-Thread device routine */
for (index = 0; index < _DRIVES; index ++)
for (index = 0; index < _VOLUMES; index ++)
{
if (disk[index] == RT_NULL)
{
break;
}
}
if (index == _DRIVES) return -DFS_STATUS_ENOSPC;
if (index == _VOLUMES) return -DFS_STATUS_ENOSPC;
/* get device */
disk[index] = fs->dev_id;
......@@ -106,7 +106,7 @@ int dfs_elm_unmount(struct dfs_filesystem* fs)
RT_ASSERT(fat != RT_NULL);
/* find the device index and then umount it */
for (index = 0; index < _DRIVES; index ++)
for (index = 0; index < _VOLUMES; index ++)
{
if (disk[index] == fs->dev_id)
{
......@@ -132,7 +132,7 @@ int dfs_elm_mkfs(const char* device_name)
FRESULT result;
/* find device name */
for (drv = 0; drv < _DRIVES; drv ++)
for (drv = 0; drv < _VOLUMES; drv ++)
{
dev = disk[drv];
if (rt_strncmp(dev->parent.name, device_name, RT_NAME_MAX) == 0)
......@@ -167,12 +167,12 @@ int dfs_elm_statfs(struct dfs_filesystem* fs, struct statfs *buf)
f = (FATFS*) fs->data;
rt_snprintf(driver, sizeof(driver), "%d:", f->drive);
rt_snprintf(driver, sizeof(driver), "%d:", f->drv);
res = f_getfree(driver, &fre_clust, &f);
if (res) return elm_result_to_dfs(res);
/* Get total sectors and free sectors */
tot_sect = (f->max_clust - 2) * f->csize;
tot_sect = (f->n_fatent - 2) * f->csize;
fre_sect = fre_clust * f->csize;
buf->f_bfree = fre_sect;
......@@ -189,10 +189,10 @@ int dfs_elm_open(struct dfs_fd* file)
FRESULT result;
char *drivers_fn;
#if (_DRIVES > 1)
#if (_VOLUMES > 1)
int vol;
extern int elm_get_vol(FATFS *fat);
/* add path for ELM FatFS driver support */
vol = elm_get_vol((FATFS *)file->fs->data);
if (vol < 0) return -DFS_STATUS_ENOENT;
......@@ -213,7 +213,7 @@ int dfs_elm_open(struct dfs_fd* file)
result = f_mkdir(drivers_fn);
if (result != FR_OK)
{
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
return elm_result_to_dfs(result);
......@@ -224,14 +224,14 @@ int dfs_elm_open(struct dfs_fd* file)
dir = (DIR *)rt_malloc(sizeof(DIR));
if (dir == RT_NULL)
{
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
return -DFS_STATUS_ENOMEM;
}
result = f_opendir(dir, drivers_fn);
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
if (result != FR_OK)
......@@ -264,7 +264,7 @@ int dfs_elm_open(struct dfs_fd* file)
}
result = f_open(fd, drivers_fn, mode);
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
if (result == FR_OK)
......@@ -464,7 +464,7 @@ int dfs_elm_unlink(struct dfs_filesystem* fs, const char* path)
{
FRESULT result;
#if _DRIVES > 1
#if _VOLUMES > 1
int vol;
char *drivers_fn;
extern int elm_get_vol(FATFS *fat);
......@@ -482,7 +482,7 @@ int dfs_elm_unlink(struct dfs_filesystem* fs, const char* path)
#endif
result = f_unlink(drivers_fn);
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
return elm_result_to_dfs(result);
......@@ -492,7 +492,7 @@ int dfs_elm_rename(struct dfs_filesystem* fs, const char* oldpath, const char* n
{
FRESULT result;
#if _DRIVES > 1
#if _VOLUMES > 1
char *drivers_oldfn, *drivers_newfn;
int vol;
extern int elm_get_vol(FATFS *fat);
......@@ -504,7 +504,7 @@ int dfs_elm_rename(struct dfs_filesystem* fs, const char* oldpath, const char* n
drivers_oldfn = rt_malloc(256);
if (drivers_oldfn == RT_NULL) return -DFS_STATUS_ENOMEM;
drivers_newfn = rt_malloc(256);
if (drivers_newfn == RT_NULL)
if (drivers_newfn == RT_NULL)
{
rt_free(drivers_oldfn);
return -DFS_STATUS_ENOMEM;
......@@ -520,7 +520,7 @@ int dfs_elm_rename(struct dfs_filesystem* fs, const char* oldpath, const char* n
#endif
result = f_rename(drivers_oldfn, drivers_newfn);
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_oldfn);
rt_free(drivers_newfn);
#endif
......@@ -533,7 +533,7 @@ int dfs_elm_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
FRESULT result;
#if _DRIVES > 1
#if _VOLUMES > 1
int vol;
char *drivers_fn;
extern int elm_get_vol(FATFS *fat);
......@@ -557,7 +557,7 @@ int dfs_elm_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
#endif
result = f_stat(drivers_fn, &file_info);
#if _DRIVES > 1
#if _VOLUMES > 1
rt_free(drivers_fn);
#endif
if (result == FR_OK)
......@@ -587,7 +587,7 @@ int dfs_elm_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
return elm_result_to_dfs(result);
}
static const struct dfs_filesystem_operation dfs_elm =
static const struct dfs_filesystem_operation dfs_elm =
{
"elm",
dfs_elm_mount,
......@@ -669,7 +669,7 @@ DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff)
rt_device_t device = disk[drv];
if (device == RT_NULL) return RES_ERROR;
if (ctrl == GET_SECTOR_COUNT)
{
struct rt_device_blk_geometry geometry;
......@@ -687,7 +687,7 @@ DRESULT disk_ioctl (BYTE drv, BYTE ctrl, void *buff)
rt_memset(&geometry, 0, sizeof(geometry));
rt_device_control(device, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
*(DWORD*)buff = geometry.bytes_per_sector;
*(WORD*)buff = geometry.bytes_per_sector;
}
else if (ctrl == GET_BLOCK_SIZE) /* Get erase block size in unit of sectors (DWORD) */
{
......@@ -708,7 +708,7 @@ rt_time_t get_fattime()
}
#if _FS_REENTRANT
BOOL ff_cre_syncobj(BYTE drv, _SYNC_t* m)
int ff_cre_syncobj(BYTE drv, _SYNC_t* m)
{
char name[8];
rt_mutex_t mutex;
......@@ -718,24 +718,24 @@ BOOL ff_cre_syncobj(BYTE drv, _SYNC_t* m)
if (mutex != RT_NULL)
{
*m = mutex;
return TRUE;
return RT_TRUE;
}
return FALSE;
return RT_FALSE;
}
BOOL ff_del_syncobj(_SYNC_t m)
int ff_del_syncobj(_SYNC_t m)
{
rt_mutex_delete(m);
return TRUE;
return RT_TRUE;
}
BOOL ff_req_grant(_SYNC_t m)
int ff_req_grant(_SYNC_t m)
{
if (rt_mutex_take(m, _FS_TIMEOUT) == RT_EOK) return TRUE;
if (rt_mutex_take(m, _FS_TIMEOUT) == RT_EOK) return RT_TRUE;
return FALSE;
return RT_FALSE;
}
void ff_rel_grant(_SYNC_t m)
......
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/
#include "diskio.h"
/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive. */
#define ATA 0
#define MMC 1
#define USB 2
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
int result;
switch (drv) {
case ATA :
result = ATA_disk_initialize();
// translate the reslut code here
return stat;
case MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive nmuber (0..) */
)
{
DSTATUS stat;
int result;
switch (drv) {
case ATA :
result = ATA_disk_status();
// translate the reslut code here
return stat;
case MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
result = ATA_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case MMC :
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case USB :
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
result = ATA_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case MMC :
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case USB :
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (drv) {
case ATA :
// pre-process here
result = ATA_disk_ioctl(ctrl, buff);
// post-process here
return res;
case MMC :
// pre-process here
result = MMC_disk_ioctl(ctrl, buff);
// post-process here
return res;
case USB :
// pre-process here
result = USB_disk_ioctl(ctrl, buff);
// post-process here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2009
/ Low level disk interface modlue include file
/-----------------------------------------------------------------------*/
#ifndef _DISKIO
#define _READONLY 0 /* 1: Read-only mode */
#define _USE_IOCTL 1
#define _READONLY 0 /* 1: Remove write functions */
#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */
#include "integer.h"
......@@ -26,7 +26,7 @@ typedef enum {
/*---------------------------------------*/
/* Prototypes for disk control functions */
BOOL assign_drives (int argc, char *argv[]);
int assign_drives (int, int);
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
......@@ -44,26 +44,34 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl() */
/* Command code for disk_ioctrl fucntion */
/* Generic command (defined for FatFs) */
#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
/* Generic command */
#define CTRL_SYNC 0 /* Mandatory for write functions */
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
#define CTRL_POWER 4
#define CTRL_LOCK 5
#define CTRL_EJECT 6
/* MMC/SDC command */
#define MMC_GET_TYPE 10
#define MMC_GET_CSD 11
#define MMC_GET_CID 12
#define MMC_GET_OCR 13
#define MMC_GET_SDSTAT 14
/* ATA/CF command */
#define ATA_GET_REV 20
#define ATA_GET_MODEL 21
#define ATA_GET_SN 22
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
/* NAND specific ioctl command */
#define NAND_FORMAT 30 /* Create physical format */
#define _DISKIO
......
......@@ -3,10 +3,14 @@
/*-------------------------------------------*/
#ifndef _INTEGER
#define _INTEGER
#ifdef _WIN32 /* FatFs development platform */
#if 0
#include <windows.h>
#else
#include <tchar.h>
#else /* Embedded platform */
/* These types must be 16-bit, 32-bit or larger integer */
typedef int INT;
......@@ -28,10 +32,6 @@ typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned long DWORD;
/* Boolean type */
typedef enum { FALSE = 0, TRUE } BOOL;
#endif
#define _INTEGER
#endif
......@@ -9,7 +9,7 @@
#define _TINY_TABLE 0
#if !_USE_LFN || _CODE_PAGE != 932
#error This file is not needed in current configuration.
#error This file is not needed in current configuration. Remove from the project.
#endif
......@@ -111,7 +111,7 @@ const WCHAR uni2sjis[] = {
0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9,
0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED,
0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1,
0x3094, 0x8394, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154,
0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154,
0x309E, 0x8155, 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342,
0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346,
0x30A8, 0x8347, 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A,
......@@ -1979,7 +1979,7 @@ const WCHAR sjis2uni[] = {
0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9,
0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED,
0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1,
0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x3094, 0x8394, 0x30F4,
0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4,
0x8395, 0x30F5, 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392,
0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396,
0x83A5, 0x0397, 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A,
......@@ -3760,9 +3760,9 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */
do {
c = *p;
p += 2;
} while (c && c != src);
p -= 3;
c = *p;
} while (c && c != src);
} else { /* Unicode to OEMCP */
li = 0; hi = sizeof(uni2sjis) / 4 - 1;
for (n = 16; n; n--) {
......
......@@ -8,7 +8,7 @@
#if !_USE_LFN || _CODE_PAGE != 936
#error This file is not needed in current configuration.
#error This file is not needed in current configuration. Remove from the project.
#endif
static
......
/*------------------------------------------------------------------------*/
/* Unicode - OEM code bidirectional converter (C)ChaN, 2009 */
/* */
/* CP949 (Korean) */
/* CP949 (Korean EUC-KR) */
/*------------------------------------------------------------------------*/
#include "../ff.h"
#if !_USE_LFN || _CODE_PAGE != 949
#error This file is not needed in current configuration.
#error This file is not needed in current configuration. Remove from the project.
#endif
......
......@@ -8,7 +8,7 @@
#if !_USE_LFN || _CODE_PAGE != 950
#error This file is not needed in current configuration.
#error This file is not needed in current configuration. Remove from the project.
#endif
......
......@@ -329,7 +329,7 @@ const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
0x0428, 0x0429, 0x042A, 0x042D, 0x042C, 0x042D, 0x042E, 0x042F,
0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
......@@ -351,7 +351,7 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,
0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,
0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,
0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,
0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,
0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,
0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,
......@@ -494,7 +494,7 @@ const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
#if !_TBLDEF || !_USE_LFN
#error This file is not needed in current configuration
#error This file is not needed in current configuration. Remove from the project.
#endif
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册