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

📄 ffs.c

📁 Source Code for the Flash Audio Head Unit Player
💻 C
📖 第 1 页 / 共 2 页
字号:
{
	static char name83[12];		   
	int cnt;
	char *p,c;

	// copy name portion of filename, converting case
	cnt=0;
	p=filename;
	while(cnt<8)
	{
		c=*p;
		if(c=='.' || c==0)
			break;
		name83[cnt++]=toupper(c);
		p++;
	}

	// pad name out with spaces
	while(cnt<8)
		name83[cnt++]=' ';

	// copy extension portion of filename, converting case
	if(*p++=='.')
	{
		while(cnt<11)
		{
			c=*p;
			if(c==0)
				break;
			name83[cnt++]=toupper(c);
			p++;
		}
	}

	// pad extension out with spaces
	while(cnt<11)
		name83[cnt++]=' ';

	name83[11]=0;

	return name83;
}

bool  dir_findbyname(char *filename)
{
	char *name = __create_83_name(filename);

#ifdef CCD_DEBUG
	char tmp[12];

	mprintf("Open %s\n",name);

#endif


	if (dir_examine(FILE_USED))
	{
	
		do
		{
		    
			if (de_cur.Attr != ATTR_LONG_NAME)
			{
#ifdef CCD_DEBUG
				memcpy(tmp,de_cur.Name,11);
				tmp[11]=0;
				mprintf("Scan %s\n",tmp);
#endif
			    // We stop at first match, only comparing at strlen(filename) maxed at 11
				if (!(strncmp(name,	de_cur.Name,	11	)))
				{
					return TRUE;
				}
			}
		}
		while (dir_next(FILE_USED));
	}

	return FALSE;
}
 

//
//
// ****************** LV6 - P O S I X   L I B   P R O T O S ******************
//
//

static inline bool  __h_in_use(u8 handle)
{
	// Limit collateral damages in case of wrong handle
	if (handle >= MAX_FILES) return FALSE;

	return __files[handle].inuse;
}

static u8  __h_findfree(void)
{
	u8 hnum;

	for (hnum = 0 ; (hnum < MAX_FILES) && (__h_in_use(hnum)) ; ++hnum);

	return hnum;
}

s8  close(u8 handle)
									/* Close file handle
										Parameter
											handle	Handle referring to open file

										Returns
											0 if the file was successfully closed.
											A return value of -1 indicates an error,
											in which case errno is set to EBADF,
											indicating an invalid file-handle parameter.
									*/
{
#ifdef CCD_DEBUG
	mprintf("close %d",handle);
#endif

	if (!(__h_in_use(handle)))	return -1;

	__files[handle].inuse = FALSE;

#ifdef CCD_DEBUG
	mprintf("close() OK");
#endif

	return 0;
}


s8  eof(u8 handle)
									/* Tests for end-of-file.
										Parameter
											handle	Handle referring to open file

										Returns
											1 if the current position is end of file,
											or 0 if it is not. A return value of -1
											indicates an error; in this case, errno
											is set to EBADF, which indicates an invalid
											file handle.
									*/
{
	if (!(__h_in_use(handle)))	return -1;

	if (__files[handle].pos + 1 > __files[handle].size) return 1;

	return 0;
}

s8  open(char *filename, u8 oflag, u8 pmode)
									/* Open a file.
										Parameters
											filename	Filename
											oflag		Type of operations allowed
											pmode		Permission mode

										Returns
											Returns a file handle for the opened file.
											A return value of -1 indicates an error,
											in which case errno is set to one of the following
											values:
												EACCES	Tried to open read-only file for
														writing, or file抯 sharing mode does
														not allow specified operations, or
														given path is directory
												EEXIST	O_CREAT and O_EXCL flags specified,
														but filename already exists
												EINVAL	Invalid oflag or pmode argument
												EMFILE	No more file handles available
														(too many open files)
												ENOENT	File or path not found

											oflag is an integer expression formed from one
											or more of the following manifest constants
											or constant combinations :
												O_APPEND	Moves file pointer to end of
														file before every write operation.
												O_CREAT		Creates and opens new file for
														writing. Has no effect if file
														specified by filename exists. pmode
														argument is required when O_CREAT is
														specified.
												O_CREAT | O_EXCL	Returns error value
														if file specified by filename
														exists. Applies only when used
														with O_CREAT.
												O_RDONLY	Opens file for reading only;
														cannot be specified with O_RDWR
														or O_WRONLY.
												O_RDWR	Opens file for both reading and
														writing; you cannot specify this
														flag with O_RDONLY or O_WRONLY.
												O_TRUNC	Opens file and truncates it to zero
														length; file must have write
														permission. You cannot specify this
														flag with O_RDONLY. O_TRUNC used
														with O_CREAT opens an existing file
														or creates a new file.
														Warning   The O_TRUNC flag destroys
														the contents of the specified file.
												O_WRONLY	Opens file for writing only;
														cannot be specified with O_RDONLY
														or O_RDWR.

											To specify the file access mode, you must specify
											either O_RDONLY, O_RDWR, or O_WRONLY. There is no
											default value for the access mode.

											The pmode argument is required only when O_CREAT
											is specified. If the file already exists, pmode
											is ignored. Otherwise, pmode specifies the file
											permission settings, which are set when the new
											file is closed the first time. open applies the
											current file-permission mask to pmode before
											setting the permissions (for more information,
											see umask). pmode is an integer expression
											containing one or both of the following manifest
											constants :
												S_IREAD		Reading only permitted
												S_IWRITE	Writing permitted (effectively
													permits reading and writing)
												S_IREAD | S_IWRITE	Reading and writing
													permitted
									*/
{
	// Find a free handle
	u8 handle = __h_findfree();
	file_handle *fd = &(__files[handle]);
	u32 curlba,next_lba;

	// Check if file already exists
	bool bexist;

#ifdef CCD_DEBUG
	mprintf("open(%s mode %d)\n\r",filename,oflag);
#endif

	bexist = dir_findbyname(filename);

	// If no more handle available then error EMFILE
	if (handle >= MAX_FILES) return -1;

	// If asked to create a new file which already exists, error
	if (bexist && (oflag & O_CREAT) && (oflag & O_EXCL)) return -1;

	// If asked to truncate a file without write permission, error
	if (bexist && (oflag & O_TRUNC) && (pde_cur -> Attr & ATTR_READ_ONLY)) return -1;

	// If asked to create or truncate, error
	if ((oflag & O_CREAT) || (oflag & O_TRUNC)) return -1;

	// Now we are left with O_APPEND, O_RDONLY, O_RDWR. File must exist.
	if (!bexist) return -1;

	// If asked for meaningless combinations of RDWR, WRONLY and RDONLY then error
	if ((oflag & O_RDWR)	&& (oflag & O_RDONLY)) return -1;
	if ((oflag & O_RDWR)	&& (oflag & O_WRONLY)) return -1;
	if ((oflag & O_RDONLY)	&& (oflag & O_WRONLY)) return -1;

	// Everything is OK, open file
	fd -> size = peekl((u16)((char *)&pde_cur->FileSize - (char*)sector));
	fd -> clust = peekw((u16)((char *)&pde_cur->FstClusLO - (char*)sector));
	fd -> pos = (oflag & O_APPEND ? pde_cur -> FileSize : 0);
	fd -> mode = oflag & (O_RDWR | O_WRONLY | O_RDONLY);
	fd -> inuse = TRUE;
	fd -> dirlba = lba_tmpdir;
	fd -> dirptr = pde_cur;
	fd -> curlba = clust2lba(fd -> clust);

	// Scan for contigous clusters
	curlba = fd->curlba;
	fd->sector_rl=0;			
	next_lba=clust_nextlba(curlba);
	while(next_lba && (next_lba == curlba+1))
	{
		fd->sector_rl++;
		curlba=next_lba;
		next_lba=clust_nextlba(curlba);
	}

	return handle;
}

long  lseek(u8 handle, s32 offset, u8 origin)
									/* Move a file pointer to the specified location.
										Parameters
											handle	Handle referring to open file
											offset	Number of u8s from origin
											origin	Initial position
											origin argument must be one of the following
											constants :
												SEEK_SET	Beginning of file
												SEEK_CUR	Current position of file pointer
												SEEK_END	End of file

										Returns
											the offset, in u8s, of the new position from
											the beginning of the file. Returns -1L to
											indicate an error and sets errno either to EBADF,
											meaning the file handle is invalid, or to EINVAL,
											meaning the value for origin is invalid or the
											position specified by offset is before the
											beginning of the file.
									*/
{
	file_handle *fd = &(__files[handle]);
	u16 clust, clustcnt;
	u8 secoff;

	if (!(__h_in_use(handle)))	return -1;

	// Recalculate the offset from the start of the file
	switch(origin)
	{
		default:
			return -1;

		case SEEK_SET:
			break;

		case SEEK_CUR :	//	Current position of file pointer
			offset += fd -> pos;
			break;

		case SEEK_END :	//	End of file
			offset = fd -> size - 1 + offset;
			break;
	}

	// Process special offsets
	if (offset > fd -> size ) return -1;

	if (offset == fd -> pos)
		return offset;


	// Update current pos
	fd -> pos = offset;

	// Calculate cluster / sector number of new pos
	clustcnt =  offset / hd1_geom_clustsize;
	secoff = (u8) ((offset % hd1_geom_clustsize) / (u32) BLOCKSIZE);

	// Update current LBA
	clust = fd -> clust;
	while ((clustcnt--) && (clust < CLUSTCHAIN_END)) clust = clust_next(clust);

	if (clust < CLUSTCHAIN_END)
	{
	
		fd -> curlba = clust2lba(clust) + secoff;
	}
	else
		fd->curlba = 0; // flag for extending chain

	return offset;
}

s16  read(u8 handle, u8 *buffer, u16 count)
									/* Reads data from a file.
											Parameters
												handle	Handle referring to open file
												buffer	Storage location for data
												count	Maximum number of u8s

											Returns
												the number of u8s read, which may be less
												than count if there are fewer than count u8s
												left in the file.
												If the function tries to read at end of file,
												it returns 0. If the handle is invalid, or the
												file is not open for reading, the function
												returns -1 and sets errno to EBADF.
									*/
{
	file_handle *fd = &(__files[handle]);

	u16
		offset_start = (u16) (fd -> pos & (BLOCKSIZE-1)),
		u8s_read = 0,
		u8s_toread,
		u8s_leftinsec;

	if (!(__h_in_use(handle)))	return -1;

	// If asked to read from a non read file then error
	if (!((fd -> mode & O_RDWR) || (fd -> mode & O_RDONLY)))	return -1;

	while ((u8s_read < count) && !(eof(handle)))
	{
		// Read in the file current sector
		sec_get(&(fd -> curlba));

		// 1 - calculate how many u8s are left in the current sector
		u8s_leftinsec = BLOCKSIZE - offset_start;

		// 2 - calculate how many u8s we can thus read in the current sector
		u8s_toread = min(count - u8s_read, u8s_leftinsec);


		// 3 - read these u8s in the user buffer
		memcpy(buffer+u8s_read, sector+offset_start,u8s_toread);

		// 4 - increment the read u8s counter
		u8s_read += u8s_toread;

		// 5 - if necessary go to next sector
		if (u8s_toread == u8s_leftinsec)
		{
			if(fd->sector_rl)
			{	 
				fd->sector_rl--;
				fd->curlba++;
			}
			else
			{
			    
				fd -> curlba = clust_nextlba(fd -> curlba);
			}
		}

		// 6 - zero offset_start, which is only useful in 1st pass
		offset_start = 0;
	}

	// Adjust file pos
	fd -> pos += u8s_read;

	return u8s_read;
}

//
// read N sectors. file position must be aligned on sector offset
// 
s16 read_sectors(u8 handle,u8 *buffer,u16 sectors)
{
	file_handle *fd = &(__files[handle]);
   	u16 actual;

	if (!(__h_in_use(handle)))	return -1;

	// If asked to read from a non read file then error
	if (!((fd -> mode & O_RDWR) || (fd -> mode & O_RDONLY)))	return -1;

	if(fd->pos & 511) return -1;

	actual=0;

	while(!eof(handle) && sectors!=0)
	{
	  mmc_SectorRead(buffer,fd -> curlba);	   	

	  fd->pos+=512;
  	  buffer+=512;
	  sectors--;
	  actual++;

	  if(fd->sector_rl)
			{	 
      		
				fd->sector_rl--;
				fd->curlba++;
			}
			else
			{
			    
				fd -> curlba = clust_nextlba(fd -> curlba);
			}
   }

	return actual;	  
}

//
// count number of directories, or seek to a particular directory index
//
s16 scan_dirs(int no,char *dirname)
{
	s16 count=0;

	// back to root directory
	lba_curdir = lba_rd;
	strcpy(dirname,"TOP");

	if(!no)
		return 0;

	if (dir_examine(FILE_USED))
	{
	
		do
		{
				if(de_cur.Attr & ATTR_DIRECTORY)
				{
					if(++count==no)
					{
						if(dirname!=NULL)
						{
 							memcpy(dirname,&de_cur.Name[0],11);
							dirname[11]=0;
						}

						// change current directory
						lba_curdir = clust2lba(peekw((u16)((char *)&pde_cur->FstClusLO - (char*)sector)));

						return count;
					}
				}
		
		}
		while (dir_next(FILE_USED));
	}

  	return count;
}

//
// count number of tracks within a given directory, or seek to a particular track
//
s16 scan_tracks(int dirno,int fileno,char *filename,char *dirname)
{
	s16 count=0;
	int i;

	// scan to appropriate directory
	if(scan_dirs(dirno,dirname)!=dirno)	
	{
			return -1; // not found
	}
	
	if (dir_examine(FILE_USED))
	{
		do
		{
			if (de_cur.Attr != ATTR_LONG_NAME && (!(de_cur.Attr & ATTR_DIRECTORY)))
			{
				if(!strncmp("WAV", &de_cur.Name[8], 3))
				{
					if(++count == fileno)
					{
					 if(filename!=NULL)
					 {
					    memcpy(filename, &de_cur.Name[0], 11);
					    filename[11]=0;

					    // convert name back to standard filename convention
					    for(i=7; i>0; i--)
						{
							if(filename[i]!=' ')
								break;
						}
		
						filename[i+1]=0;
		
						strcat(filename, ".WAV");

					 }
					 return count;
					}		
				}
			}
		}
		while (dir_next(FILE_USED));
	}

	return count;
   	
}

#endif

⌨️ 快捷键说明

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