1 /****************************************************************************** 2 3 AudioScience HPI driver 4 Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com> 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of version 2 of the GNU General Public License as 8 published by the Free Software Foundation; 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 19 \file hpicmn.c 20 21 Common functions used by hpixxxx.c modules 22 23 (C) Copyright AudioScience Inc. 1998-2003 24 *******************************************************************************/ 25 #define SOURCEFILE_NAME "hpicmn.c" 26 27 #include "hpi_internal.h" 28 #include "hpidebug.h" 29 #include "hpicmn.h" 30 31 struct hpi_adapters_list { 32 struct hpios_spinlock list_lock; 33 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS]; 34 u16 gw_num_adapters; 35 }; 36 37 static struct hpi_adapters_list adapters; 38 39 /** 40 * Given an HPI Message that was sent out and a response that was received, 41 * validate that the response has the correct fields filled in, 42 * i.e ObjectType, Function etc 43 **/ 44 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) 45 { 46 u16 error = 0; 47 48 if ((phr->type != HPI_TYPE_RESPONSE) 49 || (phr->object != phm->object) 50 || (phr->function != phm->function)) 51 error = HPI_ERROR_INVALID_RESPONSE; 52 53 return error; 54 } 55 56 u16 hpi_add_adapter(struct hpi_adapter_obj *pao) 57 { 58 u16 retval = 0; 59 /*HPI_ASSERT(pao->wAdapterType); */ 60 61 hpios_alistlock_lock(&adapters); 62 63 if (pao->index >= HPI_MAX_ADAPTERS) { 64 retval = HPI_ERROR_BAD_ADAPTER_NUMBER; 65 goto unlock; 66 } 67 68 if (adapters.adapter[pao->index].adapter_type) { 69 { 70 retval = HPI_DUPLICATE_ADAPTER_NUMBER; 71 goto unlock; 72 } 73 } 74 adapters.adapter[pao->index] = *pao; 75 hpios_dsplock_init(&adapters.adapter[pao->index]); 76 adapters.gw_num_adapters++; 77 78 unlock: 79 hpios_alistlock_un_lock(&adapters); 80 return retval; 81 } 82 83 void hpi_delete_adapter(struct hpi_adapter_obj *pao) 84 { 85 memset(pao, 0, sizeof(struct hpi_adapter_obj)); 86 87 hpios_alistlock_lock(&adapters); 88 adapters.gw_num_adapters--; /* dec the number of adapters */ 89 hpios_alistlock_un_lock(&adapters); 90 } 91 92 /** 93 * FindAdapter returns a pointer to the struct hpi_adapter_obj with 94 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure. 95 * 96 */ 97 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) 98 { 99 struct hpi_adapter_obj *pao = NULL; 100 101 if (adapter_index >= HPI_MAX_ADAPTERS) { 102 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ", 103 adapter_index); 104 return NULL; 105 } 106 107 pao = &adapters.adapter[adapter_index]; 108 if (pao->adapter_type != 0) { 109 /* 110 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n", 111 wAdapterIndex); 112 */ 113 return pao; 114 } else { 115 /* 116 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n", 117 wAdapterIndex); 118 */ 119 return NULL; 120 } 121 } 122 123 /** 124 * 125 * wipe an HPI_ADAPTERS_LIST structure. 126 * 127 **/ 128 static void wipe_adapter_list(void 129 ) 130 { 131 memset(&adapters, 0, sizeof(adapters)); 132 } 133 134 /** 135 * SubSysGetAdapters fills awAdapterList in an struct hpi_response structure 136 * with all adapters in the given HPI_ADAPTERS_LIST. 137 * 138 */ 139 static void subsys_get_adapters(struct hpi_response *phr) 140 { 141 /* fill in the response adapter array with the position */ 142 /* identified by the adapter number/index of the adapters in */ 143 /* this HPI */ 144 /* i.e. if we have an A120 with it's jumper set to */ 145 /* Adapter Number 2 then put an Adapter type A120 in the */ 146 /* array in position 1 */ 147 /* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */ 148 149 /* input: NONE */ 150 /* output: wNumAdapters */ 151 /* awAdapter[] */ 152 /* */ 153 154 short i; 155 struct hpi_adapter_obj *pao = NULL; 156 157 HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n"); 158 159 /* for each adapter, place it's type in the position of the array */ 160 /* corresponding to it's adapter number */ 161 for (i = 0; i < adapters.gw_num_adapters; i++) { 162 pao = &adapters.adapter[i]; 163 if (phr->u.s.aw_adapter_list[pao->index] != 0) { 164 phr->error = HPI_DUPLICATE_ADAPTER_NUMBER; 165 phr->specific_error = pao->index; 166 return; 167 } 168 phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type; 169 } 170 171 phr->u.s.num_adapters = adapters.gw_num_adapters; 172 phr->error = 0; /* the function completed OK; */ 173 } 174 175 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) 176 { 177 unsigned int i; 178 int cached = 0; 179 if (!pC) 180 return 0; 181 if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count) 182 && (pC->cache_size_in_bytes) 183 ) { 184 u32 *p_master_cache; 185 pC->init = 1; 186 187 p_master_cache = (u32 *)pC->p_cache; 188 HPI_DEBUG_LOG(VERBOSE, "check %d controls\n", 189 pC->control_count); 190 for (i = 0; i < pC->control_count; i++) { 191 struct hpi_control_cache_info *info = 192 (struct hpi_control_cache_info *) 193 p_master_cache; 194 195 if (info->control_type) { 196 pC->p_info[i] = info; 197 cached++; 198 } else 199 pC->p_info[i] = NULL; 200 201 if (info->size_in32bit_words) 202 p_master_cache += info->size_in32bit_words; 203 else 204 p_master_cache += 205 sizeof(struct 206 hpi_control_cache_single) / 207 sizeof(u32); 208 209 HPI_DEBUG_LOG(VERBOSE, 210 "cached %d, pinfo %p index %d type %d\n", 211 cached, pC->p_info[i], info->control_index, 212 info->control_type); 213 } 214 /* 215 We didn't find anything to cache, so try again later ! 216 */ 217 if (!cached) 218 pC->init = 0; 219 } 220 return pC->init; 221 } 222 223 /** Find a control. 224 */ 225 static short find_control(struct hpi_message *phm, 226 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI, 227 u16 *pw_control_index) 228 { 229 *pw_control_index = phm->obj_index; 230 231 if (!control_cache_alloc_check(p_cache)) { 232 HPI_DEBUG_LOG(VERBOSE, 233 "control_cache_alloc_check() failed. adap%d ci%d\n", 234 phm->adapter_index, *pw_control_index); 235 return 0; 236 } 237 238 *pI = p_cache->p_info[*pw_control_index]; 239 if (!*pI) { 240 HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n", 241 phm->adapter_index, *pw_control_index); 242 return 0; 243 } else { 244 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", 245 (*pI)->control_type); 246 } 247 return 1; 248 } 249 250 /** Used by the kernel driver to figure out if a buffer needs mapping. 251 */ 252 short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache, 253 struct hpi_message *phm, void **p, unsigned int *pN) 254 { 255 *pN = 0; 256 *p = NULL; 257 if ((phm->function == HPI_CONTROL_GET_STATE) 258 && (phm->object == HPI_OBJ_CONTROLEX) 259 ) { 260 u16 control_index; 261 struct hpi_control_cache_info *pI; 262 263 if (!find_control(phm, p_cache, &pI, &control_index)) 264 return 0; 265 } 266 return 0; 267 } 268 269 /* allow unified treatment of several string fields within struct */ 270 #define HPICMN_PAD_OFS_AND_SIZE(m) {\ 271 offsetof(struct hpi_control_cache_pad, m), \ 272 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) } 273 274 struct pad_ofs_size { 275 unsigned int offset; 276 unsigned int field_size; 277 }; 278 279 static struct pad_ofs_size pad_desc[] = { 280 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ 281 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ 282 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ 283 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */ 284 }; 285 286 /** CheckControlCache checks the cache and fills the struct hpi_response 287 * accordingly. It returns one if a cache hit occurred, zero otherwise. 288 */ 289 short hpi_check_control_cache(struct hpi_control_cache *p_cache, 290 struct hpi_message *phm, struct hpi_response *phr) 291 { 292 short found = 1; 293 u16 control_index; 294 struct hpi_control_cache_info *pI; 295 struct hpi_control_cache_single *pC; 296 struct hpi_control_cache_pad *p_pad; 297 298 if (!find_control(phm, p_cache, &pI, &control_index)) 299 return 0; 300 301 phr->error = 0; 302 303 /* pC is the default cached control strucure. May be cast to 304 something else in the following switch statement. 305 */ 306 pC = (struct hpi_control_cache_single *)pI; 307 p_pad = (struct hpi_control_cache_pad *)pI; 308 309 switch (pI->control_type) { 310 311 case HPI_CONTROL_METER: 312 if (phm->u.c.attribute == HPI_METER_PEAK) { 313 phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0]; 314 phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1]; 315 } else if (phm->u.c.attribute == HPI_METER_RMS) { 316 phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0]; 317 phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1]; 318 } else 319 found = 0; 320 break; 321 case HPI_CONTROL_VOLUME: 322 if (phm->u.c.attribute == HPI_VOLUME_GAIN) { 323 phr->u.c.an_log_value[0] = pC->u.v.an_log[0]; 324 phr->u.c.an_log_value[1] = pC->u.v.an_log[1]; 325 } else 326 found = 0; 327 break; 328 case HPI_CONTROL_MULTIPLEXER: 329 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { 330 phr->u.c.param1 = pC->u.x.source_node_type; 331 phr->u.c.param2 = pC->u.x.source_node_index; 332 } else { 333 found = 0; 334 } 335 break; 336 case HPI_CONTROL_CHANNEL_MODE: 337 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) 338 phr->u.c.param1 = pC->u.m.mode; 339 else 340 found = 0; 341 break; 342 case HPI_CONTROL_LEVEL: 343 if (phm->u.c.attribute == HPI_LEVEL_GAIN) { 344 phr->u.c.an_log_value[0] = pC->u.l.an_log[0]; 345 phr->u.c.an_log_value[1] = pC->u.l.an_log[1]; 346 } else 347 found = 0; 348 break; 349 case HPI_CONTROL_TUNER: 350 if (phm->u.c.attribute == HPI_TUNER_FREQ) 351 phr->u.c.param1 = pC->u.t.freq_ink_hz; 352 else if (phm->u.c.attribute == HPI_TUNER_BAND) 353 phr->u.c.param1 = pC->u.t.band; 354 else if ((phm->u.c.attribute == HPI_TUNER_LEVEL) 355 && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE)) 356 if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) { 357 phr->u.c.param1 = 0; 358 phr->error = 359 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 360 } else 361 phr->u.c.param1 = pC->u.t.level; 362 else 363 found = 0; 364 break; 365 case HPI_CONTROL_AESEBU_RECEIVER: 366 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) 367 phr->u.c.param1 = pC->u.aes3rx.error_status; 368 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) 369 phr->u.c.param1 = pC->u.aes3rx.source; 370 else 371 found = 0; 372 break; 373 case HPI_CONTROL_AESEBU_TRANSMITTER: 374 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) 375 phr->u.c.param1 = pC->u.aes3tx.format; 376 else 377 found = 0; 378 break; 379 case HPI_CONTROL_TONEDETECTOR: 380 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE) 381 phr->u.c.param1 = pC->u.tone.state; 382 else 383 found = 0; 384 break; 385 case HPI_CONTROL_SILENCEDETECTOR: 386 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { 387 phr->u.c.param1 = pC->u.silence.state; 388 phr->u.c.param2 = pC->u.silence.count; 389 } else 390 found = 0; 391 break; 392 case HPI_CONTROL_MICROPHONE: 393 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) 394 phr->u.c.param1 = pC->u.phantom_power.state; 395 else 396 found = 0; 397 break; 398 case HPI_CONTROL_SAMPLECLOCK: 399 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) 400 phr->u.c.param1 = pC->u.clk.source; 401 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { 402 if (pC->u.clk.source_index == 403 HPI_ERROR_ILLEGAL_CACHE_VALUE) { 404 phr->u.c.param1 = 0; 405 phr->error = 406 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 407 } else 408 phr->u.c.param1 = pC->u.clk.source_index; 409 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) 410 phr->u.c.param1 = pC->u.clk.sample_rate; 411 else 412 found = 0; 413 break; 414 case HPI_CONTROL_PAD: 415 416 if (!(p_pad->field_valid_flags & (1 << 417 HPI_CTL_ATTR_INDEX(phm->u.c. 418 attribute)))) { 419 phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 420 break; 421 } 422 423 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) 424 phr->u.c.param1 = p_pad->pI; 425 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) 426 phr->u.c.param1 = p_pad->pTY; 427 else { 428 unsigned int index = 429 HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1; 430 unsigned int offset = phm->u.c.param1; 431 unsigned int pad_string_len, field_size; 432 char *pad_string; 433 unsigned int tocopy; 434 435 HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n", 436 phm->u.c.attribute); 437 438 if (index > ARRAY_SIZE(pad_desc) - 1) { 439 phr->error = 440 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 441 break; 442 } 443 444 pad_string = ((char *)p_pad) + pad_desc[index].offset; 445 field_size = pad_desc[index].field_size; 446 /* Ensure null terminator */ 447 pad_string[field_size - 1] = 0; 448 449 pad_string_len = strlen(pad_string) + 1; 450 451 if (offset > pad_string_len) { 452 phr->error = HPI_ERROR_INVALID_CONTROL_VALUE; 453 break; 454 } 455 456 tocopy = pad_string_len - offset; 457 if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) 458 tocopy = sizeof(phr->u.cu.chars8.sz_data); 459 460 HPI_DEBUG_LOG(VERBOSE, 461 "PADS memcpy(%d), offset %d \n", tocopy, 462 offset); 463 memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset], 464 tocopy); 465 466 phr->u.cu.chars8.remaining_chars = 467 pad_string_len - offset - tocopy; 468 } 469 break; 470 default: 471 found = 0; 472 break; 473 } 474 475 if (found) 476 HPI_DEBUG_LOG(VERBOSE, 477 "cached adap %d, ctl %d, type %d, attr %d\n", 478 phm->adapter_index, pI->control_index, 479 pI->control_type, phm->u.c.attribute); 480 else 481 HPI_DEBUG_LOG(VERBOSE, 482 "uncached adap %d, ctl %d, ctl type %d\n", 483 phm->adapter_index, pI->control_index, 484 pI->control_type); 485 486 if (found) 487 phr->size = 488 sizeof(struct hpi_response_header) + 489 sizeof(struct hpi_control_res); 490 491 return found; 492 } 493 494 /** Updates the cache with Set values. 495 496 Only update if no error. 497 Volume and Level return the limited values in the response, so use these 498 Multiplexer does so use sent values 499 */ 500 void hpi_sync_control_cache(struct hpi_control_cache *p_cache, 501 struct hpi_message *phm, struct hpi_response *phr) 502 { 503 u16 control_index; 504 struct hpi_control_cache_single *pC; 505 struct hpi_control_cache_info *pI; 506 507 if (phr->error) 508 return; 509 510 if (!find_control(phm, p_cache, &pI, &control_index)) 511 return; 512 513 /* pC is the default cached control strucure. 514 May be cast to something else in the following switch statement. 515 */ 516 pC = (struct hpi_control_cache_single *)pI; 517 518 switch (pI->control_type) { 519 case HPI_CONTROL_VOLUME: 520 if (phm->u.c.attribute == HPI_VOLUME_GAIN) { 521 pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; 522 pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; 523 } 524 break; 525 case HPI_CONTROL_MULTIPLEXER: 526 /* mux does not return its setting on Set command. */ 527 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { 528 pC->u.x.source_node_type = (u16)phm->u.c.param1; 529 pC->u.x.source_node_index = (u16)phm->u.c.param2; 530 } 531 break; 532 case HPI_CONTROL_CHANNEL_MODE: 533 /* mode does not return its setting on Set command. */ 534 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) 535 pC->u.m.mode = (u16)phm->u.c.param1; 536 break; 537 case HPI_CONTROL_LEVEL: 538 if (phm->u.c.attribute == HPI_LEVEL_GAIN) { 539 pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; 540 pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; 541 } 542 break; 543 case HPI_CONTROL_MICROPHONE: 544 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) 545 pC->u.phantom_power.state = (u16)phm->u.c.param1; 546 break; 547 case HPI_CONTROL_AESEBU_TRANSMITTER: 548 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) 549 pC->u.aes3tx.format = phm->u.c.param1; 550 break; 551 case HPI_CONTROL_AESEBU_RECEIVER: 552 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) 553 pC->u.aes3rx.source = phm->u.c.param1; 554 break; 555 case HPI_CONTROL_SAMPLECLOCK: 556 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) 557 pC->u.clk.source = (u16)phm->u.c.param1; 558 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) 559 pC->u.clk.source_index = (u16)phm->u.c.param1; 560 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) 561 pC->u.clk.sample_rate = phm->u.c.param1; 562 break; 563 default: 564 break; 565 } 566 } 567 568 struct hpi_control_cache *hpi_alloc_control_cache(const u32 569 number_of_controls, const u32 size_in_bytes, 570 struct hpi_control_cache_info *pDSP_control_buffer) 571 { 572 struct hpi_control_cache *p_cache = 573 kmalloc(sizeof(*p_cache), GFP_KERNEL); 574 if (!p_cache) 575 return NULL; 576 p_cache->p_info = 577 kmalloc(sizeof(*p_cache->p_info) * number_of_controls, 578 GFP_KERNEL); 579 if (!p_cache->p_info) { 580 kfree(p_cache); 581 return NULL; 582 } 583 p_cache->cache_size_in_bytes = size_in_bytes; 584 p_cache->control_count = number_of_controls; 585 p_cache->p_cache = 586 (struct hpi_control_cache_single *)pDSP_control_buffer; 587 p_cache->init = 0; 588 return p_cache; 589 } 590 591 void hpi_free_control_cache(struct hpi_control_cache *p_cache) 592 { 593 if (p_cache->init) { 594 kfree(p_cache->p_info); 595 p_cache->p_info = NULL; 596 p_cache->init = 0; 597 kfree(p_cache); 598 } 599 } 600 601 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) 602 { 603 604 switch (phm->function) { 605 case HPI_SUBSYS_OPEN: 606 case HPI_SUBSYS_CLOSE: 607 case HPI_SUBSYS_DRIVER_UNLOAD: 608 phr->error = 0; 609 break; 610 case HPI_SUBSYS_DRIVER_LOAD: 611 wipe_adapter_list(); 612 hpios_alistlock_init(&adapters); 613 phr->error = 0; 614 break; 615 case HPI_SUBSYS_GET_INFO: 616 subsys_get_adapters(phr); 617 break; 618 case HPI_SUBSYS_CREATE_ADAPTER: 619 case HPI_SUBSYS_DELETE_ADAPTER: 620 phr->error = 0; 621 break; 622 default: 623 phr->error = HPI_ERROR_INVALID_FUNC; 624 break; 625 } 626 } 627 628 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr) 629 { 630 switch (phm->type) { 631 case HPI_TYPE_MESSAGE: 632 switch (phm->object) { 633 case HPI_OBJ_SUBSYSTEM: 634 subsys_message(phm, phr); 635 break; 636 } 637 break; 638 639 default: 640 phr->error = HPI_ERROR_INVALID_TYPE; 641 break; 642 } 643 } 644