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

Revision 1742, 63.5 kB (checked in by arnonym, 11 years ago)

Extend the interface of the MatrixMixer?:

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