47 #define FILESIZE_MAX 100 48 #define MAX_PATH_LEN 64 52 #define TPS_DIRECTORY "tps/" 53 #define MAX_WRITES_IN_PERIOD 64 54 #define WRITE_PERIOD_DAYS 28 59 #define DBG_PRINT(x) DBG_PRINTF x 60 #define DBG_TPS(x) do { DBG_PRINTF("%s: ", __func__); DBG_PRINTF x; } while (0) 72 typedef struct s_TruePersistentFile
83 struct s_TruePersistentFile *next;
84 struct s_TruePersistentFile *previous;
85 } t_TruePersistentFile;
90 static t_TruePersistentFile *file_list_head = NULL;
91 static t_TruePersistentFile *file_list_tail = NULL;
92 static U16BIT file_count = 0;
93 static BOOLEAN init = FALSE;
95 static MHEG5Bool TPS_enabled = MHEG5TRUE;
103 static BOOLEAN TPS_StorageRead(
S_STRING filename,
void **data, U32BIT *data_len);
104 static BOOLEAN TPS_StorageWrite(
S_STRING filename,
void *data, U32BIT data_len);
105 static E_MhegErr TPS_StorageOpen();
106 static void TPS_StorageClose(
void);
107 static BOOLEAN TPS_StorageGetEnabled();
109 static void FreeFile(t_TruePersistentFile *file);
110 static void DeleteFile(t_TruePersistentFile *file);
111 static void ClearCache();
112 static BOOLEAN AddFileToList(t_TruePersistentFile *file);
113 static BOOLEAN LoadFile(
char *filename);
114 static t_TruePersistentFile* FindFileByName(
S_STRING filename);
115 static BOOLEAN DeleteFileByService(
pS_DvbLocator service_info);
116 static BOOLEAN DeleteOldFile();
119 static MHEG5Bool WriteFileToStore( t_TruePersistentFile *out_file);
120 static t_TruePersistentFile* NewFile(
S_STRING filename,
void *data, MHEG5Int len,
123 static t_TruePersistentFile* OverwriteFileEntry(
void *data, MHEG5Int len,
125 t_TruePersistentFile *replaced_file);
127 static t_TruePersistentFile* UpdateFileEntry(t_TruePersistentFile *file,
void *data, MHEG5Int len,
130 static U32BIT Read32Bits(U8BIT *bytes);
131 static void Store32Bits(U8BIT *bytes, U32BIT value);
132 static U16BIT Read16Bits(U8BIT *bytes);
133 static void Store16Bits(U8BIT *bytes, U16BIT value);
146 current_service = *pDvbLoc;
161 filename.zptr = fn.data;
162 filename.zlen = fn.len;
164 DBG_TPS((
"reading:%.*s\n", (
int)fn.len, fn.data));
165 if (filename.zlen && filename.zlen < 9)
167 rc = TPS_StorageRead(filename, data, (U32BIT *)len);
173 DBG_TPS((
"read:\n"));
174 for (i = 0; i < *len; i++)
176 DBG_PRINT((
"0x%x ", ((U8BIT *)*data)[i]));
198 MHEG5Bool success = MHEG5FALSE;
201 if (len <= FILESIZE_MAX)
206 DBG_TPS((
"writing:%.*s\n", (
int)fn.len, fn.data));
207 DBG_TPS((
"writing:\n"));
208 for (i = 0; i < len; i++)
210 DBG_PRINT((
"0x%x ", ((U8BIT *)data)[i]));
214 filename.zptr = fn.data;
215 filename.zlen = fn.len;
216 if (filename.zlen && filename.zlen < 9)
218 rc = TPS_StorageWrite(filename, data, len);
237 if (TPS_StorageGetEnabled())
265 static void MHEG5NotifyTpsFilesChanged(
void *dummy)
267 USE_UNWANTED_PARAM(dummy);
278 E_MhegErr MHEG5_NotifyNvmFilesChanged(
void)
281 event_msg.proc_msg_func = MHEG5NotifyTpsFilesChanged;
282 event_msg.data_type = DT_VALUE;
283 return VQ_PutMsg(&event_msg, PRTY_NORMAL);
294 static BOOLEAN TPS_StorageRead(
S_STRING filename,
void **data, U32BIT *data_len)
296 t_TruePersistentFile *file_entry;
304 file_entry = FindFileByName(filename);
307 *data = file_entry->file_data;
308 *data_len = file_entry->file_len;
325 static BOOLEAN TPS_StorageWrite(
S_STRING filename,
void *data, U32BIT data_len)
327 t_TruePersistentFile *replaced_file;
328 t_TruePersistentFile *updated_file;
329 BOOLEAN write = TRUE;
330 BOOLEAN check_service = TRUE;
331 BOOLEAN success = FALSE;
342 DBG_TPS((
"current service_id 0x%x\n", current_service.service_id));
344 replaced_file = FindFileByName(filename);
348 DBG_TPS((
"File exists\n"));
349 if (replaced_file->write_date >= day - WRITE_PERIOD_DAYS)
351 replaced_file->num_writes = 0;
354 if (replaced_file->num_writes >= MAX_WRITES_IN_PERIOD)
357 DBG_TPS((
"Warning: File has been written too many times\n"));
362 else if (ServicesEqual(¤t_service, &replaced_file->service_info))
364 check_service = FALSE;
368 if (write && check_service)
371 DeleteFileByService(¤t_service);
374 if (write && file_count == MAX_FILES)
376 DBG_TPS((
"Store full, deleting old files\n"));
378 if (file_count == MAX_FILES)
388 updated_file = OverwriteFileEntry(data, data_len, ¤t_service, day, replaced_file);
392 updated_file = NewFile(filename, data, data_len, ¤t_service, day);
394 if (WriteFileToStore( updated_file ))
408 static void FreeFile(t_TruePersistentFile *file)
414 MHEG5freeMem(file->file_path);
418 MHEG5freeMem(file->file_data);
428 static void DeleteFile(t_TruePersistentFile *file)
434 file->next->previous = file->previous;
438 file_list_tail = file->previous;
444 file->previous->next = file->next;
448 file_list_head = file->next;
459 static void ClearCache(
void)
461 t_TruePersistentFile *current;
462 t_TruePersistentFile *next;
464 current = file_list_head;
468 next = current->next;
472 file_list_head = NULL;
473 file_list_tail = NULL;
494 static BOOLEAN AddFileToList(t_TruePersistentFile *file)
496 t_TruePersistentFile *current;
498 if (file_list_tail == NULL)
500 file_list_tail = file;
501 file_list_head = file;
505 current = file_list_tail;
508 if (file->write_date >= current->write_date)
510 file->previous = current;
511 file->next = current->next;
514 current->next->previous = file;
515 current->next = file;
519 file_list_tail = file;
520 current->next = file;
526 current = current->previous;
531 file_list_head->previous = file;
532 file->next = file_list_head;
533 file_list_head = file;
543 static BOOLEAN LoadFile(
char *filename)
546 t_TruePersistentFile *new_file;
552 BOOLEAN success = FALSE;
555 full_path = MHEG5getMem(strlen(TPS_DIRECTORY) + strlen(filename) + 1);
557 memcpy(full_path, (
char *)TPS_DIRECTORY, strlen(TPS_DIRECTORY) + 1);
558 strncat(full_path, filename, strlen(filename) + 1);
560 DBG_TPS((
"Loading File %s\n", filename));
562 new_file = MHEG5getMem(
sizeof(t_TruePersistentFile));
564 new_file->previous = NULL;
565 new_file->next = NULL;
566 new_file->num_writes = 0;
567 new_file->write_date = 0;
568 new_file->file_path = full_path;
569 new_file->filename = (U8BIT *)full_path + strlen(TPS_DIRECTORY);
570 new_file->filename_len = strlen(filename);
575 if (file_size >= HEADER_SIZE)
582 data = MHEG5getMem(file_size);
587 service_info = &new_file->service_info;
589 service_info->original_network_id = Read16Bits(data + offset);
591 service_info->service_id = Read16Bits(data + offset);
594 service_info->transport_stream_id = 0;
596 new_file->num_writes = *(data + offset);
598 new_file->write_date = Read32Bits(data + offset);
601 new_file->file_len = file_size - offset;
602 new_file->file_data = MHEG5getMem(new_file->file_len);
603 if (new_file->file_data)
605 memcpy(new_file->file_data, data + offset, new_file->file_len);
606 success = AddFileToList(new_file);
615 MHEG5freeMem(new_file);
616 MHEG5freeMem(full_path);
622 static U32BIT Read32Bits(U8BIT *bytes)
637 static void Store32Bits(U8BIT *bytes, U32BIT value)
639 bytes[0] = value & 0xFF;
640 bytes[1] = (value >> 8) & 0xFF;
641 bytes[2] = (value >> 16) & 0xFF;
642 bytes[3] = (value >> 24) & 0xFF;
645 static U16BIT Read16Bits(U8BIT *bytes)
656 static void Store16Bits(U8BIT *bytes, U16BIT value)
658 bytes[0] = value & 0xFF;
659 bytes[1] = (value >> 8) & 0xFF;
665 static E_MhegErr TPS_StorageOpen(
void)
668 char filename_buffer[MAX_PATH_LEN];
669 E_MhegErr retval = MHERR_OK;
670 E_STB_DIR_ENTRY_TYPE entry_type;
672 if (!init && TPS_enabled)
682 if (entry_type == DIR_ENTRY_FILE)
684 if (!LoadFile(filename_buffer))
686 retval = MHERR_OTHER;
700 static void TPS_StorageClose(
void)
714 static t_TruePersistentFile* FindFileByName(
S_STRING filename)
716 t_TruePersistentFile *file_entry;
717 file_entry = file_list_tail;
721 if (filename.zlen == file_entry->filename_len)
723 if (!memcmp(filename.zptr, file_entry->filename, filename.zlen))
728 file_entry = file_entry->previous;
739 static BOOLEAN DeleteOldFile(
void)
741 t_TruePersistentFile *current;
744 current = file_list_head;
754 current = current->next;
767 if (service_a->service_id != service_b->service_id)
771 else if (service_a->original_network_id != service_b->original_network_id)
785 static BOOLEAN DeleteFileByService(
pS_DvbLocator service_info)
787 t_TruePersistentFile *file_entry;
789 file_entry = file_list_head;
790 DBG_TPS((
"deleting files on service 0x%x\n", service_info->service_id));
793 if (ServicesEqual(service_info, &file_entry->service_info))
795 DeleteFile(file_entry);
799 file_entry = file_entry->next;
808 static MHEG5Bool WriteFileToStore( t_TruePersistentFile *out_file)
817 len += out_file->file_len;
819 file_data = MHEG5getMem(len);
822 Store16Bits(file_data + offset, out_file->service_info.original_network_id);
824 Store16Bits(file_data + offset, out_file->service_info.service_id);
826 memcpy(file_data + offset, &out_file->num_writes, 1);
828 Store32Bits(file_data + offset, out_file->write_date);
831 memcpy(file_data + offset, out_file->file_data, out_file->file_len);
833 filep =
STB_NVMOpenFile((U8BIT *) out_file->file_path, FILE_MODE_OVERWRITE);
858 static t_TruePersistentFile* NewFile(
S_STRING filename,
void *data, MHEG5Int len,
862 t_TruePersistentFile *new_file;
863 MHEG5Bool success = MHEG5FALSE;
866 new_file = MHEG5getMem(
sizeof(t_TruePersistentFile));
869 full_path = MHEG5getMem(strlen(TPS_DIRECTORY) + filename.zlen + 1);
879 strncat(full_path, TPS_DIRECTORY, strlen(TPS_DIRECTORY));
880 strncat(full_path, (
char *)filename.zptr, filename.zlen);
882 new_file->file_path = full_path;
883 new_file->filename = (U8BIT *)full_path + strlen(TPS_DIRECTORY);
884 new_file->filename_len = filename.zlen;
885 new_file->num_writes = 1;
886 new_file->write_date = today;
888 UpdateFileEntry(new_file, data, len, service);
898 static t_TruePersistentFile* OverwriteFileEntry(
void *data, MHEG5Int len,
900 t_TruePersistentFile *replaced_file)
902 MHEG5Bool success = MHEG5TRUE;
904 assert(replaced_file);
907 if (today <= replaced_file->write_date + WRITE_PERIOD_DAYS)
909 if (replaced_file->num_writes == MAX_WRITES_IN_PERIOD)
911 success = MHEG5FALSE;
915 replaced_file->num_writes++;
920 replaced_file->write_date = today;
921 replaced_file->num_writes = 1;
927 if (replaced_file->previous && replaced_file->next)
930 replaced_file->previous->next = replaced_file->next;
931 replaced_file->next->previous = replaced_file->previous;
933 else if (replaced_file->next)
936 replaced_file->next->previous = NULL;
938 else if (replaced_file->previous)
940 replaced_file->previous->next = NULL;
943 if (file_list_head == replaced_file)
945 file_list_head = replaced_file->next;
947 if (file_list_tail == replaced_file)
949 file_list_tail = replaced_file->previous;
953 MHEG5freeMem(replaced_file->file_data);
954 replaced_file->file_data = NULL;
955 replaced_file->file_len = 0;
956 replaced_file->next = NULL;
957 replaced_file->previous = NULL;
958 return UpdateFileEntry(replaced_file, data, len, service);
970 static t_TruePersistentFile* UpdateFileEntry(t_TruePersistentFile *file,
void *data, MHEG5Int len,
975 file_list_tail->next = file;
979 file_list_head = file;
983 file->previous = file_list_tail;
985 file_list_tail = file;
987 file->service_info.original_network_id = service->original_network_id;
988 file->service_info.transport_stream_id = service->transport_stream_id;
989 file->service_info.service_id = service->service_id;
990 file->file_data = MHEG5getMem( len );
993 memcpy(file->file_data, data, len);
994 file->file_len = len;
1009 E_MhegErr MHEG5_GetTPSStatus(BOOLEAN *enabled)
1011 *enabled = (TPS_enabled) ? TRUE : FALSE;
1021 E_MhegErr MHEG5_EnableTPS(BOOLEAN enabled)
1023 if (TPS_enabled && !enabled)
1028 TPS_enabled = enabled;
1038 E_MhegErr MHEG5_GetTPSServices(U16BIT *pfile_count,
pS_DvbLocator *first_file)
1040 t_TruePersistentFile *cursor;
1042 if (current_file_list)
1044 return MHERR_COMP_ALREADY_OPEN;
1049 current_file_list = MHEG5getMem(
sizeof(
S_DvbLocator) * file_count);
1050 if (current_file_list)
1052 for (cursor = file_list_head, file_count = 0; cursor; file_count++, cursor = cursor->next)
1054 current_file_list[file_count].original_network_id = cursor->service_info.original_network_id;
1055 current_file_list[file_count].transport_stream_id = cursor->service_info.transport_stream_id;
1056 current_file_list[file_count].service_id = cursor->service_info.service_id;
1058 *pfile_count = file_count;
1059 *first_file = current_file_list;
1081 E_MhegErr MHEG5_AckTPSServiceList(
void)
1083 if (current_file_list)
1085 MHEG5freeMem(current_file_list);
1086 current_file_list = NULL;
1099 if (DeleteFileByService(service))
1105 return MHERR_OBJECT_NOT_FOUND;
1112 BOOLEAN TPS_StorageGetEnabled(
void)
1114 return TPS_enabled ? TRUE : FALSE;
void * STB_NVMOpenFile(U8BIT *name, E_STB_DSK_FILE_MODE mode)
Opens an existing file or creates a new one.
E_MhegErr VQ_PutMsg(S_MhegMessage *pMsg, E_PRIORITY priority)
Post event or section message on queue. Copies data into queue.
MHEG5Bool MHEG5TpsWrite(MHEG5String fn, void *data, MHEG5Int len)
Write data passed from the application into the TPS stroe.
void STB_NVMCloseDirectory(void *dir)
Closes the directory for reading.
MHEG5Bool MHEG5GetTpsStatus(void)
Get the status of the TPS store for the PST resident program. none.
void MHEG5TpsClose(void)
Close the clear the store and delete the cache none.
True Persistent Storage functions.
void MHEG5getDate(S32BIT *day, S32BIT *sec)
Modified Julian Date - see Davic 9.2.12.1.
MHEG5Bool MHEG5TpsRead(MHEG5String fn, void **data, MHEG5Int *len)
Read a file from the TPS store and pass it back to the application.
void STB_NVMCloseFile(void *file)
Flushes and closes an open file.
BOOLEAN STB_NVMFileSize(U8BIT *filename, U32BIT *filesize)
Returns the size in KB of the given file.
MHEG5 engine interface error codes.
void * STB_NVMOpenDirectory(U8BIT *dir_name)
Opens a directory in order to read the entries.
DVB Service information functions are required by MHEG5 engine. All required functions should be non-...
U32BIT STB_NVMReadFile(void *file, U8BIT *data, U32BIT size)
Reads data from an open file.
void MHEG5TpsSetCurrentService(S_DvbLocator *pDvbLoc)
Set current service for application none.
System Wide Global Technical Data Type Definitions.
BOOLEAN STB_NVMReadDirectory(void *dir, U8BIT *filename, U16BIT filename_len, E_STB_DIR_ENTRY_TYPE *entry_type)
Reads the next entry from the directory, returning the name of the entry and the type of the entry...
U32BIT STB_NVMWriteFile(void *file, U8BIT *data, U32BIT size)
Writes data to an open file.
Non-Volatile Memory functions and file access for caching files during power cycles. All file/path names are relative to some implementation dependent root path for MHEG's NVM storage area. So a path of "" (i.e. zero length name), is the root directory of storage area.
E_MhegErr DVB_MhegDvbLocatorToIndex(S_DvbLocator *pDvbLocator, S32BIT *pServiceIndex)
Get a DVB implementation dependant service index - an integer greater or equal to 0...
BOOLEAN STB_NVMDeleteFile(U8BIT *filename)
Deletes the file.