blob: 3e9c5c289764d7bc1923169853950028f95e129d [file] [log] [blame]
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001/******************************************************************************
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"
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130029#include "hpimsginit.h"
30
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020031#include "hpicmn.h"
32
33struct hpi_adapters_list {
34 struct hpios_spinlock list_lock;
35 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36 u16 gw_num_adapters;
37};
38
39static struct hpi_adapters_list adapters;
40
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**/
46u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130048 if (phr->type != HPI_TYPE_RESPONSE) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130049 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130050 return HPI_ERROR_INVALID_RESPONSE;
51 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020052
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130053 if (phr->object != phm->object) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130054 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55 phr->object);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130056 return HPI_ERROR_INVALID_RESPONSE;
57 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020058
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130059 if (phr->function != phm->function) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +130060 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
61 phr->function);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130062 return HPI_ERROR_INVALID_RESPONSE;
63 }
64
65 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020066}
67
68u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69{
70 u16 retval = 0;
71 /*HPI_ASSERT(pao->wAdapterType); */
72
73 hpios_alistlock_lock(&adapters);
74
75 if (pao->index >= HPI_MAX_ADAPTERS) {
76 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
77 goto unlock;
78 }
79
80 if (adapters.adapter[pao->index].adapter_type) {
Eliot Blennerhassettd6f1c1c2011-02-10 17:26:12 +130081 int a;
82 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83 if (!adapters.adapter[a].adapter_type) {
84 HPI_DEBUG_LOG(WARNING,
85 "ASI%X duplicate index %d moved to %d\n",
86 pao->adapter_type, pao->index, a);
87 pao->index = a;
88 break;
89 }
90 }
91 if (a < 0) {
92 retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020093 goto unlock;
94 }
95 }
96 adapters.adapter[pao->index] = *pao;
97 hpios_dsplock_init(&adapters.adapter[pao->index]);
98 adapters.gw_num_adapters++;
99
100unlock:
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300101 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200102 return retval;
103}
104
105void hpi_delete_adapter(struct hpi_adapter_obj *pao)
106{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300107 if (!pao->adapter_type) {
108 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109 return;
110 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200111
112 hpios_alistlock_lock(&adapters);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300113 if (adapters.adapter[pao->index].adapter_type)
114 adapters.gw_num_adapters--;
115 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200117}
118
119/**
120* FindAdapter returns a pointer to the struct hpi_adapter_obj with
121* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
122*
123*/
124struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
125{
126 struct hpi_adapter_obj *pao = NULL;
127
128 if (adapter_index >= HPI_MAX_ADAPTERS) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300129 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200130 adapter_index);
131 return NULL;
132 }
133
134 pao = &adapters.adapter[adapter_index];
135 if (pao->adapter_type != 0) {
136 /*
137 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138 wAdapterIndex);
139 */
140 return pao;
141 } else {
142 /*
143 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144 wAdapterIndex);
145 */
146 return NULL;
147 }
148}
149
150/**
151*
152* wipe an HPI_ADAPTERS_LIST structure.
153*
154**/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300155static void wipe_adapter_list(void)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200156{
157 memset(&adapters, 0, sizeof(adapters));
158}
159
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300160static void subsys_get_adapter(struct hpi_message *phm,
161 struct hpi_response *phr)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200162{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300163 int count = phm->obj_index;
164 u16 index = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200165
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300166 /* find the nCount'th nonzero adapter in array */
167 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168 if (adapters.adapter[index].adapter_type) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300169 if (!count)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300170 break;
171 count--;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200172 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200173 }
174
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300175 if (index < HPI_MAX_ADAPTERS) {
176 phr->u.s.adapter_index = adapters.adapter[index].index;
Eliot Blennerhassett2f918a62011-02-10 17:26:09 +1300177 phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300178 } else {
179 phr->u.s.adapter_index = 0;
Eliot Blennerhassett2f918a62011-02-10 17:26:09 +1300180 phr->u.s.adapter_type = 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300181 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
182 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200183}
184
185static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
186{
187 unsigned int i;
188 int cached = 0;
189 if (!pC)
190 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200191
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300192 if (pC->init)
193 return pC->init;
194
195 if (!pC->p_cache)
196 return 0;
197
198 if (pC->control_count && pC->cache_size_in_bytes) {
199 char *p_master_cache;
200 unsigned int byte_count = 0;
201
202 p_master_cache = (char *)pC->p_cache;
203 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200204 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 *)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300208 &p_master_cache[byte_count];
209
210 if (!info->size_in32bit_words) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300211 if (!i) {
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300212 HPI_DEBUG_LOG(INFO,
213 "adap %d cache not ready?\n",
214 pC->adap_idx);
215 return 0;
216 }
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300217 /* The cache is invalid.
218 * Minimum valid entry size is
219 * sizeof(struct hpi_control_cache_info)
220 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300221 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300222 "adap %d zero size cache entry %d\n",
223 pC->adap_idx, i);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300224 break;
225 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200226
227 if (info->control_type) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300228 pC->p_info[info->control_index] = info;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200229 cached++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300230 } else /* dummy cache entry */
231 pC->p_info[info->control_index] = NULL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200232
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300233 byte_count += info->size_in32bit_words * 4;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200234
235 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300236 "cached %d, pinfo %p index %d type %d size %d\n",
237 cached, pC->p_info[info->control_index],
238 info->control_index, info->control_type,
239 info->size_in32bit_words);
240
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300241 /* quit loop early if whole cache has been scanned.
242 * dwControlCount is the maximum possible entries
243 * but some may be absent from the cache
244 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300245 if (byte_count >= pC->cache_size_in_bytes)
246 break;
247 /* have seen last control index */
248 if (info->control_index == pC->control_count - 1)
249 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200250 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300251
252 if (byte_count != pC->cache_size_in_bytes)
253 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300254 "adap %d bytecount %d != cache size %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300255 pC->adap_idx, byte_count,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300256 pC->cache_size_in_bytes);
257 else
258 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300259 "adap %d cache good, bytecount == cache size = %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300260 pC->adap_idx, byte_count);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300261
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300262 pC->init = (u16)cached;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200263 }
264 return pC->init;
265}
266
267/** Find a control.
268*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300269static short find_control(u16 control_index,
270 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200271{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200272 if (!control_cache_alloc_check(p_cache)) {
273 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300274 "control_cache_alloc_check() failed %d\n",
275 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200276 return 0;
277 }
278
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300279 *pI = p_cache->p_info[control_index];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200280 if (!*pI) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300281 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
282 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200283 return 0;
284 } else {
285 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
286 (*pI)->control_type);
287 }
288 return 1;
289}
290
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200291/* allow unified treatment of several string fields within struct */
292#define HPICMN_PAD_OFS_AND_SIZE(m) {\
293 offsetof(struct hpi_control_cache_pad, m), \
294 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
295
296struct pad_ofs_size {
297 unsigned int offset;
298 unsigned int field_size;
299};
300
301static struct pad_ofs_size pad_desc[] = {
302 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
303 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
304 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
305 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
306};
307
308/** CheckControlCache checks the cache and fills the struct hpi_response
309 * accordingly. It returns one if a cache hit occurred, zero otherwise.
310 */
311short hpi_check_control_cache(struct hpi_control_cache *p_cache,
312 struct hpi_message *phm, struct hpi_response *phr)
313{
314 short found = 1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200315 struct hpi_control_cache_info *pI;
316 struct hpi_control_cache_single *pC;
317 struct hpi_control_cache_pad *p_pad;
318
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300319 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);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200323 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300324 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200325
326 phr->error = 0;
327
328 /* pC is the default cached control strucure. May be cast to
329 something else in the following switch statement.
330 */
331 pC = (struct hpi_control_cache_single *)pI;
332 p_pad = (struct hpi_control_cache_pad *)pI;
333
334 switch (pI->control_type) {
335
336 case HPI_CONTROL_METER:
337 if (phm->u.c.attribute == HPI_METER_PEAK) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300338 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
339 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200340 } else if (phm->u.c.attribute == HPI_METER_RMS) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300341 if (pC->u.meter.an_logRMS[0] ==
342 HPI_CACHE_INVALID_SHORT) {
343 phr->error =
344 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
345 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
346 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
347 } else {
348 phr->u.c.an_log_value[0] =
349 pC->u.meter.an_logRMS[0];
350 phr->u.c.an_log_value[1] =
351 pC->u.meter.an_logRMS[1];
352 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200353 } else
354 found = 0;
355 break;
356 case HPI_CONTROL_VOLUME:
357 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300358 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
359 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300360 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
361 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
362 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
363 phr->u.c.param1 =
364 HPI_BITMASK_ALL_CHANNELS;
365 else
366 phr->u.c.param1 = 0;
367 } else {
368 phr->error =
369 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
370 phr->u.c.param1 = 0;
371 }
372 } else {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200373 found = 0;
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300374 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200375 break;
376 case HPI_CONTROL_MULTIPLEXER:
377 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300378 phr->u.c.param1 = pC->u.mux.source_node_type;
379 phr->u.c.param2 = pC->u.mux.source_node_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200380 } else {
381 found = 0;
382 }
383 break;
384 case HPI_CONTROL_CHANNEL_MODE:
385 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300386 phr->u.c.param1 = pC->u.mode.mode;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200387 else
388 found = 0;
389 break;
390 case HPI_CONTROL_LEVEL:
391 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300392 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
393 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200394 } else
395 found = 0;
396 break;
397 case HPI_CONTROL_TUNER:
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200398 if (phm->u.c.attribute == HPI_TUNER_FREQ)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300399 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200400 else if (phm->u.c.attribute == HPI_TUNER_BAND)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300401 phr->u.c.param1 = pC->u.tuner.band;
402 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
403 if (pC->u.tuner.s_level_avg ==
404 HPI_CACHE_INVALID_SHORT) {
405 phr->u.cu.tuner.s_level = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200406 phr->error =
407 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
408 } else
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300409 phr->u.cu.tuner.s_level =
410 pC->u.tuner.s_level_avg;
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200411 else
412 found = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200413 break;
414 case HPI_CONTROL_AESEBU_RECEIVER:
415 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
416 phr->u.c.param1 = pC->u.aes3rx.error_status;
417 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300418 phr->u.c.param1 = pC->u.aes3rx.format;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200419 else
420 found = 0;
421 break;
422 case HPI_CONTROL_AESEBU_TRANSMITTER:
423 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
424 phr->u.c.param1 = pC->u.aes3tx.format;
425 else
426 found = 0;
427 break;
428 case HPI_CONTROL_TONEDETECTOR:
429 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
430 phr->u.c.param1 = pC->u.tone.state;
431 else
432 found = 0;
433 break;
434 case HPI_CONTROL_SILENCEDETECTOR:
435 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
436 phr->u.c.param1 = pC->u.silence.state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200437 } else
438 found = 0;
439 break;
440 case HPI_CONTROL_MICROPHONE:
441 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300442 phr->u.c.param1 = pC->u.microphone.phantom_state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200443 else
444 found = 0;
445 break;
446 case HPI_CONTROL_SAMPLECLOCK:
447 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
448 phr->u.c.param1 = pC->u.clk.source;
449 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
450 if (pC->u.clk.source_index ==
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300451 HPI_CACHE_INVALID_UINT16) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200452 phr->u.c.param1 = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200453 phr->error =
454 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200455 } else
456 phr->u.c.param1 = pC->u.clk.source_index;
457 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
458 phr->u.c.param1 = pC->u.clk.sample_rate;
459 else
460 found = 0;
461 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300462 case HPI_CONTROL_PAD:{
463 struct hpi_control_cache_pad *p_pad;
464 p_pad = (struct hpi_control_cache_pad *)pI;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200465
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300466 if (!(p_pad->field_valid_flags & (1 <<
467 HPI_CTL_ATTR_INDEX(phm->u.c.
468 attribute)))) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200469 phr->error =
470 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
471 break;
472 }
473
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300474 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
475 phr->u.c.param1 = p_pad->pI;
476 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
477 phr->u.c.param1 = p_pad->pTY;
478 else {
479 unsigned int index =
480 HPI_CTL_ATTR_INDEX(phm->u.c.
481 attribute) - 1;
482 unsigned int offset = phm->u.c.param1;
483 unsigned int pad_string_len, field_size;
484 char *pad_string;
485 unsigned int tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200486
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300487 if (index > ARRAY_SIZE(pad_desc) - 1) {
488 phr->error =
489 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
490 break;
491 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200492
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300493 pad_string =
494 ((char *)p_pad) +
495 pad_desc[index].offset;
496 field_size = pad_desc[index].field_size;
497 /* Ensure null terminator */
498 pad_string[field_size - 1] = 0;
499
500 pad_string_len = strlen(pad_string) + 1;
501
502 if (offset > pad_string_len) {
503 phr->error =
504 HPI_ERROR_INVALID_CONTROL_VALUE;
505 break;
506 }
507
508 tocopy = pad_string_len - offset;
509 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
510 tocopy = sizeof(phr->u.cu.chars8.
511 sz_data);
512
513 memcpy(phr->u.cu.chars8.sz_data,
514 &pad_string[offset], tocopy);
515
516 phr->u.cu.chars8.remaining_chars =
517 pad_string_len - offset - tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200518 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200519 }
520 break;
521 default:
522 found = 0;
523 break;
524 }
525
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300526 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
527 found ? "Cached" : "Uncached", phm->adapter_index,
528 pI->control_index, pI->control_type, phm->u.c.attribute);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200529
530 if (found)
531 phr->size =
532 sizeof(struct hpi_response_header) +
533 sizeof(struct hpi_control_res);
534
535 return found;
536}
537
538/** Updates the cache with Set values.
539
540Only update if no error.
541Volume and Level return the limited values in the response, so use these
542Multiplexer does so use sent values
543*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300544void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200545 struct hpi_message *phm, struct hpi_response *phr)
546{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200547 struct hpi_control_cache_single *pC;
548 struct hpi_control_cache_info *pI;
549
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200550 if (phr->error)
551 return;
552
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300553 if (!find_control(phm->obj_index, p_cache, &pI)) {
554 HPI_DEBUG_LOG(VERBOSE,
555 "HPICMN find_control() failed for adap %d\n",
556 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200557 return;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300558 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200559
560 /* pC is the default cached control strucure.
561 May be cast to something else in the following switch statement.
562 */
563 pC = (struct hpi_control_cache_single *)pI;
564
565 switch (pI->control_type) {
566 case HPI_CONTROL_VOLUME:
567 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300568 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
569 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassettfc3a3992011-02-10 17:26:11 +1300570 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
571 if (phm->u.c.param1)
572 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
573 else
574 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200575 }
576 break;
577 case HPI_CONTROL_MULTIPLEXER:
578 /* mux does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200579 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300580 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
581 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200582 }
583 break;
584 case HPI_CONTROL_CHANNEL_MODE:
585 /* mode does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200586 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300587 pC->u.mode.mode = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200588 break;
589 case HPI_CONTROL_LEVEL:
590 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300591 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
592 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200593 }
594 break;
595 case HPI_CONTROL_MICROPHONE:
596 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300597 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200598 break;
599 case HPI_CONTROL_AESEBU_TRANSMITTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200600 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
601 pC->u.aes3tx.format = phm->u.c.param1;
602 break;
603 case HPI_CONTROL_AESEBU_RECEIVER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200604 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300605 pC->u.aes3rx.format = phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200606 break;
607 case HPI_CONTROL_SAMPLECLOCK:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200608 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
609 pC->u.clk.source = (u16)phm->u.c.param1;
610 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
611 pC->u.clk.source_index = (u16)phm->u.c.param1;
612 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
613 pC->u.clk.sample_rate = phm->u.c.param1;
614 break;
615 default:
616 break;
617 }
618}
619
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300620struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
621 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200622{
623 struct hpi_control_cache *p_cache =
624 kmalloc(sizeof(*p_cache), GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200625 if (!p_cache)
626 return NULL;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300627
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200628 p_cache->p_info =
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300629 kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200630 if (!p_cache->p_info) {
631 kfree(p_cache);
632 return NULL;
633 }
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300634 memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200635 p_cache->cache_size_in_bytes = size_in_bytes;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300636 p_cache->control_count = control_count;
637 p_cache->p_cache = p_dsp_control_buffer;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200638 p_cache->init = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200639 return p_cache;
640}
641
642void hpi_free_control_cache(struct hpi_control_cache *p_cache)
643{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300644 if (p_cache) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200645 kfree(p_cache->p_info);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200646 kfree(p_cache);
647 }
648}
649
650static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
651{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300652 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200653
654 switch (phm->function) {
655 case HPI_SUBSYS_OPEN:
656 case HPI_SUBSYS_CLOSE:
657 case HPI_SUBSYS_DRIVER_UNLOAD:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200658 break;
659 case HPI_SUBSYS_DRIVER_LOAD:
660 wipe_adapter_list();
661 hpios_alistlock_init(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200662 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300663 case HPI_SUBSYS_GET_ADAPTER:
664 subsys_get_adapter(phm, phr);
665 break;
666 case HPI_SUBSYS_GET_NUM_ADAPTERS:
667 phr->u.s.num_adapters = adapters.gw_num_adapters;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200668 break;
669 case HPI_SUBSYS_CREATE_ADAPTER:
670 case HPI_SUBSYS_DELETE_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200671 break;
672 default:
673 phr->error = HPI_ERROR_INVALID_FUNC;
674 break;
675 }
676}
677
678void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
679{
680 switch (phm->type) {
681 case HPI_TYPE_MESSAGE:
682 switch (phm->object) {
683 case HPI_OBJ_SUBSYSTEM:
684 subsys_message(phm, phr);
685 break;
686 }
687 break;
688
689 default:
690 phr->error = HPI_ERROR_INVALID_TYPE;
691 break;
692 }
693}