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

Revision 1725, 63.7 kB (checked in by arnonym, 11 years ago)

As far as I can say this function works. Don't display the warning. But I think the control-interface needs to be extended to allow to call save and restore from gui.

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