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

Revision 1655, 63.5 kB (checked in by arnonym, 12 years ago)

Thinking about getting structured info about the router-channels.

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::Groups
1232 Device::EAP::Router::getSources()
1233 {
1234     debugError("Device::EAP::Router::getSources() is not yet implemented!");
1235     return Control::CrossbarRouter::Groups();
1236 }
1237
1238 Control::CrossbarRouter::Groups
1239 Device::EAP::Router::getDestinations()
1240 {
1241     debugError("Device::EAP::Router::getDestinations() is not yet implemented!");
1242     return Control::CrossbarRouter::Groups();
1243 }
1244
1245 Control::CrossbarRouter::IntVector
1246 Device::EAP::Router::getDestinationsForSource(const int srcid)
1247 {
1248     IntVector retval;
1249     if((unsigned)srcid < m_sources.size()) {
1250         Source s = m_sources.at(srcid);
1251
1252         // get the routing configuration
1253         RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1254         if(rcfg == NULL) {
1255             debugError("Could not request active router configuration\n");
1256             return retval;
1257         }
1258         // get the source routes
1259         RouterConfig::RouteVector v = rcfg->getRoutesForSource(s.src, s.srcChannel);
1260
1261         for ( RouterConfig::RouteVectorIterator it = v.begin();
1262             it != v.end();
1263             ++it )
1264         {
1265             // FIXME: some more efficient datastructure might be good to
1266             // avoid this loop
1267             RouterConfig::Route &r = *it;
1268             int i = 0;
1269             for ( DestinationVectorIterator it = m_destinations.begin();
1270                 it != m_destinations.end();
1271                 ++it )
1272             {
1273                 if((it->dst == r.dst) && (it->dstChannel == r.dstChannel)) {
1274                     retval.push_back(i);
1275                     break; // can only match once
1276                 }
1277                 i++;
1278             }
1279         }
1280         return retval;
1281     } else {
1282         debugWarning("source id out of range (%d)\n", srcid);
1283         return retval;
1284     }
1285 }
1286
1287 int
1288 Device::EAP::Router::getSourceForDestination(const int dstid)
1289 {
1290     if((unsigned)dstid < m_destinations.size()) {
1291         Destination d = m_destinations.at(dstid);
1292
1293         // get the routing configuration
1294         RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1295         if(rcfg == NULL) {
1296             debugError("Could not request active router configuration\n");
1297             return false;
1298         }
1299
1300         RouterConfig::Route r = rcfg->getRouteForDestination(d.dst, d.dstChannel);
1301         if(r.src == eRS_Invalid) {
1302             return -1;
1303         } else {
1304             // FIXME: some more efficient datastructure might be good to
1305             // avoid this loop
1306             int i = 0;
1307             for ( SourceVectorIterator it = m_sources.begin();
1308                 it != m_sources.end();
1309                 ++it )
1310             {
1311                 if((it->src == r.src) && (it->srcChannel == r.srcChannel)) return i;
1312                 i++;
1313             }
1314             return -1;
1315         }
1316     } else {
1317         debugWarning("destination id out of range (%d)\n", dstid);
1318         return -1;
1319     }
1320 }
1321
1322 int
1323 Device::EAP::Router::getNbSources()
1324 {
1325     return m_sources.size();
1326 }
1327
1328 int
1329 Device::EAP::Router::getNbDestinations()
1330 {
1331     return m_destinations.size();
1332 }
1333
1334 bool
1335 Device::EAP::Router::canConnect(const int source, const int dest)
1336 {
1337     if((unsigned)source >= m_sources.size()) {
1338         debugWarning("source id out of range (%d)\n", source);
1339         return false;
1340     }
1341     Source s = m_sources.at(source);
1342
1343     if((unsigned)dest >= m_destinations.size()) {
1344         debugWarning("destination id out of range (%d)\n", dest);
1345         return false;
1346     }
1347     Destination d = m_destinations.at(dest);
1348
1349     // we can connect anything
1350     // FIXME: can we?
1351     return true;
1352 }
1353
1354 bool
1355 Device::EAP::Router::setConnectionState(const int source, const int dest, const bool enable)
1356 {
1357     if((unsigned)source >= m_sources.size()) {
1358         debugWarning("source id out of range (%d)\n", source);
1359         return false;
1360     }
1361     Source s = m_sources.at(source);
1362
1363     if((unsigned)dest >= m_destinations.size()) {
1364         debugWarning("destination id out of range (%d)\n", dest);
1365         return false;
1366     }
1367     Destination d = m_destinations.at(dest);
1368
1369     // get the routing configuration
1370     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1371     if(rcfg == NULL) {
1372         debugError("Could not request active router configuration\n");
1373         return false;
1374     }
1375
1376     // build a new routing configuration
1377     RouterConfig newcfg = Device::EAP::RouterConfig(*rcfg);
1378
1379     // construct the routing entry to find
1380     RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel};
1381
1382     // find the appropriate entry
1383     int idx = newcfg.getRouteIndex(r);
1384
1385     if (idx < 0) {
1386         // we have to add the route
1387         newcfg.insertRoute(r);
1388     } else {
1389         // the route is already present, so we can replace it
1390         if(enable) {
1391             debugOutput(DEBUG_LEVEL_VERBOSE, "connection %d => %d already present\n", source, dest);
1392             return true;
1393         } else {
1394             // remove the route
1395             newcfg.removeRoute(idx);
1396         }
1397     }
1398
1399     // if we get here it means we have to upload a new router config
1400     if(!m_eap.updateCurrentRouterConfig(newcfg)) {
1401         debugError("Could not update router config\n");
1402         return false;
1403     }
1404
1405     return true;
1406 }
1407
1408 bool
1409 Device::EAP::Router::getConnectionState(const int source, const int dest)
1410 {
1411     if((unsigned)source >= m_sources.size()) {
1412         debugWarning("source id out of range (%d)\n", source);
1413         return false;
1414     }
1415     Source s = m_sources.at(source);
1416
1417     if((unsigned)dest >= m_destinations.size()) {
1418         debugWarning("destination id out of range (%d)\n", dest);
1419         return false;
1420     }
1421     Destination d = m_destinations.at(dest);
1422
1423     // get the routing configuration
1424     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1425     if(rcfg == NULL) {
1426         debugError("Could not request active router configuration\n");
1427         return false;
1428     }
1429
1430     // build a new routing configuration
1431     RouterConfig newcfg = Device::EAP::RouterConfig(*rcfg);
1432
1433     // construct the routing entry to find
1434     RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel};
1435
1436     // find the appropriate entry
1437     int idx = newcfg.getRouteIndex(r);
1438
1439     if (idx < 0) {
1440         // the route is not present
1441         return false;
1442     } else {
1443         // the route is already present
1444         return true;
1445     }
1446 }
1447
1448 bool
1449 Device::EAP::Router::canConnect(std::string src, std::string dst)
1450 {
1451     int srcidx = getSourceIndex(src);
1452     int dstidx = getDestinationIndex(dst);
1453     return canConnect(srcidx, dstidx);
1454 }
1455
1456 bool
1457 Device::EAP::Router::setConnectionState(std::string src, std::string dst, const bool enable)
1458 {
1459     int srcidx = getSourceIndex(src);
1460     int dstidx = getDestinationIndex(dst);
1461     return setConnectionState(srcidx, dstidx, enable);
1462 }
1463
1464 bool
1465 Device::EAP::Router::getConnectionState(std::string src, std::string dst)
1466 {
1467     int srcidx = getSourceIndex(src);
1468     int dstidx = getDestinationIndex(dst);
1469     return getConnectionState(srcidx, dstidx);
1470 }
1471
1472 // the map is organized as a matrix where the
1473 // rows are the destinations and the columns are
1474 // the sources
1475
1476 // note that map as assumed to be big enough and
1477 // allocated by the user
1478 bool
1479 Device::EAP::Router::getConnectionMap(int *map)
1480 {
1481     unsigned int nb_sources = getNbSources();
1482     unsigned int nb_destinations = getNbDestinations();
1483
1484     // clear the map
1485     memset(map, 0, nb_sources * nb_destinations * sizeof(int));
1486
1487     // get the routing configuration
1488     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1489     if(rcfg == NULL) {
1490         debugError("Could not request active router configuration\n");
1491         return false;
1492     }
1493
1494     unsigned int nb_routes = rcfg->getNbRoutes();
1495
1496     for(unsigned int i=0; i<nb_routes; i++) {
1497         struct RouterConfig::Route r = rcfg->getRoute(i);
1498         int srcidx = getSourceIndex(r.src, r.srcChannel);
1499         int dstidx = getDestinationIndex(r.dst, r.dstChannel);
1500         if(srcidx < 0) {
1501             debugWarning("bogus source (%d, %d) in route table\n", r.src, r.srcChannel);
1502         } else if(dstidx < 0) {
1503             debugWarning("bogus destination (%d, %d) in route table\n", r.dst, r.dstChannel);
1504         } else {
1505             int *ptr = map;
1506             ptr += dstidx * nb_sources;
1507             ptr += srcidx;
1508             *ptr = 1; // route present
1509         }
1510     }
1511     return true;
1512 }
1513
1514 bool
1515 Device::EAP::Router::setConnectionMap(int *map)
1516 {
1517     return false;
1518 }
1519
1520 bool
1521 Device::EAP::Router::clearAllConnections()
1522 {
1523     // build a new empty routing configuration
1524     RouterConfig newcfg = Device::EAP::RouterConfig(m_eap);
1525
1526     // upload the new router config
1527     if(!m_eap.updateCurrentRouterConfig(newcfg)) {
1528         debugError("Could not update router config\n");
1529         return false;
1530     }
1531     return true;
1532 }
1533
1534 bool
1535 Device::EAP::Router::hasPeakMetering()
1536 {
1537     return m_eap.m_router_exposed;
1538 }
1539
1540 double
1541 Device::EAP::Router::getPeakValue(const int source, const int dest)
1542 {
1543     if((unsigned)source >= m_sources.size()) {
1544         debugWarning("source id out of range (%d)\n", source);
1545         return false;
1546     }
1547     Source s = m_sources.at(source);
1548
1549     if((unsigned)dest >= m_destinations.size()) {
1550         debugWarning("destination id out of range (%d)\n", dest);
1551         return false;
1552     }
1553     Destination d = m_destinations.at(dest);
1554
1555     debugOutput(DEBUG_LEVEL_VERBOSE, "getting peak info for [%d] %s => [%d] %s\n",
1556                                      source, s.name.c_str(),
1557                                      dest, d.name.c_str());
1558
1559     // update the peak information
1560     m_peak.read();
1561
1562     // construct the routing entry to find
1563     RouterConfig::Route r = {s.src, s.srcChannel, d.dst, d.dstChannel, 0};
1564
1565     // find the appropriate entry
1566     int idx = m_peak.getRouteIndex(r);
1567
1568     if (idx < 0) {
1569         // the route is not present
1570         return -1;
1571     } else {
1572         // the route is present
1573         r = m_peak.getRoute(idx);
1574         return r.peak;
1575     }
1576
1577 }
1578
1579 Control::CrossbarRouter::PeakValues
1580 Device::EAP::Router::getPeakValues()
1581 {
1582     m_peak.read();
1583     Control::CrossbarRouter::PeakValues values;
1584     for (unsigned int i=0; i<m_peak.getNbRoutes(); ++i) {
1585         Control::CrossbarRouter::PeakValue tmp;
1586         RouterConfig::Route route = m_peak.getRoute(i);
1587         tmp.destination = getDestinationIndex(route.dst, route.dstChannel);
1588         tmp.peakvalue = route.peak;
1589         values.push_back(tmp);
1590     }
1591     return values;
1592 }
1593
1594 void
1595 Device::EAP::Router::show()
1596 {
1597     // print the peak space as it also contains the routing configuration
1598     printMessage("Active router config:\n");
1599     m_peak.read();
1600     m_peak.show();
1601 }
1602
1603 // ----------- routing config -------------
1604 Device::EAP::RouterConfig::RouterConfig(EAP &p)
1605 : m_eap(p)
1606 , m_base(eRT_None), m_offset(0)
1607 , m_debugModule(p.m_debugModule)
1608 {}
1609
1610 Device::EAP::RouterConfig::RouterConfig(EAP &p, enum eRegBase b, unsigned int o)
1611 : m_eap(p)
1612 , m_base(b), m_offset(o)
1613 , m_debugModule(p.m_debugModule)
1614 {}
1615
1616 Device::EAP::RouterConfig::~RouterConfig()
1617 {}
1618
1619 bool
1620 Device::EAP::RouterConfig::read(enum eRegBase base, unsigned offset)
1621 {
1622     // first clear the current route vector
1623     m_routes.clear();
1624
1625     uint32_t nb_routes;
1626     if(!m_eap.readRegBlock(base, offset, &nb_routes, 4)) {
1627         debugError("Failed to read number of entries\n");
1628         return false;
1629     }
1630     if(nb_routes == 0) {
1631         debugWarning("No routes found\n");
1632     }
1633
1634     // read the route info
1635     uint32_t tmp_entries[nb_routes];
1636     if(!m_eap.readRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1637         debugError("Failed to read router config block information\n");
1638         return false;
1639     }
1640
1641     // decode into the routing vector
1642     for(unsigned int i=0; i < nb_routes; i++) {
1643         m_routes.push_back(decodeRoute(tmp_entries[i]));
1644     }
1645     return true;
1646 }
1647
1648 bool
1649 Device::EAP::RouterConfig::write(enum eRegBase base, unsigned offset)
1650 {
1651     uint32_t nb_routes = m_routes.size();
1652     if(nb_routes == 0) {
1653         debugWarning("Writing 0 routes?\n");
1654     }
1655     uint32_t tmp_entries[nb_routes];
1656
1657     // encode from the routing vector
1658     int i=0;
1659     for ( RouteVectorIterator it = m_routes.begin();
1660         it != m_routes.end();
1661         ++it )
1662     {
1663         tmp_entries[i] = encodeRoute( *it );
1664         i++;
1665     }
1666
1667     // write the result to the device
1668     if(!m_eap.writeRegBlock(base, offset+4, tmp_entries, nb_routes*4)) {
1669         debugError("Failed to write router config block information\n");
1670         return false;
1671     }
1672     if(!m_eap.writeRegBlock(base, offset, &nb_routes, 4)) {
1673         debugError("Failed to write number of entries\n");
1674         return false;
1675     }
1676     return true;
1677 }
1678
1679 bool
1680 Device::EAP::RouterConfig::insertRoute(struct Route r, unsigned int index)
1681 {
1682     unsigned int nb_routes = getNbRoutes();
1683     if(index > nb_routes) {
1684         debugError("Index out of range\n");
1685         return false;
1686     }
1687     if (index == nb_routes) { // append
1688         m_routes.push_back(r);
1689         return true;
1690     }
1691     // insert
1692     RouteVectorIterator pos = m_routes.begin() + index;
1693     m_routes.insert(pos, r);
1694     return true;
1695 }
1696
1697 bool
1698 Device::EAP::RouterConfig::replaceRoute(unsigned int old_index, struct Route new_route)
1699 {
1700     if(old_index >= getNbRoutes()) {
1701         debugError("Index out of range\n");
1702         return false;
1703     }
1704     if(!removeRoute(old_index)) {
1705         debugError("Could not remove old route\n");
1706         return false;
1707     }
1708     return insertRoute(new_route, old_index);
1709 }
1710
1711 bool
1712 Device::EAP::RouterConfig::replaceRoute(struct Route old_route, struct Route new_route)
1713 {
1714     int idx = getRouteIndex(old_route);
1715     if(idx < 0) {
1716         debugWarning("Route not found\n");
1717         return false;
1718     }
1719     return replaceRoute((unsigned int)idx, new_route);
1720 }
1721
1722 bool
1723 Device::EAP::RouterConfig::removeRoute(struct Route r)
1724 {
1725     int idx = getRouteIndex(r);
1726     if(idx < 0) {
1727         debugWarning("Route not found\n");
1728         return false;
1729     }
1730     return removeRoute((unsigned int)idx);
1731 }
1732
1733 bool
1734 Device::EAP::RouterConfig::removeRoute(unsigned int index)
1735 {
1736     if(index >= getNbRoutes()) {
1737         debugError("Index out of range\n");
1738         return false;
1739     }
1740     RouteVectorIterator pos = m_routes.begin() + index;
1741     m_routes.erase(pos);
1742     return true;
1743 }
1744
1745 int
1746 Device::EAP::RouterConfig::getRouteIndex(struct Route r)
1747 {
1748     int i = 0;
1749     for ( RouteVectorIterator it = m_routes.begin();
1750         it != m_routes.end();
1751         ++it )
1752     {
1753         struct Route t = *it;
1754         if ((t.src == r.src) && (t.srcChannel == r.srcChannel) && (t.dst == r.dst) && (t.dstChannel == r.dstChannel)) return i;
1755         i++;
1756     }
1757     return -1;
1758 }
1759
1760 struct Device::EAP::RouterConfig::Route
1761 Device::EAP::RouterConfig::getRoute(unsigned int idx)
1762 {
1763     if( (idx < 0) || (idx >= m_routes.size()) ) {
1764         debugWarning("Route index out of range (%d)\n", idx);
1765         Route r = {eRS_Invalid, -1, eRD_Invalid, -1, 0};
1766         return r;
1767     }
1768     return m_routes.at(idx);
1769 }
1770
1771 #define CASE_INT_EQUAL_RETURN(_x) case (int)(_x): return _x;
1772 enum Device::EAP::eRouteDestination
1773 Device::EAP::RouterConfig::intToRouteDestination(int dst)
1774 {
1775     switch(dst) {
1776         CASE_INT_EQUAL_RETURN(eRD_AES);
1777         CASE_INT_EQUAL_RETURN(eRD_ADAT);
1778         CASE_INT_EQUAL_RETURN(eRD_Mixer0);
1779         CASE_INT_EQUAL_RETURN(eRD_Mixer1);
1780         CASE_INT_EQUAL_RETURN(eRD_InS0);
1781         CASE_INT_EQUAL_RETURN(eRD_InS1);
1782         CASE_INT_EQUAL_RETURN(eRD_ARM);
1783         CASE_INT_EQUAL_RETURN(eRD_ATX0);
1784         CASE_INT_EQUAL_RETURN(eRD_ATX1);
1785         CASE_INT_EQUAL_RETURN(eRD_Muted);
1786         default: return eRD_Invalid;
1787     }
1788 }
1789
1790 enum Device::EAP::eRouteSource
1791 Device::EAP::RouterConfig::intToRouteSource(int src)
1792 {
1793     switch(src) {
1794         CASE_INT_EQUAL_RETURN(eRS_AES);
1795         CASE_INT_EQUAL_RETURN(eRS_ADAT);
1796         CASE_INT_EQUAL_RETURN(eRS_Mixer);
1797         CASE_INT_EQUAL_RETURN(eRS_InS0);
1798         CASE_INT_EQUAL_RETURN(eRS_InS1);
1799         CASE_INT_EQUAL_RETURN(eRS_ARM);
1800         CASE_INT_EQUAL_RETURN(eRS_ARX0);
1801         CASE_INT_EQUAL_RETURN(eRS_ARX1);
1802         CASE_INT_EQUAL_RETURN(eRS_Muted);
1803         default: return eRS_Invalid;
1804     }
1805 }
1806
1807 struct Device::EAP::RouterConfig::Route
1808 Device::EAP::RouterConfig::decodeRoute(uint32_t val) {
1809     int routerval = val & 0xFFFF;
1810     int peak = (val >> 16) & 0x0FFF;
1811     int src_blk = (routerval >> 12) & 0xF;
1812     int src_ch = (routerval >> 8) & 0xF;
1813     int dst_blk = (routerval >> 4) & 0xF;
1814     int dst_ch = (routerval >> 0) & 0xF;
1815     struct Route r = {intToRouteSource(src_blk), src_ch, intToRouteDestination(dst_blk), dst_ch, peak};
1816     return r;
1817 }
1818
1819 uint32_t
1820 Device::EAP::RouterConfig::encodeRoute(struct Route r) {
1821     if(r.src == eRS_Invalid || r.dst == eRD_Invalid) {
1822         debugWarning("Encoding invalid source/dest (%d/%d)\n", r.src, r.dst);
1823 //         return 0xFFFFFFFF;
1824     }
1825     unsigned int src_blk = ((unsigned int)r.src) & 0xF;
1826     unsigned int src_ch = ((unsigned int)r.srcChannel) & 0xF;
1827     unsigned int dst_blk = ((unsigned int)r.dst) & 0xF;
1828     unsigned int dst_ch = ((unsigned int)r.dstChannel) & 0xF;
1829     uint32_t routerval = 0;
1830     routerval |= (src_blk << 12);
1831     routerval |= (src_ch << 8);
1832     routerval |= (dst_blk << 4);
1833     routerval |= (dst_ch << 0);
1834     return routerval;
1835 }
1836
1837 struct Device::EAP::RouterConfig::Route
1838 Device::EAP::RouterConfig::getRouteForDestination(enum eRouteDestination dst, int channel)
1839 {
1840     for ( RouteVectorIterator it = m_routes.begin();
1841         it != m_routes.end();
1842         ++it )
1843     {
1844         struct Route r = *it;
1845         if((r.dst == (int)dst) && (r.dstChannel == channel)) {
1846             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d comes from %s:%02d\n",
1847                                                   dstBlockToString(r.dst), r.dstChannel,
1848                                                   srcBlockToString(r.src), r.srcChannel);
1849             return r;
1850         }
1851     }
1852     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d source can't be found\n",
1853                                           dstBlockToString((int)dst), channel);
1854     struct Route r = {eRS_Invalid, -1, eRD_Invalid, 0, 0};
1855     return r;
1856 }
1857
1858 std::vector<struct Device::EAP::RouterConfig::Route>
1859 Device::EAP::RouterConfig::getRoutesForSource(enum eRouteSource src, int channel)
1860 {
1861     std::vector<struct Route>routes;
1862     for ( RouteVectorIterator it = m_routes.begin();
1863         it != m_routes.end();
1864         ++it )
1865     {
1866         struct Route r = *it;
1867         if((r.src == (int)src) && (r.srcChannel == channel)) {
1868             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d goes to %s:%02d\n",
1869                                                   srcBlockToString(r.src), r.srcChannel,
1870                                                   dstBlockToString(r.dst), r.dstChannel);
1871             routes.push_back(r);
1872         }
1873     }
1874     return routes;
1875 }
1876
1877 void
1878 Device::EAP::RouterConfig::show()
1879 {
1880     for ( RouteVectorIterator it = m_routes.begin();
1881         it != m_routes.end();
1882         ++it )
1883     {
1884         struct Route r = *it;
1885         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d\n",
1886                                               srcBlockToString(r.src), r.srcChannel,
1887                                               dstBlockToString(r.dst), r.dstChannel);
1888     }
1889 }
1890
1891
1892 // ----------- peak space -------------
1893
1894 bool
1895 Device::EAP::PeakSpace::read(enum eRegBase base, unsigned offset)
1896 {
1897     // first clear the current route vector
1898     m_routes.clear();
1899
1900     uint32_t nb_routes;
1901     // we have to figure out the number of entries through the currently
1902     // active router config
1903     RouterConfig *rcfg = m_eap.getActiveRouterConfig();
1904     if(rcfg == NULL) {
1905         debugError("Could not get active router config\n");
1906         return false;
1907     }
1908     nb_routes = rcfg->getNbRoutes();
1909
1910     // read the route info
1911     uint32_t tmp_entries[nb_routes];
1912     if(!m_eap.readRegBlock(base, offset, tmp_entries, nb_routes*4)) {
1913         debugError("Failed to read peak block information\n");
1914         return false;
1915     }
1916
1917     // decode into the routing vector
1918     for(unsigned int i=0; i < nb_routes; i++) {
1919         m_routes.push_back(decodeRoute(tmp_entries[i]));
1920     }
1921 //     show();
1922     return true;
1923 }
1924
1925 bool
1926 Device::EAP::PeakSpace::write(enum eRegBase base, unsigned offset)
1927 {
1928     debugError("Peak space is read-only\n");
1929     return true;
1930 }
1931
1932 void
1933 Device::EAP::PeakSpace::show()
1934 {
1935     for ( RouteVectorIterator it = m_routes.begin();
1936         it != m_routes.end();
1937         ++it )
1938     {
1939         struct Route r = *it;
1940         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "%s:%02d => %s:%02d : %06d\n",
1941                                               srcBlockToString(r.src), r.srcChannel,
1942                                               dstBlockToString(r.dst), r.dstChannel,
1943                                               r.peak);
1944     }
1945 }
1946
1947 // ----------- stream config block -------------
1948 Device::EAP::StreamConfig::StreamConfig(EAP &p, enum eRegBase b, unsigned int o)
1949 : m_eap(p)
1950 , m_base(b), m_offset(o)
1951 , m_nb_tx(0), m_nb_rx(0)
1952 , m_tx_configs(NULL), m_rx_configs(NULL)
1953 , m_debugModule(p.m_debugModule)
1954 {
1955
1956 }
1957
1958 Device::EAP::StreamConfig::~StreamConfig()
1959 {
1960     if(m_tx_configs) delete[]m_tx_configs;
1961     if(m_rx_configs) delete[]m_rx_configs;
1962 }
1963
1964 bool
1965 Device::EAP::StreamConfig::read(enum eRegBase base, unsigned offset)
1966 {
1967     if(!m_eap.readRegBlock(base, offset, &m_nb_tx, 4)) {
1968         debugError("Failed to read number of tx entries\n");
1969         return false;
1970     }
1971     if(!m_eap.readRegBlock(base, offset+4, &m_nb_rx, 4)) {
1972         debugError("Failed to read number of rx entries\n");
1973         return false;
1974     }
1975     debugOutput(DEBUG_LEVEL_VERBOSE, " Entries: TX: %lu, RX: %lu\n", m_nb_tx, m_nb_rx);
1976
1977     if(m_tx_configs) {
1978         delete[]m_tx_configs;
1979         m_tx_configs = NULL;
1980     }
1981     if(m_rx_configs) {
1982         delete[]m_rx_configs;
1983         m_rx_configs = NULL;
1984     }
1985    
1986     offset += 8;
1987     if(m_nb_tx > 0) {
1988         m_tx_configs = new struct ConfigBlock[m_nb_tx];
1989         for(unsigned int i=0; i<m_nb_tx; i++) {
1990             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
1991             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
1992                 debugError("Failed to read tx entry %d\n", i);
1993                 return false;
1994             }
1995             offset += sizeof(struct ConfigBlock);
1996         }
1997     }
1998
1999     if(m_nb_rx > 0) {
2000         m_rx_configs = new struct ConfigBlock[m_nb_rx];
2001         for(unsigned int i=0; i<m_nb_rx; i++) {
2002             fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2003             if(!m_eap.readRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2004                 debugError("Failed to read rx entry %d\n", i);
2005                 return false;
2006             }
2007             offset += sizeof(struct ConfigBlock);
2008         }
2009     }
2010     return true;
2011 }
2012
2013 bool
2014 Device::EAP::StreamConfig::write(enum eRegBase base, unsigned offset)
2015 {
2016     if(!m_eap.writeRegBlock(base, offset, &m_nb_tx, 4)) {
2017         debugError("Failed to write number of tx entries\n");
2018         return false;
2019     }
2020     if(!m_eap.writeRegBlock(base, offset+4, &m_nb_rx, 4)) {
2021         debugError("Failed to write number of rx entries\n");
2022         return false;
2023     }
2024
2025     offset += 8;
2026     for(unsigned int i=0; i<m_nb_tx; i++) {
2027         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_tx_configs[i]));
2028         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2029             debugError("Failed to write tx entry %d\n", i);
2030             return false;
2031         }
2032         offset += sizeof(struct ConfigBlock);
2033     }
2034
2035     for(unsigned int i=0; i<m_nb_rx; i++) {
2036         fb_quadlet_t *ptr = reinterpret_cast<fb_quadlet_t *>(&(m_rx_configs[i]));
2037         if(!m_eap.writeRegBlock(base, offset, ptr, sizeof(struct ConfigBlock))) {
2038             debugError("Failed to write rx entry %d\n", i);
2039             return false;
2040         }
2041         offset += sizeof(struct ConfigBlock);
2042     }
2043     return true;
2044 }
2045
2046 Device::diceNameVector
2047 Device::EAP::StreamConfig::getNamesForBlock(struct ConfigBlock &b)
2048 {
2049     diceNameVector names;
2050     char namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES+1];
2051
2052     memcpy(namestring, b.names, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES);
2053
2054     // Strings from the device are always little-endian,
2055     // so byteswap for big-endian machines
2056     #if __BYTE_ORDER == __BIG_ENDIAN
2057     byteSwapBlock((quadlet_t *)namestring, DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_QUADS);
2058     #endif
2059
2060     namestring[DICE_EAP_CHANNEL_CONFIG_NAMESTR_LEN_BYTES]='\0';
2061     return m_eap.m_device.splitNameString(std::string(namestring));
2062 }
2063
2064 void
2065 Device::EAP::StreamConfig::showConfigBlock(struct ConfigBlock &b)
2066 {
2067     debugOutput(DEBUG_LEVEL_VERBOSE, " Channel count : %lu audio, %lu midi\n", b.nb_audio, b.nb_midi);
2068     debugOutput(DEBUG_LEVEL_VERBOSE, " AC3 Map       : 0x%08X\n", b.ac3_map);
2069     diceNameVector channel_names  = getNamesForBlock(b);
2070     debugOutput(DEBUG_LEVEL_VERBOSE,"  Channel names :\n");
2071     for ( diceNameVectorIterator it = channel_names.begin();
2072         it != channel_names.end();
2073         ++it )
2074     {
2075         debugOutput(DEBUG_LEVEL_VERBOSE,"     %s\n", (*it).c_str());
2076     }
2077 }
2078
2079 void
2080 Device::EAP::StreamConfig::show()
2081 {
2082     for(unsigned int i=0; i<m_nb_tx; i++) {
2083         debugOutput(DEBUG_LEVEL_VERBOSE, "TX Config block %d\n", i);
2084         showConfigBlock(m_tx_configs[i]);
2085     }
2086     for(unsigned int i=0; i<m_nb_rx; i++) {
2087         debugOutput(DEBUG_LEVEL_VERBOSE, "RX Config block %d\n", i);
2088         showConfigBlock(m_rx_configs[i]);
2089     }
2090 }
2091
2092 } // namespace Dice
2093
2094
2095
Note: See TracBrowser for help on using the browser.