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

Revision 1713, 63.6 kB (checked in by arnonym, 13 years ago)

Print the hexdump of the quadlets to stderr.

Print the stuff from show() as normal messages, not as debug.
And print the first 512 bytes of the application space of the dice-chip. Trying to figure out which bits to set to control line/instrument and high/low switches.

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