Project

General

Profile

#include "pff_file.h"

#include "pff.h"
#include "utils.h"
#include "diskio.h"
#include "simplefile.h"
//#include "printf.h"
#include "regs.h"

struct SimpleFile * openfile;

void * dir_cache;
int dir_cache_size;

FATFS fatfs;
DIR dir;
FILINFO filinfo;

int write_pending;

#define translateStatus(res) (res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL)
#define translateDStatus(res) (res == RES_OK ? SimpleFile_OK: SimpleFile_FAIL)

/*
enum SimpleFileStatus translateStatus(FRESULT res)
{
return res == FR_OK ? SimpleFile_OK: SimpleFile_FAIL;
}

enum SimpleFileStatus translateDStatus(DSTATUS res)
{
return res == RES_OK ? SimpleFile_OK: SimpleFile_FAIL;
}*/

char const * file_of(char const * path)
{
char const * start = path + strlen(path);
while (start!=path)
{
--start;
if (*start == '/')
{
++start;
break;
}
}
return start;
}

void dir_of(char * dir, char const * path)
{
char const * end = file_of(path);
if (end != path)
{
int len = end-path;
while (len--)
{
*dir++ = *path++;
}
--dir;
}

*dir = '\0';
return;
}

char const * file_name(struct SimpleFile * file)
{
return file_of(&file->path[0]);
}

char const * file_path(struct SimpleFile * file)
{
return &file->path[0];
}

void file_init(struct SimpleFile * file)
{
file->path[0] = '\0';
file->is_readonly = 1;
file->size = 0;
}

void file_check_open(struct SimpleFile * file)
{
if (openfile!=file)
{
file_write_flush();

*zpu_uart_debug2=0x83;
pf_open(&file->path[0]);
*zpu_uart_debug2=0x93;
openfile = file;
}
}

enum SimpleFileStatus file_read(struct SimpleFile * file, void * buffer, int bytes, int * bytesread)
{
UINT bytesread_word;
FRESULT res;

file_write_flush();
file_check_open(file);

res = pf_read(buffer, bytes, &bytesread_word);
*bytesread = bytesread_word;

return translateStatus(res);
}

enum SimpleFileStatus file_write(struct SimpleFile * file, void * buffer, int bytes, int * byteswritten)
{
UINT byteswritten_word;
FRESULT res = FR_OK;

//printf("went\n");
if (file->is_readonly) return SimpleFile_FAIL;

file_check_open(file);

int rem = bytes;
while (rem>0)
{
int sector = fatfs.fptr>>9;
int pos = fatfs.fptr&0x1ff;

int bytes_this_cycle = rem;
if (bytes_this_cycle>(512-pos))
bytes_this_cycle = 512-pos;

//printf("file_write:%d/%d - %d/%d\n",sector,pos,bytes_this_cycle,bytes);

if (sector != write_pending)
{
file_write_flush();
}

if (write_pending <0)
{
// read the sector into our 512 byte buffer...
pf_lseek(sector<<9);
int fptr = fatfs.fptr;

char temp_buffer[1];
pf_read(&temp_buffer[0], 1, &byteswritten_word);

//printf("Writing initial pos:%d\n",pos);

// seek to the initial pos
fatfs.fptr = fptr + pos;

write_pending = sector;
}

res = disk_writep(buffer, pos, bytes_this_cycle);

fatfs.fptr += bytes_this_cycle;
rem-=bytes_this_cycle;
buffer+=bytes_this_cycle;
}
*byteswritten = bytes;

//printf("wend\n");
return translateStatus(res);
}

enum SimpleFileStatus file_write_flush()
{
if (write_pending >= 0)
{
//printf("wflush\n");
disk_writeflush();
write_pending = -1;
}
return SimpleFile_OK;
}

enum SimpleFileStatus file_seek(struct SimpleFile * file, int offsetFromStart)
{
FRESULT res;

int location = offsetFromStart>>9;
if (write_pending >=0 && write_pending != offsetFromStart)
{
//printf("flush on seek\n");
*zpu_uart_debug2 = 0x43;
*zpu_uart_debug3 = write_pending;
file_write_flush();
}

*zpu_uart_debug2 = 0x53;

file_check_open(file);

*zpu_uart_debug2 = 0x63;

res = pf_lseek(offsetFromStart);

*zpu_uart_debug2 = 0x73;

return translateStatus(res);
}

int file_size(struct SimpleFile * file)
{
return file->size;
}

int file_readonly(struct SimpleFile * file)
{
return file->is_readonly;
}

int file_struct_size()
{
return sizeof(struct SimpleFile);
}

enum SimpleFileStatus file_open_name_in_dir(struct SimpleDirEntry * entry, char const * filename, struct SimpleFile * file)
{
file_write_flush();

while (entry)
{
//printf("%s ",entry->filename_ptr);
if (0==stricmp(filename,entry->filename_ptr))
{
return file_open_dir(entry, file);
}
entry = entry->next;
}

return SimpleFile_FAIL;
}

enum SimpleFileStatus file_open_name(char const * path, struct SimpleFile * file)
{
char dirname[MAX_DIR_LENGTH];
char const * filename = file_of(path);
dir_of(&dirname[0], path);

file_write_flush();

//printf("filename:%s dirname:%s ", filename,&dirname[0]);

struct SimpleDirEntry * entry = dir_entries(&dirname[0]);
return file_open_name_in_dir(entry,filename, file);
}

enum SimpleFileStatus file_open_dir(struct SimpleDirEntry * dir, struct SimpleFile * file)
{
FRESULT res;

strcpy(&file->path[0],dir->path);
file->is_readonly = dir->is_readonly;
file->size = dir->size;

file_write_flush();

res = pf_open(&file->path[0]);
openfile = file;

return translateStatus(res);
}

enum SimpleFileStatus dir_init(void * mem, int space)
{
FRESULT fres;
DSTATUS res;

write_pending = -1;

//printf("dir_init\n");

dir_cache = mem;
dir_cache_size = space;

//printf("disk_init go\n");
res = disk_initialize();
//printf("disk_init done\n");
if (res!=RES_OK) return translateDStatus(res);

//printf("pf_mount\n");
fres = pf_mount(&fatfs);
//printf("pf_mount done\n");

return translateStatus(fres);
}

// Read entire dir into memory (i.e. give it a decent chunk of sdram)
struct SimpleDirEntry * dir_entries(char const * dirPath)
{
return dir_entries_filtered(dirPath,0);
}

int dircmp(struct SimpleDirEntry * a, struct SimpleDirEntry * b)
{
if (a->is_subdir==b->is_subdir)
return strcmp(a->lfn,b->lfn);
else
return a->is_subdir<b->is_subdir;
}

void sort_ll(struct SimpleDirEntry * h)
{
//struct SimpleDirEntry
//{
// char path[MAX_PATH_LENGTH];
// char * filename_ptr;
// int size;
// int is_subdir;
// struct SimpleDirEntry * next; // as linked list - want to allow sorting...
//};

struct SimpleDirEntry * p,*temp,*prev;
int i,j,n,sorted=0;
temp=h;
prev=0;
for(n=0;temp!=0;temp=temp->next) n++;

for(i=0;i<n-1 && !sorted;i++){
p=h;sorted=1;
prev=0;
for(j=0;j<n-(i+1);j++){
// printf("p->issubdir:%d(%s) p->next->issubdir:%d(%s)",p->is_subdir,p->path,p->next->is_subdir,p->next->path);

if(dircmp(p,p->next)>0) {
// printf("SWITCH!\n");
struct SimpleDirEntry * a = p;
struct SimpleDirEntry * b = p->next;
a->next=b->next;
b->next=a;
if (prev)
prev->next=b;
p=b;

sorted=0;
}
prev=p;
p=p->next;
}
}

//temp=h;
//for(n=0;temp!=0;temp=temp->next) printf("POST:%s\n",temp->path);
}

struct SimpleDirEntry * dir_entries_filtered(char const * dirPath,int(* filter)(struct SimpleDirEntry *))
{
int room = dir_cache_size/sizeof(struct SimpleDirEntry);

file_write_flush();

//printf("opendir ");
if (FR_OK != pf_opendir(&dir,dirPath))
{
//printf("FAIL ");
return 0;
}
//printf("OK ");

struct SimpleDirEntry * prev = (struct SimpleDirEntry *)dir_cache;
strcpy(prev->path,"..");
strcpy(prev->lfn,"..");
prev->filename_ptr = prev->path;
prev->size = 0;
prev->is_subdir = 1;
prev->is_readonly = 1;
prev->next = 0;
--room;

//int count=0;
struct SimpleDirEntry * entry = prev + 1;
while (room && FR_OK == pf_readdir(&dir,&filinfo) && filinfo.fname[0]!='\0')
{
char * ptr;

if (filinfo.fattrib & AM_SYS)
{
continue;
}
if (filinfo.fattrib & AM_HID)
{
continue;
}

//printf("next %x %d ",entry,room);

entry->is_subdir = (filinfo.fattrib & AM_DIR) ? 1 : 0;
entry->is_readonly = (filinfo.fattrib & AM_RDO) ? 1 : 0;

//printf("%s ",filinfo.fname);

strcpy(&entry->path[0],dirPath);
ptr = &entry->path[0];
ptr += strlen(&entry->path[0]);
*ptr++ = '/';
entry->filename_ptr = ptr;
strcpy(ptr,filinfo.fname);
entry->size = filinfo.fsize;

//printf("LFN:%s\n",&filinfo.lfname[0]);
strcpy(&entry->lfn[0],&filinfo.lfname[0]);

//int count;
//printf("%d %s %s\n",count++, filinfo.fname, filinfo.lfname);


if (filter && !filter(entry))
{
continue;
}

entry->next = 0;

if (prev)
prev->next = entry;
prev = entry;
entry++;
room--;

//printf("n %d %d %x ",filinfo.fsize, entry->size, entry->next);
}

//printf("dir_entries done ");

/*struct SimpleDirEntry * begin = (struct SimpleDirEntry *) dir_cache;
int count = 0;
while (begin)
{
printf("%d %s\n",count++, begin->path);
begin = begin->next;
}*/

if (filter)
{
sort_ll((struct SimpleDirEntry *) dir_cache);
}
return (struct SimpleDirEntry *) dir_cache;
}

char const * dir_path(struct SimpleDirEntry * entry)
{
return &entry->path[0];
}

char const * dir_filename(struct SimpleDirEntry * entry)
{
//return entry->filename_ptr;
return &entry->lfn[0];
}

int dir_filesize(struct SimpleDirEntry * entry)
{
return entry->size;
}

struct SimpleDirEntry * dir_next(struct SimpleDirEntry * entry)
{
return entry->next;
}

int dir_is_subdir(struct SimpleDirEntry * entry)
{
return entry->is_subdir;
}


(4-4/6)