Home | History | Annotate | Download | only in darwin-x86
      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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    317 EAS_EXPORT void EAS_DLLSetDebugLevel (int severity)
    318 {
    319     severityLevel = severity;
    320 }
    321 
    322 /*----------------------------------------------------------------------------
    323  * EAS_ExSetDebugLevel()
    324  *----------------------------------------------------------------------------
    325 */
    326 void EAS_SetDebugLevel (int severity)
    327 {
    328     severityLevel = severity;
    329 }
    330 
    331 /*----------------------------------------------------------------------------
    332  * EAS_SelectLibrary()
    333  *----------------------------------------------------------------------------
    334 */
    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
    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 
    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 
    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
    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 
    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 
    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 
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   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 */
   1803 EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData)
   1804 {
   1805     /* put your code here */
   1806     return EAS_FALSE;
   1807 }
   1808 
   1809 
   1810