blob: 4d696ab4b1f068d9fcfaf3f0bff59939e8ab956f [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) {
81 {
82 retval = HPI_DUPLICATE_ADAPTER_NUMBER;
83 goto unlock;
84 }
85 }
86 adapters.adapter[pao->index] = *pao;
87 hpios_dsplock_init(&adapters.adapter[pao->index]);
88 adapters.gw_num_adapters++;
89
90unlock:
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130091 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020092 return retval;
93}
94
95void hpi_delete_adapter(struct hpi_adapter_obj *pao)
96{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130097 if (!pao->adapter_type) {
98 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
99 return;
100 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200101
102 hpios_alistlock_lock(&adapters);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300103 if (adapters.adapter[pao->index].adapter_type)
104 adapters.gw_num_adapters--;
105 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
106 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200107}
108
109/**
110* FindAdapter returns a pointer to the struct hpi_adapter_obj with
111* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
112*
113*/
114struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
115{
116 struct hpi_adapter_obj *pao = NULL;
117
118 if (adapter_index >= HPI_MAX_ADAPTERS) {
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300119 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200120 adapter_index);
121 return NULL;
122 }
123
124 pao = &adapters.adapter[adapter_index];
125 if (pao->adapter_type != 0) {
126 /*
127 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
128 wAdapterIndex);
129 */
130 return pao;
131 } else {
132 /*
133 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
134 wAdapterIndex);
135 */
136 return NULL;
137 }
138}
139
140/**
141*
142* wipe an HPI_ADAPTERS_LIST structure.
143*
144**/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300145static void wipe_adapter_list(void)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200146{
147 memset(&adapters, 0, sizeof(adapters));
148}
149
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300150static void subsys_get_adapter(struct hpi_message *phm,
151 struct hpi_response *phr)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200152{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300153 int count = phm->obj_index;
154 u16 index = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200155
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300156 /* find the nCount'th nonzero adapter in array */
157 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
158 if (adapters.adapter[index].adapter_type) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300159 if (!count)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300160 break;
161 count--;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200162 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200163 }
164
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300165 if (index < HPI_MAX_ADAPTERS) {
166 phr->u.s.adapter_index = adapters.adapter[index].index;
167 phr->u.s.aw_adapter_list[0] =
168 adapters.adapter[index].adapter_type;
169 } else {
170 phr->u.s.adapter_index = 0;
171 phr->u.s.aw_adapter_list[0] = 0;
172 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
173 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200174}
175
176static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
177{
178 unsigned int i;
179 int cached = 0;
180 if (!pC)
181 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200182
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300183 if (pC->init)
184 return pC->init;
185
186 if (!pC->p_cache)
187 return 0;
188
189 if (pC->control_count && pC->cache_size_in_bytes) {
190 char *p_master_cache;
191 unsigned int byte_count = 0;
192
193 p_master_cache = (char *)pC->p_cache;
194 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200195 pC->control_count);
196 for (i = 0; i < pC->control_count; i++) {
197 struct hpi_control_cache_info *info =
198 (struct hpi_control_cache_info *)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300199 &p_master_cache[byte_count];
200
201 if (!info->size_in32bit_words) {
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300202 if (!i) {
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300203 HPI_DEBUG_LOG(INFO,
204 "adap %d cache not ready?\n",
205 pC->adap_idx);
206 return 0;
207 }
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300208 /* The cache is invalid.
209 * Minimum valid entry size is
210 * sizeof(struct hpi_control_cache_info)
211 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300212 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300213 "adap %d zero size cache entry %d\n",
214 pC->adap_idx, i);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300215 break;
216 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200217
218 if (info->control_type) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300219 pC->p_info[info->control_index] = info;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200220 cached++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300221 } else /* dummy cache entry */
222 pC->p_info[info->control_index] = NULL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200223
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300224 byte_count += info->size_in32bit_words * 4;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200225
226 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300227 "cached %d, pinfo %p index %d type %d size %d\n",
228 cached, pC->p_info[info->control_index],
229 info->control_index, info->control_type,
230 info->size_in32bit_words);
231
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300232 /* quit loop early if whole cache has been scanned.
233 * dwControlCount is the maximum possible entries
234 * but some may be absent from the cache
235 */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300236 if (byte_count >= pC->cache_size_in_bytes)
237 break;
238 /* have seen last control index */
239 if (info->control_index == pC->control_count - 1)
240 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200241 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300242
243 if (byte_count != pC->cache_size_in_bytes)
244 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300245 "adap %d bytecount %d != cache size %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300246 pC->adap_idx, byte_count,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300247 pC->cache_size_in_bytes);
248 else
249 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300250 "adap %d cache good, bytecount == cache size = %d\n",
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300251 pC->adap_idx, byte_count);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300252
Eliot Blennerhassett1528fbb2011-02-10 17:26:02 +1300253 pC->init = (u16)cached;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200254 }
255 return pC->init;
256}
257
258/** Find a control.
259*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300260static short find_control(u16 control_index,
261 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200262{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200263 if (!control_cache_alloc_check(p_cache)) {
264 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300265 "control_cache_alloc_check() failed %d\n",
266 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200267 return 0;
268 }
269
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300270 *pI = p_cache->p_info[control_index];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200271 if (!*pI) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300272 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
273 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200274 return 0;
275 } else {
276 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
277 (*pI)->control_type);
278 }
279 return 1;
280}
281
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200282/* allow unified treatment of several string fields within struct */
283#define HPICMN_PAD_OFS_AND_SIZE(m) {\
284 offsetof(struct hpi_control_cache_pad, m), \
285 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
286
287struct pad_ofs_size {
288 unsigned int offset;
289 unsigned int field_size;
290};
291
292static struct pad_ofs_size pad_desc[] = {
293 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
294 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
295 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
296 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
297};
298
299/** CheckControlCache checks the cache and fills the struct hpi_response
300 * accordingly. It returns one if a cache hit occurred, zero otherwise.
301 */
302short hpi_check_control_cache(struct hpi_control_cache *p_cache,
303 struct hpi_message *phm, struct hpi_response *phr)
304{
305 short found = 1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200306 struct hpi_control_cache_info *pI;
307 struct hpi_control_cache_single *pC;
308 struct hpi_control_cache_pad *p_pad;
309
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300310 if (!find_control(phm->obj_index, p_cache, &pI)) {
311 HPI_DEBUG_LOG(VERBOSE,
312 "HPICMN find_control() failed for adap %d\n",
313 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200314 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300315 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200316
317 phr->error = 0;
318
319 /* pC is the default cached control strucure. May be cast to
320 something else in the following switch statement.
321 */
322 pC = (struct hpi_control_cache_single *)pI;
323 p_pad = (struct hpi_control_cache_pad *)pI;
324
325 switch (pI->control_type) {
326
327 case HPI_CONTROL_METER:
328 if (phm->u.c.attribute == HPI_METER_PEAK) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300329 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
330 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200331 } else if (phm->u.c.attribute == HPI_METER_RMS) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300332 if (pC->u.meter.an_logRMS[0] ==
333 HPI_CACHE_INVALID_SHORT) {
334 phr->error =
335 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
336 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
337 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
338 } else {
339 phr->u.c.an_log_value[0] =
340 pC->u.meter.an_logRMS[0];
341 phr->u.c.an_log_value[1] =
342 pC->u.meter.an_logRMS[1];
343 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200344 } else
345 found = 0;
346 break;
347 case HPI_CONTROL_VOLUME:
348 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300349 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
350 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200351 } else
352 found = 0;
353 break;
354 case HPI_CONTROL_MULTIPLEXER:
355 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300356 phr->u.c.param1 = pC->u.mux.source_node_type;
357 phr->u.c.param2 = pC->u.mux.source_node_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200358 } else {
359 found = 0;
360 }
361 break;
362 case HPI_CONTROL_CHANNEL_MODE:
363 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300364 phr->u.c.param1 = pC->u.mode.mode;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200365 else
366 found = 0;
367 break;
368 case HPI_CONTROL_LEVEL:
369 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300370 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
371 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200372 } else
373 found = 0;
374 break;
375 case HPI_CONTROL_TUNER:
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200376 if (phm->u.c.attribute == HPI_TUNER_FREQ)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300377 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200378 else if (phm->u.c.attribute == HPI_TUNER_BAND)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300379 phr->u.c.param1 = pC->u.tuner.band;
380 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
381 if (pC->u.tuner.s_level_avg ==
382 HPI_CACHE_INVALID_SHORT) {
383 phr->u.cu.tuner.s_level = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200384 phr->error =
385 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
386 } else
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300387 phr->u.cu.tuner.s_level =
388 pC->u.tuner.s_level_avg;
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200389 else
390 found = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200391 break;
392 case HPI_CONTROL_AESEBU_RECEIVER:
393 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
394 phr->u.c.param1 = pC->u.aes3rx.error_status;
395 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300396 phr->u.c.param1 = pC->u.aes3rx.format;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200397 else
398 found = 0;
399 break;
400 case HPI_CONTROL_AESEBU_TRANSMITTER:
401 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
402 phr->u.c.param1 = pC->u.aes3tx.format;
403 else
404 found = 0;
405 break;
406 case HPI_CONTROL_TONEDETECTOR:
407 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
408 phr->u.c.param1 = pC->u.tone.state;
409 else
410 found = 0;
411 break;
412 case HPI_CONTROL_SILENCEDETECTOR:
413 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
414 phr->u.c.param1 = pC->u.silence.state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200415 } else
416 found = 0;
417 break;
418 case HPI_CONTROL_MICROPHONE:
419 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300420 phr->u.c.param1 = pC->u.microphone.phantom_state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200421 else
422 found = 0;
423 break;
424 case HPI_CONTROL_SAMPLECLOCK:
425 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
426 phr->u.c.param1 = pC->u.clk.source;
427 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
428 if (pC->u.clk.source_index ==
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300429 HPI_CACHE_INVALID_UINT16) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200430 phr->u.c.param1 = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200431 phr->error =
432 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200433 } else
434 phr->u.c.param1 = pC->u.clk.source_index;
435 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
436 phr->u.c.param1 = pC->u.clk.sample_rate;
437 else
438 found = 0;
439 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300440 case HPI_CONTROL_PAD:{
441 struct hpi_control_cache_pad *p_pad;
442 p_pad = (struct hpi_control_cache_pad *)pI;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200443
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300444 if (!(p_pad->field_valid_flags & (1 <<
445 HPI_CTL_ATTR_INDEX(phm->u.c.
446 attribute)))) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200447 phr->error =
448 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
449 break;
450 }
451
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300452 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
453 phr->u.c.param1 = p_pad->pI;
454 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
455 phr->u.c.param1 = p_pad->pTY;
456 else {
457 unsigned int index =
458 HPI_CTL_ATTR_INDEX(phm->u.c.
459 attribute) - 1;
460 unsigned int offset = phm->u.c.param1;
461 unsigned int pad_string_len, field_size;
462 char *pad_string;
463 unsigned int tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200464
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300465 if (index > ARRAY_SIZE(pad_desc) - 1) {
466 phr->error =
467 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
468 break;
469 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200470
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300471 pad_string =
472 ((char *)p_pad) +
473 pad_desc[index].offset;
474 field_size = pad_desc[index].field_size;
475 /* Ensure null terminator */
476 pad_string[field_size - 1] = 0;
477
478 pad_string_len = strlen(pad_string) + 1;
479
480 if (offset > pad_string_len) {
481 phr->error =
482 HPI_ERROR_INVALID_CONTROL_VALUE;
483 break;
484 }
485
486 tocopy = pad_string_len - offset;
487 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
488 tocopy = sizeof(phr->u.cu.chars8.
489 sz_data);
490
491 memcpy(phr->u.cu.chars8.sz_data,
492 &pad_string[offset], tocopy);
493
494 phr->u.cu.chars8.remaining_chars =
495 pad_string_len - offset - tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200496 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200497 }
498 break;
499 default:
500 found = 0;
501 break;
502 }
503
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300504 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
505 found ? "Cached" : "Uncached", phm->adapter_index,
506 pI->control_index, pI->control_type, phm->u.c.attribute);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200507
508 if (found)
509 phr->size =
510 sizeof(struct hpi_response_header) +
511 sizeof(struct hpi_control_res);
512
513 return found;
514}
515
516/** Updates the cache with Set values.
517
518Only update if no error.
519Volume and Level return the limited values in the response, so use these
520Multiplexer does so use sent values
521*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300522void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200523 struct hpi_message *phm, struct hpi_response *phr)
524{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200525 struct hpi_control_cache_single *pC;
526 struct hpi_control_cache_info *pI;
527
Eliot Blennerhassett3ee317f2010-05-27 17:53:55 +1200528 if (phr->error)
529 return;
530
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300531 if (!find_control(phm->obj_index, p_cache, &pI)) {
532 HPI_DEBUG_LOG(VERBOSE,
533 "HPICMN find_control() failed for adap %d\n",
534 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200535 return;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300536 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200537
538 /* pC is the default cached control strucure.
539 May be cast to something else in the following switch statement.
540 */
541 pC = (struct hpi_control_cache_single *)pI;
542
543 switch (pI->control_type) {
544 case HPI_CONTROL_VOLUME:
545 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300546 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
547 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200548 }
549 break;
550 case HPI_CONTROL_MULTIPLEXER:
551 /* mux does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200552 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300553 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
554 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200555 }
556 break;
557 case HPI_CONTROL_CHANNEL_MODE:
558 /* mode does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200559 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300560 pC->u.mode.mode = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200561 break;
562 case HPI_CONTROL_LEVEL:
563 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300564 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
565 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200566 }
567 break;
568 case HPI_CONTROL_MICROPHONE:
569 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300570 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200571 break;
572 case HPI_CONTROL_AESEBU_TRANSMITTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200573 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
574 pC->u.aes3tx.format = phm->u.c.param1;
575 break;
576 case HPI_CONTROL_AESEBU_RECEIVER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200577 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300578 pC->u.aes3rx.format = phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200579 break;
580 case HPI_CONTROL_SAMPLECLOCK:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200581 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
582 pC->u.clk.source = (u16)phm->u.c.param1;
583 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
584 pC->u.clk.source_index = (u16)phm->u.c.param1;
585 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
586 pC->u.clk.sample_rate = phm->u.c.param1;
587 break;
588 default:
589 break;
590 }
591}
592
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300593struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
594 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200595{
596 struct hpi_control_cache *p_cache =
597 kmalloc(sizeof(*p_cache), GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200598 if (!p_cache)
599 return NULL;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300600
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200601 p_cache->p_info =
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300602 kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200603 if (!p_cache->p_info) {
604 kfree(p_cache);
605 return NULL;
606 }
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300607 memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200608 p_cache->cache_size_in_bytes = size_in_bytes;
Eliot Blennerhassett47049982011-02-10 17:26:06 +1300609 p_cache->control_count = control_count;
610 p_cache->p_cache = p_dsp_control_buffer;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200611 p_cache->init = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200612 return p_cache;
613}
614
615void hpi_free_control_cache(struct hpi_control_cache *p_cache)
616{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300617 if (p_cache) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200618 kfree(p_cache->p_info);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200619 kfree(p_cache);
620 }
621}
622
623static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
624{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300625 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200626
627 switch (phm->function) {
628 case HPI_SUBSYS_OPEN:
629 case HPI_SUBSYS_CLOSE:
630 case HPI_SUBSYS_DRIVER_UNLOAD:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200631 break;
632 case HPI_SUBSYS_DRIVER_LOAD:
633 wipe_adapter_list();
634 hpios_alistlock_init(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200635 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300636 case HPI_SUBSYS_GET_ADAPTER:
637 subsys_get_adapter(phm, phr);
638 break;
639 case HPI_SUBSYS_GET_NUM_ADAPTERS:
640 phr->u.s.num_adapters = adapters.gw_num_adapters;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200641 break;
642 case HPI_SUBSYS_CREATE_ADAPTER:
643 case HPI_SUBSYS_DELETE_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200644 break;
645 default:
646 phr->error = HPI_ERROR_INVALID_FUNC;
647 break;
648 }
649}
650
651void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
652{
653 switch (phm->type) {
654 case HPI_TYPE_MESSAGE:
655 switch (phm->object) {
656 case HPI_OBJ_SUBSYSTEM:
657 subsys_message(phm, phr);
658 break;
659 }
660 break;
661
662 default:
663 phr->error = HPI_ERROR_INVALID_TYPE;
664 break;
665 }
666}