blob: 793236ef0a540468d9aaa80ff3684fc797e586e4 [file] [log] [blame]
Eliot Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-04-21 18:17:39 +0200150{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300151 int count = phm->obj_index;
152 u16 index = 0;
Eliot Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-04-21 18:17:39 +0200160 }
Eliot Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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 Blennerhassett719f82d32010-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) {
200 /* ? This is a severe error, the cache is probably
201 corrupted. Minimum valid entry size is
202 sizeof(struct hpi_control_cache_info) */
203 HPI_DEBUG_LOG(ERROR,
204 "zero size cache entry %d\n", i);
205 break;
206 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200207
208 if (info->control_type) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300209 pC->p_info[info->control_index] = info;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200210 cached++;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300211 } else /* dummy cache entry */
212 pC->p_info[info->control_index] = NULL;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200213
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300214 byte_count += info->size_in32bit_words * 4;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200215
216 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300217 "cached %d, pinfo %p index %d type %d size %d\n",
218 cached, pC->p_info[info->control_index],
219 info->control_index, info->control_type,
220 info->size_in32bit_words);
221
222 /* quit loop early if whole cache has been scanned. */
223 /* pC->dwControlCount is the maximum possible entries, */
224 /* but some may not be in the cache at all */
225 if (byte_count >= pC->cache_size_in_bytes)
226 break;
227 /* have seen last control index */
228 if (info->control_index == pC->control_count - 1)
229 break;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200230 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300231
232 if (byte_count != pC->cache_size_in_bytes)
233 HPI_DEBUG_LOG(WARNING,
234 "bytecount %d != cache size %d", byte_count,
235 pC->cache_size_in_bytes);
236 else
237 HPI_DEBUG_LOG(DEBUG,
238 "cache good. bytecount == cache size = %d",
239 byte_count);
240
241 pC->init = cached;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200242 }
243 return pC->init;
244}
245
246/** Find a control.
247*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300248static short find_control(u16 control_index,
249 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200250{
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200251 if (!control_cache_alloc_check(p_cache)) {
252 HPI_DEBUG_LOG(VERBOSE,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300253 "control_cache_alloc_check() failed %d\n",
254 control_index);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200255 return 0;
256 }
257
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300258 *pI = p_cache->p_info[control_index];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200259 if (!*pI) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300260 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
261 control_index);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200262 return 0;
263 } else {
264 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
265 (*pI)->control_type);
266 }
267 return 1;
268}
269
270/** Used by the kernel driver to figure out if a buffer needs mapping.
271 */
272short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
273 struct hpi_message *phm, void **p, unsigned int *pN)
274{
275 *pN = 0;
276 *p = NULL;
277 if ((phm->function == HPI_CONTROL_GET_STATE)
278 && (phm->object == HPI_OBJ_CONTROLEX)
279 ) {
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200280 struct hpi_control_cache_info *pI;
281
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300282 if (!find_control(phm->obj_index, p_cache, &pI)) {
283 HPI_DEBUG_LOG(VERBOSE,
284 "HPICMN find_control() failed for adap %d\n",
285 phm->adapter_index);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200286 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300287 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200288 }
289 return 0;
290}
291
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) }
296
297struct pad_ofs_size {
298 unsigned int offset;
299 unsigned int field_size;
300};
301
302static 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 */
307};
308
309/** CheckControlCache checks the cache and fills the struct hpi_response
310 * accordingly. It returns one if a cache hit occurred, zero otherwise.
311 */
312short hpi_check_control_cache(struct hpi_control_cache *p_cache,
313 struct hpi_message *phm, struct hpi_response *phr)
314{
315 short found = 1;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200316 struct hpi_control_cache_info *pI;
317 struct hpi_control_cache_single *pC;
318 struct hpi_control_cache_pad *p_pad;
319
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300320 if (!find_control(phm->obj_index, p_cache, &pI)) {
321 HPI_DEBUG_LOG(VERBOSE,
322 "HPICMN find_control() failed for adap %d\n",
323 phm->adapter_index);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200324 return 0;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300325 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200326
327 phr->error = 0;
328
329 /* pC is the default cached control strucure. May be cast to
330 something else in the following switch statement.
331 */
332 pC = (struct hpi_control_cache_single *)pI;
333 p_pad = (struct hpi_control_cache_pad *)pI;
334
335 switch (pI->control_type) {
336
337 case HPI_CONTROL_METER:
338 if (phm->u.c.attribute == HPI_METER_PEAK) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300339 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
340 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200341 } else if (phm->u.c.attribute == HPI_METER_RMS) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300342 if (pC->u.meter.an_logRMS[0] ==
343 HPI_CACHE_INVALID_SHORT) {
344 phr->error =
345 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
346 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
347 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
348 } else {
349 phr->u.c.an_log_value[0] =
350 pC->u.meter.an_logRMS[0];
351 phr->u.c.an_log_value[1] =
352 pC->u.meter.an_logRMS[1];
353 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200354 } else
355 found = 0;
356 break;
357 case HPI_CONTROL_VOLUME:
358 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300359 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
360 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200361 } else
362 found = 0;
363 break;
364 case HPI_CONTROL_MULTIPLEXER:
365 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300366 phr->u.c.param1 = pC->u.mux.source_node_type;
367 phr->u.c.param2 = pC->u.mux.source_node_index;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200368 } else {
369 found = 0;
370 }
371 break;
372 case HPI_CONTROL_CHANNEL_MODE:
373 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300374 phr->u.c.param1 = pC->u.mode.mode;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200375 else
376 found = 0;
377 break;
378 case HPI_CONTROL_LEVEL:
379 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300380 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
381 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200382 } else
383 found = 0;
384 break;
385 case HPI_CONTROL_TUNER:
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200386 if (phm->u.c.attribute == HPI_TUNER_FREQ)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300387 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200388 else if (phm->u.c.attribute == HPI_TUNER_BAND)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300389 phr->u.c.param1 = pC->u.tuner.band;
390 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
391 if (pC->u.tuner.s_level_avg ==
392 HPI_CACHE_INVALID_SHORT) {
393 phr->u.cu.tuner.s_level = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200394 phr->error =
395 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
396 } else
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300397 phr->u.cu.tuner.s_level =
398 pC->u.tuner.s_level_avg;
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200399 else
400 found = 0;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200401 break;
402 case HPI_CONTROL_AESEBU_RECEIVER:
403 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
404 phr->u.c.param1 = pC->u.aes3rx.error_status;
405 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300406 phr->u.c.param1 = pC->u.aes3rx.format;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200407 else
408 found = 0;
409 break;
410 case HPI_CONTROL_AESEBU_TRANSMITTER:
411 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
412 phr->u.c.param1 = pC->u.aes3tx.format;
413 else
414 found = 0;
415 break;
416 case HPI_CONTROL_TONEDETECTOR:
417 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
418 phr->u.c.param1 = pC->u.tone.state;
419 else
420 found = 0;
421 break;
422 case HPI_CONTROL_SILENCEDETECTOR:
423 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
424 phr->u.c.param1 = pC->u.silence.state;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300425 /*? phr->u.c.dwParam2 = pC->u.silence.dwCount; */
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200426 } else
427 found = 0;
428 break;
429 case HPI_CONTROL_MICROPHONE:
430 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300431 phr->u.c.param1 = pC->u.microphone.phantom_state;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200432 else
433 found = 0;
434 break;
435 case HPI_CONTROL_SAMPLECLOCK:
436 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
437 phr->u.c.param1 = pC->u.clk.source;
438 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
439 if (pC->u.clk.source_index ==
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300440 HPI_CACHE_INVALID_UINT16) {
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200441 phr->u.c.param1 = 0;
Eliot Blennerhassett36ed8bd2010-07-06 08:37:10 +1200442 phr->error =
443 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200444 } else
445 phr->u.c.param1 = pC->u.clk.source_index;
446 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
447 phr->u.c.param1 = pC->u.clk.sample_rate;
448 else
449 found = 0;
450 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300451 case HPI_CONTROL_PAD:{
452 struct hpi_control_cache_pad *p_pad;
453 p_pad = (struct hpi_control_cache_pad *)pI;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200454
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300455 if (!(p_pad->field_valid_flags & (1 <<
456 HPI_CTL_ATTR_INDEX(phm->u.c.
457 attribute)))) {
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200458 phr->error =
459 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
460 break;
461 }
462
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300463 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
464 phr->u.c.param1 = p_pad->pI;
465 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
466 phr->u.c.param1 = p_pad->pTY;
467 else {
468 unsigned int index =
469 HPI_CTL_ATTR_INDEX(phm->u.c.
470 attribute) - 1;
471 unsigned int offset = phm->u.c.param1;
472 unsigned int pad_string_len, field_size;
473 char *pad_string;
474 unsigned int tocopy;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200475
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300476 if (index > ARRAY_SIZE(pad_desc) - 1) {
477 phr->error =
478 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
479 break;
480 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200481
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300482 pad_string =
483 ((char *)p_pad) +
484 pad_desc[index].offset;
485 field_size = pad_desc[index].field_size;
486 /* Ensure null terminator */
487 pad_string[field_size - 1] = 0;
488
489 pad_string_len = strlen(pad_string) + 1;
490
491 if (offset > pad_string_len) {
492 phr->error =
493 HPI_ERROR_INVALID_CONTROL_VALUE;
494 break;
495 }
496
497 tocopy = pad_string_len - offset;
498 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
499 tocopy = sizeof(phr->u.cu.chars8.
500 sz_data);
501
502 memcpy(phr->u.cu.chars8.sz_data,
503 &pad_string[offset], tocopy);
504
505 phr->u.cu.chars8.remaining_chars =
506 pad_string_len - offset - tocopy;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200507 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200508 }
509 break;
510 default:
511 found = 0;
512 break;
513 }
514
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300515 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
516 found ? "Cached" : "Uncached", phm->adapter_index,
517 pI->control_index, pI->control_type, phm->u.c.attribute);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200518
519 if (found)
520 phr->size =
521 sizeof(struct hpi_response_header) +
522 sizeof(struct hpi_control_res);
523
524 return found;
525}
526
527/** Updates the cache with Set values.
528
529Only update if no error.
530Volume and Level return the limited values in the response, so use these
531Multiplexer does so use sent values
532*/
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300533void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200534 struct hpi_message *phm, struct hpi_response *phr)
535{
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200536 struct hpi_control_cache_single *pC;
537 struct hpi_control_cache_info *pI;
538
Eliot Blennerhassett3ee317fe2010-05-27 17:53:55 +1200539 if (phr->error)
540 return;
541
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300542 if (!find_control(phm->obj_index, p_cache, &pI)) {
543 HPI_DEBUG_LOG(VERBOSE,
544 "HPICMN find_control() failed for adap %d\n",
545 phm->adapter_index);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200546 return;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300547 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200548
549 /* pC is the default cached control strucure.
550 May be cast to something else in the following switch statement.
551 */
552 pC = (struct hpi_control_cache_single *)pI;
553
554 switch (pI->control_type) {
555 case HPI_CONTROL_VOLUME:
556 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300557 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
558 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200559 }
560 break;
561 case HPI_CONTROL_MULTIPLEXER:
562 /* mux does not return its setting on Set command. */
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200563 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300564 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
565 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200566 }
567 break;
568 case HPI_CONTROL_CHANNEL_MODE:
569 /* mode does not return its setting on Set command. */
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200570 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300571 pC->u.mode.mode = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200572 break;
573 case HPI_CONTROL_LEVEL:
574 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300575 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
576 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200577 }
578 break;
579 case HPI_CONTROL_MICROPHONE:
580 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300581 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200582 break;
583 case HPI_CONTROL_AESEBU_TRANSMITTER:
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200584 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
585 pC->u.aes3tx.format = phm->u.c.param1;
586 break;
587 case HPI_CONTROL_AESEBU_RECEIVER:
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200588 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300589 pC->u.aes3rx.format = phm->u.c.param1;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200590 break;
591 case HPI_CONTROL_SAMPLECLOCK:
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200592 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
593 pC->u.clk.source = (u16)phm->u.c.param1;
594 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
595 pC->u.clk.source_index = (u16)phm->u.c.param1;
596 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
597 pC->u.clk.sample_rate = phm->u.c.param1;
598 break;
599 default:
600 break;
601 }
602}
603
604struct hpi_control_cache *hpi_alloc_control_cache(const u32
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300605 number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer)
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200606{
607 struct hpi_control_cache *p_cache =
608 kmalloc(sizeof(*p_cache), GFP_KERNEL);
Jesper Juhlfd0977d2010-10-29 21:35:25 +0200609 if (!p_cache)
610 return NULL;
611 p_cache->p_info =
612 kmalloc(sizeof(*p_cache->p_info) * number_of_controls,
613 GFP_KERNEL);
614 if (!p_cache->p_info) {
615 kfree(p_cache);
616 return NULL;
617 }
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200618 p_cache->cache_size_in_bytes = size_in_bytes;
619 p_cache->control_count = number_of_controls;
620 p_cache->p_cache =
621 (struct hpi_control_cache_single *)pDSP_control_buffer;
622 p_cache->init = 0;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200623 return p_cache;
624}
625
626void hpi_free_control_cache(struct hpi_control_cache *p_cache)
627{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300628 if (p_cache) {
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200629 kfree(p_cache->p_info);
630 p_cache->p_info = NULL;
631 p_cache->init = 0;
632 kfree(p_cache);
633 }
634}
635
636static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
637{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300638 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200639
640 switch (phm->function) {
641 case HPI_SUBSYS_OPEN:
642 case HPI_SUBSYS_CLOSE:
643 case HPI_SUBSYS_DRIVER_UNLOAD:
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200644 break;
645 case HPI_SUBSYS_DRIVER_LOAD:
646 wipe_adapter_list();
647 hpios_alistlock_init(&adapters);
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200648 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300649 case HPI_SUBSYS_GET_ADAPTER:
650 subsys_get_adapter(phm, phr);
651 break;
652 case HPI_SUBSYS_GET_NUM_ADAPTERS:
653 phr->u.s.num_adapters = adapters.gw_num_adapters;
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200654 break;
655 case HPI_SUBSYS_CREATE_ADAPTER:
656 case HPI_SUBSYS_DELETE_ADAPTER:
Eliot Blennerhassett719f82d32010-04-21 18:17:39 +0200657 break;
658 default:
659 phr->error = HPI_ERROR_INVALID_FUNC;
660 break;
661 }
662}
663
664void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
665{
666 switch (phm->type) {
667 case HPI_TYPE_MESSAGE:
668 switch (phm->object) {
669 case HPI_OBJ_SUBSYSTEM:
670 subsys_message(phm, phr);
671 break;
672 }
673 break;
674
675 default:
676 phr->error = HPI_ERROR_INVALID_TYPE;
677 break;
678 }
679}