1 |
/* |
---|
2 |
* Copyright (C) 2005-2009 by Pieter Palmers |
---|
3 |
* |
---|
4 |
* This file is part of FFADO |
---|
5 |
* FFADO = Free Firewire (pro-)audio drivers for linux |
---|
6 |
* |
---|
7 |
* FFADO is based upon FreeBoB |
---|
8 |
* |
---|
9 |
* This program is free software: you can redistribute it and/or modify |
---|
10 |
* it under the terms of the GNU General Public License as published by |
---|
11 |
* the Free Software Foundation, either version 2 of the License, or |
---|
12 |
* (at your option) version 3 of the License. |
---|
13 |
* |
---|
14 |
* This program is distributed in the hope that it will be useful, |
---|
15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
16 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
17 |
* GNU General Public License for more details. |
---|
18 |
* |
---|
19 |
* You should have received a copy of the GNU General Public License |
---|
20 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
21 |
* |
---|
22 |
*/ |
---|
23 |
|
---|
24 |
#include "dice_avdevice.h" |
---|
25 |
|
---|
26 |
#include "dice_eap.h" |
---|
27 |
#include "dice_defines.h" |
---|
28 |
|
---|
29 |
#include "libutil/SystemTimeSource.h" |
---|
30 |
|
---|
31 |
#include <cstdio> |
---|
32 |
|
---|
33 |
namespace Dice { |
---|
34 |
|
---|
35 |
// ----------- helper functions ------------- |
---|
36 |
|
---|
37 |
static const char * |
---|
38 |
srcBlockToString(const char id) |
---|
39 |
{ |
---|
40 |
switch(id) { |
---|
41 |
case 0: return "AES "; |
---|
42 |
case 1: return "ADAT"; |
---|
43 |
case 2: return "MXR "; |
---|
44 |
case 4: return "INS0"; |
---|
45 |
case 5: return "INS1"; |
---|
46 |
case 10: return "ARM "; |
---|
47 |
case 11: return "AVS0"; |
---|
48 |
case 12: return "AVS1"; |
---|
49 |
case 15: return "MUTE"; |
---|
50 |
default : return "RSVD"; |
---|
51 |
} |
---|
52 |
} |
---|
53 |
|
---|
54 |
static const char * |
---|
55 |
dstBlockToString(const char id) |
---|
56 |
{ |
---|
57 |
switch(id) { |
---|
58 |
case 0: return "AES "; |
---|
59 |
case 1: return "ADAT"; |
---|
60 |
case 2: return "MXR0"; |
---|
61 |
case 3: return "MXR1"; |
---|
62 |
case 4: return "INS0"; |
---|
63 |
case 5: return "INS1"; |
---|
64 |
case 10: return "ARM "; |
---|
65 |
case 11: return "AVS0"; |
---|
66 |
case 12: return "AVS1"; |
---|
67 |
case 15: return "MUTE"; |
---|
68 |
default : return "RSVD"; |
---|
69 |
} |
---|
70 |
} |
---|
71 |
|
---|
72 |
|
---|
73 |
Device::EAP::EAP(Device &d) |
---|
74 |
: Control::Container(&d, "EAP") |
---|
75 |
, m_debugModule(d.m_debugModule) // NOTE: has to be initialized before creating the config classes |
---|
76 |
// otherwise the reference content used by those is bogus |
---|
77 |
, m_device(d) |
---|
78 |
, m_mixer( NULL ) |
---|
79 |
, m_router( NULL ) |
---|
80 |
, m_current_cfg_routing_low( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_ROUTER) ) |
---|
81 |
, m_current_cfg_routing_mid( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_ROUTER) ) |
---|
82 |
, m_current_cfg_routing_high( RouterConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_ROUTER) ) |
---|
83 |
, m_current_cfg_stream_low( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM) ) |
---|
84 |
, m_current_cfg_stream_mid( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_MID_STREAM) ) |
---|
85 |
, m_current_cfg_stream_high( StreamConfig(*this, eRT_CurrentCfg, DICE_EAP_CURRCFG_HIGH_STREAM) ) |
---|
86 |
{ |
---|
87 |
} |
---|
88 |
|
---|
89 |
Device::EAP::~EAP() |
---|
90 |
{ |
---|
91 |
// remove all control elements registered to this device (w/o free) |
---|
92 |
clearElements(false); |
---|
93 |
|
---|
94 |
// delete the helper classes |
---|
95 |
if(m_mixer) delete m_mixer; |
---|
96 |
if(m_router) delete m_router; |
---|
97 |
} |
---|
98 |
|
---|
99 |
// offsets and sizes are returned in quadlets, but we use byte values, hence the *= 4 |
---|
100 |
#define DICE_EAP_READREG_AND_CHECK(base, addr, var) { \ |
---|
101 |
if(!readReg(base, addr, &var)) { \ |
---|
102 |
debugError("Could not initialize " #var "\n"); \ |
---|
103 |
return false; \ |
---|
104 |
} \ |
---|
105 |
var *= 4; \ |
---|
106 |
} |
---|
107 |
|
---|
108 |
bool |
---|
109 |
Device::EAP::init() { |
---|
110 |
if(!supportsEAP(m_device)) { |
---|
111 |
debugError("Device does not support EAP"); |
---|
112 |
return false; |
---|
113 |
} |
---|
114 |
|
---|
115 |
// offsets and sizes are returned in quadlets, but we use byte values |
---|
116 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_OFF, m_capability_offset); |
---|
117 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CAPABILITY_SPACE_SZ, m_capability_size); |
---|
118 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_OFF, m_cmd_offset); |
---|
119 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CMD_SPACE_SZ, m_cmd_size); |
---|
120 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_OFF, m_mixer_offset); |
---|
121 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_MIXER_SPACE_SZ, m_mixer_size); |
---|
122 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_OFF, m_peak_offset); |
---|
123 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_PEAK_SPACE_SZ, m_peak_size); |
---|
124 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_OFF, m_new_routing_offset); |
---|
125 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_ROUTING_SPACE_SZ, m_new_routing_size); |
---|
126 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_OFF, m_new_stream_cfg_offset); |
---|
127 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_NEW_STREAM_CFG_SPACE_SZ, m_new_stream_cfg_size); |
---|
128 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_OFF, m_curr_cfg_offset); |
---|
129 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_CURR_CFG_SPACE_SZ, m_curr_cfg_size); |
---|
130 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_OFF, m_standalone_offset); |
---|
131 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_STAND_ALONE_CFG_SPACE_SZ, m_standalone_size); |
---|
132 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_OFF, m_app_offset); |
---|
133 |
DICE_EAP_READREG_AND_CHECK(eRT_Base, DICE_EAP_APP_SPACE_SZ, m_app_size); |
---|
134 |
|
---|
135 |
// initialize the capability info |
---|
136 |
quadlet_t tmp; |
---|
137 |
if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_ROUTER, &tmp)) { |
---|
138 |
debugError("Could not read router capabilities\n"); |
---|
139 |
return false; |
---|
140 |
} |
---|
141 |
m_router_exposed = (tmp >> DICE_EAP_CAP_ROUTER_EXPOSED) & 0x01; |
---|
142 |
m_router_readonly = (tmp >> DICE_EAP_CAP_ROUTER_READONLY) & 0x01; |
---|
143 |
m_router_flashstored = (tmp >> DICE_EAP_CAP_ROUTER_FLASHSTORED) & 0x01; |
---|
144 |
m_router_nb_entries = (tmp >> DICE_EAP_CAP_ROUTER_MAXROUTES) & 0xFFFF; |
---|
145 |
|
---|
146 |
if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_MIXER, &tmp)) { |
---|
147 |
debugError("Could not read mixer capabilities\n"); |
---|
148 |
return false; |
---|
149 |
} |
---|
150 |
m_mixer_exposed = (tmp >> DICE_EAP_CAP_MIXER_EXPOSED) & 0x01; |
---|
151 |
m_mixer_readonly = (tmp >> DICE_EAP_CAP_MIXER_READONLY) & 0x01; |
---|
152 |
m_mixer_flashstored = (tmp >> DICE_EAP_CAP_MIXER_FLASHSTORED) & 0x01; |
---|
153 |
m_mixer_tx_id = (tmp >> DICE_EAP_CAP_MIXER_IN_DEV) & 0x000F; |
---|
154 |
m_mixer_rx_id = (tmp >> DICE_EAP_CAP_MIXER_OUT_DEV) & 0x000F; |
---|
155 |
m_mixer_nb_tx = (tmp >> DICE_EAP_CAP_MIXER_INPUTS) & 0x00FF; |
---|
156 |
m_mixer_nb_rx = (tmp >> DICE_EAP_CAP_MIXER_OUTPUTS) & 0x00FF; |
---|
157 |
|
---|
158 |
if(!readReg(eRT_Capability, DICE_EAP_CAPABILITY_GENERAL, &tmp)) { |
---|
159 |
debugError("Could not read general capabilities\n"); |
---|
160 |
return false; |
---|
161 |
} |
---|
162 |
m_general_support_dynstream = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_EN) & 0x01; |
---|
163 |
m_general_support_flash = (tmp >> DICE_EAP_CAP_GENERAL_FLASH_EN) & 0x01; |
---|
164 |
m_general_peak_enabled = (tmp >> DICE_EAP_CAP_GENERAL_PEAK_EN) & 0x01; |
---|
165 |
m_general_max_tx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_TX_STREAM) & 0x0F; |
---|
166 |
m_general_max_rx = (tmp >> DICE_EAP_CAP_GENERAL_MAX_RX_STREAM) & 0x0F; |
---|
167 |
m_general_stream_cfg_stored = (tmp >> DICE_EAP_CAP_GENERAL_STRM_CFG_FLS) & 0x01; |
---|
168 |
m_general_chip = (tmp >> DICE_EAP_CAP_GENERAL_CHIP) & 0xFFFF; |
---|
169 |
|
---|
170 |
// update our view on the current configuration |
---|
171 |
if(!updateConfigurationCache()) { |
---|
172 |
debugError("Could not initialize configuration cache\n"); |
---|
173 |
return false; |
---|
174 |
} |
---|
175 |
|
---|
176 |
// initialize the helper classes |
---|
177 |
if (m_mixer_exposed) { |
---|
178 |
// initialize the mixer |
---|
179 |
m_mixer = new EAP::Mixer(*this); |
---|
180 |
if(m_mixer == NULL) { |
---|
181 |
debugError("Could not allocate memory for mixer\n"); |
---|
182 |
return false; |
---|
183 |
} |
---|
184 |
if(!m_mixer->init()) { |
---|
185 |
debugError("Could not initialize mixer\n"); |
---|
186 |
delete m_mixer; |
---|
187 |
m_mixer = NULL; |
---|
188 |
return false; |
---|
189 |
} |
---|
190 |
// add the mixer to the EAP control container |
---|
191 |
if(!addElement(m_mixer)) { |
---|
192 |
debugWarning("Failed to add mixer to control tree\n"); |
---|
193 |
} |
---|
194 |
|
---|
195 |
// initialize the peak meter |
---|
196 |
m_router = new EAP::Router(*this); |
---|
197 |
if(m_router == NULL) { |
---|
198 |
debugError("Could not allocate memory for router\n"); |
---|
199 |
return false; |
---|
200 |
} |
---|
201 |
|
---|
202 |
// add the router to the EAP control container |
---|
203 |
if(!addElement(m_router)) { |
---|
204 |
debugWarning("Failed to add router to control tree\n"); |
---|
205 |
} |
---|
206 |
} |
---|
207 |
|
---|
208 |
return true; |
---|
209 |
} |
---|
210 |
|
---|
211 |
bool |
---|
212 |
Device::EAP::updateConfigurationCache() |
---|
213 |
{ |
---|
214 |
if(!m_current_cfg_routing_low.read()) { |
---|
215 |
debugError("Could not initialize current routing configuration (low rates)\n"); |
---|
216 |
return false; |
---|
217 |
} |
---|
218 |
if(!m_current_cfg_routing_mid.read()) { |
---|
219 |
debugError("Could not initialize current routing configuration (mid rates)\n"); |
---|
220 |
return false; |
---|
221 |
} |
---|
222 |
if(!m_current_cfg_routing_high.read()) { |
---|
223 |
debugError("Could not initialize current routing configuration (high rates)\n"); |
---|
224 |
return false; |
---|
225 |
} |
---|
226 |
if(!m_current_cfg_stream_low.read()) { |
---|
227 |
debugError("Could not initialize current stream configuration (low rates)\n"); |
---|
228 |
return false; |
---|
229 |
} |
---|
230 |
if(!m_current_cfg_stream_mid.read()) { |
---|
231 |
debugError("Could not initialize current stream configuration (mid rates)\n"); |
---|
232 |
return false; |
---|
233 |
} |
---|
234 |
if(!m_current_cfg_stream_high.read()) { |
---|
235 |
debugError("Could not initialize current stream configuration (high rates)\n"); |
---|
236 |
return false; |
---|
237 |
} |
---|
238 |
if(m_mixer) m_mixer->updateNameCache(); |
---|
239 |
return true; |
---|
240 |
} |
---|
241 |
|
---|
242 |
/** |
---|
243 |
* Returns the router configuration for the current rate mode |
---|
244 |
* @return |
---|
245 |
*/ |
---|
246 |
Device::EAP::RouterConfig * |
---|
247 |
Device::EAP::getActiveRouterConfig() |
---|
248 |
{ |
---|
249 |
switch(m_device.getCurrentConfig()) { |
---|
250 |
case eDC_Low: return &m_current_cfg_routing_low; |
---|
251 |
case eDC_Mid: return &m_current_cfg_routing_mid; |
---|
252 |
case eDC_High: return &m_current_cfg_routing_high; |
---|
253 |
default: |
---|
254 |
debugError("Unsupported configuration mode\n"); |
---|
255 |
return NULL; |
---|
256 |
} |
---|
257 |
} |
---|
258 |
|
---|
259 |
/** |
---|
260 |
* Returns the stream configuration for the current rate mode |
---|
261 |
* @return |
---|
262 |
*/ |
---|
263 |
Device::EAP::StreamConfig * |
---|
264 |
Device::EAP::getActiveStreamConfig() |
---|
265 |
{ |
---|
266 |
switch(m_device.getCurrentConfig()) { |
---|
267 |
case eDC_Low: return &m_current_cfg_stream_low; |
---|
268 |
case eDC_Mid: return &m_current_cfg_stream_mid; |
---|
269 |
case eDC_High: return &m_current_cfg_stream_high; |
---|
270 |
default: |
---|
271 |
debugError("Unsupported configuration mode\n"); |
---|
272 |
return NULL; |
---|
273 |
} |
---|
274 |
} |
---|
275 |
|
---|
276 |
/** |
---|
277 |
* Uploads a new router configuration to the device |
---|
278 |
* @param rcfg The new RouterConfig |
---|
279 |
* @param low store as config for the low rates |
---|
280 |
* @param mid store as config for the mid rates |
---|
281 |
* @param high store as config for the high rates |
---|
282 |
* @return true if successful, false otherwise |
---|
283 |
*/ |
---|
284 |
bool |
---|
285 |
Device::EAP::updateRouterConfig(RouterConfig& rcfg, bool low, bool mid, bool high) { |
---|
286 |
// write the router config to the appropriate memory space on the device |
---|
287 |
if(!rcfg.write(eRT_NewRouting, 0)) { |
---|
288 |
debugError("Could not write new router configuration\n"); |
---|
289 |
return false; |
---|
290 |
} |
---|
291 |
// perform the store operation |
---|
292 |
if(!loadRouterConfig(low, mid, high)) { |
---|
293 |
debugError("Could not activate new router configuration\n"); |
---|
294 |
updateConfigurationCache(); // for consistency |
---|
295 |
return false; |
---|
296 |
} |
---|
297 |
return updateConfigurationCache(); |
---|
298 |
} |
---|
299 |
|
---|
300 |
/** |
---|
301 |
* Uploads a new router configuration to replace the configuration |
---|
302 |
* for the current rate. |
---|
303 |
* @param rcfg The new RouterConfig |
---|
304 |
* @return true if successful, false otherwise |
---|
305 |
*/ |
---|
306 |
bool |
---|
307 |
Device::EAP::updateCurrentRouterConfig(RouterConfig& rcfg) { |
---|
308 |
switch(m_device.getCurrentConfig()) { |
---|
309 |
case eDC_Low: return updateRouterConfig(rcfg, true, false, false); |
---|
310 |
case eDC_Mid: return updateRouterConfig(rcfg, false, true, false); |
---|
311 |
case eDC_High: return updateRouterConfig(rcfg, false, false, true); |
---|
312 |
default: |
---|
313 |
debugError("Unsupported configuration mode\n"); |
---|
314 |
return false; |
---|
315 |
} |
---|
316 |
} |
---|
317 |
|
---|
318 |
/** |
---|
319 |
* Uploads a new stream configuration to the device |
---|
320 |
* @param scfg The new StreamConfig |
---|
321 |
* @param low store as config for the low rates |
---|
322 |
* @param mid store as config for the mid rates |
---|
323 |
* @param high store as config for the high rates |
---|
324 |
* @return true if successful, false otherwise |
---|
325 |
*/ |
---|
326 |
bool |
---|
327 |
Device::EAP::updateStreamConfig(StreamConfig& scfg, bool low, bool mid, bool high) { |
---|
328 |
// write the stream config to the appropriate memory space on the device |
---|
329 |
if(!scfg.write(eRT_NewStreamCfg, 0)) { |
---|
330 |
debugError("Could not write new stream configuration\n"); |
---|
331 |
return false; |
---|
332 |
} |
---|
333 |
// perform the store operation |
---|
334 |
if(!loadStreamConfig(low, mid, high)) { |
---|
335 |
debugError("Could not activate new stream configuration\n"); |
---|
336 |
updateConfigurationCache(); // for consistency |
---|
337 |
return false; |
---|
338 |
} |
---|
339 |
return updateConfigurationCache(); |
---|
340 |
} |
---|
341 |
|
---|
342 |
/** |
---|
343 |
* Uploads a new router and stream configuration to the device |
---|
344 |
* @param rcfg The new RouterConfig |
---|
345 |
* @param scfg The new StreamConfig |
---|
346 |
* @param low store as config for the low rates |
---|
347 |
* @param mid store as config for the mid rates |
---|
348 |
* @param high store as config for the high rates |
---|
349 |
* @return true if successful, false otherwise |
---|
350 |
*/ |
---|
351 |
bool |
---|
352 |
Device::EAP::updateStreamConfig(RouterConfig& rcfg, StreamConfig& scfg, bool low, bool mid, bool high) { |
---|
353 |
// write the router config to the appropriate memory space on the device |
---|
354 |
if(!rcfg.write(eRT_NewRouting, 0)) { |
---|
355 |
debugError("Could not write new router configuration\n"); |
---|
356 |
return false; |
---|
357 |
} |
---|
358 |
// write the stream config to the appropriate memory space on the device |
---|
359 |
if(!scfg.write(eRT_NewStreamCfg, 0)) { |
---|
360 |
debugError("Could not write new stream configuration\n"); |
---|
361 |
return false; |
---|
362 |
} |
---|
363 |
// perform the store operation |
---|
364 |
if(!loadRouterAndStreamConfig(low, mid, high)) { |
---|
365 |
debugError("Could not activate new router/stream configuration\n"); |
---|
366 |
updateConfigurationCache(); // for consistency |
---|
367 |
return false; |
---|
368 |
} |
---|
369 |
return updateConfigurationCache(); |
---|
370 |
} |
---|
371 |
|
---|
372 |
|
---|
373 |
bool |
---|
374 |
Device::EAP::loadFlashConfig() { |
---|
375 |
bool retval = true; |
---|
376 |
debugWarning("Untested code\n"); |
---|
377 |
fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_FLASH_CFG; |
---|
378 |
cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE; |
---|
379 |
if(!commandHelper(cmd)) { |
---|
380 |
debugWarning("Command failed\n"); |
---|
381 |
retval = false; |
---|
382 |
} |
---|
383 |
retval &= updateConfigurationCache(); |
---|
384 |
return retval; |
---|
385 |
} |
---|
386 |
|
---|
387 |
bool |
---|
388 |
Device::EAP::storeFlashConfig() { |
---|
389 |
debugWarning("Untested code\n"); |
---|
390 |
fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_ST_FLASH_CFG; |
---|
391 |
cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE; |
---|
392 |
return commandHelper(cmd); |
---|
393 |
} |
---|
394 |
|
---|
395 |
// helpers |
---|
396 |
void |
---|
397 |
Device::EAP::show() |
---|
398 |
{ |
---|
399 |
printMessage("== DICE EAP ==\n"); |
---|
400 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Parameter Space info:\n"); |
---|
401 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Capability : offset=%04X size=%06d\n", m_capability_offset, m_capability_size); |
---|
402 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Command : offset=%04X size=%06d\n", m_cmd_offset, m_cmd_size); |
---|
403 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Mixer : offset=%04X size=%06d\n", m_mixer_offset, m_mixer_size); |
---|
404 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Peak : offset=%04X size=%06d\n", m_peak_offset, m_peak_size); |
---|
405 |
debugOutput(DEBUG_LEVEL_VERBOSE, " New Routing Cfg : offset=%04X size=%06d\n", m_new_routing_offset, m_new_routing_size); |
---|
406 |
debugOutput(DEBUG_LEVEL_VERBOSE, " New Stream Cfg : offset=%04X size=%06d\n", m_new_stream_cfg_offset, m_new_stream_cfg_size); |
---|
407 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Current Cfg : offset=%04X size=%06d\n", m_curr_cfg_offset, m_curr_cfg_size); |
---|
408 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Standalone Cfg : offset=%04X size=%06d\n", m_standalone_offset, m_standalone_size); |
---|
409 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Application Space : offset=%04X size=%06d\n", m_app_offset, m_app_size); |
---|
410 |
|
---|
411 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Capabilities:\n"); |
---|
412 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Router: %sexposed, %swritable, %sstored, %d routes\n", |
---|
413 |
(m_router_exposed?"":"not "), |
---|
414 |
(m_router_readonly?"not ":""), |
---|
415 |
(m_router_flashstored?"":"not "), |
---|
416 |
m_router_nb_entries); |
---|
417 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Mixer : %sexposed, %swritable, %sstored\n", |
---|
418 |
(m_mixer_exposed?"":"not "), |
---|
419 |
(m_mixer_readonly?"not ":""), |
---|
420 |
(m_mixer_flashstored?"":"not ")); |
---|
421 |
debugOutput(DEBUG_LEVEL_VERBOSE, " tx id: %s [%d], rx id: %s [%d]\n", |
---|
422 |
dstBlockToString(m_mixer_tx_id), m_mixer_tx_id, |
---|
423 |
srcBlockToString(m_mixer_rx_id), m_mixer_rx_id); |
---|
424 |
debugOutput(DEBUG_LEVEL_VERBOSE, " nb tx channels: %d, nb rx channels: %d\n", m_mixer_nb_tx, m_mixer_nb_rx); |
---|
425 |
debugOutput(DEBUG_LEVEL_VERBOSE, " General: dynamic stream config %ssupported\n", |
---|
426 |
(m_general_support_dynstream?"":"not ")); |
---|
427 |
debugOutput(DEBUG_LEVEL_VERBOSE, " flash load and store %ssupported\n", |
---|
428 |
(m_general_support_flash?"":"not ")); |
---|
429 |
debugOutput(DEBUG_LEVEL_VERBOSE, " peak metering %s\n", |
---|
430 |
(m_general_peak_enabled?"enabled":"disabled")); |
---|
431 |
debugOutput(DEBUG_LEVEL_VERBOSE, " stream config %sstored\n", |
---|
432 |
(m_general_stream_cfg_stored?"":"not ")); |
---|
433 |
debugOutput(DEBUG_LEVEL_VERBOSE, " max TX streams: %d, max RX streams: %d\n", |
---|
434 |
m_general_max_tx, m_general_max_rx); |
---|
435 |
|
---|
436 |
if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEII) { |
---|
437 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Chip: DICE-II\n"); |
---|
438 |
} else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEMINI) { |
---|
439 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Chip: DICE Mini (TCD2210)\n"); |
---|
440 |
} else if(m_general_chip == DICE_EAP_CAP_GENERAL_CHIP_DICEJR) { |
---|
441 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Chip: DICE Junior (TCD2220)\n"); |
---|
442 |
} |
---|
443 |
|
---|
444 |
debugOutput(DEBUG_LEVEL_VERBOSE, "--- Mixer configuration ---\n"); |
---|
445 |
if(m_mixer) { |
---|
446 |
m_mixer->show(); |
---|
447 |
} |
---|
448 |
debugOutput(DEBUG_LEVEL_VERBOSE, "--- Router/Peak space ---\n"); |
---|
449 |
if(m_router) { |
---|
450 |
m_router->show(); |
---|
451 |
} |
---|
452 |
|
---|
453 |
RouterConfig *rcfg = getActiveRouterConfig(); |
---|
454 |
if(rcfg) { |
---|
455 |
rcfg->show(); |
---|
456 |
} |
---|
457 |
StreamConfig *scfg = getActiveStreamConfig(); |
---|
458 |
if(scfg) { |
---|
459 |
scfg->show(); |
---|
460 |
} |
---|
461 |
|
---|
462 |
// fixme |
---|
463 |
// size_t len = 0x1000; |
---|
464 |
// quadlet_t tmp[len]; |
---|
465 |
// if(!readRegBlock( eRT_CurrentCfg, DICE_EAP_CURRCFG_LOW_STREAM, tmp, len*4) ) { |
---|
466 |
// debugError("Failed to read block\n"); |
---|
467 |
// } else { |
---|
468 |
// hexDumpQuadlets(tmp, len); |
---|
469 |
// } |
---|
470 |
|
---|
471 |
} |
---|
472 |
|
---|
473 |
// EAP load/store operations |
---|
474 |
|
---|
475 |
enum Device::EAP::eWaitReturn |
---|
476 |
Device::EAP::operationBusy() { |
---|
477 |
fb_quadlet_t tmp; |
---|
478 |
if(!readReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, &tmp)) { |
---|
479 |
debugError("Could not read opcode register\n"); |
---|
480 |
return eWR_Error; |
---|
481 |
} |
---|
482 |
if( (tmp & DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) == DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE) { |
---|
483 |
return eWR_Busy; |
---|
484 |
} else { |
---|
485 |
return eWR_Done; |
---|
486 |
} |
---|
487 |
} |
---|
488 |
|
---|
489 |
enum Device::EAP::eWaitReturn |
---|
490 |
Device::EAP::waitForOperationEnd(int max_wait_time_ms) { |
---|
491 |
int max_waits = max_wait_time_ms; |
---|
492 |
|
---|
493 |
while(max_waits--) { |
---|
494 |
enum eWaitReturn retval = operationBusy(); |
---|
495 |
switch(retval) { |
---|
496 |
case eWR_Busy: |
---|
497 |
break; // not done yet, keep waiting |
---|
498 |
case eWR_Done: |
---|
499 |
return eWR_Done; |
---|
500 |
case eWR_Error: |
---|
501 |
case eWR_Timeout: |
---|
502 |
debugError("Error while waiting for operation to end. (%d)\n", retval); |
---|
503 |
} |
---|
504 |
Util::SystemTimeSource::SleepUsecRelative(1000); |
---|
505 |
} |
---|
506 |
return eWR_Timeout; |
---|
507 |
} |
---|
508 |
|
---|
509 |
bool |
---|
510 |
Device::EAP::commandHelper(fb_quadlet_t cmd) { |
---|
511 |
// check whether another command is still running |
---|
512 |
if(operationBusy() == eWR_Busy) { |
---|
513 |
debugError("Other operation in progress\n"); |
---|
514 |
return false; |
---|
515 |
} |
---|
516 |
|
---|
517 |
// execute the command |
---|
518 |
if(!writeReg(eRT_Command, DICE_EAP_COMMAND_OPCODE, cmd)) { |
---|
519 |
debugError("Could not write opcode register\n"); |
---|
520 |
return false; |
---|
521 |
} |
---|
522 |
|
---|
523 |
// wait for the operation to end |
---|
524 |
enum eWaitReturn retval = waitForOperationEnd(); |
---|
525 |
switch(retval) { |
---|
526 |
case eWR_Done: |
---|
527 |
break; // do nothing |
---|
528 |
case eWR_Timeout: |
---|
529 |
debugWarning("Time-out while waiting for operation to end. (%d)\n", retval); |
---|
530 |
return false; |
---|
531 |
case eWR_Error: |
---|
532 |
case eWR_Busy: // can't be returned |
---|
533 |
debugError("Error while waiting for operation to end. (%d)\n", retval); |
---|
534 |
return false; |
---|
535 |
} |
---|
536 |
|
---|
537 |
// check the return value |
---|
538 |
if(!readReg(eRT_Command, DICE_EAP_COMMAND_RETVAL, &cmd)) { |
---|
539 |
debugError("Could not read return value register\n"); |
---|
540 |
return false; |
---|
541 |
} |
---|
542 |
if(cmd != 0) { |
---|
543 |
debugWarning("Command failed\n"); |
---|
544 |
return false; |
---|
545 |
} else { |
---|
546 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Command successful\n"); |
---|
547 |
return true; |
---|
548 |
} |
---|
549 |
} |
---|
550 |
|
---|
551 |
bool |
---|
552 |
Device::EAP::loadRouterConfig(bool low, bool mid, bool high) { |
---|
553 |
fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_ROUTER; |
---|
554 |
if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW; |
---|
555 |
if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID; |
---|
556 |
if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH; |
---|
557 |
cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE; |
---|
558 |
return commandHelper(cmd); |
---|
559 |
} |
---|
560 |
|
---|
561 |
bool |
---|
562 |
Device::EAP::loadStreamConfig(bool low, bool mid, bool high) { |
---|
563 |
debugWarning("Untested code\n"); |
---|
564 |
fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_STRM_CFG; |
---|
565 |
if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW; |
---|
566 |
if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID; |
---|
567 |
if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH; |
---|
568 |
cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE; |
---|
569 |
return commandHelper(cmd); |
---|
570 |
} |
---|
571 |
|
---|
572 |
bool |
---|
573 |
Device::EAP::loadRouterAndStreamConfig(bool low, bool mid, bool high) { |
---|
574 |
debugWarning("Untested code\n"); |
---|
575 |
fb_quadlet_t cmd = DICE_EAP_CMD_OPCODE_LD_RTR_STRM_CFG; |
---|
576 |
if(low) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_LOW; |
---|
577 |
if(mid) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_MID; |
---|
578 |
if(high) cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_HIGH; |
---|
579 |
cmd |= DICE_EAP_CMD_OPCODE_FLAG_LD_EXECUTE; |
---|
580 |
return commandHelper(cmd); |
---|
581 |
} |
---|
582 |
|
---|
583 |
// internal I/O operations |
---|
584 |
bool |
---|
585 |
Device::EAP::readReg(enum eRegBase base, unsigned offset, fb_quadlet_t *result) { |
---|
586 |
fb_nodeaddr_t addr = offsetGen(base, offset, 4); |
---|
587 |
return m_device.readReg(addr, result); |
---|
588 |
} |
---|
589 |
|
---|
590 |
bool |
---|
591 |
Device::EAP::writeReg(enum eRegBase base, unsigned offset, fb_quadlet_t data) { |
---|
592 |
fb_nodeaddr_t addr = offsetGen(base, offset, 4); |
---|
593 |
return m_device.writeReg(addr, data); |
---|
594 |
} |
---|
595 |
|
---|
596 |
bool |
---|
597 |
Device::EAP::readRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) { |
---|
598 |
fb_nodeaddr_t addr = offsetGen(base, offset, length); |
---|
599 |
return m_device.readRegBlock(addr, data, length); |
---|
600 |
} |
---|
601 |
|
---|
602 |
bool |
---|
603 |
Device::EAP::writeRegBlock(enum eRegBase base, unsigned offset, fb_quadlet_t *data, size_t length) { |
---|
604 |
fb_nodeaddr_t addr = offsetGen(base, offset, length); |
---|
605 |
return m_device.writeRegBlock(addr, data, length); |
---|
606 |
} |
---|
607 |
|
---|
608 |
fb_nodeaddr_t |
---|
609 |
Device::EAP::offsetGen(enum eRegBase base, unsigned offset, size_t length) { |
---|
610 |
fb_nodeaddr_t addr; |
---|
611 |
fb_nodeaddr_t maxlen; |
---|
612 |
switch(base) { |
---|
613 |
case eRT_Base: |
---|
614 |
addr = 0; |
---|
615 |
maxlen = DICE_EAP_MAX_SIZE; |
---|
616 |
break; |
---|
617 |
case eRT_Capability: |
---|
618 |
addr = m_capability_offset; |
---|
619 |
maxlen = m_capability_size; |
---|
620 |
break; |
---|
621 |
case eRT_Command: |
---|
622 |
addr = m_cmd_offset; |
---|
623 |
maxlen = m_cmd_size; |
---|
624 |
break; |
---|
625 |
case eRT_Mixer: |
---|
626 |
addr = m_mixer_offset; |
---|
627 |
maxlen = m_mixer_size; |
---|
628 |
break; |
---|
629 |
case eRT_Peak: |
---|
630 |
addr = m_peak_offset; |
---|
631 |
maxlen = m_peak_size; |
---|
632 |
break; |
---|
633 |
case eRT_NewRouting: |
---|
634 |
addr = m_new_routing_offset; |
---|
635 |
maxlen = m_new_routing_size; |
---|
636 |
break; |
---|
637 |
case eRT_NewStreamCfg: |
---|
638 |
addr = m_new_stream_cfg_offset; |
---|
639 |
maxlen = m_new_stream_cfg_size; |
---|
640 |
break; |
---|
641 |
case eRT_CurrentCfg: |
---|
642 |
addr = m_curr_cfg_offset; |
---|
643 |
maxlen = m_curr_cfg_size; |
---|
644 |
break; |
---|
645 |
case eRT_Standalone: |
---|
646 |
addr = m_standalone_offset; |
---|
647 |
maxlen = m_standalone_size; |
---|
648 |
break; |
---|
649 |
case eRT_Application: |
---|
650 |
addr = m_app_offset; |
---|
651 |
maxlen = m_app_size; |
---|
652 |
break; |
---|
653 |
default: |
---|
654 |
debugError("Unsupported base address\n"); |
---|
655 |
return 0; |
---|
656 |
}; |
---|
657 |
|
---|
658 |
// out-of-range check |
---|
659 |
if(length > maxlen) { |
---|
660 |
debugError("requested length too large: %d > %d\n", length, maxlen); |
---|
661 |
return DICE_INVALID_OFFSET; |
---|
662 |
} |
---|
663 |
return DICE_EAP_BASE + addr + offset; |
---|
664 |
} |
---|
665 |
|
---|
666 |
/** |
---|
667 |
* Check whether a device supports eap |
---|
668 |
* @param d the device to check |
---|
669 |
* @return true if the device supports EAP |
---|
670 |
*/ |
---|
671 |
bool |
---|
672 |
Device::EAP::supportsEAP(Device &d) |
---|
673 |
{ |
---|
674 |
DebugModule &m_debugModule = d.m_debugModule; |
---|
675 |
quadlet_t tmp; |
---|
676 |
if(!d.readReg(DICE_EAP_BASE, &tmp)) { |
---|
677 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP base address\n"); |
---|
678 |
return false; |
---|
679 |
} |
---|
680 |
if(!d.readReg(DICE_EAP_BASE + DICE_EAP_ZERO_MARKER_1, &tmp)) { |
---|
681 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Could not read from DICE EAP zero marker\n"); |
---|
682 |
return false; |
---|
683 |
} |
---|
684 |
if(tmp != 0) { |
---|
685 |
debugOutput(DEBUG_LEVEL_VERBOSE, "DICE EAP zero marker not zero\n"); |
---|
686 |
return false; |
---|
687 |
} |
---|
688 |
return true; |
---|
689 |
} |
---|
690 |
|
---|
691 |
// ----------- Mixer ------------- |
---|
692 |
Device::EAP::Mixer::Mixer(EAP &p) |
---|
693 |
: Control::MatrixMixer(&p.m_device, "MatrixMixer") |
---|
694 |
, m_eap(p) |
---|
695 |
, m_coeff(NULL) |
---|
696 |
, m_debugModule(p.m_debugModule) |
---|
697 |
{ |
---|
698 |
} |
---|
699 |
|
---|
700 |
Device::EAP::Mixer::~Mixer() |
---|
701 |
{ |
---|
702 |
if (m_coeff) { |
---|
703 |
free(m_coeff); |
---|
704 |
m_coeff = NULL; |
---|
705 |
} |
---|
706 |
} |
---|
707 |
|
---|
708 |
bool |
---|
709 |
Device::EAP::Mixer::init() |
---|
710 |
{ |
---|
711 |
if(!m_eap.m_mixer_exposed) { |
---|
712 |
debugError("Device does not expose mixer\n"); |
---|
713 |
return false; |
---|
714 |
} |
---|
715 |
|
---|
716 |
// remove previous coefficient array |
---|
717 |
if(m_coeff) { |
---|
718 |
free(m_coeff); |
---|
719 |
m_coeff = NULL; |
---|
720 |
} |
---|
721 |
|
---|
722 |
// allocate coefficient array |
---|
723 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
724 |
int nb_outputs = m_eap.m_mixer_nb_rx; |
---|
725 |
|
---|
726 |
m_coeff = (fb_quadlet_t *)calloc(nb_outputs * nb_inputs, sizeof(fb_quadlet_t)); |
---|
727 |
|
---|
728 |
// load initial values |
---|
729 |
if(!loadCoefficients()) { |
---|
730 |
debugWarning("Could not initialize coefficients\n"); |
---|
731 |
return false; |
---|
732 |
} |
---|
733 |
updateNameCache(); |
---|
734 |
return true; |
---|
735 |
} |
---|
736 |
|
---|
737 |
bool |
---|
738 |
Device::EAP::Mixer::loadCoefficients() |
---|
739 |
{ |
---|
740 |
if(m_coeff == NULL) { |
---|
741 |
debugError("Coefficient cache not initialized\n"); |
---|
742 |
return false; |
---|
743 |
} |
---|
744 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
745 |
int nb_outputs = m_eap.m_mixer_nb_rx; |
---|
746 |
if(!m_eap.readRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) { |
---|
747 |
debugError("Failed to read coefficients\n"); |
---|
748 |
return false; |
---|
749 |
} |
---|
750 |
return true; |
---|
751 |
} |
---|
752 |
|
---|
753 |
bool |
---|
754 |
Device::EAP::Mixer::storeCoefficients() |
---|
755 |
{ |
---|
756 |
if(m_coeff == NULL) { |
---|
757 |
debugError("Coefficient cache not initialized\n"); |
---|
758 |
return false; |
---|
759 |
} |
---|
760 |
if(m_eap.m_mixer_readonly) { |
---|
761 |
debugWarning("Mixer is read-only\n"); |
---|
762 |
return false; |
---|
763 |
} |
---|
764 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
765 |
int nb_outputs = m_eap.m_mixer_nb_rx; |
---|
766 |
if(!m_eap.writeRegBlock(eRT_Mixer, 4, m_coeff, nb_inputs * nb_outputs * 4)) { |
---|
767 |
debugError("Failed to read coefficients\n"); |
---|
768 |
return false; |
---|
769 |
} |
---|
770 |
return true; |
---|
771 |
} |
---|
772 |
|
---|
773 |
void |
---|
774 |
Device::EAP::Mixer::updateNameCache() |
---|
775 |
{ |
---|
776 |
// figure out the number of i/o's |
---|
777 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
778 |
int nb_outputs = m_eap.m_mixer_nb_rx; |
---|
779 |
|
---|
780 |
// clear the previous map |
---|
781 |
m_input_route_map.clear(); |
---|
782 |
m_output_route_map.clear(); |
---|
783 |
|
---|
784 |
// find the active router configuration |
---|
785 |
RouterConfig * rcfg = m_eap.getActiveRouterConfig(); |
---|
786 |
if(rcfg == NULL) { |
---|
787 |
debugError("Could not get active routing info\n"); |
---|
788 |
return; |
---|
789 |
} |
---|
790 |
|
---|
791 |
// find the inputs |
---|
792 |
for(int i=0; i < nb_inputs; i++) { |
---|
793 |
int ch = i; |
---|
794 |
// the destination id of the mixer input |
---|
795 |
int dest_int = m_eap.m_mixer_tx_id; |
---|
796 |
|
---|
797 |
// from the DICE mixer spec: |
---|
798 |
// we can have 16 channels per "block" |
---|
799 |
// if there are more, consecutive block id's are assumed |
---|
800 |
while(ch > 15) { |
---|
801 |
ch -= 16; |
---|
802 |
dest_int += 1; |
---|
803 |
} |
---|
804 |
// the destination block and channel corresponding with this |
---|
805 |
// mixer input is now known |
---|
806 |
enum eRouteDestination dest = rcfg->intToRouteDestination(dest_int); |
---|
807 |
|
---|
808 |
// get the source for this mixer channel |
---|
809 |
m_input_route_map[i] = rcfg->getRouteForDestination(dest, ch); |
---|
810 |
|
---|
811 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer input channel %2d source: %s\n", i, |
---|
812 |
srcBlockToString(m_input_route_map[i].src), |
---|
813 |
m_input_route_map[i].srcChannel); |
---|
814 |
} |
---|
815 |
|
---|
816 |
// find where the outputs are connected to |
---|
817 |
for(int i=0; i < nb_outputs; i++) { |
---|
818 |
int ch = i; |
---|
819 |
// the source id of the mixer input |
---|
820 |
int src_int = m_eap.m_mixer_rx_id; |
---|
821 |
|
---|
822 |
// from the DICE mixer spec: |
---|
823 |
// we can have 16 channels per "block" |
---|
824 |
// if there are more, consecutive block id's are assumed |
---|
825 |
while(ch > 15) { |
---|
826 |
ch -= 16; |
---|
827 |
src_int += 1; |
---|
828 |
} |
---|
829 |
|
---|
830 |
// the source block and channel corresponding with this |
---|
831 |
// mixer output is now known |
---|
832 |
enum eRouteSource src = rcfg->intToRouteSource(src_int); |
---|
833 |
|
---|
834 |
// get the routing destinations for this mixer channel |
---|
835 |
m_output_route_map[i] = rcfg->getRoutesForSource(src, ch); |
---|
836 |
|
---|
837 |
#ifdef DEBUG |
---|
838 |
std::string destinations; |
---|
839 |
for ( RouterConfig::RouteVectorIterator it = m_output_route_map[i].begin(); |
---|
840 |
it != m_output_route_map[i].end(); |
---|
841 |
++it ) |
---|
842 |
{ |
---|
843 |
RouterConfig::Route r = *it; |
---|
844 |
// check whether the destination is valid |
---|
845 |
if((r.dst != eRD_Invalid) && (r.dstChannel >= 0)) { |
---|
846 |
char tmp[128]; |
---|
847 |
snprintf(tmp, 128, "%s:%d,", dstBlockToString(r.dst), r.dstChannel); |
---|
848 |
destinations += tmp; |
---|
849 |
} |
---|
850 |
} |
---|
851 |
debugOutput(DEBUG_LEVEL_VERBOSE, "Mixer output channel %2d destinations: %s\n", i, destinations.c_str()); |
---|
852 |
#endif |
---|
853 |
} |
---|
854 |
} |
---|
855 |
|
---|
856 |
void |
---|
857 |
Device::EAP::Mixer::show() |
---|
858 |
{ |
---|
859 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
860 |
int nb_outputs = m_eap.m_mixer_nb_rx; |
---|
861 |
|
---|
862 |
updateNameCache(); |
---|
863 |
|
---|
864 |
const size_t bufflen = 4096; |
---|
865 |
char tmp[bufflen]; |
---|
866 |
int cnt; |
---|
867 |
|
---|
868 |
cnt = 0; |
---|
869 |
for(int j=0; j < nb_inputs; j++) { |
---|
870 |
cnt += snprintf(tmp+cnt, bufflen-cnt, " %02d ", j); |
---|
871 |
} |
---|
872 |
printMessage("%s\n", tmp); |
---|
873 |
|
---|
874 |
cnt = 0; |
---|
875 |
for(int j=0; j < nb_inputs; j++) { |
---|
876 |
cnt += snprintf(tmp+cnt, bufflen-cnt, "%s:%02d ", |
---|
877 |
srcBlockToString(m_input_route_map[j].src), |
---|
878 |
m_input_route_map[j].srcChannel); |
---|
879 |
} |
---|
880 |
printMessage("%s\n", tmp); |
---|
881 |
|
---|
882 |
// display coefficients |
---|
883 |
for(int i=0; i < nb_outputs; i++) { |
---|
884 |
cnt = 0; |
---|
885 |
for(int j=0; j < nb_inputs; j++) { |
---|
886 |
cnt += snprintf(tmp+cnt, bufflen-cnt, "%07d ", *(m_coeff + nb_inputs * i + j)); |
---|
887 |
} |
---|
888 |
|
---|
889 |
// construct the set of destinations |
---|
890 |
std::string destinations; |
---|
891 |
for ( RouterConfig::RouteVectorIterator it = m_output_route_map[i].begin(); |
---|
892 |
it != m_output_route_map[i].end(); |
---|
893 |
++it ) |
---|
894 |
{ |
---|
895 |
RouterConfig::Route r = *it; |
---|
896 |
// check whether the destination is valid |
---|
897 |
if((r.dst != eRD_Invalid) && (r.dstChannel >= 0)) { |
---|
898 |
char tmp[128]; |
---|
899 |
snprintf(tmp, 128, "%s:%d,", dstBlockToString(r.dst), r.dstChannel); |
---|
900 |
destinations += tmp; |
---|
901 |
} |
---|
902 |
} |
---|
903 |
|
---|
904 |
cnt += snprintf(tmp+cnt, bufflen-cnt, "=[%02d]=> %s ", i, destinations.c_str()); |
---|
905 |
printMessage("%s\n", tmp); |
---|
906 |
} |
---|
907 |
|
---|
908 |
} |
---|
909 |
|
---|
910 |
// The control interface to the mixer |
---|
911 |
std::string |
---|
912 |
Device::EAP::Mixer::getRowName( const int row ) |
---|
913 |
{ |
---|
914 |
return "FIXME"; |
---|
915 |
} |
---|
916 |
|
---|
917 |
std::string |
---|
918 |
Device::EAP::Mixer::getColName( const int col ) |
---|
919 |
{ |
---|
920 |
return "FIXME"; |
---|
921 |
} |
---|
922 |
|
---|
923 |
int |
---|
924 |
Device::EAP::Mixer::canWrite( const int row, const int col) |
---|
925 |
{ |
---|
926 |
if(m_eap.m_mixer_readonly) { |
---|
927 |
return false; |
---|
928 |
} |
---|
929 |
return (row >= 0 && row < m_eap.m_mixer_nb_tx && col >= 0 && col < m_eap.m_mixer_nb_rx); |
---|
930 |
} |
---|
931 |
|
---|
932 |
double |
---|
933 |
Device::EAP::Mixer::setValue( const int row, const int col, const double val) |
---|
934 |
{ |
---|
935 |
if(m_eap.m_mixer_readonly) { |
---|
936 |
debugWarning("Mixer is read-only\n"); |
---|
937 |
return false; |
---|
938 |
} |
---|
939 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
940 |
int addr = ((nb_inputs * row) + col) * 4; |
---|
941 |
quadlet_t tmp = (quadlet_t) val; |
---|
942 |
if(!m_eap.writeRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) { |
---|
943 |
debugError("Failed to write coefficient\n"); |
---|
944 |
return 0; |
---|
945 |
} |
---|
946 |
return (double)(tmp); |
---|
947 |
} |
---|
948 |
|
---|
949 |
double |
---|
950 |
Device::EAP::Mixer::getValue( const int row, const int col) |
---|
951 |
{ |
---|
952 |
int nb_inputs = m_eap.m_mixer_nb_tx; |
---|
953 |
int addr = ((nb_inputs * row) + col) * 4; |
---|
954 |
quadlet_t tmp; |
---|
955 |
if(!m_eap.readRegBlock(eRT_Mixer, 4+addr, &tmp, 4)) { |
---|
956 |
debugError("Failed to read coefficient\n"); |
---|
957 |
return 0; |
---|
958 |
} |
---|
959 |
return (double)(tmp); |
---|
960 |
} |
---|
961 |
|
---|
962 |
int |
---|
963 |
Device::EAP::Mixer::getRowCount() |
---|
964 |
{ |
---|
965 |
return m_eap.m_mixer_nb_tx; |
---|
966 |
} |
---|
967 |
|
---|
968 |
int |
---|
969 |
Device::EAP::Mixer::getColCount() |
---|
970 |
{ |
---|
971 |
return m_eap.m_mixer_nb_rx; |
---|
972 |
} |
---|
973 |
|
---|
974 |
// full map updates are unsupported |
---|
975 |
bool |
---|
976 |
Device::EAP::Mixer::getCoefficientMap(int &) { |
---|
977 |
return false; |
---|
978 |
} |
---|
979 |
|
---|
980 |
bool |
---|
981 |
Device::EAP::Mixer::storeCoefficientMap(int &) { |
---|
982 |
if(m_eap.m_mixer_readonly) { |
---|
983 |
debugWarning("Mixer is read-only\n"); |
---|
984 |
return false; |
---|
985 |
} |
---|
986 |
return false; |
---|
987 |
} |
---|
988 |
|
---|
989 |
// ----------- Router ------------- |
---|
990 |
// FIXME: some more efficient datastructure for the |
---|
991 |
// sources and destinations might be good |
---|
992 |
|
---|
993 |
|
---|
994 |
Device::EAP::Router::Router(EAP &p) |
---|
995 |
: Control::CrossbarRouter(&p.m_device, "Router") |
---|
996 |
, m_eap(p) |
---|
997 |
, m_peak( *(new PeakSpace(p)) ) |
---|
998 |
, m_debugModule(p.m_debugModule) |
---|
999 |
{ |
---|
1000 |
setupSources(); |
---|
1001 |
setupDestinations(); |
---|
1002 |
} |
---|
1003 |
|
---|
1004 |
Device::EAP::Router::~Router() |
---|
1005 |
{ |
---|
1006 |
delete &m_peak; |
---|
1007 |
} |
---|
1008 |
|
---|
1009 |
void |
---|
1010 |
Device::EAP::Router::setupSourcesAddSource(const char *basename, enum eRouteSource srcid, |
---|
1011 |
unsigned int base, unsigned int cnt) |
---|
1012 |
{ |
---|
1013 |
unsigned int i=0; |
---|
1014 |
char name[16]; |
---|
1015 |
for (i=0; i<cnt; i++) { |
---|
1016 |
snprintf(name, 16, "%s:%02d", basename, base+i); |
---|
1017 |
struct Source s = {name, srcid, i}; |
---|
1018 |
m_sources.push_back(s); |
---|
1019 |
} |
---|
1020 |
} |
---|
1021 |
|
---|
1022 |
void |
---|
1023 |
Device::EAP::Router::setupDestinationsAddDestination(const char *basename, enum eRouteDestination dstid, |
---|
1024 |
unsigned int base, unsigned int cnt) |
---|
1025 |
{ |
---|
1026 |
unsigned int i=0; |
---|
1027 |
char name[16]; |
---|
1028 |
for (i=0; i<cnt; i++) { |
---|
1029 |
snprintf(name, 16, "%s:%02d", basename, base+i); |
---|
1030 |
struct Destination d = {name, dstid, i}; |
---|
1031 |
m_destinations.push_back(d); |
---|
1032 |
} |
---|
1033 |
} |
---|
1034 |
|
---|
1035 |
|
---|
1036 |
void |
---|
1037 |
Device::EAP::Router::setupSources() { |
---|
1038 |
// add the routing sources and destinations for a DICE chip |
---|
1039 |
switch(m_eap.m_general_chip) { |
---|
1040 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEII: |
---|
1041 |
// router/EAP currently not supported |
---|
1042 |
break; |
---|
1043 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEJR: |
---|
1044 |
// these are unique to the junior |
---|
1045 |
|
---|
1046 |
// second audio port |
---|
1047 |
setupSourcesAddSource("InS1", eRS_InS1, 0, 8); |
---|
1048 |
|
---|
1049 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI: |
---|
1050 |
// these are common to the mini and junior |
---|
1051 |
|
---|
1052 |
// the AES receiver |
---|
1053 |
setupSourcesAddSource("AES", eRS_AES, 0, 8); |
---|
1054 |
|
---|
1055 |
// the ADAT receiver |
---|
1056 |
setupSourcesAddSource("ADAT", eRS_ADAT, 0, 8); |
---|
1057 |
|
---|
1058 |
// the Mixer outputs |
---|
1059 |
setupSourcesAddSource("MixerOut", eRS_Mixer, 0, 16); |
---|
1060 |
|
---|
1061 |
// the first audio port |
---|
1062 |
setupSourcesAddSource("InS0", eRS_InS0, 0, 8); |
---|
1063 |
|
---|
1064 |
// the ARM audio port |
---|
1065 |
setupSourcesAddSource("ARM", eRS_ARM, 0, 8); |
---|
1066 |
|
---|
1067 |
// the 1394 stream receivers |
---|
1068 |
setupSourcesAddSource("1394_0", eRS_ARX0, 0, 16); |
---|
1069 |
setupSourcesAddSource("1394_1", eRS_ARX1, 0, 16); |
---|
1070 |
|
---|
1071 |
// mute |
---|
1072 |
setupSourcesAddSource("Mute", eRS_Muted, 0, 1); |
---|
1073 |
|
---|
1074 |
break; |
---|
1075 |
default: |
---|
1076 |
// this is an unsupported chip |
---|
1077 |
break; |
---|
1078 |
} |
---|
1079 |
} |
---|
1080 |
|
---|
1081 |
void |
---|
1082 |
Device::EAP::Router::setupDestinations() { |
---|
1083 |
// add the routing sources and destinations for a DICE chip |
---|
1084 |
switch(m_eap.m_general_chip) { |
---|
1085 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEII: |
---|
1086 |
// router/EAP currently not supported |
---|
1087 |
break; |
---|
1088 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEJR: |
---|
1089 |
// these are unique to the junior |
---|
1090 |
|
---|
1091 |
// second audio port |
---|
1092 |
setupDestinationsAddDestination("InS1", eRD_InS1, 0, 8); |
---|
1093 |
|
---|
1094 |
case DICE_EAP_CAP_GENERAL_CHIP_DICEMINI: |
---|
1095 |
// these are common to the mini and junior |
---|
1096 |
|
---|
1097 |
// the AES receiver |
---|
1098 |
setupDestinationsAddDestination("AES", eRD_AES, 0, 8); |
---|
1099 |
|
---|
1100 |
// the ADAT receiver |
---|
1101 |
setupDestinationsAddDestination("ADAT", eRD_ADAT, 0, 8); |
---|
1102 |
|
---|
1103 |
// the Mixer outputs |
---|
1104 |
setupDestinationsAddDestination("MixerIn", eRD_Mixer0, 0, 16); |
---|
1105 |
setupDestinationsAddDestination("MixerIn", eRD_Mixer1, 16, 2); |
---|
1106 |
|
---|
1107 |
// the first audio port |
---|
1108 |
setupDestinationsAddDestination("InS0", eRD_InS0, 0, 8); |
---|
1109 |
|
---|
1110 |
// the ARM audio port |
---|
1111 |
setupDestinationsAddDestination("ARM", eRD_ARM, 0, 8); |
---|
1112 |
|
---|
1113 |
// the 1394 stream receivers |
---|
1114 |
setupDestinationsAddDestination("1394_0", eRD_ATX0, 0, 16); |
---|
1115 |
setupDestinationsAddDestination("1394_1", eRD_ATX1, 0, 16); |
---|
1116 |
|
---|
1117 |
// mute |
---|
1118 |
setupDestinationsAddDestination("Mute", eRD_Muted, 0, 1); |
---|
1119 |
|
---|
1120 |
break; |
---|
1121 |
default: |
---|
1122 |
// this is an unsupported chip |
---|
1123 |
break; |
---|
1124 |
} |
---|
1125 |
} |
---|
1126 |
|
---|
1127 |
std::string |
---|
1128 |
Device::EAP::Router::getSourceName(const int srcid) |
---|
1129 |
{ |
---|
1130 |
if((unsigned)srcid < m_sources.size()) { |
---|
1131 |
return m_sources.at(srcid).name; |
---|
1132 |
} else { |
---|
1133 |
debugWarning("source id out of range (%d)\n", srcid); |
---|
1134 |
return ""; |
---|
1135 |
} |
---|
1136 |
} |
---|
1137 |
|
---|
1138 |
std::string |
---|
1139 |
Device::EAP::Router::getDestinationName(const int dstid) |
---|
1140 |
{ |
---|
1141 |
if((unsigned)dstid < m_destinations.size()) { |
---|
1142 |
return m_destinations.at(dstid).name; |
---|
1143 |
} else { |
---|
1144 |
debugWarning("destination id out of range (%d)\n", dstid); |
---|
1145 |
return ""; |
---|
1146 |
} |
---|
1147 |
} |
---|
1148 |
|
---|
1149 |
int |
---|
1150 |
Device::EAP::Router::getSourceIndex(std::string name) |
---|
1151 |
{ |
---|
1152 |
int i = 0; |
---|
1153 |
for ( SourceVectorIterator it = m_sources.begin(); |
---|
1154 |
it != m_sources.end(); |
---|
1155 |
++it ) |
---|
1156 |
{ |
---|
1157 |
if(it->name == name) return i; |
---|
1158 |
i++; |
---|
1159 |
} |
---|
1160 |
return -1; |
---|
1161 |
} |
---|
1162 |
|
---|
1163 |
int |
---|
1164 |
Device::EAP::Router::getDestinationIndex(std::string name) |
---|
1165 |
{ |
---|
1166 |
int i = 0; |
---|
1167 |
for ( DestinationVectorIterator it = m_destinations.begin(); |
---|
1168 |
it != m_destinations.end(); |
---|
1169 |
++it ) |
---|
1170 |
{ |
---|
1171 |
if(it->name == name) return i; |
---|
1172 |
i++; |
---|
1173 |
} |
---|
1174 |
return -1; |
---|
1175 |
} |
---|
1176 |
|
---|
1177 |
int |
---|
1178 |
Device::EAP::Router::getSourceIndex(enum eRouteSource srcid, int channel) |
---|
1179 |
{ |
---|
1180 |
int i = 0; |
---|
1181 |
for ( SourceVectorIterator it = m_sources.begin(); |
---|
1182 |
it != m_sources.end(); |
---|
1183 |
++it ) |
---|
1184 |
{ |
---|
1185 |
if((it->src == srcid) && (it->srcChannel == channel)) return i; |
---|
1186 |
i++; |
---|
1187 |
} |
---|
1188 |
return -1; |
---|
1189 |
} |
---|
1190 |
|
---|
1191 |
int |
---|
1192 |
Device::EAP::Router::getDestinationIndex(enum eRouteDestination dstid, int channel) |
---|
1193 |
{ |
---|
1194 |
int i = 0; |
---|
1195 |
for ( DestinationVectorIterator it = m_destinations.begin(); |
---|
1196 |
it != m_destinations.end(); |
---|
1197 |
++it ) |
---|
1198 |
{ |
---|
1199 |
if((it->dst == dstid) && (it->dstChannel == channel)) return i; |
---|
1200 |
i++; |
---|
1201 |
} |
---|
1202 |
return -1; |
---|
1203 |
} |
---|
1204 |
|
---|
1205 |
Control::CrossbarRouter::NameVector |
---|
1206 |
Device::EAP::Router::getSourceNames() |
---|
1207 |
{ |
---|
1208 |
Control::CrossbarRouter::NameVector n; |
---|
1209 |
for ( SourceVectorIterator it = m_sources.begin(); |
---|
1210 |
it != m_sources.end(); |
---|
1211 |
++it ) |
---|
1212 |
{ |
---|
1213 |
n.push_back(it->name); |
---|
1214 |
} |
---|
1215 |
return n; |
---|
1216 |
} |
---|
1217 |
|
---|
1218 |
Control::CrossbarRouter::NameVector |
---|
1219 |
Device::EAP::Router::getDestinationNames() |
---|
1220 |
{ |
---|
1221 |
Control::CrossbarRouter::NameVector n; |
---|
1222 |
for ( DestinationVectorIterator it = m_destinations.begin(); |
---|
1223 |
it != m_destinations.end(); |
---|
1224 |
++it ) |
---|
1225 |
{ |
---|
1226 |
n.push_back(it->name); |
---|
1227 |
} |
---|
1228 |
return n; |
---|
1229 |
} |
---|
1230 |
|
---|
1231 |
Control::CrossbarRouter::IntVector |
---|
1232 |
Device::EAP::Router::getDestinationsForSource(const int srcid) |
---|
1233 |
{ |
---|
1234 |
IntVector retval; |
---|
1235 |
if((unsigned)srcid < m_sources.size()) { |
---|
1236 |
Source s = m_sources.at(srcid); |
---|
1237 |
|
---|
1238 |
// get the routing configuration |
---|
1239 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1240 |
if(rcfg == NULL) { |
---|
1241 |
debugError("Could not request active router configuration\n"); |
---|
1242 |
return retval; |
---|
1243 |
} |
---|
1244 |
// get the source routes |
---|
1245 |
RouterConfig::RouteVector v = rcfg->getRoutesForSource(s.src, s.srcChannel); |
---|
1246 |
|
---|
1247 |
for ( RouterConfig::RouteVectorIterator it = v.begin(); |
---|
1248 |
it != v.end(); |
---|
1249 |
++it ) |
---|
1250 |
{ |
---|
1251 |
// FIXME: some more efficient datastructure might be good to |
---|
1252 |
// avoid this loop |
---|
1253 |
RouterConfig::Route &r = *it; |
---|
1254 |
int i = 0; |
---|
1255 |
for ( DestinationVectorIterator it = m_destinations.begin(); |
---|
1256 |
it != m_destinations.end(); |
---|
1257 |
++it ) |
---|
1258 |
{ |
---|
1259 |
if((it->dst == r.dst) && (it->dstChannel == r.dstChannel)) { |
---|
1260 |
retval.push_back(i); |
---|
1261 |
break; // can only match once |
---|
1262 |
} |
---|
1263 |
i++; |
---|
1264 |
} |
---|
1265 |
} |
---|
1266 |
return retval; |
---|
1267 |
} else { |
---|
1268 |
debugWarning("source id out of range (%d)\n", srcid); |
---|
1269 |
return retval; |
---|
1270 |
} |
---|
1271 |
} |
---|
1272 |
|
---|
1273 |
int |
---|
1274 |
Device::EAP::Router::getSourceForDestination(const int dstid) |
---|
1275 |
{ |
---|
1276 |
if((unsigned)dstid < m_destinations.size()) { |
---|
1277 |
Destination d = m_destinations.at(dstid); |
---|
1278 |
|
---|
1279 |
// get the routing configuration |
---|
1280 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1281 |
if(rcfg == NULL) { |
---|
1282 |
debugError("Could not request active router configuration\n"); |
---|
1283 |
return false; |
---|
1284 |
} |
---|
1285 |
|
---|
1286 |
RouterConfig::Route r = rcfg->getRouteForDestination(d.dst, d.dstChannel); |
---|
1287 |
if(r.src == eRS_Invalid) { |
---|
1288 |
return -1; |
---|
1289 |
} else { |
---|
1290 |
// FIXME: some more efficient datastructure might be good to |
---|
1291 |
// avoid this loop |
---|
1292 |
int i = 0; |
---|
1293 |
for ( SourceVectorIterator it = m_sources.begin(); |
---|
1294 |
it != m_sources.end(); |
---|
1295 |
++it ) |
---|
1296 |
{ |
---|
1297 |
if((it->src == r.src) && (it->srcChannel == r.srcChannel)) return i; |
---|
1298 |
i++; |
---|
1299 |
} |
---|
1300 |
return -1; |
---|
1301 |
} |
---|
1302 |
} else { |
---|
1303 |
debugWarning("destination id out of range (%d)\n", dstid); |
---|
1304 |
return -1; |
---|
1305 |
} |
---|
1306 |
} |
---|
1307 |
|
---|
1308 |
int |
---|
1309 |
Device::EAP::Router::getNbSources() |
---|
1310 |
{ |
---|
1311 |
return m_sources.size(); |
---|
1312 |
} |
---|
1313 |
|
---|
1314 |
int |
---|
1315 |
Device::EAP::Router::getNbDestinations() |
---|
1316 |
{ |
---|
1317 |
return m_destinations.size(); |
---|
1318 |
} |
---|
1319 |
|
---|
1320 |
bool |
---|
1321 |
Device::EAP::Router::canConnect(const int source, const int dest) |
---|
1322 |
{ |
---|
1323 |
if((unsigned)source >= m_sources.size()) { |
---|
1324 |
debugWarning("source id out of range (%d)\n", source); |
---|
1325 |
return false; |
---|
1326 |
} |
---|
1327 |
Source s = m_sources.at(source); |
---|
1328 |
|
---|
1329 |
if((unsigned)dest >= m_destinations.size()) { |
---|
1330 |
debugWarning("destination id out of range (%d)\n", dest); |
---|
1331 |
return false; |
---|
1332 |
} |
---|
1333 |
Destination d = m_destinations.at(dest); |
---|
1334 |
|
---|
1335 |
// we can connect anything |
---|
1336 |
// FIXME: can we? |
---|
1337 |
return true; |
---|
1338 |
} |
---|
1339 |
|
---|
1340 |
bool |
---|
1341 |
Device::EAP::Router::setConnectionState(const int source, const int dest, const bool enable) |
---|
1342 |
{ |
---|
1343 |
if((unsigned)source >= m_sources.size()) { |
---|
1344 |
debugWarning("source id out of range (%d)\n", source); |
---|
1345 |
return false; |
---|
1346 |
} |
---|
1347 |
Source s = m_sources.at(source); |
---|
1348 |
|
---|
1349 |
if((unsigned)dest >= m_destinations.size()) { |
---|
1350 |
debugWarning("destination id out of range (%d)\n", dest); |
---|
1351 |
return false; |
---|
1352 |
} |
---|
1353 |
Destination d = m_destinations.at(dest); |
---|
1354 |
|
---|
1355 |
// get the routing configuration |
---|
1356 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1357 |
if(rcfg == NULL) { |
---|
1358 |
debugError("Could not request active router configuration\n"); |
---|
1359 |
return false; |
---|
1360 |
} |
---|
1361 |
|
---|
1362 |
// build a new routing configuration |
---|
1363 |
RouterConfig newcfg = Device::EAP::RouterConfig(*rcfg); |
---|
1364 |
|
---|
1365 |
// construct the routing entry to find |
---|
1366 |
RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel}; |
---|
1367 |
|
---|
1368 |
// find the appropriate entry |
---|
1369 |
int idx = newcfg.getRouteIndex(r); |
---|
1370 |
|
---|
1371 |
if (idx < 0) { |
---|
1372 |
// we have to add the route |
---|
1373 |
newcfg.insertRoute(r); |
---|
1374 |
} else { |
---|
1375 |
// the route is already present, so we can replace it |
---|
1376 |
if(enable) { |
---|
1377 |
debugOutput(DEBUG_LEVEL_VERBOSE, "connection %d => %d already present\n", source, dest); |
---|
1378 |
return true; |
---|
1379 |
} else { |
---|
1380 |
// remove the route |
---|
1381 |
newcfg.removeRoute(idx); |
---|
1382 |
} |
---|
1383 |
} |
---|
1384 |
|
---|
1385 |
// if we get here it means we have to upload a new router config |
---|
1386 |
if(!m_eap.updateCurrentRouterConfig(newcfg)) { |
---|
1387 |
debugError("Could not update router config\n"); |
---|
1388 |
return false; |
---|
1389 |
} |
---|
1390 |
|
---|
1391 |
return true; |
---|
1392 |
} |
---|
1393 |
|
---|
1394 |
bool |
---|
1395 |
Device::EAP::Router::getConnectionState(const int source, const int dest) |
---|
1396 |
{ |
---|
1397 |
if((unsigned)source >= m_sources.size()) { |
---|
1398 |
debugWarning("source id out of range (%d)\n", source); |
---|
1399 |
return false; |
---|
1400 |
} |
---|
1401 |
Source s = m_sources.at(source); |
---|
1402 |
|
---|
1403 |
if((unsigned)dest >= m_destinations.size()) { |
---|
1404 |
debugWarning("destination id out of range (%d)\n", dest); |
---|
1405 |
return false; |
---|
1406 |
} |
---|
1407 |
Destination d = m_destinations.at(dest); |
---|
1408 |
|
---|
1409 |
// get the routing configuration |
---|
1410 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1411 |
if(rcfg == NULL) { |
---|
1412 |
debugError("Could not request active router configuration\n"); |
---|
1413 |
return false; |
---|
1414 |
} |
---|
1415 |
|
---|
1416 |
// build a new routing configuration |
---|
1417 |
RouterConfig newcfg = Device::EAP::RouterConfig(*rcfg); |
---|
1418 |
|
---|
1419 |
// construct the routing entry to find |
---|
1420 |
RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel}; |
---|
1421 |
|
---|
1422 |
// find the appropriate entry |
---|
1423 |
int idx = newcfg.getRouteIndex(r); |
---|
1424 |
|
---|
1425 |
if (idx < 0) { |
---|
1426 |
// the route is not present |
---|
1427 |
return false; |
---|
1428 |
} else { |
---|
1429 |
// the route is already present |
---|
1430 |
return true; |
---|
1431 |
} |
---|
1432 |
} |
---|
1433 |
|
---|
1434 |
bool |
---|
1435 |
Device::EAP::Router::canConnect(std::string src, std::string dst) |
---|
1436 |
{ |
---|
1437 |
int srcidx = getSourceIndex(src); |
---|
1438 |
int dstidx = getDestinationIndex(dst); |
---|
1439 |
return canConnect(srcidx, dstidx); |
---|
1440 |
} |
---|
1441 |
|
---|
1442 |
bool |
---|
1443 |
Device::EAP::Router::setConnectionState(std::string src, std::string dst, const bool enable) |
---|
1444 |
{ |
---|
1445 |
int srcidx = getSourceIndex(src); |
---|
1446 |
int dstidx = getDestinationIndex(dst); |
---|
1447 |
return setConnectionState(srcidx, dstidx, enable); |
---|
1448 |
} |
---|
1449 |
|
---|
1450 |
bool |
---|
1451 |
Device::EAP::Router::getConnectionState(std::string src, std::string dst) |
---|
1452 |
{ |
---|
1453 |
int srcidx = getSourceIndex(src); |
---|
1454 |
int dstidx = getDestinationIndex(dst); |
---|
1455 |
return getConnectionState(srcidx, dstidx); |
---|
1456 |
} |
---|
1457 |
|
---|
1458 |
// the map is organized as a matrix where the |
---|
1459 |
// rows are the destinations and the columns are |
---|
1460 |
// the sources |
---|
1461 |
|
---|
1462 |
// note that map as assumed to be big enough and |
---|
1463 |
// allocated by the user |
---|
1464 |
bool |
---|
1465 |
Device::EAP::Router::getConnectionMap(int *map) |
---|
1466 |
{ |
---|
1467 |
unsigned int nb_sources = getNbSources(); |
---|
1468 |
unsigned int nb_destinations = getNbDestinations(); |
---|
1469 |
|
---|
1470 |
// clear the map |
---|
1471 |
memset(map, 0, nb_sources * nb_destinations * sizeof(int)); |
---|
1472 |
|
---|
1473 |
// get the routing configuration |
---|
1474 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1475 |
if(rcfg == NULL) { |
---|
1476 |
debugError("Could not request active router configuration\n"); |
---|
1477 |
return false; |
---|
1478 |
} |
---|
1479 |
|
---|
1480 |
unsigned int nb_routes = rcfg->getNbRoutes(); |
---|
1481 |
|
---|
1482 |
for(unsigned int i=0; i<nb_routes; i++) { |
---|
1483 |
struct RouterConfig::Route r = rcfg->getRoute(i); |
---|
1484 |
int srcidx = getSourceIndex(r.src, r.srcChannel); |
---|
1485 |
int dstidx = getDestinationIndex(r.dst, r.dstChannel); |
---|
1486 |
if(srcidx < 0) { |
---|
1487 |
debugWarning("bogus source (%d, %d) in route table\n", r.src, r.srcChannel); |
---|
1488 |
} else if(dstidx < 0) { |
---|
1489 |
debugWarning("bogus destination (%d, %d) in route table\n", r.dst, r.dstChannel); |
---|
1490 |
} else { |
---|
1491 |
int *ptr = map; |
---|
1492 |
ptr += dstidx * nb_sources; |
---|
1493 |
ptr += srcidx; |
---|
1494 |
*ptr = 1; // route present |
---|
1495 |
} |
---|
1496 |
} |
---|
1497 |
return true; |
---|
1498 |
} |
---|
1499 |
|
---|
1500 |
bool |
---|
1501 |
Device::EAP::Router::setConnectionMap(int *map) |
---|
1502 |
{ |
---|
1503 |
return false; |
---|
1504 |
} |
---|
1505 |
|
---|
1506 |
bool |
---|
1507 |
Device::EAP::Router::clearAllConnections() |
---|
1508 |
{ |
---|
1509 |
// build a new empty routing configuration |
---|
1510 |
RouterConfig newcfg = Device::EAP::RouterConfig(m_eap); |
---|
1511 |
|
---|
1512 |
// upload the new router config |
---|
1513 |
if(!m_eap.updateCurrentRouterConfig(newcfg)) { |
---|
1514 |
debugError("Could not update router config\n"); |
---|
1515 |
return false; |
---|
1516 |
} |
---|
1517 |
return true; |
---|
1518 |
} |
---|
1519 |
|
---|
1520 |
bool |
---|
1521 |
Device::EAP::Router::hasPeakMetering() |
---|
1522 |
{ |
---|
1523 |
return m_eap.m_router_exposed; |
---|
1524 |
} |
---|
1525 |
|
---|
1526 |
double |
---|
1527 |
Device::EAP::Router::getPeakValue(const int source, const int dest) |
---|
1528 |
{ |
---|
1529 |
if((unsigned)source >= m_sources.size()) { |
---|
1530 |
debugWarning("source id out of range (%d)\n", source); |
---|
1531 |
return false; |
---|
1532 |
} |
---|
1533 |
Source s = m_sources.at(source); |
---|
1534 |
|
---|
1535 |
if((unsigned)dest >= m_destinations.size()) { |
---|
1536 |
debugWarning("destination id out of range (%d)\n", dest); |
---|
1537 |
return false; |
---|
1538 |
} |
---|
1539 |
Destination d = m_destinations.at(dest); |
---|
1540 |
|
---|
1541 |
debugOutput(DEBUG_LEVEL_VERBOSE, "getting peak info for [%d] %s => [%d] %s\n", |
---|
1542 |
source, s.name.c_str(), |
---|
1543 |
dest, d.name.c_str()); |
---|
1544 |
|
---|
1545 |
// update the peak information |
---|
1546 |
m_peak.read(); |
---|
1547 |
|
---|
1548 |
// construct the routing entry to find |
---|
1549 |
RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel, 0}; |
---|
1550 |
|
---|
1551 |
// find the appropriate entry |
---|
1552 |
int idx = m_peak.getRouteIndex(r); |
---|
1553 |
|
---|
1554 |
if (idx < 0) { |
---|
1555 |
// the route is not present |
---|
1556 |
return -1; |
---|
1557 |
} else { |
---|
1558 |
// the route is present |
---|
1559 |
r = m_peak.getRoute(idx); |
---|
1560 |
return r.peak; |
---|
1561 |
} |
---|
1562 |
|
---|
1563 |
} |
---|
1564 |
|
---|
1565 |
Control::CrossbarRouter::PeakValues |
---|
1566 |
Device::EAP::Router::getPeakValues() |
---|
1567 |
{ |
---|
1568 |
// To be implemented by ppalmers |
---|
1569 |
return PeakValues(); |
---|
1570 |
} |
---|
1571 |
|
---|
1572 |
void |
---|
1573 |
Device::EAP::Router::show() |
---|
1574 |
{ |
---|
1575 |
// print the peak space as it also contains the routing configuration |
---|
1576 |
printMessage("Active router config:\n"); |
---|
1577 |
m_peak.read(); |
---|
1578 |
m_peak.show(); |
---|
1579 |
} |
---|
1580 |
|
---|
1581 |
// ----------- routing config ------------- |
---|
1582 |
Device::EAP::RouterConfig::RouterConfig(EAP &p) |
---|
1583 |
: m_eap(p) |
---|
1584 |
, m_base(eRT_None), m_offset(0) |
---|
1585 |
, m_debugModule(p.m_debugModule) |
---|
1586 |
{} |
---|
1587 |
|
---|
1588 |
Device::EAP::RouterConfig::RouterConfig(EAP &p, enum eRegBase b, unsigned int o) |
---|
1589 |
: m_eap(p) |
---|
1590 |
, m_base(b), m_offset(o) |
---|
1591 |
, m_debugModule(p.m_debugModule) |
---|
1592 |
{} |
---|
1593 |
|
---|
1594 |
Device::EAP::RouterConfig::~RouterConfig() |
---|
1595 |
{} |
---|
1596 |
|
---|
1597 |
bool |
---|
1598 |
Device::EAP::RouterConfig::read(enum eRegBase base, unsigned offset) |
---|
1599 |
{ |
---|
1600 |
// first clear the current route vector |
---|
1601 |
m_routes.clear(); |
---|
1602 |
|
---|
1603 |
uint32_t nb_routes; |
---|
1604 |
if(!m_eap.readRegBlock(base, offset, &nb_routes, 4)) { |
---|
1605 |
debugError("Failed to read number of entries\n"); |
---|
1606 |
return false; |
---|
1607 |
} |
---|
1608 |
if(nb_routes == 0) { |
---|
1609 |
debugWarning("No routes found\n"); |
---|
1610 |
} |
---|
1611 |
|
---|
1612 |
// read the route info |
---|
1613 |
uint32_t tmp_entries[nb_routes]; |
---|
1614 |
if(!m_eap.readRegBlock(base, offset+4, tmp_entries, nb_routes*4)) { |
---|
1615 |
debugError("Failed to read router config block information\n"); |
---|
1616 |
return false; |
---|
1617 |
} |
---|
1618 |
|
---|
1619 |
// decode into the routing vector |
---|
1620 |
for(unsigned int i=0; i < nb_routes; i++) { |
---|
1621 |
m_routes.push_back(decodeRoute(tmp_entries[i])); |
---|
1622 |
} |
---|
1623 |
return true; |
---|
1624 |
} |
---|
1625 |
|
---|
1626 |
bool |
---|
1627 |
Device::EAP::RouterConfig::write(enum eRegBase base, unsigned offset) |
---|
1628 |
{ |
---|
1629 |
uint32_t nb_routes = m_routes.size(); |
---|
1630 |
if(nb_routes == 0) { |
---|
1631 |
debugWarning("Writing 0 routes?\n"); |
---|
1632 |
} |
---|
1633 |
uint32_t tmp_entries[nb_routes]; |
---|
1634 |
|
---|
1635 |
// encode from the routing vector |
---|
1636 |
int i=0; |
---|
1637 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1638 |
it != m_routes.end(); |
---|
1639 |
++it ) |
---|
1640 |
{ |
---|
1641 |
tmp_entries[i] = encodeRoute( *it ); |
---|
1642 |
i++; |
---|
1643 |
} |
---|
1644 |
|
---|
1645 |
// write the result to the device |
---|
1646 |
if(!m_eap.writeRegBlock(base, offset+4, tmp_entries, nb_routes*4)) { |
---|
1647 |
debugError("Failed to write router config block information\n"); |
---|
1648 |
return false; |
---|
1649 |
} |
---|
1650 |
if(!m_eap.writeRegBlock(base, offset, &nb_routes, 4)) { |
---|
1651 |
debugError("Failed to write number of entries\n"); |
---|
1652 |
return false; |
---|
1653 |
} |
---|
1654 |
return true; |
---|
1655 |
} |
---|
1656 |
|
---|
1657 |
bool |
---|
1658 |
Device::EAP::RouterConfig::insertRoute(struct Route r, unsigned int index) |
---|
1659 |
{ |
---|
1660 |
unsigned int nb_routes = getNbRoutes(); |
---|
1661 |
if(index > nb_routes) { |
---|
1662 |
debugError("Index out of range\n"); |
---|
1663 |
return false; |
---|
1664 |
} |
---|
1665 |
if (index == nb_routes) { // append |
---|
1666 |
m_routes.push_back(r); |
---|
1667 |
return true; |
---|
1668 |
} |
---|
1669 |
// insert |
---|
1670 |
RouteVectorIterator pos = m_routes.begin() + index; |
---|
1671 |
m_routes.insert(pos, r); |
---|
1672 |
return true; |
---|
1673 |
} |
---|
1674 |
|
---|
1675 |
bool |
---|
1676 |
Device::EAP::RouterConfig::replaceRoute(unsigned int old_index, struct Route new_route) |
---|
1677 |
{ |
---|
1678 |
if(old_index >= getNbRoutes()) { |
---|
1679 |
debugError("Index out of range\n"); |
---|
1680 |
return false; |
---|
1681 |
} |
---|
1682 |
if(!removeRoute(old_index)) { |
---|
1683 |
debugError("Could not remove old route\n"); |
---|
1684 |
return false; |
---|
1685 |
} |
---|
1686 |
return insertRoute(new_route, old_index); |
---|
1687 |
} |
---|
1688 |
|
---|
1689 |
bool |
---|
1690 |
Device::EAP::RouterConfig::replaceRoute(struct Route old_route, struct Route new_route) |
---|
1691 |
{ |
---|
1692 |
int idx = getRouteIndex(old_route); |
---|
1693 |
if(idx < 0) { |
---|
1694 |
debugWarning("Route not found\n"); |
---|
1695 |
return false; |
---|
1696 |
} |
---|
1697 |
return replaceRoute((unsigned int)idx, new_route); |
---|
1698 |
} |
---|
1699 |
|
---|
1700 |
bool |
---|
1701 |
Device::EAP::RouterConfig::removeRoute(struct Route r) |
---|
1702 |
{ |
---|
1703 |
int idx = getRouteIndex(r); |
---|
1704 |
if(idx < 0) { |
---|
1705 |
debugWarning("Route not found\n"); |
---|
1706 |
return false; |
---|
1707 |
} |
---|
1708 |
return removeRoute((unsigned int)idx); |
---|
1709 |
} |
---|
1710 |
|
---|
1711 |
bool |
---|
1712 |
Device::EAP::RouterConfig::removeRoute(unsigned int index) |
---|
1713 |
{ |
---|
1714 |
if(index >= getNbRoutes()) { |
---|
1715 |
debugError("Index out of range\n"); |
---|
1716 |
return false; |
---|
1717 |
} |
---|
1718 |
RouteVectorIterator pos = m_routes.begin() + index; |
---|
1719 |
m_routes.erase(pos); |
---|
1720 |
return true; |
---|
1721 |
} |
---|
1722 |
|
---|
1723 |
int |
---|
1724 |
Device::EAP::RouterConfig::getRouteIndex(struct Route r) |
---|
1725 |
{ |
---|
1726 |
int i = 0; |
---|
1727 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1728 |
it != m_routes.end(); |
---|
1729 |
++it ) |
---|
1730 |
{ |
---|
1731 |
struct Route t = *it; |
---|
1732 |
if ((t.src == r.src) && (t.srcChannel == r.srcChannel) && (t.dst == r.dst) && (t.dstChannel == r.dstChannel)) return i; |
---|
1733 |
i++; |
---|
1734 |
} |
---|
1735 |
return -1; |
---|
1736 |
} |
---|
1737 |
|
---|
1738 |
struct Device::EAP::RouterConfig::Route |
---|
1739 |
Device::EAP::RouterConfig::getRoute(unsigned int idx) |
---|
1740 |
{ |
---|
1741 |
if( (idx < 0) || (idx >= m_routes.size()) ) { |
---|
1742 |
debugWarning("Route index out of range (%d)\n", idx); |
---|
1743 |
Route r = {eRS_Invalid, -1, eRD_Invalid, -1, 0}; |
---|
1744 |
return r; |
---|
1745 |
} |
---|
1746 |
return m_routes.at(idx); |
---|
1747 |
} |
---|
1748 |
|
---|
1749 |
#define CASE_INT_EQUAL_RETURN(_x) case (int)(_x): return _x; |
---|
1750 |
enum Device::EAP::eRouteDestination |
---|
1751 |
Device::EAP::RouterConfig::intToRouteDestination(int dst) |
---|
1752 |
{ |
---|
1753 |
switch(dst) { |
---|
1754 |
CASE_INT_EQUAL_RETURN(eRD_AES); |
---|
1755 |
CASE_INT_EQUAL_RETURN(eRD_ADAT); |
---|
1756 |
CASE_INT_EQUAL_RETURN(eRD_Mixer0); |
---|
1757 |
CASE_INT_EQUAL_RETURN(eRD_Mixer1); |
---|
1758 |
CASE_INT_EQUAL_RETURN(eRD_InS0); |
---|
1759 |
CASE_INT_EQUAL_RETURN(eRD_InS1); |
---|
1760 |
CASE_INT_EQUAL_RETURN(eRD_ARM); |
---|
1761 |
CASE_INT_EQUAL_RETURN(eRD_ATX0); |
---|
1762 |
CASE_INT_EQUAL_RETURN(eRD_ATX1); |
---|
1763 |
CASE_INT_EQUAL_RETURN(eRD_Muted); |
---|
1764 |
default: return eRD_Invalid; |
---|
1765 |
} |
---|
1766 |
} |
---|
1767 |
|
---|
1768 |
enum Device::EAP::eRouteSource |
---|
1769 |
Device::EAP::RouterConfig::intToRouteSource(int src) |
---|
1770 |
{ |
---|
1771 |
switch(src) { |
---|
1772 |
CASE_INT_EQUAL_RETURN(eRS_AES); |
---|
1773 |
CASE_INT_EQUAL_RETURN(eRS_ADAT); |
---|
1774 |
CASE_INT_EQUAL_RETURN(eRS_Mixer); |
---|
1775 |
CASE_INT_EQUAL_RETURN(eRS_InS0); |
---|
1776 |
CASE_INT_EQUAL_RETURN(eRS_InS1); |
---|
1777 |
CASE_INT_EQUAL_RETURN(eRS_ARM); |
---|
1778 |
CASE_INT_EQUAL_RETURN(eRS_ARX0); |
---|
1779 |
CASE_INT_EQUAL_RETURN(eRS_ARX1); |
---|
1780 |
CASE_INT_EQUAL_RETURN(eRS_Muted); |
---|
1781 |
default: return eRS_Invalid; |
---|
1782 |
} |
---|
1783 |
} |
---|
1784 |
|
---|
1785 |
struct Device::EAP::RouterConfig::Route |
---|
1786 |
Device::EAP::RouterConfig::decodeRoute(uint32_t val) { |
---|
1787 |
int routerval = val & 0xFFFF; |
---|
1788 |
int peak = (val >> 16) & 0x0FFF; |
---|
1789 |
int src_blk = (routerval >> 12) & 0xF; |
---|
1790 |
int src_ch = (routerval >> 8) & 0xF; |
---|
1791 |
int dst_blk = (routerval >> 4) & 0xF; |
---|
1792 |
int dst_ch = (routerval >> 0) & 0xF; |
---|
1793 |
struct Route r = {intToRouteSource(src_blk), src_ch, intToRouteDestination(dst_blk), dst_ch, peak}; |
---|
1794 |
return r; |
---|
1795 |
} |
---|
1796 |
|
---|
1797 |
uint32_t |
---|
1798 |
Device::EAP::RouterConfig::encodeRoute(struct Route r) { |
---|
1799 |
if(r.src == eRS_Invalid || r.dst == eRD_Invalid) { |
---|
1800 |
debugWarning("Encoding invalid source/dest (%d/%d)\n", r.src, r.dst); |
---|
1801 |
// return 0xFFFFFFFF; |
---|
1802 |
} |
---|
1803 |
unsigned int src_blk = ((unsigned int)r.src) & 0xF; |
---|
1804 |
unsigned int src_ch = ((unsigned int)r.srcChannel) & 0xF; |
---|
1805 |
unsigned int dst_blk = ((unsigned int)r.dst) & 0xF; |
---|
1806 |
unsigned int dst_ch = ((unsigned int)r.dstChannel) & 0xF; |
---|
1807 |
uint32_t routerval = 0; |
---|
1808 |
routerval |= (src_blk << 12); |
---|
1809 |
routerval |= (src_ch << 8); |
---|
1810 |
routerval |= (dst_blk << 4); |
---|
1811 |
routerval |= (dst_ch << 0); |
---|
1812 |
return routerval; |
---|
1813 |
} |
---|
1814 |
|
---|
1815 |
struct Device::EAP::RouterConfig::Route |
---|
1816 |
Device::EAP::RouterConfig::getRouteForDestination(enum eRouteDestination dst, int channel) |
---|
1817 |
{ |
---|
1818 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1819 |
it != m_routes.end(); |
---|
1820 |
++it ) |
---|
1821 |
{ |
---|
1822 |
struct Route r = *it; |
---|
1823 |
if((r.dst == (int)dst) && (r.dstChannel == channel)) { |
---|
1824 |
debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d comes from %s:%02d\n", |
---|
1825 |
dstBlockToString(r.dst), r.dstChannel, |
---|
1826 |
srcBlockToString(r.src), r.srcChannel); |
---|
1827 |
return r; |
---|
1828 |
} |
---|
1829 |
} |
---|
1830 |
debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d source can't be found\n", |
---|
1831 |
dstBlockToString((int)dst), channel); |
---|
1832 |
struct Route r = {eRS_Invalid, -1, eRD_Invalid, 0, 0}; |
---|
1833 |
return r; |
---|
1834 |
} |
---|
1835 |
|
---|
1836 |
std::vector<struct Device::EAP::RouterConfig::Route> |
---|
1837 |
Device::EAP::RouterConfig::getRoutesForSource(enum eRouteSource src, int channel) |
---|
1838 |
{ |
---|
1839 |
std::vector<struct Route>routes; |
---|
1840 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1841 |
it != m_routes.end(); |
---|
1842 |
++it ) |
---|
1843 |
{ |
---|
1844 |
struct Route r = *it; |
---|
1845 |
if((r.src == (int)src) && (r.srcChannel == channel)) { |
---|
1846 |
debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d goes to %s:%02d\n", |
---|
1847 |
srcBlockToString(r.src), r.srcChannel, |
---|
1848 |
dstBlockToString(r.dst), r.dstChannel); |
---|
1849 |
routes.push_back(r); |
---|
1850 |
} |
---|
1851 |
} |
---|
1852 |
return routes; |
---|
1853 |
} |
---|
1854 |
|
---|
1855 |
void |
---|
1856 |
Device::EAP::RouterConfig::show() |
---|
1857 |
{ |
---|
1858 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1859 |
it != m_routes.end(); |
---|
1860 |
++it ) |
---|
1861 |
{ |
---|
1862 |
struct Route r = *it; |
---|
1863 |
debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d\n", |
---|
1864 |
srcBlockToString(r.src), r.srcChannel, |
---|
1865 |
dstBlockToString(r.dst), r.dstChannel); |
---|
1866 |
} |
---|
1867 |
} |
---|
1868 |
|
---|
1869 |
|
---|
1870 |
// ----------- peak space ------------- |
---|
1871 |
|
---|
1872 |
bool |
---|
1873 |
Device::EAP::PeakSpace::read(enum eRegBase base, unsigned offset) |
---|
1874 |
{ |
---|
1875 |
// first clear the current route vector |
---|
1876 |
m_routes.clear(); |
---|
1877 |
|
---|
1878 |
uint32_t nb_routes; |
---|
1879 |
// we have to figure out the number of entries through the currently |
---|
1880 |
// active router config |
---|
1881 |
RouterConfig *rcfg = m_eap.getActiveRouterConfig(); |
---|
1882 |
if(rcfg == NULL) { |
---|
1883 |
debugError("Could not get active router config\n"); |
---|
1884 |
return false; |
---|
1885 |
} |
---|
1886 |
nb_routes = rcfg->getNbRoutes(); |
---|
1887 |
|
---|
1888 |
// read the route info |
---|
1889 |
uint32_t tmp_entries[nb_routes]; |
---|
1890 |
if(!m_eap.readRegBlock(base, offset, tmp_entries, nb_routes*4)) { |
---|
1891 |
debugError("Failed to read peak block information\n"); |
---|
1892 |
return false; |
---|
1893 |
} |
---|
1894 |
|
---|
1895 |
// decode into the routing vector |
---|
1896 |
for(unsigned int i=0; i < nb_routes; i++) { |
---|
1897 |
m_routes.push_back(decodeRoute(tmp_entries[i])); |
---|
1898 |
} |
---|
1899 |
// show(); |
---|
1900 |
return true; |
---|
1901 |
} |
---|
1902 |
|
---|
1903 |
bool |
---|
1904 |
Device::EAP::PeakSpace::write(enum eRegBase base, unsigned offset) |
---|
1905 |
{ |
---|
1906 |
debugError("Peak space is read-only\n"); |
---|
1907 |
return true; |
---|
1908 |
} |
---|
1909 |
|
---|
1910 |
void |
---|
1911 |
Device::EAP::PeakSpace::show() |
---|
1912 |
{ |
---|
1913 |
for ( RouteVectorIterator it = m_routes.begin(); |
---|
1914 |
it != m_routes.end(); |
---|
1915 |
++it ) |
---|
1916 |
{ |
---|
1917 |
struct Route r = *it; |
---|
1918 |
debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d : %06d\n", |
---|
1919 |
srcBlockToString(r.src), r.srcChannel, |
---|
1920 |
dstBlockToString(r.dst), r.dstChannel, |
---|
1921 |
r.peak); |
---|
1922 |
} |
---|
1923 |
} |
---|
1924 |
|
---|
1925 |
// ----------- stream config block ------------- |
---|
1926 |
Device::EAP::StreamConfig::StreamConfig(EAP &p, enum eRegBase b, unsigned int o) |
---|
1927 |
: m_eap(p) |
---|
1928 |
, m_base(b), m_offset(o) |
---|
1929 |
, m_nb_tx(0), m_nb_rx(0) |
---|
1930 |
, m_tx_configs(NULL), m_rx_configs(NULL) |
---|
1931 |
, m_debugModule(p.m_debugModule) |
---|
1932 |
{ |
---|
1933 |
|
---|
1934 |
} |
---|
1935 |
|
---|
1936 |
Device::EAP::StreamConfig::~StreamConfig() |
---|
1937 |
{ |
---|
1938 |
if(m_tx_configs) delete[]m_tx_configs; |
---|
1939 |
if(m_rx_configs) delete[]m_rx_configs; |
---|
1940 |
} |
---|
1941 |
|
---|
1942 |
bool |
---|
1943 |
Device::EAP::StreamConfig::read(enum eRegBase base, unsigned offset) |
---|
1944 |
{ |
---|
1945 |
if(!m_eap.readRegBlock(base, offset, &m_nb_tx, 4)) { |
---|
1946 |
debugError("Failed to read number of tx entries\n"); |
---|
1947 |
return false; |
---|
1948 |
} |
---|
1949 |
if(!m_eap.readRegBlock(base, offset+4, &m_nb_rx, 4)) { |
---|
1950 |
debugError("Failed to read number of rx entries\n"); |
---|
1951 |
return false; |
---|
1952 |
} |
---|
1953 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Entries: TX: %lu, RX: %lu\n", m_nb_tx, m_nb_rx); |
---|
1954 |
|
---|
1955 |
if(m_tx_configs) { |
---|
1956 |
delete[]m_tx_configs; |
---|
1957 |
m_tx_configs = NULL; |
---|
1958 |
} |
---|
1959 |
if(m_rx_configs) { |
---|
1960 |
delete[]m_rx_configs; |
---|
1961 |
m_rx_configs = NULL; |
---|
1962 |
} |
---|
1963 |
|
---|
1964 |
offset += 8; |
---|
1965 |
if(m_nb_tx > 0) { |
---|
1966 |
m_tx_configs = new struct ConfigBlock[m_nb_tx]; |
---|
1967 |
for(unsigned int i=0; i<m_nb_tx; i++) { |
---|
1968 |
fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i])); |
---|
1969 |
if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) { |
---|
1970 |
debugError("Failed to read tx entry %d\n", i); |
---|
1971 |
return false; |
---|
1972 |
} |
---|
1973 |
offset += sizeof(struct ConfigBlock); |
---|
1974 |
} |
---|
1975 |
} |
---|
1976 |
|
---|
1977 |
if(m_nb_rx > 0) { |
---|
1978 |
m_rx_configs = new struct ConfigBlock[m_nb_rx]; |
---|
1979 |
for(unsigned int i=0; i<m_nb_rx; i++) { |
---|
1980 |
fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i])); |
---|
1981 |
if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) { |
---|
1982 |
debugError("Failed to read rx entry %d\n", i); |
---|
1983 |
return false; |
---|
1984 |
} |
---|
1985 |
offset += sizeof(struct ConfigBlock); |
---|
1986 |
} |
---|
1987 |
} |
---|
1988 |
return true; |
---|
1989 |
} |
---|
1990 |
|
---|
1991 |
bool |
---|
1992 |
Device::EAP::StreamConfig::write(enum eRegBase base, unsigned offset) |
---|
1993 |
{ |
---|
1994 |
if(!m_eap.writeRegBlock(base, offset, &m_nb_tx, 4)) { |
---|
1995 |
debugError("Failed to write number of tx entries\n"); |
---|
1996 |
return false; |
---|
1997 |
} |
---|
1998 |
if(!m_eap.writeRegBlock(base, offset+4, &m_nb_rx, 4)) { |
---|
1999 |
debugError("Failed to write number of rx entries\n"); |
---|
2000 |
return false; |
---|
2001 |
} |
---|
2002 |
|
---|
2003 |
offset += 8; |
---|
2004 |
for(unsigned int i=0; i<m_nb_tx; i++) { |
---|
2005 |
fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i])); |
---|
2006 |
if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) { |
---|
2007 |
debugError("Failed to write tx entry %d\n", i); |
---|
2008 |
return false; |
---|
2009 |
} |
---|
2010 |
offset += sizeof(struct ConfigBlock); |
---|
2011 |
} |
---|
2012 |
|
---|
2013 |
for(unsigned int i=0; i<m_nb_rx; i++) { |
---|
2014 |
fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i])); |
---|
2015 |
if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) { |
---|
2016 |
debugError("Failed to write rx entry %d\n", i); |
---|
2017 |
return false; |
---|
2018 |
} |
---|
2019 |
offset += sizeof(struct ConfigBlock); |
---|
2020 |
} |
---|
2021 |
return true; |
---|
2022 |
} |
---|
2023 |
|
---|
2024 |
Device::diceNameVector |
---|
2025 |
Device::EAP::StreamConfig::getNamesForBlock(struct ConfigBlock &b) |
---|
2026 |
{ |
---|
2027 |
diceNameVector names; |
---|
2028 |
char namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES+1]; |
---|
2029 |
|
---|
2030 |
memcpy(namestring, b.names, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES); |
---|
2031 |
|
---|
2032 |
// Strings from the device are always little-endian, |
---|
2033 |
// so byteswap for big-endian machines |
---|
2034 |
#if __BYTE_ORDER == __BIG_ENDIAN |
---|
2035 |
byteSwapBlock((quadlet_t *)namestring, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS); |
---|
2036 |
#endif |
---|
2037 |
|
---|
2038 |
namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES]='\0'; |
---|
2039 |
return m_eap.m_device.splitNameString(std::string(namestring)); |
---|
2040 |
} |
---|
2041 |
|
---|
2042 |
void |
---|
2043 |
Device::EAP::StreamConfig::showConfigBlock(struct ConfigBlock &b) |
---|
2044 |
{ |
---|
2045 |
debugOutput(DEBUG_LEVEL_VERBOSE, " Channel count : %lu audio, %lu midi\n", b.nb_audio, b.nb_midi); |
---|
2046 |
debugOutput(DEBUG_LEVEL_VERBOSE, " AC3 Map : 0x%08X\n", b.ac3_map); |
---|
2047 |
diceNameVector channel_names = getNamesForBlock(b); |
---|
2048 |
debugOutput(DEBUG_LEVEL_VERBOSE," Channel names :\n"); |
---|
2049 |
for ( diceNameVectorIterator it = channel_names.begin(); |
---|
2050 |
it != channel_names.end(); |
---|
2051 |
++it ) |
---|
2052 |
{ |
---|
2053 |
debugOutput(DEBUG_LEVEL_VERBOSE," %s\n", (*it).c_str()); |
---|
2054 |
} |
---|
2055 |
} |
---|
2056 |
|
---|
2057 |
void |
---|
2058 |
Device::EAP::StreamConfig::show() |
---|
2059 |
{ |
---|
2060 |
for(unsigned int i=0; i<m_nb_tx; i++) { |
---|
2061 |
debugOutput(DEBUG_LEVEL_VERBOSE, "TX Config block %d\n", i); |
---|
2062 |
showConfigBlock(m_tx_configs[i]); |
---|
2063 |
} |
---|
2064 |
for(unsigned int i=0; i<m_nb_rx; i++) { |
---|
2065 |
debugOutput(DEBUG_LEVEL_VERBOSE, "RX Config block %d\n", i); |
---|
2066 |
showConfigBlock(m_rx_configs[i]); |
---|
2067 |
} |
---|
2068 |
} |
---|
2069 |
|
---|
2070 |
} // namespace Dice |
---|
2071 |
|
---|
2072 |
|
---|
2073 |
|
---|