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

Revision 1651, 62.8 kB (checked in by arnonym, 13 years ago)

Lets see if this works out: Work for ppalmers.

A new way to get the peakvalues. Getting each value individual is really cpu-heavy. Getting them all toghether should be better.

(My first real code commit to the internals:)

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