1 /*
2  *  EASLib.c
3  *  EASLIb
4  *
5  *
6  * Copyright (C) 2008 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
26 
27 #include "eas.h"
28 #include "eas_report.h"
29 #include "eas_host.h"
30 #include <AudioUnit/AudioUnit.h>
31 #include <CoreServices/CoreServices.h>
32 
33 #ifdef JET_INTERFACE
34 #include "jet.h"
35 #endif
36 
37 
38 #define EAS_EXPORT __attribute__((visibility("default")))
39 
40 // #define DEBUG_FILE_IO
41 
42 /* include debug interface */
43 #include "eas_host_debug.h"
44 
45 #ifdef AUX_MIXER
46 #include "eas_auxmix.h"
47 #endif
48 
49 /* this module requires dynamic memory support */
50 #ifdef _STATIC_MEMORY
51 #error "eas_hostmm.c requires the dynamic memory model!\n"
52 #endif
53 
54 #ifndef EAS_MAX_FILE_HANDLES
55 #define EAS_MAX_FILE_HANDLES    32
56 #endif
57 
58 #ifndef EAS_FILE_BUFFER_SIZE
59 #define EAS_FILE_BUFFER_SIZE    32
60 #endif
61 
62 /*
63  * this structure and the related function are here
64  * to support the ability to create duplicate handles
65  * and buffering it in memory. If your system uses
66  * in-memory resources, you can eliminate the calls
67  * to malloc and free, the dup flag, and simply track
68  * the file size and read position.
69  */
70  #ifdef BUFFERED_FILE_ACCESS
71 typedef struct eas_hw_file_tag
72 {
73     FILE *pFile;
74     EAS_I32 bytesInBuffer;
75     EAS_I32 readIndex;
76     EAS_I32 filePos;
77     EAS_I32 fileSize;
78     EAS_BOOL dup;
79     EAS_U8 buffer[EAS_FILE_BUFFER_SIZE];
80 } EAS_HW_FILE;
81 #else
82 typedef struct eas_hw_file_tag
83 {
84     EAS_I32         fileSize;
85     EAS_I32         filePos;
86     EAS_BOOL        dup;
87     EAS_U8          *buffer;
88 } EAS_HW_FILE;
89 #endif
90 
91 typedef struct eas_hw_inst_data_tag
92 {
93     EAS_HW_FILE     files[EAS_MAX_FILE_HANDLES];
94 } EAS_HW_INST_DATA;
95 
96 EAS_BOOL errorConditions[eNumErrorConditions];
97 EAS_BOOL ledState;
98 EAS_BOOL vibState;
99 EAS_BOOL backlightState;
100 
101 #define MAX_DEBUG_MSG_LEN 1024
102 
103 typedef void (*EAS_LOG_FUNC)(EAS_INT severity, char *msg);
104 
105 static EAS_LOG_FUNC logCallback = NULL;
106 static char messageBuffer[MAX_DEBUG_MSG_LEN];
107 
108 /* error counts */
109 static EAS_INT eas_fatalErrors;
110 static EAS_INT eas_errors;
111 static EAS_INT eas_warnings;
112 static int severityLevel = 9999;
113 
114 
115 #define MAX_BUFFERS         8
116 
117 // The output unit
118 AudioUnit   OutputUnit;
119 AudioStreamBasicDescription streamFormat;
120 
121 // sync stuf
122 pthread_mutex_t mtx;
123 pthread_cond_t  cond;
124 bool bStopped = true;
125 
126 // buffer to hold the data
127 typedef struct
128 {
129     UInt32          uOutBufferLength;
130     UInt32          uOutFrames;
131     int             ix;
132     short*          pData[8];
133     unsigned int    uLength;
134 } S_BUFFER_INFO;
135 
136 static S_BUFFER_INFO *pBuf = NULL;
137 const S_EAS_LIB_CONFIG *pConfig = NULL;
138 
139 /*----------------------------------------------------------------------------
140  * ResetErrorCounters()
141  *----------------------------------------------------------------------------
142 */
ResetErrorCounters()143 EAS_EXPORT void ResetErrorCounters()
144 {
145     eas_fatalErrors = 0;
146     eas_errors = 0;
147     eas_warnings = 0;
148 }
149 
150 /*----------------------------------------------------------------------------
151  * SetLogCallback()
152  *----------------------------------------------------------------------------
153 */
SetLogCallback(EAS_LOG_FUNC callback)154 EAS_EXPORT void SetLogCallback (EAS_LOG_FUNC callback)
155 {
156     logCallback = callback;
157 }
158 
159 #ifndef _NO_DEBUG_PREPROCESSOR
160 static S_DEBUG_MESSAGES debugMessages[] =
161 {
162 #ifdef UNIFIED_DEBUG_MESSAGES
163 #include "eas_debugmsgs.h"
164 #endif
165     { 0,0,0 }
166 };
167 
168 /*----------------------------------------------------------------------------
169  * EAS_ReportEx()
170  *----------------------------------------------------------------------------
171 */
EAS_ReportEx(int severity,unsigned long hashCode,int serialNum,...)172 void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...)
173 {
174     va_list vargs;
175     int i;
176 
177     switch (severity)
178     {
179         case _EAS_SEVERITY_FATAL:
180             eas_fatalErrors++;
181             break;
182 
183         case _EAS_SEVERITY_ERROR:
184             eas_errors++;
185             break;
186 
187         case _EAS_SEVERITY_WARNING:
188             eas_warnings++;
189             break;
190 
191         default:
192             break;
193     }
194 
195     /* check severity level */
196     if (severity > severityLevel)
197         return;
198 
199     /* check for callback */
200     if (logCallback == NULL)
201         return;
202 
203     /* find the error message and output to stdout */
204     for (i = 0; debugMessages[i].m_pDebugMsg; i++)
205     {
206         if ((debugMessages[i].m_nHashCode == hashCode) &&
207         (debugMessages[i].m_nSerialNum == serialNum))
208         {
209             va_start(vargs, serialNum);
210 #ifdef WIN32
211             vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs);
212 #else
213             vsprintf(messageBuffer, debugMessages[i].m_pDebugMsg, vargs);
214 #endif
215             logCallback(severity, messageBuffer);
216             va_end(vargs);
217             return;
218         }
219     }
220     printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum);
221 } /* end EAS_ReportEx */
222 
223 #else
224 /*----------------------------------------------------------------------------
225  * EAS_Report()
226  *----------------------------------------------------------------------------
227 */
EAS_Report(int severity,const char * fmt,...)228 void EAS_Report (int severity, const char *fmt, ...)
229 {
230     va_list vargs;
231 
232     switch (severity)
233     {
234         case _EAS_SEVERITY_FATAL:
235             eas_fatalErrors++;
236             break;
237 
238         case _EAS_SEVERITY_ERROR:
239             eas_errors++;
240             break;
241 
242         case _EAS_SEVERITY_WARNING:
243             eas_warnings++;
244             break;
245 
246         default:
247             break;
248     }
249 
250     /* check severity level */
251     if (severity > severityLevel)
252         return;
253 
254     /* check for callback */
255     if (logCallback == NULL)
256         return;
257 
258     va_start(vargs, fmt);
259 #ifdef _WIN32
260     vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs);
261 #else
262     vsprintf(messageBuffer, fmt, vargs);
263 #endif
264     logCallback(severity, messageBuffer);
265     va_end(vargs);
266 } /* end EAS_Report */
267 
268 /*----------------------------------------------------------------------------
269  * EAS_ReportX()
270  *----------------------------------------------------------------------------
271 */
EAS_ReportX(int severity,const char * fmt,...)272 void EAS_ReportX (int severity, const char *fmt, ...)
273 {
274     va_list vargs;
275 
276     switch (severity)
277     {
278         case _EAS_SEVERITY_FATAL:
279             eas_fatalErrors++;
280             break;
281 
282         case _EAS_SEVERITY_ERROR:
283             eas_errors++;
284             break;
285 
286         case _EAS_SEVERITY_WARNING:
287             eas_warnings++;
288             break;
289 
290         default:
291             break;
292     }
293 
294     /* check severity level */
295     if (severity > severityLevel)
296         return;
297 
298     /* check for callback */
299     if (logCallback == NULL)
300         return;
301 
302     va_start(vargs, fmt);
303 #ifdef _WIN32
304     vsprintf_s(messageBuffer, sizeof(messageBuffer), fmt, vargs);
305 #else
306     vsprintf(messageBuffer, fmt, vargs);
307 #endif
308     logCallback(severity, messageBuffer);
309     va_end(vargs);
310 }
311 #endif
312 
313 /*----------------------------------------------------------------------------
314  * EAS_DLLSetDebugLevel()
315  *----------------------------------------------------------------------------
316 */
EAS_DLLSetDebugLevel(int severity)317 EAS_EXPORT void EAS_DLLSetDebugLevel (int severity)
318 {
319     severityLevel = severity;
320 }
321 
322 /*----------------------------------------------------------------------------
323  * EAS_ExSetDebugLevel()
324  *----------------------------------------------------------------------------
325 */
EAS_SetDebugLevel(int severity)326 void EAS_SetDebugLevel (int severity)
327 {
328     severityLevel = severity;
329 }
330 
331 /*----------------------------------------------------------------------------
332  * EAS_SelectLibrary()
333  *----------------------------------------------------------------------------
334 */
EAS_SelectLib(EAS_DATA_HANDLE pEASData,EAS_HANDLE streamHandle,EAS_BOOL testLib)335 EAS_EXPORT EAS_RESULT EAS_SelectLib (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_BOOL testLib)
336 {
337     extern EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum);
338     return EAS_SetSoundLibrary(pEASData, streamHandle, VMGetLibHandle(testLib ? 1 : 0));
339 }
340 
341 // Callback proc
RenderProc(void * inRefCon,AudioUnitRenderActionFlags * ioActionFlags,const AudioTimeStamp * inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList * ioData)342 static OSStatus RenderProc( void                                    *inRefCon,
343                                         AudioUnitRenderActionFlags  *ioActionFlags,
344                                         const AudioTimeStamp                *inTimeStamp,
345                                         UInt32                              inBusNumber,
346                                         UInt32                              inNumberFrames,
347                                         AudioBufferList                 *ioData)
348 {
349     // Get the mutex
350     pthread_mutex_lock(&mtx);
351 
352     short* ptrOutL = (short *)ioData->mBuffers[0].mData;
353     short* ptrOutR = (short *)ioData->mBuffers[1].mData;
354 
355     memset(ptrOutL, 0, pBuf->uOutFrames);
356     memset(ptrOutR, 0, pBuf->uOutFrames);
357 
358     // check if there is any data in the buffer
359     if (pBuf->ix == 0 )
360     {
361         // Release the mutex and signal the python thread
362         pthread_mutex_unlock(&mtx);
363         pthread_cond_signal(&cond);
364         return 0;
365     }
366 
367     // Get a ptr to the data
368     short* pData = pBuf->pData[--(pBuf->ix)];
369 
370     // Now copy the data
371     int i;
372     for (i = 0; i < pBuf->uOutFrames; i+=2 )
373     {
374         *ptrOutL++ = pData[i];
375         *ptrOutR++ = pData[i+1];
376     }
377 
378     // Release the mutex
379     pthread_mutex_unlock(&mtx);
380     pthread_cond_signal(&cond);
381 
382     return 0;
383 }
384 
addData(EAS_PCM * pAudioBuffer)385 EAS_RESULT addData(EAS_PCM *pAudioBuffer)
386 {
387     // Copy the data we got from the synth
388     memcpy(pBuf->pData[(pBuf->ix)++], pAudioBuffer, 2048);
389 
390     // Start the output Audio Unit only the first time
391     if ( bStopped == true )
392     {
393         bStopped = false;
394         OSStatus err = AudioOutputUnitStart (OutputUnit);
395         if (err)
396         {
397             printf ("AudioDeviceStart=%ld\n", err);
398             return EAS_FAILURE;
399         }
400     }
401 
402     return EAS_SUCCESS;
403 }
404 
405 
EAS_RenderWaveOut(EAS_DATA_HANDLE easHandle,EAS_PCM * pAudioBuffer,EAS_I32 numRequested,EAS_I32 * pNumGenerated)406 EAS_EXPORT EAS_RESULT EAS_RenderWaveOut(EAS_DATA_HANDLE easHandle, EAS_PCM *pAudioBuffer, EAS_I32 numRequested, EAS_I32 *pNumGenerated)
407 {
408     // Get the mutex
409     pthread_mutex_lock(&mtx);
410 
411     // Check if our buffer is full
412     while(pBuf->ix == MAX_BUFFERS - 1)
413         pthread_cond_wait(&cond, &mtx);
414 
415     // Call the synth the render a buffer
416     EAS_RESULT result = EAS_Render(easHandle, pAudioBuffer, numRequested, pNumGenerated);
417     addData( pAudioBuffer );
418 
419     // Release the mutex
420     pthread_mutex_unlock(&mtx);
421 
422     //Done
423     return result;
424 }
425 
426 #ifdef AUX_MIXER
EAS_RenderAuxMixerWaveOut(EAS_DATA_HANDLE easHandle,EAS_PCM * pAudioBuffer,EAS_I32 * pNumGenerated)427 EAS_EXPORT EAS_RESULT EAS_RenderAuxMixerWaveOut (EAS_DATA_HANDLE easHandle, EAS_PCM *pAudioBuffer, EAS_I32 *pNumGenerated)
428 {
429     // Get the mutex
430     pthread_mutex_lock(&mtx);
431 
432     // Check if our buffer is full
433     while(pBuf->ix == MAX_BUFFERS - 1)
434         pthread_cond_wait(&cond, &mtx);
435 
436     EAS_RESULT result = EAS_RenderAuxMixer(easHandle, pAudioBuffer, pNumGenerated);
437     addData( pAudioBuffer );
438 
439     // Release the mutex
440     pthread_mutex_unlock(&mtx);
441 
442     return result;
443 }
444 #endif
445 
OpenWaveOutDevice(EAS_INT devNum,EAS_INT sampleRate,EAS_INT maxBufSize)446 EAS_EXPORT EAS_RESULT OpenWaveOutDevice(EAS_INT devNum, EAS_INT sampleRate, EAS_INT maxBufSize)
447 {
448     // Open the default output unit
449     ComponentDescription desc;
450     desc.componentType = kAudioUnitType_Output;
451     desc.componentSubType = kAudioUnitSubType_DefaultOutput;
452     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
453     desc.componentFlags = 0;
454     desc.componentFlagsMask = 0;
455 
456     Component comp = FindNextComponent(NULL, &desc);
457     if (comp == NULL)
458     {
459         printf ("Could find the default output unit!!!\n");
460         return EAS_FAILURE;
461     }
462 
463     OSStatus err = OpenAComponent(comp, &OutputUnit);
464     if (comp == NULL)
465     {
466         printf ("OpenAComponent=%ld\n", err);
467         return EAS_FAILURE;
468     }
469 
470     // Set up a callback function to generate output to the output unit
471     AURenderCallbackStruct auRenderCallback;
472     auRenderCallback.inputProc = RenderProc;
473     auRenderCallback.inputProcRefCon = NULL;
474 
475     err = AudioUnitSetProperty (OutputUnit,
476                                 kAudioUnitProperty_SetRenderCallback,
477                                 kAudioUnitScope_Input,
478                                 0,
479                                 &auRenderCallback,
480                                 sizeof(auRenderCallback));
481     if (err)
482     {
483         printf ("AudioUnitSetProperty-CB=%ld\n", err);
484         return EAS_FAILURE;;
485     }
486 
487     pConfig = EAS_Config();
488 
489     // The synth engine already uses short* for the buffers so let CoreAudio do any conversions if needed
490     if (sampleRate != 0)
491         streamFormat.mSampleRate = sampleRate;
492     else
493         streamFormat.mSampleRate = pConfig->sampleRate;
494 
495     streamFormat.mFormatID =    kAudioFormatLinearPCM;
496     streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger
497                                 | kAudioFormatFlagsNativeEndian
498                                 | kLinearPCMFormatFlagIsPacked
499                                 | kAudioFormatFlagIsNonInterleaved;
500 
501     streamFormat.mBytesPerPacket   = 2;
502     streamFormat.mFramesPerPacket  = 1;
503     streamFormat.mBytesPerFrame    = 2;
504     streamFormat.mChannelsPerFrame = 2;
505     streamFormat.mBitsPerChannel   = 16;
506 
507     err = AudioUnitSetProperty (OutputUnit,
508                                 kAudioUnitProperty_StreamFormat,
509                                 kAudioUnitScope_Input,
510                                 0,
511                                 &streamFormat,
512                                 sizeof(AudioStreamBasicDescription));
513     if (err)
514     {
515         printf ("AudioUnitSetProperty-SF= %4.4s, %ld\n", (char*)&err, err);
516         return EAS_FAILURE;
517     }
518 
519      // Initialize
520     err = AudioUnitInitialize(OutputUnit);
521     if (err)
522     {
523         printf ("AudioUnitInitialize = %ld\n", err);
524         return EAS_FAILURE;
525     }
526 
527     pBuf = (S_BUFFER_INFO *) malloc(sizeof(S_BUFFER_INFO));
528     if( !pBuf )
529         return EAS_FAILURE;
530 
531     pBuf->uOutBufferLength = pConfig->mixBufferSize * streamFormat.mBitsPerChannel / 2;
532     UInt32 uDataSize = sizeof(pBuf->uOutBufferLength);
533 
534     err = AudioUnitSetProperty(OutputUnit, kAudioDevicePropertyBufferSize, kAudioUnitScope_Output, 0, &pBuf->uOutBufferLength, uDataSize);
535     if (err)
536     {
537         printf ("AudioUnitSetProperty = %ld\n", err);
538         return EAS_FAILURE;
539     }
540 
541     err = AudioUnitGetProperty(OutputUnit, kAudioDevicePropertyBufferSize, kAudioUnitScope_Output, 0, &pBuf->uOutBufferLength, &uDataSize);
542     if (err)
543     {
544         printf ("AudioUnitGetProperty = %ld\n", err);
545         return EAS_FAILURE;
546     }
547 
548     pBuf->uLength = pBuf->uOutBufferLength;
549     int i;
550     for ( i = 0; i < MAX_BUFFERS; i++)
551         pBuf->pData[i]   = malloc(pBuf->uLength);
552 
553     pBuf->uOutBufferLength /= pConfig->numChannels;
554     pBuf->uOutFrames = pBuf->uOutBufferLength / sizeof(short);
555 
556     pBuf->ix = 0;
557 
558     // Init the stop flag
559     bStopped = true;
560 
561     int result = pthread_mutex_init(&mtx, NULL);
562     if (result)
563     {
564         printf("pthread_mutex_init failed\n");
565         return EAS_FAILURE;
566     }
567 
568     result = pthread_cond_init(&cond, NULL);
569     if (result)
570     {
571         printf("pthread_cond_init failed\n");
572         return EAS_FAILURE;
573     }
574 
575     // Done
576     return EAS_SUCCESS;
577 }
578 
579 
StartStream()580 EAS_EXPORT EAS_RESULT StartStream()
581 {
582     OSStatus err = noErr;
583     pthread_mutex_lock(&mtx);
584     if ( bStopped == true )
585     {
586         err = AudioOutputUnitStart (OutputUnit);
587         if (err)
588         {
589             printf ("AudioOutputUnitStart=%ld\n", err);
590             return EAS_FAILURE;
591         }
592         bStopped = false;
593     }
594 
595     return EAS_SUCCESS;
596 }
597 
598 
CloseWaveOutDevice()599 EAS_EXPORT EAS_RESULT CloseWaveOutDevice()
600 {
601     OSStatus err;
602 
603     pthread_mutex_lock(&mtx);
604     if( false == bStopped )
605     {
606         AudioOutputUnitStop (OutputUnit);
607         bStopped = true;
608 
609         err = AudioUnitUninitialize (OutputUnit);
610         if (err)
611         {
612             printf ("AudioUnitUninitialize=%ld\n", err);
613             return EAS_FAILURE;
614         }
615 
616         CloseComponent (OutputUnit);
617         int i = 0;
618         for(i; i < MAX_BUFFERS; i++)
619             free(pBuf->pData[i]);
620 
621         free(pBuf);
622     }
623 
624     pthread_mutex_unlock(&mtx);
625     return EAS_SUCCESS;
626 }
627 
628 
629 #if defined(_DEBUG) && !defined(MSC)
630 #include <crtdbg.h>
631 /*----------------------------------------------------------------------------
632  * EnableHeapDebug()
633  *----------------------------------------------------------------------------
634 */
EnableHeapDebug(void)635 static void EnableHeapDebug (void)
636 {
637     int temp;
638     temp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
639     temp |= _CRTDBG_ALLOC_MEM_DF;
640     temp |= _CRTDBG_CHECK_ALWAYS_DF;
641     temp |= _CRTDBG_LEAK_CHECK_DF;
642 //  temp |= _CRTDBG_DELAY_FREE_MEM_DF;
643     _CrtSetDbgFlag(temp);
644 }
645 
646 /*----------------------------------------------------------------------------
647  * HeapCheck()
648  *----------------------------------------------------------------------------
649  * Check heap status
650  *----------------------------------------------------------------------------
651 */
HeapCheck(void)652 void HeapCheck (void)
653 {
654     int heapStatus;
655 
656     /* Check heap status */
657     heapStatus = _heapchk();
658     if ((heapStatus == _HEAPOK) || (heapStatus == _HEAPEMPTY))
659         return;
660 
661     EAS_ReportX(_EAS_SEVERITY_FATAL, "Heap corrupt\n" );
662 }
663 #endif
664 
665 
666 /*----------------------------------------------------------------------------
667  * EAS_HWInit
668  *
669  * Initialize host wrapper interface
670  *
671  *----------------------------------------------------------------------------
672 */
EAS_HWInit(EAS_HW_DATA_HANDLE * pHWInstData)673 EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData)
674 {
675 
676 #if defined(_DEBUG) && !defined(MSC)
677     EnableHeapDebug();
678 #endif
679 
680  #ifdef BUFFERED_FILE_ACCESS
681     EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Buffered file access\n");
682  #else
683     EAS_ReportX(_EAS_SEVERITY_INFO, "EAS_HWInit: Memory mapped file access\n");
684  #endif
685 
686     /* simulate failure */
687     if (errorConditions[eInitError])
688         return EAS_FAILURE;
689 
690     /* need to track file opens for duplicate handles */
691     *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA));
692     if (!(*pHWInstData))
693         return EAS_ERROR_MALLOC_FAILED;
694 
695     EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA));
696     return EAS_SUCCESS;
697 }
698 
699 /*----------------------------------------------------------------------------
700  * EAS_HWShutdown
701  *
702  * Shut down host wrapper interface
703  *
704  *----------------------------------------------------------------------------
705 */
EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData)706 EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData)
707 {
708 
709     /* simulate failure */
710     if (errorConditions[eShutdownError])
711         return EAS_FAILURE;
712 
713     free(hwInstData);
714 
715 #if defined(_DEBUG) && !defined(MSC)
716     HeapCheck();
717 #endif
718 
719     return EAS_SUCCESS;
720 }
721 
722 /*----------------------------------------------------------------------------
723  *
724  * EAS_HWMalloc
725  *
726  * Allocates dynamic memory
727  *
728  *----------------------------------------------------------------------------
729 */
730 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData,EAS_I32 size)731 void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size)
732 {
733     /* simulate failure */
734     if (errorConditions[eMallocError])
735         return NULL;
736 
737     return malloc((size_t) size);
738 }
739 
740 /*----------------------------------------------------------------------------
741  *
742  * EAS_HWFree
743  *
744  * Frees dynamic memory
745  *
746  *----------------------------------------------------------------------------
747 */
748 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData,void * p)749 void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p)
750 {
751     free(p);
752 }
753 
754 /*----------------------------------------------------------------------------
755  *
756  * EAS_HWMemCpy
757  *
758  * Copy memory wrapper
759  *
760  *----------------------------------------------------------------------------
761 */
EAS_HWMemCpy(void * dest,const void * src,EAS_I32 amount)762 void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount)
763 {
764     return memcpy(dest, src, (size_t) amount);
765 }
766 
767 /*----------------------------------------------------------------------------
768  *
769  * EAS_HWMemSet
770  *
771  * Set memory wrapper
772  *
773  *----------------------------------------------------------------------------
774 */
EAS_HWMemSet(void * dest,int val,EAS_I32 amount)775 void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount)
776 {
777     return memset(dest, val, (size_t) amount);
778 }
779 
780 /*----------------------------------------------------------------------------
781  *
782  * EAS_HWMemCmp
783  *
784  * Compare memory wrapper
785  *
786  *----------------------------------------------------------------------------
787 */
EAS_HWMemCmp(const void * s1,const void * s2,EAS_I32 amount)788 EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount)
789 {
790     return (EAS_I32) memcmp(s1, s2, (size_t) amount);
791 }
792 
793 #ifdef BUFFERED_FILE_ACCESS
794 /*----------------------------------------------------------------------------
795  *
796  * EAS_HWOpenFile
797  *
798  * Open a file for read or write
799  *
800  *----------------------------------------------------------------------------
801 */
EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_LOCATOR locator,EAS_FILE_HANDLE * pFile,EAS_FILE_MODE mode)802 EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode)
803 {
804     EAS_HW_FILE *file;
805     int i;
806 
807     /* set return value to NULL */
808     *pFile = NULL;
809 
810     /* only support read mode at this time */
811     if (mode != EAS_FILE_READ)
812         return EAS_ERROR_INVALID_FILE_MODE;
813 
814     /* find an empty entry in the file table */
815     file = hwInstData->files;
816     for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
817     {
818         /* is this slot being used? */
819         if (file->pFile == NULL)
820         {
821             EAS_RESULT result;
822 
823             /* open the file */
824             file->pFile = fopen((const char*) locator, "rb");
825             if (file->pFile == NULL)
826                 return EAS_ERROR_FILE_OPEN_FAILED;
827 
828             /* get file length */
829             if ((result = EAS_HWFileLength(hwInstData, file, &file->fileSize)) != EAS_SUCCESS)
830             {
831                 EAS_HWCloseFile(hwInstData, file);
832                 return result;
833             }
834 
835 #ifdef DEBUG_FILE_IO
836             EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWOpenFile: Open file %d\n", i);
837 #endif
838 
839             /* initialize some values */
840             file->bytesInBuffer = 0;
841             file->readIndex = 0;
842             file->filePos = 0;
843             file->dup = EAS_FALSE;
844 
845             *pFile = file;
846             return EAS_SUCCESS;
847         }
848         file++;
849     }
850 
851     /* too many open files */
852     return EAS_ERROR_MAX_FILES_OPEN;
853 }
854 
855 /*----------------------------------------------------------------------------
856  *
857  * EAS_HWFillBuffer
858  *
859  * Fill buffer from file
860  *----------------------------------------------------------------------------
861 */
862 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWFillBuffer(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file)863 EAS_RESULT EAS_HWFillBuffer (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file)
864 {
865     /* reposition the file pointer */
866     if (fseek(file->pFile, file->filePos, SEEK_SET) != 0)
867         return EAS_ERROR_FILE_SEEK;
868 
869     /* read some data from the file */
870     file->bytesInBuffer = (EAS_I32) fread(file->buffer, 1, EAS_FILE_BUFFER_SIZE, file->pFile);
871     file->readIndex = 0;
872     if (file->bytesInBuffer == 0)
873         return EAS_EOF;
874     return EAS_SUCCESS;
875 }
876 
877 /*----------------------------------------------------------------------------
878  *
879  * EAS_HWReadFile
880  *
881  * Read data from a file
882  *----------------------------------------------------------------------------
883 */
884 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * pBuffer,EAS_I32 n,EAS_I32 * pBytesRead)885 EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead)
886 {
887     EAS_RESULT result;
888     EAS_I32 temp;
889     EAS_U8 *p = pBuffer;
890     EAS_I32 bytesLeft = n;
891 
892     *pBytesRead = 0;
893 
894     /* check handle integrity */
895     if (file->pFile == NULL)
896         return EAS_ERROR_INVALID_HANDLE;
897 
898 #ifdef DEBUG_FILE_IO
899     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWReadFile: Reading %d bytes from position %d\n", n, file->filePos);
900 #endif
901 
902     /* try to fulfill request from buffer */
903     for (;bytesLeft > 0;)
904     {
905         /* how many bytes can we get from buffer? */
906         temp = file->bytesInBuffer - file->readIndex;
907         if (temp > bytesLeft)
908             temp = bytesLeft;
909 
910         /* copy data from buffer */
911         EAS_HWMemCpy(p, &file->buffer[file->readIndex], temp);
912         *pBytesRead += temp;
913         file->readIndex += temp;
914         file->filePos += temp;
915         p += temp;
916         bytesLeft -= temp;
917 
918         /* don't refill buffer if request is bigger than buffer */
919         if ((bytesLeft == 0) || (bytesLeft >= EAS_FILE_BUFFER_SIZE))
920             break;
921 
922         /* refill buffer */
923         if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS)
924             return result;
925     }
926 
927     /* more to read? do unbuffered read directly to target memory */
928     if (bytesLeft)
929     {
930 
931         /* position the file pointer */
932         if (fseek(file->pFile, file->filePos, SEEK_SET) != 0)
933             return EAS_ERROR_FILE_SEEK;
934 
935         /* read data in the buffer */
936         temp = (EAS_I32) fread(p, 1, (size_t) bytesLeft, file->pFile);
937         *pBytesRead += temp;
938         file->filePos += temp;
939 
940         /* reset buffer info */
941         file->bytesInBuffer = 0;
942         file->readIndex = 0;
943     }
944 
945 #ifdef DEBUG_FILE_IO
946     {
947 #define BYTES_PER_LINE 16
948         char str[BYTES_PER_LINE * 3 + 1];
949         EAS_INT i;
950         for (i = 0; i < (n > BYTES_PER_LINE ? BYTES_PER_LINE : n) ; i ++)
951             sprintf(&str[i*3], "%02x ", ((EAS_U8*)pBuffer)[i]);
952         if (i)
953             EAS_ReportX(_EAS_SEVERITY_NOFILTER, "%s\n", str);
954     }
955 #endif
956 
957     /* were n bytes read? */
958     if (*pBytesRead != n)
959         return EAS_EOF;
960 
961     return EAS_SUCCESS;
962 }
963 
964 /*----------------------------------------------------------------------------
965  *
966  * EAS_HWGetByte
967  *
968  * Read a byte from a file
969  *----------------------------------------------------------------------------
970 */
971 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p)972 EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p)
973 {
974     EAS_RESULT result;
975 
976     /* check handle integrity */
977     if (file->pFile == NULL)
978         return EAS_ERROR_INVALID_HANDLE;
979 
980     /* use local buffer - do we have any data? */
981     if (file->readIndex >= file->bytesInBuffer)
982     {
983         if ((result = EAS_HWFillBuffer(hwInstData, file)) != EAS_SUCCESS)
984             return result;
985 
986         /* if nothing to read, return EOF */
987         if (file->bytesInBuffer == 0)
988             return EAS_EOF;
989     }
990 
991     /* get a character from the buffer */
992     *((EAS_U8*) p) = file->buffer[file->readIndex++];
993 
994 #ifdef DEBUG_FILE_IO
995     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetByte: Reading from position %d, byte = 0x%02x\n", file->filePos, *(EAS_U8*)p);
996 #endif
997 
998     file->filePos++;
999     return EAS_SUCCESS;
1000 }
1001 
1002 /*----------------------------------------------------------------------------
1003  *
1004  * EAS_HWGetWord
1005  *
1006  * Read a 16-bit value from the file
1007  *----------------------------------------------------------------------------
1008 */
EAS_HWGetWord(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p,EAS_BOOL msbFirst)1009 EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
1010 {
1011     EAS_RESULT result;
1012     EAS_I32 count;
1013     EAS_U8 c[2];
1014 
1015 #ifdef DEBUG_FILE_IO
1016     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetWord: Reading 2 bytes from position %d\n", file->filePos);
1017 #endif
1018 
1019     /* read 2 bytes from the file */
1020     if ((result = EAS_HWReadFile(hwInstData, file, c, 2, &count)) != EAS_SUCCESS)
1021         return result;
1022 
1023     /* order them as requested */
1024     if (msbFirst)
1025         *((EAS_U16*) p) = ((EAS_U16) c[0] << 8) | c[1];
1026     else
1027         *((EAS_U16*) p) = ((EAS_U16) c[1] << 8) | c[0];
1028 
1029     return EAS_SUCCESS;
1030 }
1031 
1032 /*----------------------------------------------------------------------------
1033  *
1034  * EAS_HWGetDWord
1035  *
1036  * Read a 16-bit value from the file
1037  *----------------------------------------------------------------------------
1038 */
EAS_HWGetDWord(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p,EAS_BOOL msbFirst)1039 EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
1040 {
1041     EAS_RESULT result;
1042     EAS_I32 count;
1043     EAS_U8 c[4];
1044 
1045 #ifdef DEBUG_FILE_IO
1046     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWGetDWord: Reading 4 bytes from position %d\n", file->filePos);
1047 #endif
1048 
1049     /* read 4 bytes from the file */
1050     if ((result = EAS_HWReadFile(hwInstData, file, c, 4, &count)) != EAS_SUCCESS)
1051         return result;
1052 
1053     /* order them as requested */
1054     if (msbFirst)
1055         *((EAS_U32*) p) = ((EAS_U32) c[0] << 24) | ((EAS_U32) c[1] << 16) | ((EAS_U32) c[2] << 8) | c[3];
1056     else
1057         *((EAS_U32*) p) = ((EAS_U32) c[3] << 24) | ((EAS_U32) c[2] << 16) | ((EAS_U32) c[1] << 8) | c[0];
1058 
1059     return EAS_SUCCESS;
1060 }
1061 
1062 /*----------------------------------------------------------------------------
1063  *
1064  * EAS_HWFilePos
1065  *
1066  * Returns the current location in the file
1067  *
1068  *----------------------------------------------------------------------------
1069 */
1070 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWFilePos(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 * pPosition)1071 EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition)
1072 {
1073 
1074     /* check handle integrity */
1075     if (file->pFile == NULL)
1076         return EAS_ERROR_INVALID_HANDLE;
1077 
1078     *pPosition = file->filePos;
1079     return EAS_SUCCESS;
1080 }
1081 
1082 /*----------------------------------------------------------------------------
1083  *
1084  * EAS_HWFileSeek
1085  *
1086  * Seek to a specific location in the file
1087  *
1088  *----------------------------------------------------------------------------
1089 */
1090 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWFileSeek(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 position)1091 EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
1092 {
1093     EAS_I32 newIndex;
1094 
1095     /* check handle integrity */
1096     if (file->pFile == NULL)
1097         return EAS_ERROR_INVALID_HANDLE;
1098 
1099     /* check for seek past end */
1100     if ((position < 0) || (position > file->fileSize))
1101         return EAS_ERROR_FILE_SEEK;
1102 
1103 #ifdef DEBUG_FILE_IO
1104     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeek: Seeking to new position %d\n", file->filePos);
1105 #endif
1106 
1107     /* is new position in current buffer? */
1108     newIndex = position - file->filePos + file->readIndex;
1109     if ((newIndex >= 0) && (newIndex < file->bytesInBuffer))
1110     {
1111         file->readIndex = newIndex;
1112         file->filePos = position;
1113         return EAS_SUCCESS;
1114     }
1115 
1116     /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */
1117     file->filePos = position;
1118     file->bytesInBuffer = 0;
1119     file->readIndex = 0;
1120     return EAS_SUCCESS;
1121 }
1122 
1123 /*----------------------------------------------------------------------------
1124  *
1125  * EAS_HWFileSeekOfs
1126  *
1127  * Seek forward or back relative to the current position
1128  *
1129  *----------------------------------------------------------------------------
1130 */
1131 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWFileSeekOfs(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 position)1132 EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
1133 {
1134     EAS_I32 temp;
1135 
1136 #ifdef DEBUG_FILE_IO
1137     EAS_ReportX(_EAS_SEVERITY_NOFILTER, "EAS_HWFileSeekOfs: Seeking to new position %d\n", file->filePos + position);
1138 #endif
1139 
1140     /* check handle integrity */
1141     if (file->pFile == NULL)
1142         return EAS_ERROR_INVALID_HANDLE;
1143 
1144     /* check for seek past end */
1145     temp = file->filePos + position;
1146     if ((temp < 0) || (temp > file->fileSize))
1147         return EAS_ERROR_FILE_SEEK;
1148 
1149     /* is new position in current buffer? */
1150     temp = position + file->readIndex;
1151     if ((temp >= 0) && (temp < file->bytesInBuffer))
1152     {
1153         file->readIndex = temp;
1154         file->filePos += position;
1155         return EAS_SUCCESS;
1156     }
1157 
1158     /* save new position and reset buffer info so EAS_HWGetByte doesn't fail */
1159     file->filePos += position;
1160     file->bytesInBuffer = 0;
1161     file->readIndex = 0;
1162     return EAS_SUCCESS;
1163 }
1164 
1165 /*----------------------------------------------------------------------------
1166  *
1167  * EAS_HWFileLength
1168  *
1169  * Return the file length
1170  *
1171  *----------------------------------------------------------------------------
1172 */
1173 /*lint -esym(715, hwInstData) hwInstData available for customer use */
EAS_HWFileLength(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 * pLength)1174 EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength)
1175 {
1176     long pos;
1177 
1178     /* check handle integrity */
1179     if (file->pFile == NULL)
1180         return EAS_ERROR_INVALID_HANDLE;
1181 
1182     if ((pos = ftell(file->pFile)) == -1L)
1183         return EAS_ERROR_FILE_LENGTH;
1184     if (fseek(file->pFile, 0L, SEEK_END) != 0)
1185         return EAS_ERROR_FILE_LENGTH;
1186     if ((*pLength = ftell(file->pFile)) == -1L)
1187         return EAS_ERROR_FILE_LENGTH;
1188     if (fseek(file->pFile, pos, SEEK_SET) != 0)
1189         return EAS_ERROR_FILE_LENGTH;
1190     return EAS_SUCCESS;
1191 }
1192 
1193 /*----------------------------------------------------------------------------
1194  *
1195  * EAS_HWDupHandle
1196  *
1197  * Duplicate a file handle
1198  *
1199  *----------------------------------------------------------------------------
1200 */
EAS_HWDupHandle(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_FILE_HANDLE * pDupFile)1201 EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pDupFile)
1202 {
1203     EAS_HW_FILE *dupfile;
1204     int i;
1205 
1206     /* check handle integrity */
1207     *pDupFile = NULL;
1208     if (file->pFile == NULL)
1209         return EAS_ERROR_INVALID_HANDLE;
1210 
1211     /* find an empty entry in the file table */
1212     dupfile = hwInstData->files;
1213     for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
1214     {
1215         /* is this slot being used? */
1216         if (dupfile->pFile == NULL)
1217         {
1218 
1219             /* copy info from the handle to be duplicated */
1220             dupfile->filePos = file->filePos;
1221             dupfile->pFile = file->pFile;
1222             dupfile->fileSize = file->fileSize;
1223 
1224             /* set the duplicate handle flag */
1225             dupfile->dup = file->dup = EAS_TRUE;
1226 
1227             /* initialize some values */
1228             dupfile->bytesInBuffer = 0;
1229             dupfile->readIndex = 0;
1230 
1231             *pDupFile = dupfile;
1232             return EAS_SUCCESS;
1233         }
1234         dupfile++;
1235     }
1236 
1237     /* too many open files */
1238     return EAS_ERROR_MAX_FILES_OPEN;
1239 }
1240 
1241 /*----------------------------------------------------------------------------
1242  *
1243  * EAS_HWClose
1244  *
1245  * Wrapper for fclose function
1246  *
1247  *----------------------------------------------------------------------------
1248 */
EAS_HWCloseFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file1)1249 EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1)
1250 {
1251     EAS_HW_FILE *file2,*dupFile;
1252     int i;
1253 
1254     /* check handle integrity */
1255     if (file1->pFile == NULL)
1256         return EAS_ERROR_INVALID_HANDLE;
1257 
1258     /* check for duplicate handle */
1259     if (file1->dup)
1260     {
1261         dupFile = NULL;
1262         file2 = hwInstData->files;
1263         for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
1264         {
1265             /* check for duplicate */
1266             if ((file1 != file2) && (file2->pFile == file1->pFile))
1267             {
1268                 /* is there more than one duplicate? */
1269                 if (dupFile != NULL)
1270                 {
1271                     /* clear this entry and return */
1272                     file1->pFile = NULL;
1273                     return EAS_SUCCESS;
1274                 }
1275 
1276                 /* this is the first duplicate found */
1277                 dupFile = file2;
1278             }
1279             file2++;
1280         }
1281 
1282         /* there is only one duplicate, clear the dup flag */
1283         if (dupFile)
1284             dupFile->dup = EAS_FALSE;
1285         else
1286             /* if we get here, there's a serious problem */
1287             return EAS_ERROR_HANDLE_INTEGRITY;
1288 
1289         /* clear this entry and return */
1290         file1->pFile = NULL;
1291         return EAS_SUCCESS;
1292     }
1293 
1294     /* no duplicates - close the file */
1295     if (fclose(file1->pFile) != 0)
1296         return EAS_ERROR_CLOSE_FAILED;
1297 
1298     /* clear this entry and return */
1299     file1->pFile = NULL;
1300     return EAS_SUCCESS;
1301 }
1302 #else
1303 /*----------------------------------------------------------------------------
1304  *
1305  * EAS_HWOpenFile
1306  *
1307  * Open a file for read or write
1308  *
1309  *----------------------------------------------------------------------------
1310 */
EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_LOCATOR locator,EAS_FILE_HANDLE * pFile,EAS_FILE_MODE mode)1311 EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode)
1312 {
1313     EAS_HW_FILE *file;
1314     FILE *ioFile;
1315     int i, temp;
1316 
1317     /* set return value to NULL */
1318     *pFile = NULL;
1319 
1320     /* simulate failure */
1321     if (errorConditions[eOpenError])
1322         return EAS_FAILURE;
1323 
1324     /* only support read mode at this time */
1325     if (mode != EAS_FILE_READ)
1326         return EAS_ERROR_INVALID_FILE_MODE;
1327 
1328     /* find an empty entry in the file table */
1329     file = hwInstData->files;
1330     for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
1331     {
1332         /* is this slot being used? */
1333         if (file->buffer == NULL)
1334         {
1335             /* open the file */
1336             if ((ioFile = fopen(locator,"rb")) == NULL)
1337                 return EAS_ERROR_FILE_OPEN_FAILED;
1338 
1339             /* determine the file size */
1340             if (fseek(ioFile, 0L, SEEK_END) != 0)
1341                 return EAS_ERROR_FILE_LENGTH;
1342             if ((file->fileSize = ftell(ioFile)) == -1L)
1343                 return EAS_ERROR_FILE_LENGTH;
1344             if (fseek(ioFile, 0L, SEEK_SET) != 0)
1345                 return EAS_ERROR_FILE_LENGTH;
1346 
1347             /* allocate a buffer */
1348             file->buffer = EAS_HWMalloc(hwInstData, file->fileSize);
1349             if (file->buffer == NULL)
1350             {
1351                 fclose(ioFile);
1352                 return EAS_ERROR_MALLOC_FAILED;
1353             }
1354 
1355             /* read the file into memory */
1356             temp = (int) fread(file->buffer, (size_t) file->fileSize, 1, ioFile);
1357 
1358             /* close the file - don't need it any more */
1359             fclose(ioFile);
1360 
1361             /* check for error reading file */
1362             if (temp != 1)
1363                 return EAS_ERROR_FILE_READ_FAILED;
1364 
1365             /* initialize some values */
1366             file->filePos = 0;
1367             file->dup = EAS_FALSE;
1368 
1369             *pFile = file;
1370             return EAS_SUCCESS;
1371         }
1372         file++;
1373     }
1374 
1375     /* too many open files */
1376     return EAS_ERROR_MAX_FILES_OPEN;
1377 }
1378 
1379 /*----------------------------------------------------------------------------
1380  *
1381  * EAS_HWReadFile
1382  *
1383  * Read data from a file
1384  *
1385  *----------------------------------------------------------------------------
1386 */
1387 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * pBuffer,EAS_I32 n,EAS_I32 * pBytesRead)1388 EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead)
1389 {
1390     EAS_I32 count;
1391 
1392     /* simulate failure */
1393     if (errorConditions[eReadError])
1394         return EAS_FAILURE;
1395 
1396     /* make sure we have a valid handle */
1397     if (file->buffer == NULL)
1398         return EAS_ERROR_INVALID_HANDLE;
1399 
1400     /* calculate the bytes to read */
1401     count = file->fileSize - file->filePos;
1402     if (n < count)
1403         count = n;
1404 
1405     /* copy the data to the requested location, and advance the pointer */
1406     if (count)
1407         EAS_HWMemCpy(pBuffer, &file->buffer[file->filePos], count);
1408     file->filePos += count;
1409     *pBytesRead = count;
1410 
1411     /* were n bytes read? */
1412     if (count!= n)
1413         return EAS_EOF;
1414     return EAS_SUCCESS;
1415 }
1416 
1417 /*----------------------------------------------------------------------------
1418  *
1419  * EAS_HWGetByte
1420  *
1421  * Read a byte from a file
1422  *
1423  *----------------------------------------------------------------------------
1424 */
1425 /*lint -e{715} hwInstData available for customer use */
EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p)1426 EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p)
1427 {
1428 
1429     /* simulate failure */
1430     if (errorConditions[eReadError])
1431         return EAS_FAILURE;
1432 
1433     /* make sure we have a valid handle */
1434     if (file->buffer == NULL)
1435         return EAS_ERROR_INVALID_HANDLE;
1436 
1437     /* check for end of file */
1438     if (file->filePos >= file->fileSize)
1439     {
1440         *((EAS_U8*) p) = 0;
1441         return EAS_EOF;
1442     }
1443 
1444     /* get a character from the buffer */
1445     *((EAS_U8*) p) = file->buffer[file->filePos++];
1446     return EAS_SUCCESS;
1447 }
1448 
1449 /*----------------------------------------------------------------------------
1450  *
1451  * EAS_HWGetWord
1452  *
1453  * Returns the current location in the file
1454  *
1455  *----------------------------------------------------------------------------
1456 */
1457 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWGetWord(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p,EAS_BOOL msbFirst)1458 EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
1459 {
1460     EAS_RESULT result;
1461     EAS_U8 c1, c2;
1462 
1463     /* read 2 bytes from the file */
1464     if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS)
1465         return result;
1466     if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS)
1467         return result;
1468 
1469     /* order them as requested */
1470     if (msbFirst)
1471         *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2;
1472     else
1473         *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1;
1474 
1475     return EAS_SUCCESS;
1476 }
1477 
1478 /*----------------------------------------------------------------------------
1479  *
1480  * EAS_HWGetDWord
1481  *
1482  * Returns the current location in the file
1483  *
1484  *----------------------------------------------------------------------------
1485 */
1486 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWGetDWord(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,void * p,EAS_BOOL msbFirst)1487 EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst)
1488 {
1489     EAS_RESULT result;
1490     EAS_U8 c1, c2,c3,c4;
1491 
1492     /* read 4 bytes from the file */
1493     if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS)
1494         return result;
1495     if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS)
1496         return result;
1497     if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS)
1498         return result;
1499     if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS)
1500         return result;
1501 
1502     /* order them as requested */
1503     if (msbFirst)
1504         *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4;
1505     else
1506         *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1;
1507 
1508     return EAS_SUCCESS;
1509 }
1510 
1511 /*----------------------------------------------------------------------------
1512  *
1513  * EAS_HWFilePos
1514  *
1515  * Returns the current location in the file
1516  *
1517  *----------------------------------------------------------------------------
1518 */
1519 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWFilePos(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 * pPosition)1520 EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition)
1521 {
1522 
1523     /* simulate failure */
1524     if (errorConditions[ePosError])
1525         return EAS_FAILURE;
1526 
1527     /* make sure we have a valid handle */
1528     if (file->buffer == NULL)
1529         return EAS_ERROR_INVALID_HANDLE;
1530 
1531     *pPosition = file->filePos;
1532     return EAS_SUCCESS;
1533 } /* end EAS_HWFilePos */
1534 
1535 /*----------------------------------------------------------------------------
1536  *
1537  * EAS_HWFileSeek
1538  *
1539  * Seek to a specific location in the file
1540  *
1541  *----------------------------------------------------------------------------
1542 */
1543 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWFileSeek(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 position)1544 EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
1545 {
1546 
1547     /* simulate failure */
1548     if (errorConditions[eSeekError])
1549         return EAS_FAILURE;
1550 
1551     /* make sure we have a valid handle */
1552     if (file->buffer == NULL)
1553         return EAS_ERROR_INVALID_HANDLE;
1554 
1555     /* validate new position */
1556     if ((position < 0) || (position > file->fileSize))
1557         return EAS_ERROR_FILE_SEEK;
1558 
1559     /* save new position */
1560     file->filePos = position;
1561     return EAS_SUCCESS;
1562 }
1563 
1564 /*----------------------------------------------------------------------------
1565  *
1566  * EAS_HWFileSeekOfs
1567  *
1568  * Seek forward or back relative to the current position
1569  *
1570  *----------------------------------------------------------------------------
1571 */
1572 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWFileSeekOfs(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 position)1573 EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position)
1574 {
1575 
1576     /* simulate failure */
1577     if (errorConditions[eSeekError])
1578         return EAS_FAILURE;
1579 
1580     /* make sure we have a valid handle */
1581     if (file->buffer == NULL)
1582         return EAS_ERROR_INVALID_HANDLE;
1583 
1584     /* determine the file position */
1585     position += file->filePos;
1586     if ((position < 0) || (position > file->fileSize))
1587         return EAS_ERROR_FILE_SEEK;
1588 
1589     /* save new position */
1590     file->filePos = position;
1591     return EAS_SUCCESS;
1592 }
1593 
1594 /*----------------------------------------------------------------------------
1595  *
1596  * EAS_HWFileLength
1597  *
1598  * Return the file length
1599  *
1600  *----------------------------------------------------------------------------
1601 */
1602 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWFileLength(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_I32 * pLength)1603 EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength)
1604 {
1605 
1606     /* simulate failure */
1607     if (errorConditions[eLengthError])
1608         return EAS_FAILURE;
1609 
1610     /* make sure we have a valid handle */
1611     if (file->buffer == NULL)
1612         return EAS_ERROR_INVALID_HANDLE;
1613 
1614     *pLength = file->fileSize;
1615     return EAS_SUCCESS;
1616 }
1617 
1618 /*----------------------------------------------------------------------------
1619  *
1620  * EAS_HWDupHandle
1621  *
1622  * Duplicate a file handle
1623  *
1624  *----------------------------------------------------------------------------
1625 */
EAS_HWDupHandle(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file,EAS_FILE_HANDLE * pDupFile)1626 EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile)
1627 {
1628     EAS_HW_FILE *dupFile;
1629     int i;
1630 
1631     /* simulate failure */
1632     if (errorConditions[eDupError])
1633         return EAS_FAILURE;
1634 
1635     /* make sure we have a valid handle */
1636     if (file->buffer == NULL)
1637         return EAS_ERROR_INVALID_HANDLE;
1638 
1639     /* find an empty entry in the file table */
1640     dupFile = hwInstData->files;
1641     for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
1642     {
1643         /* is this slot being used? */
1644         if (dupFile->buffer == NULL)
1645         {
1646 
1647             /* copy info from the handle to be duplicated */
1648             dupFile->filePos = file->filePos;
1649             dupFile->fileSize = file->fileSize;
1650             dupFile->buffer = file->buffer;
1651 
1652             /* set the duplicate handle flag */
1653             dupFile->dup = file->dup = EAS_TRUE;
1654 
1655             *pDupFile = dupFile;
1656             return EAS_SUCCESS;
1657         }
1658         dupFile++;
1659     }
1660 
1661     /* too many open files */
1662     return EAS_ERROR_MAX_FILES_OPEN;
1663 }
1664 
1665 /*----------------------------------------------------------------------------
1666  *
1667  * EAS_HWClose
1668  *
1669  * Wrapper for fclose function
1670  *
1671  *----------------------------------------------------------------------------
1672 */
EAS_HWCloseFile(EAS_HW_DATA_HANDLE hwInstData,EAS_FILE_HANDLE file1)1673 EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1)
1674 {
1675     EAS_HW_FILE *file2,*dupFile;
1676     int i;
1677 
1678     /* simulate failure */
1679     if (errorConditions[eCloseError])
1680         return EAS_FAILURE;
1681 
1682     /* make sure we have a valid handle */
1683     if (file1->buffer == NULL)
1684         return EAS_ERROR_INVALID_HANDLE;
1685 
1686     /* check for duplicate handle */
1687     if (file1->dup)
1688     {
1689         dupFile = NULL;
1690         file2 = hwInstData->files;
1691         for (i = 0; i < EAS_MAX_FILE_HANDLES; i++)
1692         {
1693             /* check for duplicate */
1694             if ((file1 != file2) && (file2->buffer == file1->buffer))
1695             {
1696                 /* is there more than one duplicate? */
1697                 if (dupFile != NULL)
1698                 {
1699                     /* clear this entry and return */
1700                     file1->buffer = NULL;
1701                     return EAS_SUCCESS;
1702                 }
1703 
1704                 /* this is the first duplicate found */
1705                 else
1706                     dupFile = file2;
1707             }
1708             file2++;
1709         }
1710 
1711         /* there is only one duplicate, clear the dup flag */
1712         if (dupFile)
1713             dupFile->dup = EAS_FALSE;
1714         else
1715             /* if we get here, there's a serious problem */
1716             return EAS_ERROR_HANDLE_INTEGRITY;
1717 
1718         /* clear this entry and return */
1719         file1->buffer = NULL;
1720         return EAS_SUCCESS;
1721     }
1722 
1723     /* no duplicates -free the buffer */
1724     EAS_HWFree(hwInstData, file1->buffer);
1725 
1726     /* clear this entry and return */
1727     file1->buffer = NULL;
1728     return EAS_SUCCESS;
1729 }
1730 #endif
1731 
1732 /*----------------------------------------------------------------------------
1733  *
1734  * EAS_HWVibrate
1735  *
1736  * Turn on/off vibrate function
1737  *
1738  *----------------------------------------------------------------------------
1739 */
1740 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData,EAS_BOOL state)1741 EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
1742 {
1743     vibState = state;
1744 //  EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Vibrate state: %d\n", state);
1745     return EAS_SUCCESS;
1746 } /* end EAS_HWVibrate */
1747 
1748 /*----------------------------------------------------------------------------
1749  *
1750  * EAS_HWLED
1751  *
1752  * Turn on/off LED
1753  *
1754  *----------------------------------------------------------------------------
1755 */
1756 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData,EAS_BOOL state)1757 EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
1758 {
1759     ledState = state;
1760 //  EAS_ReportX(_EAS_SEVERITY_NOFILTER, "LED state: %d\n", state);
1761     return EAS_SUCCESS;
1762 }
1763 
1764 /*----------------------------------------------------------------------------
1765  *
1766  * EAS_HWBackLight
1767  *
1768  * Turn on/off backlight
1769  *
1770  *----------------------------------------------------------------------------
1771 */
1772 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData,EAS_BOOL state)1773 EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state)
1774 {
1775     backlightState = state;
1776 //  EAS_ReportX(_EAS_SEVERITY_NOFILTER, "Backlight state: %d\n", state);
1777     return EAS_SUCCESS;
1778 }
1779 
1780 /*----------------------------------------------------------------------------
1781  *
1782  * EAS_HWYield
1783  *
1784  * This function is called periodically by the EAS library to give the
1785  * host an opportunity to allow other tasks to run. There are two ways to
1786  * use this call:
1787  *
1788  * If you have a multi-tasking OS, you can call the yield function in the
1789  * OS to allow other tasks to run. In this case, return EAS_FALSE to tell
1790  * the EAS library to continue processing when control returns from this
1791  * function.
1792  *
1793  * If tasks run in a single thread by sequential function calls (sometimes
1794  * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to
1795  * return to the caller. Be sure to check the number of bytes rendered
1796  * before passing the audio buffer to the codec - it may not be filled.
1797  * The next call to EAS_Render will continue processing until the buffer
1798  * has been filled.
1799  *
1800  *----------------------------------------------------------------------------
1801 */
1802 /*lint -esym(715, hwInstData) available for customer use */
EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData)1803 EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData)
1804 {
1805     /* put your code here */
1806     return EAS_FALSE;
1807 }
1808 
1809 
1810