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