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

Revision 1766, 63.1 kB (checked in by arnonym, 13 years ago)

Start some cleanup in the dice-code.

No need for the EAP to be defined inside Dice::Device.

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