⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
**  WASABI-Hot! version 1.2c   
**
**
**      -- copyright (c) 2001-2004 by Philips Japan, Ltd. -- All rights reserved --
**
**
**      ** This code has been made to check/learn                          ** 
**      **                             the ISP1362/ISP1363 functionalities **
**      ** Release 06-Aug-2004                                             **
**
**      OKANO, Akifumi
**      
**		Application Laboratory, Mobile and Connectivity
**      Semiconductors Div, Philips Japan Ltd.
**      akifumi.okano@philips.com
**      +81-3-3740-4668
*/


/****************************************************************************/
/*	includes																*/
/****************************************************************************/


#include		<alloc.h>

#include		"class_dr/storage/storage.h"
#include		"class_dr/storage/fs.h"
#include		"ui.h"
#include		"general.h"


/****************************************************************************/
/*	constants																*/
/****************************************************************************/



//	directory accessing mode
#define			DIR_ACCESS_READ				0
#define			DIR_ACCESS_MODIFY			1
#define			DIR_ACCESS_APPEND_NEW		2
#define			DIR_ACCESS_APPEND_OW		3

#define			FAT_CACHE_NOT_VALID			0xFFFFFFFF
#define			DIR_CACHE_NOT_VALID			0xFFFFFFFF

#define			NO_DIR_MODIFY				0
#define			OK_DIR_MODIFY				1

#define			NO_MAKE_NEW_DIR_ENT			0
#define			OK_MAKE_NEW_DIR_ENT			1

#define			FILE_SYSTEM_FAT16			0
#define			FILE_SYSTEM_FAT12			1
#define			FILE_SYSTEM_UNKNOWN			0xFF


/****************************************************************************/
/*	global vars																*/
/****************************************************************************/

drive_param		gp_drive_parameter;
volume_param	g_volume_parameter;

unsigned char	*g_fs_scratch_buffer_ptr;
unsigned short	g_fs_scratch_buffer_size;
unsigned char	g_num_of_fs_client			= 0;
unsigned char	g_recent_error;

#if BIG_ENDIAN

directory_entry	g_root_dumy		=	{ "ROOTROOT", "DIR", 0x10, {0,0,0,0,0,0,0,0,0,0}, 0, 0, 
												//	ROOT_DIRECTORY_CLUSTER, 
												(ROOT_DIRECTORY_CLUSTER << 8) | (ROOT_DIRECTORY_CLUSTER >> 8), 
									0 };

#else

directory_entry	g_root_dumy		=	{ "ROOTROOT", "DIR", 0x10, {0,0,0,0,0,0,0,0,0,0}, 0, 0, ROOT_DIRECTORY_CLUSTER, 0 };

#endif


/****************************************************************************/
/*	function prototypes														*/
/****************************************************************************/

static unsigned short	fs_read_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters );
static unsigned short	fs_read_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length );
static unsigned short	fs_write_large( fs_FILE *fp, unsigned char *buffer_ptr, unsigned long clusters );
static unsigned short	fs_write_small( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length );

static unsigned char	make_directory_entry_fp( fs_FILE *fp );
static unsigned char	make_directory_entry( char *full_path, unsigned short parent_cluster, unsigned short *index_ptr, directory_entry *dir_ptr, unsigned char make_dir );
static unsigned char	update_directory_entry( fs_FILE *fp );
static unsigned char	remove_this_entry( unsigned short base_cluster, unsigned short index, unsigned char flags, unsigned char *ep, unsigned short depth );
static unsigned short	count_free_cluster( void );
static unsigned short	find_free_cluster( unsigned short start_cluster );
static unsigned char	clear_FAT_chain( unsigned short cluster );
static unsigned char	valid_cluster( unsigned short cluster, volume_param *vpp );
static unsigned short	read_FAT( unsigned short current_cluster );
static unsigned short	write_FAT( unsigned short cluster, unsigned short value );
static unsigned short	flush_FAT_cache( volume_param *vpp );
static unsigned short	flush_FAT16_cache( volume_param *vpp );
static unsigned short	flush_FAT12_cache( volume_param *vpp );
static unsigned short	access_FAT16( unsigned char mode, unsigned short cluster, unsigned short value );
static unsigned short	access_FAT12( unsigned char mode, unsigned short cluster, unsigned short value );
static unsigned long	cluster_to_sector( unsigned short cluster );
static directory_entry	*find_entry( char *path );
static directory_entry	*find_file_entry( char *path, unsigned short *dir_cluster_ptr, unsigned short *index_ptr );
static directory_entry	*find_directory_index( unsigned short *found_index, unsigned short base_cluster, char *name );
static directory_entry	*find_free_directory_entry( unsigned short *found_index, unsigned short base_cluster, char *name );
static directory_entry	*get_directory_entry( unsigned short base_cluster, unsigned short index, unsigned char new_entry_ok );
static void				write_back_directory_entry( void );

static void				set_time_for_directory_entry( directory_entry *d );
static unsigned char	format_file_name_directory_entry( char *target_base, char *source );
static unsigned char	str_match( char *a, char *b, unsigned char n );
static void				make_full_path( char *target, char *relative, char *current );
static char				*reform_path( char *source );
static void				separate_directory_and_file( char *directory_path, char *file_name, char *source );
static unsigned short	first_char_position( char *path, char mc );
static unsigned short	last_char_position( char *path, char mc );


/****************************************************************************/
/*	function definitions													*/
/****************************************************************************/


/*
==============================================================================
==============================================================================
====	Public functions for file system access
====		Functions for APPLICATION side
==============================================================================
==============================================================================
*/

//////////
//////////	"cd" change directory
//////////
unsigned char fs_cd( char *path )
{
	char				full_path[ MAX_PATH_STRING_LENGTH ];
	directory_entry		*dp;
	volume_param		*vpp;
	
	vpp				= &g_volume_parameter;

	if ( NULL == (dp		= find_entry( path )) )
		return ( error );

	if ( !(dp->attributes & 0x10) )
		return ( error );

	make_full_path( full_path, path, vpp->current_dir );

#if BIG_ENDIAN
	vpp->current_directory_cluster	= swap16( dp->cluster );	
#else
	vpp->current_directory_cluster	= dp->cluster;	
#endif

	fs_data_copy( (unsigned char *)(vpp->current_dir), (unsigned char *)full_path, MAX_PATH_STRING_LENGTH );

	return ( no_error );
}


//////////
//////////	"pwd" working directory name
//////////
void fs_pwd( char *pwd_str )
{
	volume_param		*vpp;
	
	vpp				= &g_volume_parameter;

	fs_data_copy( (unsigned char *)pwd_str, (unsigned char *)(vpp->current_dir), MAX_PATH_STRING_LENGTH );
}


//////////
//////////	"ls" get list
//////////
unsigned char fs_ls( char *path, directory_entry *dir, unsigned short entries )
{
	fs_FILE				*fp;
	char				full_path[ MAX_PATH_STRING_LENGTH ];
	unsigned char		*buffer_ptr_base;
	unsigned char		*buffer_ptr;
	volume_param		*vpp;
	unsigned short		i;
	unsigned short		count	= 0;
	
	vpp			= &g_volume_parameter;
	
	make_full_path( full_path, path, vpp->current_dir );

	if ( str_match( full_path, "/", 2 ) )
	{
		//	root directory
		
		entries		= (vpp->root_directory_entries < entries) ? vpp->root_directory_entries : entries;

		buffer_ptr_base	= g_fs_scratch_buffer_ptr;
	
		for ( i = 0; i < entries; i++ )
		{
			if ( !( i % ((vpp->bytes_per_cluster) / sizeof( directory_entry )) ) )
			{
				storage_read_sector( buffer_ptr_base, vpp->start_sector_root_directory + count++, vpp->sector_per_cluster );
				buffer_ptr	= buffer_ptr_base;
			}
			*dir++	= *((directory_entry *)buffer_ptr)++;
		}
	}
	else
	{
		unsigned short	l_read;
		unsigned short	n_read;
	
		if ( NULL == (fp	= fs_fopen( full_path, R | D )) )
		{
			return ( error );
		}	

		l_read	= sizeof( directory_entry ) * entries;
		
		if ( l_read != (n_read		= fs_read( fp, (unsigned char *)dir, l_read )) )
			*((unsigned char *)dir + n_read)	= 0;
		
		fs_fclose( fp );
	}
	
	return ( no_error );
}


//////////
//////////	"fopen" file open
//////////
fs_FILE *fs_fopen( char *path, unsigned char mode )
{
	fs_FILE				*fp;
	directory_entry		*dp;
	volume_param		*vpp;
	unsigned char		index;
	
	vpp				= &g_volume_parameter;

	//	to find open slot to register this open-file

	for ( index = 0; index < MAX_OPEN_FILES; index++ )
		if ( (vpp->opened_FILE_pointer)[ index ] == NULL )
			break;
	
	if ( index == MAX_OPEN_FILES )
	{
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : MAX_OPEN_FILES\r\n" );

		g_recent_error	= 2;
		return ( NULL );
	}

	//	allocate fs_FILE structure 

	if ( NULL == ( fp	= (fs_FILE *)malloc( sizeof( fs_FILE ) ) ) )
	{
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : malloc1\r\n" );

		g_recent_error	= 3;
		return ( NULL );
	}
	
	//	allocate file buffer (this works as a cache for the disk)
	
	if ( NULL == ( fp->cluster_buffer_pointer	= (unsigned char *)malloc( vpp->bytes_per_cluster ) ) )
	{
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : malloc2\r\n" );

		g_recent_error	= 4;
		free( fp );
		return ( NULL );
	}

	make_full_path( fp->path, path, vpp->current_dir );
	separate_directory_and_file( fp->path_to_dir, fp->file_name, fp->path );
	
	if ((mode & 0x01) == FS_WRITE)
	{
		//	if opening for "write", needed to be sure the parent directory exists
	
		if ( NULL == find_entry( fp->path_to_dir ) )
		{
			//	no parent directory
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : no parent directory\r\n" );
		
			g_recent_error	= 9;
			free( fp->cluster_buffer_pointer );
			free( fp );
			return ( NULL );
		}
	}
	
	dp	= find_file_entry( path, &(fp->directory_entry_cluster), &(fp->directory_entry_index) );

	if ( (dp->attributes & 0x10) && ((mode & 0x01) != FS_WRITE) )
	{
		if ( (mode & 0x08) != FS_OPN_DIR )
		{
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : FS_OPN_DIR\r\n" );
			g_recent_error	= 10;
			free( fp );
			return ( NULL );
		}
	}		
	
	if ( dp )
	{
		fs_data_copy( (unsigned char *)(&(fp->file_info)), (unsigned char *)dp, sizeof( directory_entry ) );

#if BIG_ENDIAN
		(fp->file_info).time		= swap16( (fp->file_info).time );
		(fp->file_info).date		= swap16( (fp->file_info).date );
		(fp->file_info).cluster		= swap16( (fp->file_info).cluster );
		(fp->file_info).size		= swap32( (fp->file_info).size );
#endif
		fp->start_cluster	= (fp->file_info).cluster;
	}
	else
	{
		fp->start_cluster	= 0;
	}

	fp->current_cluster					= 0;
	fp->buffered_cluster				= 0;
	fp->number_of_cluster_processed		= 0;
	fp->current_file_data_position		= 0;
	fp->volume_param_ptr				= vpp;
	fp->index							= index;
	fp->mode							= mode;
	
	(vpp->opened_FILE_pointer)[ index ]	= fp;

	if ((mode & 0x01) == FS_READ)
	{
		//	to open a file to READ

		if  ( !(fp->start_cluster) )
		{
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : FS_READ\r\n" );
	
			g_recent_error	= 5;
			free( fp );
			return ( NULL );
		}
	}
	else if ((mode & 0x01) == FS_WRITE)
	{
		//	to open a file to WRITE
	
		if  ( (fp->start_cluster) )
		{
			if ((mode & 0x02) == FS_PROTECT)
			{
				//	for when the over write PROTECTed
//mprintf( WHITE, CONTINUE, "\r\nerror @ fs_fopen : FS_PROTECT\r\n" );
				g_recent_error	= 5;
				free( fp );
				return ( NULL );
			}
			else
			{
				//	for OVERWRITE an existing file		
				fs_rm( fp->path, False );
			}
		}
		
		//	make directry entry for the file
		make_directory_entry_fp( fp );
		
		//	find an open cluster to write file data
		fp->start_cluster	= find_free_cluster( 2 );		//	find open cluster
		write_FAT( fp->start_cluster, 0xFFFF );

		flush_FILE_write_buffer( fp );
	}

	return ( fp );
}


//////////
//////////	"fclose" file close
//////////
void fs_fclose( fs_FILE *fp )
{
	if ( !storage_volume_ready() )
		return;
	
	if ( fp == NULL )
		return;
		
	if ( fp->mode != FS_READ )
	{
		flush_FILE_write_buffer( fp );
		flush_FAT_cache( (volume_param *)(fp->volume_param_ptr) );
		update_directory_entry( fp );
	}

	(((volume_param *)(fp->volume_param_ptr))->opened_FILE_pointer)[ fp->index ]	= NULL;
	
	free( fp->cluster_buffer_pointer );
	free( fp );
}


//////////
//////////	"read" file read
//////////

unsigned short fs_read( fs_FILE *fp, unsigned char *buffer_ptr, unsigned short length )
{
	unsigned short	size_of_pre_read;
	unsigned short	num_of_large_read_clusters;
	unsigned short	size_of_post_read;
	unsigned short	data_offset_in_cluster;
	unsigned short	read_clusters;
	unsigned short	size;
	unsigned short	size_of_total_read	= 0;
	unsigned long	remaining_file_size;

	volume_param	*vpp;

	vpp						= fp->volume_param_ptr;	


	//	calcurate file data size left
	
	if ( (fp->file_info).attributes & 0x10 )
		remaining_file_size		= vpp->bytes_per_cluster;	//	Possible problem : No bigger directory handling
	else
		remaining_file_size		= (fp->file_info).size - fp->current_file_data_position;

	//	limit file reading size to file size.
	//	to prevent over reading.

	length					= ((unsigned long)length < remaining_file_size) ? length : (unsigned short)remaining_file_size;

	if ( length < vpp->bytes_per_cluster )
	{
		size_of_pre_read			= length;
		num_of_large_read_clusters	= 0;
		size_of_post_read			= 0;
	}
	else
	{
		data_offset_in_cluster		= fp->current_file_data_position % vpp->bytes_per_cluster;
		size_of_pre_read			= data_offset_in_cluster ? (vpp->bytes_per_cluster - data_offset_in_cluster) : 0;
		length					   -= size_of_pre_read;
		
		if ( length < vpp->bytes_per_cluster )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -