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

Revision 2256, 66.7 kB (checked in by philippe, 10 years ago)

DICE EAP Attempt to avoid application space reading errors/warning. It seems there was some confusion between quadlet/byte quantities in application space size (m_app_size). Now, at least for Pro 40, reading of applications space stops normally without warning messages; hope it helps for reading application space for firestudio tube, for instance.

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