1 /*---------------------------------------------------------------------------- 2 * 3 * File: 4 * eas_hostmm.c 5 * 6 * Contents and purpose: 7 * This file contains the host wrapper functions for stdio, stdlib, etc. 8 * This is a sample version that reads from a filedescriptor. 9 * The file locator (EAS_FILE_LOCATOR) handle passed to 10 * HWOpenFile is the same one that is passed to EAS_OpenFile. 11 * 12 * Modify this file to suit the needs of your particular system. 13 * 14 * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within 15 * a MIDI type 1 file that can be played. 16 * 17 * EAS_HW_FILE is a structure to support the file I/O functions. It 18 * comprises the file descriptor, the file read pointer, and 19 * the dup flag, which when set, indicates that the file handle has 20 * been duplicated, and offset and length within the file. 21 * 22 * Copyright 2005 Sonic Network Inc. 23 24 * Licensed under the Apache License, Version 2.0 (the "License"); 25 * you may not use this file except in compliance with the License. 26 * You may obtain a copy of the License at 27 * 28 * http://www.apache.org/licenses/LICENSE-2.0 29 * 30 * Unless required by applicable law or agreed to in writing, software 31 * distributed under the License is distributed on an "AS IS" BASIS, 32 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 33 * See the License for the specific language governing permissions and 34 * limitations under the License. 35 * 36 *---------------------------------------------------------------------------- 37 * Revision Control: 38 * $Revision: 795 $ 39 * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ 40 *---------------------------------------------------------------------------- 41 */ 42 43 #ifdef _lint 44 #include "lint_stdlib.h" 45 #else 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <unistd.h> 50 #include <sys/types.h> 51 #include <sys/stat.h> 52 #include <fcntl.h> 53 #include <limits.h> 54 #include <sys/mman.h> 55 #include <errno.h> 56 #include <signal.h> 57 #define LOG_TAG "Sonivox" 58 #include <utils/Log.h> 59 #include <media/MediaPlayerInterface.h> 60 #endif 61 62 #include "eas_host.h" 63 64 /* Only for debugging LED, vibrate, and backlight functions */ 65 #include "eas_report.h" 66 67 /* this module requires dynamic memory support */ 68 #ifdef _STATIC_MEMORY 69 #error "eas_hostmm.c requires the dynamic memory model!\n" 70 #endif 71 72 #ifndef EAS_MAX_FILE_HANDLES 73 // 100 max file handles == 3 * (nb tracks(32) + 1 for the segment) + 1 for jet file 74 // 3 == 1(playing segment) + 1(prepared segment) 75 // + 1(after end of playing segment, before files closed) 76 #define EAS_MAX_FILE_HANDLES 100 77 #endif 78 79 /* 80 * this structure and the related function are here 81 * to support the ability to create duplicate handles 82 * and buffering it in memory. If your system uses 83 * in-memory resources, you can eliminate the calls 84 * to malloc and free, the dup flag, and simply track 85 * the file size and read position. 86 */ 87 typedef struct eas_hw_file_tag 88 { 89 EAS_I32 fileSize; 90 EAS_I32 filePos; 91 EAS_BOOL dup; 92 int fd; 93 EAS_I32 offset; 94 } EAS_HW_FILE; 95 96 typedef struct eas_hw_inst_data_tag 97 { 98 EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; 99 } EAS_HW_INST_DATA; 100 101 pthread_key_t EAS_sigbuskey; 102 103 /*---------------------------------------------------------------------------- 104 * EAS_HWInit 105 * 106 * Initialize host wrapper interface 107 * 108 *---------------------------------------------------------------------------- 109 */ 110 EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) 111 { 112 EAS_HW_FILE *file; 113 int i; 114 115 /* need to track file opens for duplicate handles */ 116 *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); 117 if (!(*pHWInstData)) 118 return EAS_ERROR_MALLOC_FAILED; 119 120 EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); 121 122 file = (*pHWInstData)->files; 123 for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) 124 { 125 file->fd = -1; 126 file++; 127 } 128 129 130 return EAS_SUCCESS; 131 } 132 133 /*---------------------------------------------------------------------------- 134 * EAS_HWShutdown 135 * 136 * Shut down host wrapper interface 137 * 138 *---------------------------------------------------------------------------- 139 */ 140 EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) 141 { 142 143 free(hwInstData); 144 return EAS_SUCCESS; 145 } 146 147 /*---------------------------------------------------------------------------- 148 * 149 * EAS_HWMalloc 150 * 151 * Allocates dynamic memory 152 * 153 *---------------------------------------------------------------------------- 154 */ 155 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 156 void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) 157 { 158 /* Since this whole library loves signed sizes, let's not let 159 * negative or 0 values through */ 160 if (size <= 0) 161 return NULL; 162 return malloc((size_t) size); 163 } 164 165 /*---------------------------------------------------------------------------- 166 * 167 * EAS_HWFree 168 * 169 * Frees dynamic memory 170 * 171 *---------------------------------------------------------------------------- 172 */ 173 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 174 void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) 175 { 176 free(p); 177 } 178 179 /*---------------------------------------------------------------------------- 180 * 181 * EAS_HWMemCpy 182 * 183 * Copy memory wrapper 184 * 185 *---------------------------------------------------------------------------- 186 */ 187 void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) 188 { 189 if (amount < 0) { 190 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000004 , amount); 191 exit(255); 192 } 193 return memcpy(dest, src, (size_t) amount); 194 } 195 196 /*---------------------------------------------------------------------------- 197 * 198 * EAS_HWMemSet 199 * 200 * Set memory wrapper 201 * 202 *---------------------------------------------------------------------------- 203 */ 204 void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) 205 { 206 if (amount < 0) { 207 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000005 , amount); 208 exit(255); 209 } 210 return memset(dest, val, (size_t) amount); 211 } 212 213 /*---------------------------------------------------------------------------- 214 * 215 * EAS_HWMemCmp 216 * 217 * Compare memory wrapper 218 * 219 *---------------------------------------------------------------------------- 220 */ 221 EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) 222 { 223 if (amount < 0) { 224 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000006 , amount); 225 exit(255); 226 } 227 return (EAS_I32) memcmp(s1, s2, (size_t) amount); 228 } 229 230 /*---------------------------------------------------------------------------- 231 * 232 * EAS_HWOpenFile 233 * 234 * Open a file for read or write 235 * 236 *---------------------------------------------------------------------------- 237 */ 238 EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) 239 { 240 EAS_HW_FILE *file; 241 int fd; 242 int i, temp; 243 244 /* set return value to NULL */ 245 *pFile = NULL; 246 247 /* only support read mode at this time */ 248 if (mode != EAS_FILE_READ) 249 return EAS_ERROR_INVALID_FILE_MODE; 250 251 /* find an empty entry in the file table */ 252 file = hwInstData->files; 253 for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) 254 { 255 /* is this slot being used? */ 256 if (file->fd < 0) 257 { 258 if (locator->path) { 259 /* open the file */ 260 if ((fd = open(locator->path, O_RDONLY)) < 0) { 261 return EAS_ERROR_FILE_OPEN_FAILED; 262 } 263 } else { 264 /* else file is already open */ 265 fd = dup(locator->fd); 266 } 267 268 /* determine the file size */ 269 if (locator->length == 0) { 270 if (lseek(fd, 0, SEEK_END) < 0) { 271 close(fd); 272 return EAS_ERROR_FILE_LENGTH; 273 } 274 if ((file->fileSize = lseek(fd, 0, SEEK_CUR)) == -1L) { 275 close(fd); 276 return EAS_ERROR_FILE_LENGTH; 277 } 278 } 279 280 // file size was passed in 281 else { 282 file->fileSize = (EAS_I32) locator->length; 283 } 284 285 file->fd = fd; 286 file->offset = locator->offset; 287 288 /* initialize some values */ 289 file->filePos = 0; 290 file->dup = EAS_FALSE; 291 292 *pFile = file; 293 return EAS_SUCCESS; 294 } 295 file++; 296 } 297 298 /* too many open files */ 299 return EAS_ERROR_MAX_FILES_OPEN; 300 } 301 302 303 /*---------------------------------------------------------------------------- 304 * 305 * EAS_HWReadFile 306 * 307 * Read data from a file 308 * 309 *---------------------------------------------------------------------------- 310 */ 311 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 312 EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) 313 { 314 EAS_I32 count; 315 316 /* make sure we have a valid handle */ 317 if (file->fd < 0) 318 return EAS_ERROR_INVALID_HANDLE; 319 320 if (n < 0) 321 return EAS_EOF; 322 323 /* calculate the bytes to read */ 324 count = file->fileSize - file->filePos; 325 if (n < count) 326 count = n; 327 if (count < 0) 328 return EAS_EOF; 329 330 /* copy the data to the requested location, and advance the pointer */ 331 if (count) { 332 lseek(file->fd, file->filePos + file->offset, SEEK_SET); 333 count = read(file->fd, pBuffer, count); 334 } 335 file->filePos += count; 336 *pBytesRead = count; 337 338 /* were n bytes read? */ 339 if (count!= n) 340 return EAS_EOF; 341 return EAS_SUCCESS; 342 } 343 344 /*---------------------------------------------------------------------------- 345 * 346 * EAS_HWGetByte 347 * 348 * Read a byte from a file 349 * 350 *---------------------------------------------------------------------------- 351 */ 352 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 353 EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) 354 { 355 EAS_I32 numread; 356 return EAS_HWReadFile(hwInstData, file, p, 1, &numread); 357 } 358 359 /*---------------------------------------------------------------------------- 360 * 361 * EAS_HWGetWord 362 * 363 * Read a 16 bit word from a file 364 * 365 *---------------------------------------------------------------------------- 366 */ 367 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 368 EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) 369 { 370 EAS_RESULT result; 371 EAS_U8 c1, c2; 372 373 /* read 2 bytes from the file */ 374 if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) 375 return result; 376 if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) 377 return result; 378 379 /* order them as requested */ 380 if (msbFirst) 381 *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; 382 else 383 *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; 384 385 return EAS_SUCCESS; 386 } 387 388 /*---------------------------------------------------------------------------- 389 * 390 * EAS_HWGetDWord 391 * 392 * Returns the current location in the file 393 * 394 *---------------------------------------------------------------------------- 395 */ 396 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 397 EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) 398 { 399 EAS_RESULT result; 400 EAS_U8 c1, c2,c3,c4; 401 402 /* read 4 bytes from the file */ 403 if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) 404 return result; 405 if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) 406 return result; 407 if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) 408 return result; 409 if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) 410 return result; 411 412 /* order them as requested */ 413 if (msbFirst) 414 *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; 415 else 416 *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; 417 418 return EAS_SUCCESS; 419 } 420 421 /*---------------------------------------------------------------------------- 422 * 423 * EAS_HWFilePos 424 * 425 * Returns the current location in the file 426 * 427 *---------------------------------------------------------------------------- 428 */ 429 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 430 EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) 431 { 432 433 /* make sure we have a valid handle */ 434 if (file->fd < 0) 435 return EAS_ERROR_INVALID_HANDLE; 436 437 *pPosition = file->filePos; 438 return EAS_SUCCESS; 439 } /* end EAS_HWFilePos */ 440 441 /*---------------------------------------------------------------------------- 442 * 443 * EAS_HWFileSeek 444 * 445 * Seek to a specific location in the file 446 * 447 *---------------------------------------------------------------------------- 448 */ 449 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 450 EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) 451 { 452 453 /* make sure we have a valid handle */ 454 if (file->fd < 0) 455 return EAS_ERROR_INVALID_HANDLE; 456 457 /* validate new position */ 458 if ((position < 0) || (position > file->fileSize)) 459 return EAS_ERROR_FILE_SEEK; 460 461 /* save new position */ 462 file->filePos = position; 463 return EAS_SUCCESS; 464 } 465 466 /*---------------------------------------------------------------------------- 467 * 468 * EAS_HWFileSeekOfs 469 * 470 * Seek forward or back relative to the current position 471 * 472 *---------------------------------------------------------------------------- 473 */ 474 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 475 EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) 476 { 477 478 /* make sure we have a valid handle */ 479 if (file->fd < 0) 480 return EAS_ERROR_INVALID_HANDLE; 481 482 /* determine the file position */ 483 position += file->filePos; 484 if ((position < 0) || (position > file->fileSize)) 485 return EAS_ERROR_FILE_SEEK; 486 487 /* save new position */ 488 file->filePos = position; 489 return EAS_SUCCESS; 490 } 491 492 /*---------------------------------------------------------------------------- 493 * 494 * EAS_HWFileLength 495 * 496 * Return the file length 497 * 498 *---------------------------------------------------------------------------- 499 */ 500 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 501 EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength) 502 { 503 504 /* make sure we have a valid handle */ 505 if (file->fd < 0) 506 return EAS_ERROR_INVALID_HANDLE; 507 508 *pLength = file->fileSize; 509 return EAS_SUCCESS; 510 } 511 512 /*---------------------------------------------------------------------------- 513 * 514 * EAS_HWDupHandle 515 * 516 * Duplicate a file handle 517 * 518 *---------------------------------------------------------------------------- 519 */ 520 EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) 521 { 522 EAS_HW_FILE *dupFile; 523 int i; 524 525 /* make sure we have a valid handle */ 526 if (file->fd < 0) 527 return EAS_ERROR_INVALID_HANDLE; 528 529 /* find an empty entry in the file table */ 530 dupFile = hwInstData->files; 531 for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) 532 { 533 /* is this slot being used? */ 534 if (dupFile->fd < 0) 535 { 536 /* copy info from the handle to be duplicated */ 537 dupFile->filePos = file->filePos; 538 dupFile->fileSize = file->fileSize; 539 dupFile->fd = file->fd; 540 dupFile->offset = file->offset; 541 542 /* set the duplicate handle flag */ 543 dupFile->dup = file->dup = EAS_TRUE; 544 545 *pDupFile = dupFile; 546 return EAS_SUCCESS; 547 } 548 dupFile++; 549 } 550 551 /* too many open files */ 552 return EAS_ERROR_MAX_FILES_OPEN; 553 } 554 555 /*---------------------------------------------------------------------------- 556 * 557 * EAS_HWClose 558 * 559 * Wrapper for fclose function 560 * 561 *---------------------------------------------------------------------------- 562 */ 563 EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) 564 { 565 EAS_HW_FILE *file2,*dupFile; 566 int i; 567 568 569 /* make sure we have a valid handle */ 570 if (file1->fd < 0) 571 return EAS_ERROR_INVALID_HANDLE; 572 573 /* check for duplicate handle */ 574 if (file1->dup) 575 { 576 dupFile = NULL; 577 file2 = hwInstData->files; 578 for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) 579 { 580 /* check for duplicate */ 581 if ((file1 != file2) && (file2->fd == file1->fd)) 582 { 583 /* is there more than one duplicate? */ 584 if (dupFile != NULL) 585 { 586 /* clear this entry and return */ 587 file1->fd = -1; 588 return EAS_SUCCESS; 589 } 590 591 /* this is the first duplicate found */ 592 else 593 dupFile = file2; 594 } 595 file2++; 596 } 597 598 /* there is only one duplicate, clear the dup flag */ 599 if (dupFile) 600 dupFile->dup = EAS_FALSE; 601 else 602 /* if we get here, there's a serious problem */ 603 return EAS_ERROR_HANDLE_INTEGRITY; 604 605 /* clear this entry and return */ 606 file1->fd = -1; 607 return EAS_SUCCESS; 608 } 609 610 /* no duplicates - close the file */ 611 close(file1->fd); 612 /* clear this entry and return */ 613 file1->fd = -1; 614 return EAS_SUCCESS; 615 } 616 617 /*---------------------------------------------------------------------------- 618 * 619 * EAS_HWVibrate 620 * 621 * Turn on/off vibrate function 622 * 623 *---------------------------------------------------------------------------- 624 */ 625 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 626 EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) 627 { 628 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state); 629 return EAS_SUCCESS; 630 } /* end EAS_HWVibrate */ 631 632 /*---------------------------------------------------------------------------- 633 * 634 * EAS_HWLED 635 * 636 * Turn on/off LED 637 * 638 *---------------------------------------------------------------------------- 639 */ 640 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 641 EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) 642 { 643 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state); 644 return EAS_SUCCESS; 645 } 646 647 /*---------------------------------------------------------------------------- 648 * 649 * EAS_HWBackLight 650 * 651 * Turn on/off backlight 652 * 653 *---------------------------------------------------------------------------- 654 */ 655 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 656 EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) 657 { 658 EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state); 659 return EAS_SUCCESS; 660 } 661 662 /*---------------------------------------------------------------------------- 663 * 664 * EAS_HWYield 665 * 666 * This function is called periodically by the EAS library to give the 667 * host an opportunity to allow other tasks to run. There are two ways to 668 * use this call: 669 * 670 * If you have a multi-tasking OS, you can call the yield function in the 671 * OS to allow other tasks to run. In this case, return EAS_FALSE to tell 672 * the EAS library to continue processing when control returns from this 673 * function. 674 * 675 * If tasks run in a single thread by sequential function calls (sometimes 676 * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to 677 * return to the caller. Be sure to check the number of bytes rendered 678 * before passing the audio buffer to the codec - it may not be filled. 679 * The next call to EAS_Render will continue processing until the buffer 680 * has been filled. 681 * 682 *---------------------------------------------------------------------------- 683 */ 684 /*lint -esym(715, hwInstData) hwInstData available for customer use */ 685 EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) 686 { 687 /* put your code here */ 688 return EAS_FALSE; 689 } 690 691