Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / sound / pci / asihpi / hpicmn.c
blob7ed5c26c3737f11fd2eb98a5c4da858ac23f3731
1 /******************************************************************************
3 AudioScience HPI driver
4 Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
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;
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.
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
19 \file hpicmn.c
21 Common functions used by hpixxxx.c modules
23 (C) Copyright AudioScience Inc. 1998-2003
24 *******************************************************************************/
25 #define SOURCEFILE_NAME "hpicmn.c"
27 #include "hpi_internal.h"
28 #include "hpidebug.h"
29 #include "hpimsginit.h"
31 #include "hpicmn.h"
33 struct hpi_adapters_list {
34 struct hpios_spinlock list_lock;
35 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36 u16 gw_num_adapters;
39 static struct hpi_adapters_list adapters;
41 /**
42 * Given an HPI Message that was sent out and a response that was received,
43 * validate that the response has the correct fields filled in,
44 * i.e ObjectType, Function etc
45 **/
46 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
48 if (phr->type != HPI_TYPE_RESPONSE) {
49 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
50 return HPI_ERROR_INVALID_RESPONSE;
53 if (phr->object != phm->object) {
54 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55 phr->object);
56 return HPI_ERROR_INVALID_RESPONSE;
59 if (phr->function != phm->function) {
60 HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
61 phr->function);
62 return HPI_ERROR_INVALID_RESPONSE;
65 return 0;
68 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
70 u16 retval = 0;
71 /*HPI_ASSERT(pao->type); */
73 hpios_alistlock_lock(&adapters);
75 if (pao->index >= HPI_MAX_ADAPTERS) {
76 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
77 goto unlock;
80 if (adapters.adapter[pao->index].type) {
81 int a;
82 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83 if (!adapters.adapter[a].type) {
84 HPI_DEBUG_LOG(WARNING,
85 "ASI%X duplicate index %d moved to %d\n",
86 pao->type, pao->index, a);
87 pao->index = a;
88 break;
91 if (a < 0) {
92 retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
93 goto unlock;
96 adapters.adapter[pao->index] = *pao;
97 hpios_dsplock_init(&adapters.adapter[pao->index]);
98 adapters.gw_num_adapters++;
100 unlock:
101 hpios_alistlock_unlock(&adapters);
102 return retval;
105 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
107 if (!pao->type) {
108 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109 return;
112 hpios_alistlock_lock(&adapters);
113 if (adapters.adapter[pao->index].type)
114 adapters.gw_num_adapters--;
115 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116 hpios_alistlock_unlock(&adapters);
120 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
121 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
124 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
126 struct hpi_adapter_obj *pao = NULL;
128 if (adapter_index >= HPI_MAX_ADAPTERS) {
129 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
130 adapter_index);
131 return NULL;
134 pao = &adapters.adapter[adapter_index];
135 if (pao->type != 0) {
137 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138 wAdapterIndex);
140 return pao;
141 } else {
143 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144 wAdapterIndex);
146 return NULL;
152 * wipe an HPI_ADAPTERS_LIST structure.
155 static void wipe_adapter_list(void)
157 memset(&adapters, 0, sizeof(adapters));
160 static void subsys_get_adapter(struct hpi_message *phm,
161 struct hpi_response *phr)
163 int count = phm->obj_index;
164 u16 index = 0;
166 /* find the nCount'th nonzero adapter in array */
167 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168 if (adapters.adapter[index].type) {
169 if (!count)
170 break;
171 count--;
175 if (index < HPI_MAX_ADAPTERS) {
176 phr->u.s.adapter_index = adapters.adapter[index].index;
177 phr->u.s.adapter_type = adapters.adapter[index].type;
178 } else {
179 phr->u.s.adapter_index = 0;
180 phr->u.s.adapter_type = 0;
181 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
185 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
187 unsigned int i;
188 int cached = 0;
189 if (!pC)
190 return 0;
192 if (pC->init)
193 return pC->init;
195 if (!pC->p_cache)
196 return 0;
198 if (pC->control_count && pC->cache_size_in_bytes) {
199 char *p_master_cache;
200 unsigned int byte_count = 0;
202 p_master_cache = (char *)pC->p_cache;
203 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
204 pC->control_count);
205 for (i = 0; i < pC->control_count; i++) {
206 struct hpi_control_cache_info *info =
207 (struct hpi_control_cache_info *)
208 &p_master_cache[byte_count];
210 if (!info->size_in32bit_words) {
211 if (!i) {
212 HPI_DEBUG_LOG(INFO,
213 "adap %d cache not ready?\n",
214 pC->adap_idx);
215 return 0;
217 /* The cache is invalid.
218 * Minimum valid entry size is
219 * sizeof(struct hpi_control_cache_info)
221 HPI_DEBUG_LOG(ERROR,
222 "adap %d zero size cache entry %d\n",
223 pC->adap_idx, i);
224 break;
227 if (info->control_type) {
228 pC->p_info[info->control_index] = info;
229 cached++;
230 } else { /* dummy cache entry */
231 pC->p_info[info->control_index] = NULL;
234 byte_count += info->size_in32bit_words * 4;
236 HPI_DEBUG_LOG(VERBOSE,
237 "cached %d, pinfo %p index %d type %d size %d\n",
238 cached, pC->p_info[info->control_index],
239 info->control_index, info->control_type,
240 info->size_in32bit_words);
242 /* quit loop early if whole cache has been scanned.
243 * dwControlCount is the maximum possible entries
244 * but some may be absent from the cache
246 if (byte_count >= pC->cache_size_in_bytes)
247 break;
248 /* have seen last control index */
249 if (info->control_index == pC->control_count - 1)
250 break;
253 if (byte_count != pC->cache_size_in_bytes)
254 HPI_DEBUG_LOG(WARNING,
255 "adap %d bytecount %d != cache size %d\n",
256 pC->adap_idx, byte_count,
257 pC->cache_size_in_bytes);
258 else
259 HPI_DEBUG_LOG(DEBUG,
260 "adap %d cache good, bytecount == cache size = %d\n",
261 pC->adap_idx, byte_count);
263 pC->init = (u16)cached;
265 return pC->init;
268 /** Find a control.
270 static short find_control(u16 control_index,
271 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
273 if (!control_cache_alloc_check(p_cache)) {
274 HPI_DEBUG_LOG(VERBOSE,
275 "control_cache_alloc_check() failed %d\n",
276 control_index);
277 return 0;
280 *pI = p_cache->p_info[control_index];
281 if (!*pI) {
282 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
283 control_index);
284 return 0;
285 } else {
286 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
287 (*pI)->control_type);
289 return 1;
292 /* allow unified treatment of several string fields within struct */
293 #define HPICMN_PAD_OFS_AND_SIZE(m) {\
294 offsetof(struct hpi_control_cache_pad, m), \
295 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
297 struct pad_ofs_size {
298 unsigned int offset;
299 unsigned int field_size;
302 static const struct pad_ofs_size pad_desc[] = {
303 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
304 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
305 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
306 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
309 /** CheckControlCache checks the cache and fills the struct hpi_response
310 * accordingly. It returns one if a cache hit occurred, zero otherwise.
312 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
313 struct hpi_message *phm, struct hpi_response *phr)
315 short found = 1;
316 struct hpi_control_cache_info *pI;
317 struct hpi_control_cache_single *pC;
318 size_t response_size;
319 if (!find_control(phm->obj_index, p_cache, &pI)) {
320 HPI_DEBUG_LOG(VERBOSE,
321 "HPICMN find_control() failed for adap %d\n",
322 phm->adapter_index);
323 return 0;
326 phr->error = 0;
327 phr->specific_error = 0;
328 phr->version = 0;
330 /* set the default response size */
331 response_size =
332 sizeof(struct hpi_response_header) +
333 sizeof(struct hpi_control_res);
335 /* pC is the default cached control strucure. May be cast to
336 something else in the following switch statement.
338 pC = (struct hpi_control_cache_single *)pI;
340 switch (pI->control_type) {
342 case HPI_CONTROL_METER:
343 if (phm->u.c.attribute == HPI_METER_PEAK) {
344 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
345 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
346 } else if (phm->u.c.attribute == HPI_METER_RMS) {
347 if (pC->u.meter.an_logRMS[0] ==
348 HPI_CACHE_INVALID_SHORT) {
349 phr->error =
350 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
351 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
352 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
353 } else {
354 phr->u.c.an_log_value[0] =
355 pC->u.meter.an_logRMS[0];
356 phr->u.c.an_log_value[1] =
357 pC->u.meter.an_logRMS[1];
359 } else
360 found = 0;
361 break;
362 case HPI_CONTROL_VOLUME:
363 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
364 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
365 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
366 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
367 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
368 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
369 phr->u.c.param1 =
370 HPI_BITMASK_ALL_CHANNELS;
371 else
372 phr->u.c.param1 = 0;
373 } else {
374 phr->error =
375 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
376 phr->u.c.param1 = 0;
378 } else {
379 found = 0;
381 break;
382 case HPI_CONTROL_MULTIPLEXER:
383 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
384 phr->u.c.param1 = pC->u.mux.source_node_type;
385 phr->u.c.param2 = pC->u.mux.source_node_index;
386 } else {
387 found = 0;
389 break;
390 case HPI_CONTROL_CHANNEL_MODE:
391 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
392 phr->u.c.param1 = pC->u.mode.mode;
393 else
394 found = 0;
395 break;
396 case HPI_CONTROL_LEVEL:
397 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
398 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
399 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
400 } else
401 found = 0;
402 break;
403 case HPI_CONTROL_TUNER:
404 if (phm->u.c.attribute == HPI_TUNER_FREQ)
405 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
406 else if (phm->u.c.attribute == HPI_TUNER_BAND)
407 phr->u.c.param1 = pC->u.tuner.band;
408 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
409 if (pC->u.tuner.s_level_avg ==
410 HPI_CACHE_INVALID_SHORT) {
411 phr->u.cu.tuner.s_level = 0;
412 phr->error =
413 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
414 } else
415 phr->u.cu.tuner.s_level =
416 pC->u.tuner.s_level_avg;
417 else
418 found = 0;
419 break;
420 case HPI_CONTROL_AESEBU_RECEIVER:
421 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
422 phr->u.c.param1 = pC->u.aes3rx.error_status;
423 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
424 phr->u.c.param1 = pC->u.aes3rx.format;
425 else
426 found = 0;
427 break;
428 case HPI_CONTROL_AESEBU_TRANSMITTER:
429 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
430 phr->u.c.param1 = pC->u.aes3tx.format;
431 else
432 found = 0;
433 break;
434 case HPI_CONTROL_TONEDETECTOR:
435 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
436 phr->u.c.param1 = pC->u.tone.state;
437 else
438 found = 0;
439 break;
440 case HPI_CONTROL_SILENCEDETECTOR:
441 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
442 phr->u.c.param1 = pC->u.silence.state;
443 } else
444 found = 0;
445 break;
446 case HPI_CONTROL_MICROPHONE:
447 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
448 phr->u.c.param1 = pC->u.microphone.phantom_state;
449 else
450 found = 0;
451 break;
452 case HPI_CONTROL_SAMPLECLOCK:
453 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
454 phr->u.c.param1 = pC->u.clk.source;
455 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
456 if (pC->u.clk.source_index ==
457 HPI_CACHE_INVALID_UINT16) {
458 phr->u.c.param1 = 0;
459 phr->error =
460 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
461 } else
462 phr->u.c.param1 = pC->u.clk.source_index;
463 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
464 phr->u.c.param1 = pC->u.clk.sample_rate;
465 else
466 found = 0;
467 break;
468 case HPI_CONTROL_PAD:{
469 struct hpi_control_cache_pad *p_pad;
470 p_pad = (struct hpi_control_cache_pad *)pI;
472 if (!(p_pad->field_valid_flags & (1 <<
473 HPI_CTL_ATTR_INDEX(phm->u.c.
474 attribute)))) {
475 phr->error =
476 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
477 break;
480 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
481 phr->u.c.param1 = p_pad->pI;
482 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
483 phr->u.c.param1 = p_pad->pTY;
484 else {
485 unsigned int index =
486 HPI_CTL_ATTR_INDEX(phm->u.c.
487 attribute) - 1;
488 unsigned int offset = phm->u.c.param1;
489 unsigned int pad_string_len, field_size;
490 char *pad_string;
491 unsigned int tocopy;
493 if (index > ARRAY_SIZE(pad_desc) - 1) {
494 phr->error =
495 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
496 break;
499 pad_string =
500 ((char *)p_pad) +
501 pad_desc[index].offset;
502 field_size = pad_desc[index].field_size;
503 /* Ensure null terminator */
504 pad_string[field_size - 1] = 0;
506 pad_string_len = strlen(pad_string) + 1;
508 if (offset > pad_string_len) {
509 phr->error =
510 HPI_ERROR_INVALID_CONTROL_VALUE;
511 break;
514 tocopy = pad_string_len - offset;
515 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
516 tocopy = sizeof(phr->u.cu.chars8.
517 sz_data);
519 memcpy(phr->u.cu.chars8.sz_data,
520 &pad_string[offset], tocopy);
522 phr->u.cu.chars8.remaining_chars =
523 pad_string_len - offset - tocopy;
526 break;
527 default:
528 found = 0;
529 break;
532 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
533 found ? "Cached" : "Uncached", phm->adapter_index,
534 pI->control_index, pI->control_type, phm->u.c.attribute);
536 if (found) {
537 phr->size = (u16)response_size;
538 phr->type = HPI_TYPE_RESPONSE;
539 phr->object = phm->object;
540 phr->function = phm->function;
543 return found;
546 /** Updates the cache with Set values.
548 Only update if no error.
549 Volume and Level return the limited values in the response, so use these
550 Multiplexer does so use sent values
552 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
553 struct hpi_message *phm, struct hpi_response *phr)
555 struct hpi_control_cache_single *pC;
556 struct hpi_control_cache_info *pI;
558 if (phr->error)
559 return;
561 if (!find_control(phm->obj_index, p_cache, &pI)) {
562 HPI_DEBUG_LOG(VERBOSE,
563 "HPICMN find_control() failed for adap %d\n",
564 phm->adapter_index);
565 return;
568 /* pC is the default cached control strucure.
569 May be cast to something else in the following switch statement.
571 pC = (struct hpi_control_cache_single *)pI;
573 switch (pI->control_type) {
574 case HPI_CONTROL_VOLUME:
575 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
576 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
577 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
578 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
579 if (phm->u.c.param1)
580 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
581 else
582 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
584 break;
585 case HPI_CONTROL_MULTIPLEXER:
586 /* mux does not return its setting on Set command. */
587 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
588 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
589 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
591 break;
592 case HPI_CONTROL_CHANNEL_MODE:
593 /* mode does not return its setting on Set command. */
594 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
595 pC->u.mode.mode = (u16)phm->u.c.param1;
596 break;
597 case HPI_CONTROL_LEVEL:
598 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
599 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
600 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
602 break;
603 case HPI_CONTROL_MICROPHONE:
604 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
605 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
606 break;
607 case HPI_CONTROL_AESEBU_TRANSMITTER:
608 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
609 pC->u.aes3tx.format = phm->u.c.param1;
610 break;
611 case HPI_CONTROL_AESEBU_RECEIVER:
612 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
613 pC->u.aes3rx.format = phm->u.c.param1;
614 break;
615 case HPI_CONTROL_SAMPLECLOCK:
616 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
617 pC->u.clk.source = (u16)phm->u.c.param1;
618 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
619 pC->u.clk.source_index = (u16)phm->u.c.param1;
620 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
621 pC->u.clk.sample_rate = phm->u.c.param1;
622 break;
623 default:
624 break;
628 /** Allocate control cache.
630 \return Cache pointer, or NULL if allocation fails.
632 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
633 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
635 struct hpi_control_cache *p_cache =
636 kmalloc(sizeof(*p_cache), GFP_KERNEL);
637 if (!p_cache)
638 return NULL;
640 p_cache->p_info = kcalloc(control_count, sizeof(*p_cache->p_info),
641 GFP_KERNEL);
642 if (!p_cache->p_info) {
643 kfree(p_cache);
644 return NULL;
646 p_cache->cache_size_in_bytes = size_in_bytes;
647 p_cache->control_count = control_count;
648 p_cache->p_cache = p_dsp_control_buffer;
649 p_cache->init = 0;
650 return p_cache;
653 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
655 if (p_cache) {
656 kfree(p_cache->p_info);
657 kfree(p_cache);
661 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
663 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
665 switch (phm->function) {
666 case HPI_SUBSYS_OPEN:
667 case HPI_SUBSYS_CLOSE:
668 case HPI_SUBSYS_DRIVER_UNLOAD:
669 break;
670 case HPI_SUBSYS_DRIVER_LOAD:
671 wipe_adapter_list();
672 hpios_alistlock_init(&adapters);
673 break;
674 case HPI_SUBSYS_GET_ADAPTER:
675 subsys_get_adapter(phm, phr);
676 break;
677 case HPI_SUBSYS_GET_NUM_ADAPTERS:
678 phr->u.s.num_adapters = adapters.gw_num_adapters;
679 break;
680 case HPI_SUBSYS_CREATE_ADAPTER:
681 break;
682 default:
683 phr->error = HPI_ERROR_INVALID_FUNC;
684 break;
688 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
690 switch (phm->type) {
691 case HPI_TYPE_REQUEST:
692 switch (phm->object) {
693 case HPI_OBJ_SUBSYSTEM:
694 subsys_message(phm, phr);
695 break;
697 break;
699 default:
700 phr->error = HPI_ERROR_INVALID_TYPE;
701 break;