blob: 85c29727979213da4df60e4d7a25177d2cde175d [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) {
49 HPI_DEBUG_LOG(ERROR, "header type %d invalid", phr->type);
50 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) {
54 HPI_DEBUG_LOG(ERROR, "header object %d invalid", phr->object);
55 return HPI_ERROR_INVALID_RESPONSE;
56 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020057
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130058 if (phr->function != phm->function) {
59 HPI_DEBUG_LOG(ERROR, "header type %d invalid", phr->function);
60 return HPI_ERROR_INVALID_RESPONSE;
61 }
62
63 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020064}
65
66u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
67{
68 u16 retval = 0;
69 /*HPI_ASSERT(pao->wAdapterType); */
70
71 hpios_alistlock_lock(&adapters);
72
73 if (pao->index >= HPI_MAX_ADAPTERS) {
74 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
75 goto unlock;
76 }
77
78 if (adapters.adapter[pao->index].adapter_type) {
79 {
80 retval = HPI_DUPLICATE_ADAPTER_NUMBER;
81 goto unlock;
82 }
83 }
84 adapters.adapter[pao->index] = *pao;
85 hpios_dsplock_init(&adapters.adapter[pao->index]);
86 adapters.gw_num_adapters++;
87
88unlock:
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130089 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020090 return retval;
91}
92
93void hpi_delete_adapter(struct hpi_adapter_obj *pao)
94{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130095 if (!pao->adapter_type) {
96 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
97 return;
98 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020099
100 hpios_alistlock_lock(&adapters);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300101 if (adapters.adapter[pao->index].adapter_type)
102 adapters.gw_num_adapters--;
103 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
104 hpios_alistlock_unlock(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200105}
106
107/**
108* FindAdapter returns a pointer to the struct hpi_adapter_obj with
109* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
110*
111*/
112struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
113{
114 struct hpi_adapter_obj *pao = NULL;
115
116 if (adapter_index >= HPI_MAX_ADAPTERS) {
117 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
118 adapter_index);
119 return NULL;
120 }
121
122 pao = &adapters.adapter[adapter_index];
123 if (pao->adapter_type != 0) {
124 /*
125 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
126 wAdapterIndex);
127 */
128 return pao;
129 } else {
130 /*
131 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
132 wAdapterIndex);
133 */
134 return NULL;
135 }
136}
137
138/**
139*
140* wipe an HPI_ADAPTERS_LIST structure.
141*
142**/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300143static void wipe_adapter_list(void)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200144{
145 memset(&adapters, 0, sizeof(adapters));
146}
147
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300148static void subsys_get_adapter(struct hpi_message *phm,
149 struct hpi_response *phr)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200150{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300151 int count = phm->obj_index;
152 u16 index = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200153
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300154 /* find the nCount'th nonzero adapter in array */
155 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
156 if (adapters.adapter[index].adapter_type) {
157 if (count == 0)
158 break;
159 count--;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200160 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200161 }
162
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300163 if (index < HPI_MAX_ADAPTERS) {
164 phr->u.s.adapter_index = adapters.adapter[index].index;
165 phr->u.s.aw_adapter_list[0] =
166 adapters.adapter[index].adapter_type;
167 } else {
168 phr->u.s.adapter_index = 0;
169 phr->u.s.aw_adapter_list[0] = 0;
170 phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
171 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200172}
173
174static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
175{
176 unsigned int i;
177 int cached = 0;
178 if (!pC)
179 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200180
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300181 if (pC->init)
182 return pC->init;
183
184 if (!pC->p_cache)
185 return 0;
186
187 if (pC->control_count && pC->cache_size_in_bytes) {
188 char *p_master_cache;
189 unsigned int byte_count = 0;
190
191 p_master_cache = (char *)pC->p_cache;
192 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200193 pC->control_count);
194 for (i = 0; i < pC->control_count; i++) {
195 struct hpi_control_cache_info *info =
196 (struct hpi_control_cache_info *)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300197 &p_master_cache[byte_count];
198
199 if (!info->size_in32bit_words) {
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300200 if (i == 0) {
201 HPI_DEBUG_LOG(INFO,
202 "adap %d cache not ready?\n",
203 pC->adap_idx);
204 return 0;
205 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300206 /* ? This is a severe error, the cache is probably
207 corrupted. Minimum valid entry size is
208 sizeof(struct hpi_control_cache_info) */
209 HPI_DEBUG_LOG(ERROR,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300210 "adap %d zero size cache entry %d\n",
211 pC->adap_idx, i);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300212 break;
213 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200214
215 if (info->control_type) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300216 pC->p_info[info->control_index] = info;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200217 cached++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300218 } else /* dummy cache entry */
219 pC->p_info[info->control_index] = NULL;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200220
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300221 byte_count += info->size_in32bit_words * 4;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200222
223 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300224 "cached %d, pinfo %p index %d type %d size %d\n",
225 cached, pC->p_info[info->control_index],
226 info->control_index, info->control_type,
227 info->size_in32bit_words);
228
229 /* quit loop early if whole cache has been scanned. */
230 /* pC->dwControlCount is the maximum possible entries, */
231 /* but some may not be in the cache at all */
232 if (byte_count >= pC->cache_size_in_bytes)
233 break;
234 /* have seen last control index */
235 if (info->control_index == pC->control_count - 1)
236 break;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200237 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300238
239 if (byte_count != pC->cache_size_in_bytes)
240 HPI_DEBUG_LOG(WARNING,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300241 "adap %d bytecount %d != cache size %d",
242 pC->adap_idx, byte_count,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300243 pC->cache_size_in_bytes);
244 else
245 HPI_DEBUG_LOG(DEBUG,
Eliot Blennerhassettffdb5782011-02-10 17:26:00 +1300246 "adap %d cache good, bytecount == cache size = %d",
247 pC->adap_idx, byte_count);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300248
249 pC->init = cached;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200250 }
251 return pC->init;
252}
253
254/** Find a control.
255*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300256static short find_control(u16 control_index,
257 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200258{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200259 if (!control_cache_alloc_check(p_cache)) {
260 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300261 "control_cache_alloc_check() failed %d\n",
262 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200263 return 0;
264 }
265
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300266 *pI = p_cache->p_info[control_index];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200267 if (!*pI) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300268 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
269 control_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200270 return 0;
271 } else {
272 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
273 (*pI)->control_type);
274 }
275 return 1;
276}
277
278/** Used by the kernel driver to figure out if a buffer needs mapping.
279 */
280short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
281 struct hpi_message *phm, void **p, unsigned int *pN)
282{
283 *pN = 0;
284 *p = NULL;
285 if ((phm->function == HPI_CONTROL_GET_STATE)
286 && (phm->object == HPI_OBJ_CONTROLEX)
287 ) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200288 struct hpi_control_cache_info *pI;
289
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300290 if (!find_control(phm->obj_index, p_cache, &pI)) {
291 HPI_DEBUG_LOG(VERBOSE,
292 "HPICMN find_control() failed for adap %d\n",
293 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200294 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300295 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200296 }
297 return 0;
298}
299
300/* allow unified treatment of several string fields within struct */
301#define HPICMN_PAD_OFS_AND_SIZE(m) {\
302 offsetof(struct hpi_control_cache_pad, m), \
303 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
304
305struct pad_ofs_size {
306 unsigned int offset;
307 unsigned int field_size;
308};
309
310static struct pad_ofs_size pad_desc[] = {
311 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
312 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
313 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
314 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
315};
316
317/** CheckControlCache checks the cache and fills the struct hpi_response
318 * accordingly. It returns one if a cache hit occurred, zero otherwise.
319 */
320short hpi_check_control_cache(struct hpi_control_cache *p_cache,
321 struct hpi_message *phm, struct hpi_response *phr)
322{
323 short found = 1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200324 struct hpi_control_cache_info *pI;
325 struct hpi_control_cache_single *pC;
326 struct hpi_control_cache_pad *p_pad;
327
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300328 if (!find_control(phm->obj_index, p_cache, &pI)) {
329 HPI_DEBUG_LOG(VERBOSE,
330 "HPICMN find_control() failed for adap %d\n",
331 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200332 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300333 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200334
335 phr->error = 0;
336
337 /* pC is the default cached control strucure. May be cast to
338 something else in the following switch statement.
339 */
340 pC = (struct hpi_control_cache_single *)pI;
341 p_pad = (struct hpi_control_cache_pad *)pI;
342
343 switch (pI->control_type) {
344
345 case HPI_CONTROL_METER:
346 if (phm->u.c.attribute == HPI_METER_PEAK) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300347 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
348 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200349 } else if (phm->u.c.attribute == HPI_METER_RMS) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300350 if (pC->u.meter.an_logRMS[0] ==
351 HPI_CACHE_INVALID_SHORT) {
352 phr->error =
353 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
354 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
355 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
356 } else {
357 phr->u.c.an_log_value[0] =
358 pC->u.meter.an_logRMS[0];
359 phr->u.c.an_log_value[1] =
360 pC->u.meter.an_logRMS[1];
361 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200362 } else
363 found = 0;
364 break;
365 case HPI_CONTROL_VOLUME:
366 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300367 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
368 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200369 } else
370 found = 0;
371 break;
372 case HPI_CONTROL_MULTIPLEXER:
373 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300374 phr->u.c.param1 = pC->u.mux.source_node_type;
375 phr->u.c.param2 = pC->u.mux.source_node_index;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200376 } else {
377 found = 0;
378 }
379 break;
380 case HPI_CONTROL_CHANNEL_MODE:
381 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300382 phr->u.c.param1 = pC->u.mode.mode;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200383 else
384 found = 0;
385 break;
386 case HPI_CONTROL_LEVEL:
387 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300388 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
389 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200390 } else
391 found = 0;
392 break;
393 case HPI_CONTROL_TUNER:
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200394 if (phm->u.c.attribute == HPI_TUNER_FREQ)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300395 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200396 else if (phm->u.c.attribute == HPI_TUNER_BAND)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300397 phr->u.c.param1 = pC->u.tuner.band;
398 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
399 if (pC->u.tuner.s_level_avg ==
400 HPI_CACHE_INVALID_SHORT) {
401 phr->u.cu.tuner.s_level = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200402 phr->error =
403 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
404 } else
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300405 phr->u.cu.tuner.s_level =
406 pC->u.tuner.s_level_avg;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200407 else
408 found = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200409 break;
410 case HPI_CONTROL_AESEBU_RECEIVER:
411 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
412 phr->u.c.param1 = pC->u.aes3rx.error_status;
413 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300414 phr->u.c.param1 = pC->u.aes3rx.format;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200415 else
416 found = 0;
417 break;
418 case HPI_CONTROL_AESEBU_TRANSMITTER:
419 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
420 phr->u.c.param1 = pC->u.aes3tx.format;
421 else
422 found = 0;
423 break;
424 case HPI_CONTROL_TONEDETECTOR:
425 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
426 phr->u.c.param1 = pC->u.tone.state;
427 else
428 found = 0;
429 break;
430 case HPI_CONTROL_SILENCEDETECTOR:
431 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
432 phr->u.c.param1 = pC->u.silence.state;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300433 /*? phr->u.c.dwParam2 = pC->u.silence.dwCount; */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200434 } else
435 found = 0;
436 break;
437 case HPI_CONTROL_MICROPHONE:
438 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300439 phr->u.c.param1 = pC->u.microphone.phantom_state;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200440 else
441 found = 0;
442 break;
443 case HPI_CONTROL_SAMPLECLOCK:
444 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
445 phr->u.c.param1 = pC->u.clk.source;
446 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
447 if (pC->u.clk.source_index ==
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300448 HPI_CACHE_INVALID_UINT16) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200449 phr->u.c.param1 = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200450 phr->error =
451 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200452 } else
453 phr->u.c.param1 = pC->u.clk.source_index;
454 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
455 phr->u.c.param1 = pC->u.clk.sample_rate;
456 else
457 found = 0;
458 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300459 case HPI_CONTROL_PAD:{
460 struct hpi_control_cache_pad *p_pad;
461 p_pad = (struct hpi_control_cache_pad *)pI;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200462
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300463 if (!(p_pad->field_valid_flags & (1 <<
464 HPI_CTL_ATTR_INDEX(phm->u.c.
465 attribute)))) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200466 phr->error =
467 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
468 break;
469 }
470
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300471 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
472 phr->u.c.param1 = p_pad->pI;
473 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
474 phr->u.c.param1 = p_pad->pTY;
475 else {
476 unsigned int index =
477 HPI_CTL_ATTR_INDEX(phm->u.c.
478 attribute) - 1;
479 unsigned int offset = phm->u.c.param1;
480 unsigned int pad_string_len, field_size;
481 char *pad_string;
482 unsigned int tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200483
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300484 if (index > ARRAY_SIZE(pad_desc) - 1) {
485 phr->error =
486 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
487 break;
488 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200489
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300490 pad_string =
491 ((char *)p_pad) +
492 pad_desc[index].offset;
493 field_size = pad_desc[index].field_size;
494 /* Ensure null terminator */
495 pad_string[field_size - 1] = 0;
496
497 pad_string_len = strlen(pad_string) + 1;
498
499 if (offset > pad_string_len) {
500 phr->error =
501 HPI_ERROR_INVALID_CONTROL_VALUE;
502 break;
503 }
504
505 tocopy = pad_string_len - offset;
506 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
507 tocopy = sizeof(phr->u.cu.chars8.
508 sz_data);
509
510 memcpy(phr->u.cu.chars8.sz_data,
511 &pad_string[offset], tocopy);
512
513 phr->u.cu.chars8.remaining_chars =
514 pad_string_len - offset - tocopy;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200515 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200516 }
517 break;
518 default:
519 found = 0;
520 break;
521 }
522
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300523 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
524 found ? "Cached" : "Uncached", phm->adapter_index,
525 pI->control_index, pI->control_type, phm->u.c.attribute);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200526
527 if (found)
528 phr->size =
529 sizeof(struct hpi_response_header) +
530 sizeof(struct hpi_control_res);
531
532 return found;
533}
534
535/** Updates the cache with Set values.
536
537Only update if no error.
538Volume and Level return the limited values in the response, so use these
539Multiplexer does so use sent values
540*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300541void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200542 struct hpi_message *phm, struct hpi_response *phr)
543{
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200544 struct hpi_control_cache_single *pC;
545 struct hpi_control_cache_info *pI;
546
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200547 if (phr->error)
548 return;
549
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300550 if (!find_control(phm->obj_index, p_cache, &pI)) {
551 HPI_DEBUG_LOG(VERBOSE,
552 "HPICMN find_control() failed for adap %d\n",
553 phm->adapter_index);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200554 return;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300555 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200556
557 /* pC is the default cached control strucure.
558 May be cast to something else in the following switch statement.
559 */
560 pC = (struct hpi_control_cache_single *)pI;
561
562 switch (pI->control_type) {
563 case HPI_CONTROL_VOLUME:
564 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300565 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
566 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200567 }
568 break;
569 case HPI_CONTROL_MULTIPLEXER:
570 /* mux does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200571 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300572 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
573 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200574 }
575 break;
576 case HPI_CONTROL_CHANNEL_MODE:
577 /* mode does not return its setting on Set command. */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200578 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300579 pC->u.mode.mode = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200580 break;
581 case HPI_CONTROL_LEVEL:
582 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300583 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
584 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200585 }
586 break;
587 case HPI_CONTROL_MICROPHONE:
588 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300589 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200590 break;
591 case HPI_CONTROL_AESEBU_TRANSMITTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200592 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
593 pC->u.aes3tx.format = phm->u.c.param1;
594 break;
595 case HPI_CONTROL_AESEBU_RECEIVER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200596 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300597 pC->u.aes3rx.format = phm->u.c.param1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200598 break;
599 case HPI_CONTROL_SAMPLECLOCK:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200600 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
601 pC->u.clk.source = (u16)phm->u.c.param1;
602 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
603 pC->u.clk.source_index = (u16)phm->u.c.param1;
604 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
605 pC->u.clk.sample_rate = phm->u.c.param1;
606 break;
607 default:
608 break;
609 }
610}
611
612struct hpi_control_cache *hpi_alloc_control_cache(const u32
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300613 number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200614{
615 struct hpi_control_cache *p_cache =
616 kmalloc(sizeof(*p_cache), GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200617 if (!p_cache)
618 return NULL;
619 p_cache->p_info =
620 kmalloc(sizeof(*p_cache->p_info) * number_of_controls,
621 GFP_KERNEL);
622 if (!p_cache->p_info) {
623 kfree(p_cache);
624 return NULL;
625 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200626 p_cache->cache_size_in_bytes = size_in_bytes;
627 p_cache->control_count = number_of_controls;
628 p_cache->p_cache =
629 (struct hpi_control_cache_single *)pDSP_control_buffer;
630 p_cache->init = 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200631 return p_cache;
632}
633
634void hpi_free_control_cache(struct hpi_control_cache *p_cache)
635{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300636 if (p_cache) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200637 kfree(p_cache->p_info);
638 p_cache->p_info = NULL;
639 p_cache->init = 0;
640 kfree(p_cache);
641 }
642}
643
644static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
645{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300646 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200647
648 switch (phm->function) {
649 case HPI_SUBSYS_OPEN:
650 case HPI_SUBSYS_CLOSE:
651 case HPI_SUBSYS_DRIVER_UNLOAD:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200652 break;
653 case HPI_SUBSYS_DRIVER_LOAD:
654 wipe_adapter_list();
655 hpios_alistlock_init(&adapters);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200656 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300657 case HPI_SUBSYS_GET_ADAPTER:
658 subsys_get_adapter(phm, phr);
659 break;
660 case HPI_SUBSYS_GET_NUM_ADAPTERS:
661 phr->u.s.num_adapters = adapters.gw_num_adapters;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200662 break;
663 case HPI_SUBSYS_CREATE_ADAPTER:
664 case HPI_SUBSYS_DELETE_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200665 break;
666 default:
667 phr->error = HPI_ERROR_INVALID_FUNC;
668 break;
669 }
670}
671
672void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
673{
674 switch (phm->type) {
675 case HPI_TYPE_MESSAGE:
676 switch (phm->object) {
677 case HPI_OBJ_SUBSYSTEM:
678 subsys_message(phm, phr);
679 break;
680 }
681 break;
682
683 default:
684 phr->error = HPI_ERROR_INVALID_TYPE;
685 break;
686 }
687}