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

Revision 1653, 63.1 kB (checked in by arnonym, 12 years ago)

Implement getting a simple list of all current peaks.

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     m_peak.read();
1569     Control::CrossbarRouter::PeakValues values;
1570     for (unsigned int i=0; i<m_peak.getNbRoutes(); ++i) {
1571         Control::CrossbarRouter::PeakValue tmp;
1572         RouterConfig::Route route = m_peak.getRoute(i);
1573         tmp.destination = getDestinationIndex(route.dst, route.dstChannel);
1574         tmp.peakvalue = route.peak;
1575         values.push_back(tmp);
1576     }
1577     return values;
1578 }
1579
1580 void
1581 Device::EAP::Router::show()
1582 {
1583     // print the peak space as it also contains the routing configuration
1584     printMessage("Active router config:\n");
1585     m_peak.read();
1586     m_peak.show();
1587 }
1588
1589 // ----------- routing config -------------
1590 Device::EAP::RouterConfig::RouterConfig(EAP &p)
1591 : m_eap(p)
1592 , m_base(eRT_None), m_offset(0)
1593 , m_debugModule(p.m_debugModule)
1594 {}
1595
1596 Device::EAP::RouterConfig::RouterConfig(EAP &p, enum eRegBase b, unsigned int o)
1597 : m_eap(p)
1598 , m_base(b), m_offset(o)
1599 , m_debugModule(p.m_debugModule)
1600 {}
1601
1602 Device::EAP::RouterConfig::~RouterConfig()
1603 {}
1604
1605 bool
1606 Device::EAP::RouterConfig::read(enum eRegBase base, unsigned offset)
1607 {
1608     // first clear the current route vector
1609     m_routes.clear();
1610
1611     uint32_t nb_routes;
1612     if(!m_eap.readRegBlock(base, offset, &nb_routes, 4)) {
1613         debugError("Failed to read number of entries\n");
1614         return false;
1615     }
1616     if(nb_routes == 0) {
1617         debugWarning("No routes found\n");
1618     }
1619
1620     // read the route info
1621     uint32_t tmp_entries[nb_routes];
1622     if(!m_eap.readRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1623         debugError("Failed to read router config block information\n");
1624         return false;
1625     }
1626
1627     // decode into the routing vector
1628     for(unsigned int i=0; i < nb_routes; i++) {
1629         m_routes.push_back(decodeRoute(tmp_entries[i]));
1630     }
1631     return true;
1632 }
1633
1634 bool
1635 Device::EAP::RouterConfig::write(enum eRegBase base, unsigned offset)
1636 {
1637     uint32_t nb_routes = m_routes.size();
1638     if(nb_routes == 0) {
1639         debugWarning("Writing 0 routes?\n");
1640     }
1641     uint32_t tmp_entries[nb_routes];
1642
1643     // encode from the routing vector
1644     int i=0;
1645     for ( RouteVectorIterator it = m_routes.begin();
1646         it != m_routes.end();
1647         ++it )
1648     {
1649         tmp_entries[i] = encodeRoute( *it );
1650         i++;
1651     }
1652
1653     // write the result to the device
1654     if(!m_eap.writeRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1655         debugError("Failed to write router config block information\n");
1656         return false;
1657     }
1658     if(!m_eap.writeRegBlock(base, offset, &nb_routes, 4)) {
1659         debugError("Failed to write number of entries\n");
1660         return false;
1661     }
1662     return true;
1663 }
1664
1665 bool
1666 Device::EAP::RouterConfig::insertRoute(struct Route r, unsigned int index)
1667 {
1668     unsigned int nb_routes = getNbRoutes();
1669     if(index > nb_routes) {
1670         debugError("Index out of range\n");
1671         return false;
1672     }
1673     if (index == nb_routes) { // append
1674         m_routes.push_back(r);
1675         return true;
1676     }
1677     // insert
1678     RouteVectorIterator pos = m_routes.begin() + index;
1679     m_routes.insert(pos, r);
1680     return true;
1681 }
1682
1683 bool
1684 Device::EAP::RouterConfig::replaceRoute(unsigned int old_index, struct Route new_route)
1685 {
1686     if(old_index >= getNbRoutes()) {
1687         debugError("Index out of range\n");
1688         return false;
1689     }
1690     if(!removeRoute(old_index)) {
1691         debugError("Could not remove old route\n");
1692         return false;
1693     }
1694     return insertRoute(new_route, old_index);
1695 }
1696
1697 bool
1698 Device::EAP::RouterConfig::replaceRoute(struct Route old_route, struct Route new_route)
1699 {
1700     int idx = getRouteIndex(old_route);
1701     if(idx < 0) {
1702         debugWarning("Route not found\n");
1703         return false;
1704     }
1705     return replaceRoute((unsigned int)idx, new_route);
1706 }
1707
1708 bool
1709 Device::EAP::RouterConfig::removeRoute(struct Route r)
1710 {
1711     int idx = getRouteIndex(r);
1712     if(idx < 0) {
1713         debugWarning("Route not found\n");
1714         return false;
1715     }
1716     return removeRoute((unsigned int)idx);
1717 }
1718
1719 bool
1720 Device::EAP::RouterConfig::removeRoute(unsigned int index)
1721 {
1722     if(index >= getNbRoutes()) {
1723         debugError("Index out of range\n");
1724         return false;
1725     }
1726     RouteVectorIterator pos = m_routes.begin() + index;
1727     m_routes.erase(pos);
1728     return true;
1729 }
1730
1731 int
1732 Device::EAP::RouterConfig::getRouteIndex(struct Route r)
1733 {
1734     int i = 0;
1735     for ( RouteVectorIterator it = m_routes.begin();
1736         it != m_routes.end();
1737         ++it )
1738     {
1739         struct Route t = *it;
1740         if ((t.src == r.src) && (t.srcChannel == r.srcChannel) && (t.dst == r.dst) && (t.dstChannel == r.dstChannel)) return i;
1741         i++;
1742     }
1743     return -1;
1744 }
1745
1746 struct Device::EAP::RouterConfig::Route
1747 Device::EAP::RouterConfig::getRoute(unsigned int idx)
1748 {
1749     if( (idx < 0) || (idx >= m_routes.size()) ) {
1750         debugWarning("Route index out of range (%d)\n", idx);
1751         Route r = {eRS_Invalid, -1, eRD_Invalid, -1, 0};
1752         return r;
1753     }
1754     return m_routes.at(idx);
1755 }
1756
1757 #define CASE_INT_EQUAL_RETURN(_x) case (int)(_x): return _x;
1758 enum Device::EAP::eRouteDestination
1759 Device::EAP::RouterConfig::intToRouteDestination(int dst)
1760 {
1761     switch(dst) {
1762         CASE_INT_EQUAL_RETURN(eRD_AES);
1763         CASE_INT_EQUAL_RETURN(eRD_ADAT);
1764         CASE_INT_EQUAL_RETURN(eRD_Mixer0);
1765         CASE_INT_EQUAL_RETURN(eRD_Mixer1);
1766         CASE_INT_EQUAL_RETURN(eRD_InS0);
1767         CASE_INT_EQUAL_RETURN(eRD_InS1);
1768         CASE_INT_EQUAL_RETURN(eRD_ARM);
1769         CASE_INT_EQUAL_RETURN(eRD_ATX0);
1770         CASE_INT_EQUAL_RETURN(eRD_ATX1);
1771         CASE_INT_EQUAL_RETURN(eRD_Muted);
1772         default: return eRD_Invalid;
1773     }
1774 }
1775
1776 enum Device::EAP::eRouteSource
1777 Device::EAP::RouterConfig::intToRouteSource(int src)
1778 {
1779     switch(src) {
1780         CASE_INT_EQUAL_RETURN(eRS_AES);
1781         CASE_INT_EQUAL_RETURN(eRS_ADAT);
1782         CASE_INT_EQUAL_RETURN(eRS_Mixer);
1783         CASE_INT_EQUAL_RETURN(eRS_InS0);
1784         CASE_INT_EQUAL_RETURN(eRS_InS1);
1785         CASE_INT_EQUAL_RETURN(eRS_ARM);
1786         CASE_INT_EQUAL_RETURN(eRS_ARX0);
1787         CASE_INT_EQUAL_RETURN(eRS_ARX1);
1788         CASE_INT_EQUAL_RETURN(eRS_Muted);
1789         default: return eRS_Invalid;
1790     }
1791 }
1792
1793 struct Device::EAP::RouterConfig::Route
1794 Device::EAP::RouterConfig::decodeRoute(uint32_t val) {
1795     int routerval = val & 0xFFFF;
1796     int peak = (val >> 16) & 0x0FFF;
1797     int src_blk = (routerval >> 12) & 0xF;
1798     int src_ch = (routerval >> 8) & 0xF;
1799     int dst_blk = (routerval >> 4) & 0xF;
1800     int dst_ch = (routerval >> 0) & 0xF;
1801     struct Route r = {intToRouteSource(src_blk), src_ch, intToRouteDestination(dst_blk), dst_ch, peak};
1802     return r;
1803 }
1804
1805 uint32_t
1806 Device::EAP::RouterConfig::encodeRoute(struct Route r) {
1807     if(r.src == eRS_Invalid || r.dst == eRD_Invalid) {
1808         debugWarning("Encoding invalid source/dest (%d/%d)\n", r.src, r.dst);
1809 //         return 0xFFFFFFFF;
1810     }
1811     unsigned int src_blk = ((unsigned int)r.src) & 0xF;
1812     unsigned int src_ch = ((unsigned int)r.srcChannel) & 0xF;
1813     unsigned int dst_blk = ((unsigned int)r.dst) & 0xF;
1814     unsigned int dst_ch = ((unsigned int)r.dstChannel) & 0xF;
1815     uint32_t routerval = 0;
1816     routerval |= (src_blk << 12);
1817     routerval |= (src_ch << 8);
1818     routerval |= (dst_blk << 4);
1819     routerval |= (dst_ch << 0);
1820     return routerval;
1821 }
1822
1823 struct Device::EAP::RouterConfig::Route
1824 Device::EAP::RouterConfig::getRouteForDestination(enum eRouteDestination dst, int channel)
1825 {
1826     for ( RouteVectorIterator it = m_routes.begin();
1827         it != m_routes.end();
1828         ++it )
1829     {
1830         struct Route r = *it;
1831         if((r.dst == (int)dst) && (r.dstChannel == channel)) {
1832             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d comes from %s:%02d\n",
1833                                                   dstBlockToString(r.dst), r.dstChannel,
1834                                                   srcBlockToString(r.src), r.srcChannel);
1835             return r;
1836         }
1837     }
1838     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d source can't be found\n",
1839                                           dstBlockToString((int)dst), channel);
1840     struct Route r = {eRS_Invalid, -1, eRD_Invalid, 0, 0};
1841     return r;
1842 }
1843
1844 std::vector<struct Device::EAP::RouterConfig::Route>
1845 Device::EAP::RouterConfig::getRoutesForSource(enum eRouteSource src, int channel)
1846 {
1847     std::vector<struct Route>routes;
1848     for ( RouteVectorIterator it = m_routes.begin();
1849         it != m_routes.end();
1850         ++it )
1851     {
1852         struct Route r = *it;
1853         if((r.src == (int)src) && (r.srcChannel == channel)) {
1854             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d goes to %s:%02d\n",
1855                                                   srcBlockToString(r.src), r.srcChannel,
1856                                                   dstBlockToString(r.dst), r.dstChannel);
1857             routes.push_back(r);
1858         }
1859     }
1860     return routes;
1861 }
1862
1863 void
1864 Device::EAP::RouterConfig::show()
1865 {
1866     for ( RouteVectorIterator it = m_routes.begin();
1867         it != m_routes.end();
1868         ++it )
1869     {
1870         struct Route r = *it;
1871         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d\n",
1872                                               srcBlockToString(r.src), r.srcChannel,
1873                                               dstBlockToString(r.dst), r.dstChannel);
1874     }
1875 }
1876
1877
1878 // ----------- peak space -------------
1879
1880 bool
1881 Device::EAP::PeakSpace::read(enum eRegBase base, unsigned offset)
1882 {
1883     // first clear the current route vector
1884     m_routes.clear();
1885
1886     uint32_t nb_routes;
1887     // we have to figure out the number of entries through the currently
1888     // active router config
1889     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1890     if(rcfg == NULL) {
1891         debugError("Could not get active router config\n");
1892         return false;
1893     }
1894     nb_routes = rcfg->getNbRoutes();
1895
1896     // read the route info
1897     uint32_t tmp_entries[nb_routes];
1898     if(!m_eap.readRegBlock(base, offset, tmp_entries, nb_routes*4)) {
1899         debugError("Failed to read peak block information\n");
1900         return false;
1901     }
1902
1903     // decode into the routing vector
1904     for(unsigned int i=0; i < nb_routes; i++) {
1905         m_routes.push_back(decodeRoute(tmp_entries[i]));
1906     }
1907 //     show();
1908     return true;
1909 }
1910
1911 bool
1912 Device::EAP::PeakSpace::write(enum eRegBase base, unsigned offset)
1913 {
1914     debugError("Peak space is read-only\n");
1915     return true;
1916 }
1917
1918 void
1919 Device::EAP::PeakSpace::show()
1920 {
1921     for ( RouteVectorIterator it = m_routes.begin();
1922         it != m_routes.end();
1923         ++it )
1924     {
1925         struct Route r = *it;
1926         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d : %06d\n",
1927                                               srcBlockToString(r.src), r.srcChannel,
1928                                               dstBlockToString(r.dst), r.dstChannel,
1929                                               r.peak);
1930     }
1931 }
1932
1933 // ----------- stream config block -------------
1934 Device::EAP::StreamConfig::StreamConfig(EAP &p, enum eRegBase b, unsigned int o)
1935 : m_eap(p)
1936 , m_base(b), m_offset(o)
1937 , m_nb_tx(0), m_nb_rx(0)
1938 , m_tx_configs(NULL), m_rx_configs(NULL)
1939 , m_debugModule(p.m_debugModule)
1940 {
1941
1942 }
1943
1944 Device::EAP::StreamConfig::~StreamConfig()
1945 {
1946     if(m_tx_configs) delete[]m_tx_configs;
1947     if(m_rx_configs) delete[]m_rx_configs;
1948 }
1949
1950 bool
1951 Device::EAP::StreamConfig::read(enum eRegBase base, unsigned offset)
1952 {
1953     if(!m_eap.readRegBlock(base, offset, &m_nb_tx, 4)) {
1954         debugError("Failed to read number of tx entries\n");
1955         return false;
1956     }
1957     if(!m_eap.readRegBlock(base, offset+4, &m_nb_rx, 4)) {
1958         debugError("Failed to read number of rx entries\n");
1959         return false;
1960     }
1961     debugOutput(DEBUG_LEVEL_VERBOSE, " Entries: TX: %lu, RX: %lu\n", m_nb_tx, m_nb_rx);
1962
1963     if(m_tx_configs) {
1964         delete[]m_tx_configs;
1965         m_tx_configs = NULL;
1966     }
1967     if(m_rx_configs) {
1968         delete[]m_rx_configs;
1969         m_rx_configs = NULL;
1970     }
1971    
1972     offset += 8;
1973     if(m_nb_tx > 0) {
1974         m_tx_configs = new struct ConfigBlock[m_nb_tx];
1975         for(unsigned int i=0; i<m_nb_tx; i++) {
1976             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
1977             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
1978                 debugError("Failed to read tx entry %d\n", i);
1979                 return false;
1980             }
1981             offset += sizeof(struct ConfigBlock);
1982         }
1983     }
1984
1985     if(m_nb_rx > 0) {
1986         m_rx_configs = new struct ConfigBlock[m_nb_rx];
1987         for(unsigned int i=0; i<m_nb_rx; i++) {
1988             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
1989             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
1990                 debugError("Failed to read rx entry %d\n", i);
1991                 return false;
1992             }
1993             offset += sizeof(struct ConfigBlock);
1994         }
1995     }
1996     return true;
1997 }
1998
1999 bool
2000 Device::EAP::StreamConfig::write(enum eRegBase base, unsigned offset)
2001 {
2002     if(!m_eap.writeRegBlock(base, offset, &m_nb_tx, 4)) {
2003         debugError("Failed to write number of tx entries\n");
2004         return false;
2005     }
2006     if(!m_eap.writeRegBlock(base, offset+4, &m_nb_rx, 4)) {
2007         debugError("Failed to write number of rx entries\n");
2008         return false;
2009     }
2010
2011     offset += 8;
2012     for(unsigned int i=0; i<m_nb_tx; i++) {
2013         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2014         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2015             debugError("Failed to write tx entry %d\n", i);
2016             return false;
2017         }
2018         offset += sizeof(struct ConfigBlock);
2019     }
2020
2021     for(unsigned int i=0; i<m_nb_rx; i++) {
2022         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2023         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2024             debugError("Failed to write rx entry %d\n", i);
2025             return false;
2026         }
2027         offset += sizeof(struct ConfigBlock);
2028     }
2029     return true;
2030 }
2031
2032 Device::diceNameVector
2033 Device::EAP::StreamConfig::getNamesForBlock(struct ConfigBlock &b)
2034 {
2035     diceNameVector names;
2036     char namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES+1];
2037
2038     memcpy(namestring, b.names, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES);
2039
2040     // Strings from the device are always little-endian,
2041     // so byteswap for big-endian machines
2042     #if __BYTE_ORDER == __BIG_ENDIAN
2043     byteSwapBlock((quadlet_t *)namestring, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS);
2044     #endif
2045
2046     namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES]='\0';
2047     return m_eap.m_device.splitNameString(std::string(namestring));
2048 }
2049
2050 void
2051 Device::EAP::StreamConfig::showConfigBlock(struct ConfigBlock &b)
2052 {
2053     debugOutput(DEBUG_LEVEL_VERBOSE, " Channel count : %lu audio, %lu midi\n", b.nb_audio, b.nb_midi);
2054     debugOutput(DEBUG_LEVEL_VERBOSE, " AC3 Map       : 0x%08X\n", b.ac3_map);
2055     diceNameVector channel_names  = getNamesForBlock(b);
2056     debugOutput(DEBUG_LEVEL_VERBOSE,"  Channel names :\n");
2057     for ( diceNameVectorIterator it = channel_names.begin();
2058         it != channel_names.end();
2059         ++it )
2060     {
2061         debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
2062     }
2063 }
2064
2065 void
2066 Device::EAP::StreamConfig::show()
2067 {
2068     for(unsigned int i=0; i<m_nb_tx; i++) {
2069         debugOutput(DEBUG_LEVEL_VERBOSE, "TX Config block %d\n", i);
2070         showConfigBlock(m_tx_configs[i]);
2071     }
2072     for(unsigned int i=0; i<m_nb_rx; i++) {
2073         debugOutput(DEBUG_LEVEL_VERBOSE, "RX Config block %d\n", i);
2074         showConfigBlock(m_rx_configs[i]);
2075     }
2076 }
2077
2078 } // namespace Dice
2079
2080
2081
Note: See TracBrowser for help on using the browser.