root/trunk/libffado/src/dice/dice_eap.cpp

Revision 1776, 59.4 kB (checked in by arnonym, 11 years ago)

Reduce the LOC:

  • Use only strings as identifiers for the Dice::EAP::Router. Updating the router doesn't happen that often, using strings only is acceptable. And it eases handling so much.
  • Adapt the control interface.
  • Adapt the dbus interface.
  • Adapt the routers gui.
  • The peak-space is not yet working (I didn't actually test it), the peak-functions of EAP::Router return nothing.
  • And the test for the dice has to be adopted when the peaks are working again.

TODO:

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