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

Revision 2095, 61.5 kB (checked in by adi, 11 years ago)

DICE-EAP Use vector of pair rather than map for router config

By Philippe Carriere:

router config (m_routes2) is the image of what is really written in the flash.
The meaning of the router and peak space flash content is entirely
manufacturer dependent.

Then even the ordering followed by the destinations may be of importance
so it must be a priori preserved.

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