root/trunk/libffado/src/motu/motu_avdevice.cpp

Revision 742, 36.1 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  * Copyright (C) 2005-2007 by Jonathan Woithe
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "motu/motu_avdevice.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "libavc/avc_definitions.h"
31
32 #include "debugmodule/debugmodule.h"
33
34 #include "libstreaming/motu/MotuReceiveStreamProcessor.h"
35 #include "libstreaming/motu/MotuTransmitStreamProcessor.h"
36 #include "libstreaming/motu/MotuPort.h"
37
38 #include "libutil/DelayLockedLoop.h"
39
40 #include <string>
41 #include <stdint.h>
42 #include <assert.h>
43 #include <netinet/in.h>
44 #include <iostream>
45 #include <sstream>
46
47 #include <libraw1394/csr.h>
48
49 namespace Motu {
50
51 // to define the supported devices
52 static VendorModelEntry supportedDeviceList[] =
53 {
54 //  {vendor_id, model_id, unit_version, unit_specifier_id, model, vendor_name,model_name}
55     {FW_VENDORID_MOTU, 0, 0x00000003, 0x000001f2, MOTUFW_MODEL_828mkII, "MOTU", "828MkII"},
56     {FW_VENDORID_MOTU, 0, 0x00000009, 0x000001f2, MOTUFW_MODEL_TRAVELER, "MOTU", "Traveler"},
57     {FW_VENDORID_MOTU, 0, 0x0000000d, 0x000001f2, MOTUFW_MODEL_ULTRALITE, "MOTU", "UltraLite"},
58     {FW_VENDORID_MOTU, 0, 0x0000000f, 0x000001f2, MOTUFW_MODEL_8PRE, "MOTU", "8pre"},
59 };
60
61 // Ports declarations
62 const PortEntry Ports_828MKII[] =
63 {
64     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
65     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
66     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
67     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
68     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
69     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
70     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
71     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
72     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
73     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
74     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
75     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
76     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
77     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
78     {"Mic1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
79     {"Mic2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
80     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 46},
81     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 49},
82     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 52},
83     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 55},
84     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 58},
85     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 61},
86     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 63},
87     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 66},
88     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 69},
89     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 72},
90 };
91
92 const PortEntry Ports_TRAVELER[] =
93 {
94     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
95     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
96     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
97     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
98     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
99     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
100     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
101     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
102     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
103     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
104     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
105     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
106     {"AES/EBU1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 40},
107     {"AES/EBU2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 43},
108     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_OFF|MOTUFW_PA_OPTICAL_ADAT, 46},
109     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_OFF|MOTUFW_PA_OPTICAL_ADAT, 49},
110     {"Toslink1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_TOSLINK, 46},
111     {"Toslink2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_TOSLINK, 49},
112     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 52},
113     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 55},
114     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 58},
115     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 61},
116     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 63},
117     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 66},
118     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 69},
119     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 72},
120 };
121
122 const PortEntry Ports_ULTRALITE[] =
123 {
124     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
125     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
126     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
127     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
128     {"Mic1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
129     {"Mic2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
130     {"Analog1", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
131     {"Analog2", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
132     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
133     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
134     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
135     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
136     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
137     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
138     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
139     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
140     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
141     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
142     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 46},
143     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 49},
144 };
145
146 const PortEntry Ports_8PRE[] =
147 {
148     {"Analog1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
149     {"Analog2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
150     {"Analog3", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
151     {"Analog4", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
152     {"Analog5", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
153     {"Analog6", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
154     {"Analog7", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
155     {"Analog8", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
156     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
157     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
158     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
159     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
160     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
161     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
162     {"ADAT1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 40},
163     {"ADAT1", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 22},
164     {"ADAT2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 43},
165     {"ADAT2", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 25},
166     {"ADAT3", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 46},
167     {"ADAT3", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 28},
168     {"ADAT4", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 49},
169     {"ADAT4", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 31},
170     {"ADAT5", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 52},
171     {"ADAT5", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 34},
172     {"ADAT6", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 55},
173     {"ADAT6", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 37},
174     {"ADAT7", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 58},
175     {"ADAT7", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 40},
176     {"ADAT8", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 61},
177     {"ADAT8", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 43},
178 };
179
180 const DevicePropertyEntry DevicesProperty[] = {
181 //  { Ports_map,       sizeof( Ports_map ),        MaxSR },
182     { Ports_828MKII,   sizeof( Ports_828MKII ),    96000 },
183     { Ports_TRAVELER,  sizeof( Ports_TRAVELER ),  192000 },
184     { Ports_ULTRALITE, sizeof( Ports_ULTRALITE ),  96000 },
185     { Ports_8PRE,      sizeof( Ports_8PRE ),       96000 },
186 };
187
188 MotuDevice::MotuDevice( std::auto_ptr<ConfigRom>( configRom ))
189     : FFADODevice( configRom )
190     , m_motu_model( MOTUFW_MODEL_NONE )
191     , m_iso_recv_channel ( -1 )
192     , m_iso_send_channel ( -1 )
193     , m_rx_bandwidth ( -1 )
194     , m_tx_bandwidth ( -1 )
195     , m_receiveProcessor ( 0 )
196     , m_transmitProcessor ( 0 )
197
198 {
199     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
200                  getConfigRom().getNodeId() );
201
202 }
203
204 MotuDevice::~MotuDevice()
205 {
206     // Free ieee1394 bus resources if they have been allocated
207     if (m_iso_recv_channel>=0 && !get1394Service().freeIsoChannel(m_iso_recv_channel)) {
208         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
209     }
210     if (m_iso_send_channel>=0 && !get1394Service().freeIsoChannel(m_iso_send_channel)) {
211         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
212     }
213 }
214
215 bool
216 MotuDevice::probe( ConfigRom& configRom )
217 {
218     unsigned int vendorId = configRom.getNodeVendorId();
219 //     unsigned int modelId = configRom.getModelId();
220     unsigned int unitVersion = configRom.getUnitVersion();
221     unsigned int unitSpecifierId = configRom.getUnitSpecifierId();
222
223     for ( unsigned int i = 0;
224           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
225           ++i )
226     {
227         if ( ( supportedDeviceList[i].vendor_id == vendorId )
228 //              && ( supportedDeviceList[i].model_id == modelId )
229              && ( supportedDeviceList[i].unit_version == unitVersion )
230              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
231            )
232         {
233             return true;
234         }
235     }
236
237     return false;
238 }
239
240 FFADODevice *
241 MotuDevice::createDevice(std::auto_ptr<ConfigRom>( configRom ))
242 {
243     return new MotuDevice(configRom);
244 }
245
246 bool
247 MotuDevice::discover()
248 {
249     unsigned int vendorId = getConfigRom().getNodeVendorId();
250 //     unsigned int modelId = getConfigRom().getModelId();
251     unsigned int unitVersion = getConfigRom().getUnitVersion();
252     unsigned int unitSpecifierId = getConfigRom().getUnitSpecifierId();
253
254     for ( unsigned int i = 0;
255           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
256           ++i )
257     {
258         if ( ( supportedDeviceList[i].vendor_id == vendorId )
259 //              && ( supportedDeviceList[i].model_id == modelId )
260              && ( supportedDeviceList[i].unit_version == unitVersion )
261              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
262            )
263         {
264             m_model = &(supportedDeviceList[i]);
265             m_motu_model=supportedDeviceList[i].model;
266         }
267     }
268
269     if (m_model != NULL) {
270         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
271                 m_model->vendor_name, m_model->model_name);
272         return true;
273     }
274
275     return false;
276 }
277
278 int
279 MotuDevice::getSamplingFrequency( ) {
280 /*
281  * Retrieve the current sample rate from the MOTU device.
282  */
283     quadlet_t q = ReadRegister(MOTUFW_REG_CLK_CTRL);
284     int rate = 0;
285
286     switch (q & MOTUFW_RATE_BASE_MASK) {
287         case MOTUFW_RATE_BASE_44100:
288             rate = 44100;
289             break;
290         case MOTUFW_RATE_BASE_48000:
291             rate = 48000;
292             break;
293     }
294     switch (q & MOTUFW_RATE_MULTIPLIER_MASK) {
295         case MOTUFW_RATE_MULTIPLIER_2X:
296             rate *= 2;
297             break;
298         case MOTUFW_RATE_MULTIPLIER_4X:
299             rate *= 4;
300             break;
301     }
302     return rate;
303 }
304
305 int
306 MotuDevice::getConfigurationId()
307 {
308     return 0;
309 }
310
311 bool
312 MotuDevice::setSamplingFrequency( int samplingFrequency )
313 {
314 /*
315  * Set the MOTU device's samplerate.
316  */
317     char *src_name;
318     quadlet_t q, new_rate=0;
319     int i, supported=true, cancel_adat=false;
320
321     if ( samplingFrequency > DevicesProperty[m_motu_model-1].MaxSampleRate )
322        return false;
323
324     switch ( samplingFrequency ) {
325         case 22050:
326         case 24000:
327         case 32000:
328             supported=false;
329             break;
330         case 44100:
331             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_1X;
332             break;
333         case 48000:
334             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_1X;
335             break;
336         case 88200:
337             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_2X;
338             break;
339         case 96000:
340             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_2X;
341             break;
342         case 176400:
343             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_4X;
344             cancel_adat = true;  // current ADAT protocol doesn't support sample rate > 96000
345             break;
346         case 192000:
347             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_4X;
348             cancel_adat = true;
349             break;
350         default:
351             supported=false;
352     }
353
354     // Update the clock control register.  FIXME: while this is now rather
355     // comprehensive there may still be a need to manipulate MOTUFW_REG_CLK_CTRL
356     // a little more than we do.
357     if (supported) {
358         quadlet_t value=ReadRegister(MOTUFW_REG_CLK_CTRL);
359
360         // If optical port must be disabled (because a 4x sample rate has
361         // been selected) then do so before changing the sample rate.  At
362         // this stage it will be up to the user to re-enable the optical
363         // port if the sample rate is set to a 1x or 2x rate later.
364         if (cancel_adat) {
365             setOpticalMode(MOTUFW_DIR_INOUT, MOTUFW_OPTICAL_MODE_OFF);
366         }
367
368         value &= ~(MOTUFW_RATE_BASE_MASK|MOTUFW_RATE_MULTIPLIER_MASK);
369         value |= new_rate;
370
371         // In other OSes bit 26 of MOTUFW_REG_CLK_CTRL always seems
372         // to be set when this register is written to although the
373         // reason isn't currently known.  When we set it, it appears
374         // to prevent output being produced so we'll leave it unset
375         // until we work out what's going on.  Other systems write
376         // to MOTUFW_REG_CLK_CTRL multiple times, so that may be
377         // part of the mystery.
378         //   value |= 0x04000000;
379         if (WriteRegister(MOTUFW_REG_CLK_CTRL, value) == 0) {
380             supported=true;
381         } else {
382             supported=false;
383         }
384         // A write to the rate/clock control register requires the
385         // textual name of the current clock source be sent to the
386         // clock source name registers.
387         switch (value & MOTUFW_CLKSRC_MASK) {
388             case MOTUFW_CLKSRC_INTERNAL:
389                 src_name = "Internal        ";
390                 break;
391             case MOTUFW_CLKSRC_ADAT_OPTICAL:
392                 src_name = "ADAT Optical    ";
393                 break;
394             case MOTUFW_CLKSRC_SPDIF_TOSLINK:
395                 if (getOpticalMode(MOTUFW_DIR_IN)  == MOTUFW_OPTICAL_MODE_TOSLINK)
396                     src_name = "TOSLink         ";
397                 else
398                     src_name = "SPDIF           ";
399                 break;
400             case MOTUFW_CLKSRC_SMTPE:
401                 src_name = "SMPTE           ";
402                 break;
403             case MOTUFW_CLKSRC_WORDCLOCK:
404                 src_name = "Word Clock In   ";
405                 break;
406             case MOTUFW_CLKSRC_ADAT_9PIN:
407                 src_name = "ADAT 9-pin      ";
408                 break;
409             case MOTUFW_CLKSRC_AES_EBU:
410                 src_name = "AES-EBU         ";
411                 break;
412             default:
413                 src_name = "Unknown         ";
414         }
415         for (i=0; i<16; i+=4) {
416             q = (src_name[i]<<24) | (src_name[i+1]<<16) |
417                 (src_name[i+2]<<8) | src_name[i+3];
418             WriteRegister(MOTUFW_REG_CLKSRC_NAME0+i, q);
419         }
420     }
421     return supported;
422 }
423
424 FFADODevice::ClockSourceVector
425 MotuDevice::getSupportedClockSources() {
426     FFADODevice::ClockSourceVector r;
427     return r;
428 }
429
430 bool
431 MotuDevice::setActiveClockSource(ClockSource s) {
432     return false;
433 }
434
435 FFADODevice::ClockSource
436 MotuDevice::getActiveClockSource() {
437     ClockSource s;
438     return s;
439 }
440
441 bool
442 MotuDevice::lock() {
443
444     return true;
445 }
446
447
448 bool
449 MotuDevice::unlock() {
450
451     return true;
452 }
453
454 void
455 MotuDevice::showDevice()
456 {
457     debugOutput(DEBUG_LEVEL_VERBOSE,
458         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
459         getNodeId());
460 }
461
462 bool
463 MotuDevice::prepare() {
464
465     int samp_freq = getSamplingFrequency();
466     unsigned int optical_in_mode = getOpticalMode(MOTUFW_DIR_IN);
467     unsigned int optical_out_mode = getOpticalMode(MOTUFW_DIR_OUT);
468     unsigned int event_size_in = getEventSize(MOTUFW_DIR_IN);
469     unsigned int event_size_out= getEventSize(MOTUFW_DIR_OUT);
470
471     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
472
473     // Allocate bandwidth if not previously done.
474     // FIXME: The bandwidth allocation calculation can probably be
475     // refined somewhat since this is currently based on a rudimentary
476     // understanding of the ieee1394 iso protocol.
477     // Currently we assume the following.
478     //   * Ack/iso gap = 0.05 us
479     //   * DATA_PREFIX = 0.16 us
480     //   * DATA_END    = 0.26 us
481     // These numbers are the worst-case figures given in the ieee1394
482     // standard.  This gives approximately 0.5 us of overheads per packet -
483     // around 25 bandwidth allocation units (from the ieee1394 standard 1
484     // bandwidth allocation unit is 125/6144 us).  We further assume the
485     // MOTU is running at S400 (which it should be) so one allocation unit
486     // is equivalent to 1 transmitted byte; thus the bandwidth allocation
487     // required for the packets themselves is just the size of the packet.
488     // We used to allocate based on the maximum packet size (1160 bytes at
489     // 192 kHz for the traveler) but now do this based on the actual device
490     // state by utilising the result from getEventSize() and remembering
491     // that each packet has an 8 byte CIP header.  Note that bandwidth is
492     // allocated on a *per stream* basis - it must be allocated for both the
493     // transmit and receive streams.  While most MOTU modules are close to
494     // symmetric in terms of the number of in/out channels there are
495     // exceptions, so we deal with receive and transmit bandwidth separately.
496     signed int n_events_per_packet = samp_freq<=48000?8:(samp_freq<=96000?16:32);
497     m_rx_bandwidth = 25 + (n_events_per_packet*event_size_in);
498     m_tx_bandwidth = 25 + (n_events_per_packet*event_size_out);
499
500     // Assign iso channels if not already done
501     if (m_iso_recv_channel < 0)
502         m_iso_recv_channel = get1394Service().allocateIsoChannelGeneric(m_rx_bandwidth);
503
504     if (m_iso_send_channel < 0)
505         m_iso_send_channel = get1394Service().allocateIsoChannelGeneric(m_tx_bandwidth);
506
507     debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
508         m_iso_recv_channel, m_iso_send_channel);
509
510     if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
511         // be nice and deallocate
512         if (m_iso_recv_channel >= 0)
513             get1394Service().freeIsoChannel(m_iso_recv_channel);
514         if (m_iso_send_channel >= 0)
515             get1394Service().freeIsoChannel(m_iso_send_channel);
516
517         debugFatal("Could not allocate iso channels!\n");
518         return false;
519     }
520
521     m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor(
522         get1394Service().getPort(), event_size_in);
523
524     // The first thing is to initialize the processor.  This creates the
525     // data structures.
526     if(!m_receiveProcessor->init()) {
527         debugFatal("Could not initialize receive processor!\n");
528         return false;
529     }
530     m_receiveProcessor->setVerboseLevel(getDebugLevel());
531
532     // Now we add ports to the processor
533     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
534
535     char *buff;
536     Streaming::Port *p=NULL;
537
538     // retrieve the ID
539     std::string id=std::string("dev?");
540     if(!getOption("id", id)) {
541         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
542     }
543
544     // Add audio capture ports
545     if (!addDirPorts(Streaming::Port::E_Capture, samp_freq, optical_in_mode)) {
546         return false;
547     }
548
549     // Add MIDI port.  The MOTU only has one MIDI input port, with each
550     // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
551     // event data.
552     asprintf(&buff,"%s_cap_MIDI0",id.c_str());
553     p = new Streaming::MotuMidiPort(buff,
554         Streaming::Port::E_Capture, 4);
555     if (!p) {
556         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
557     } else {
558         if (!m_receiveProcessor->addPort(p)) {
559             debugWarning("Could not register port with stream processor\n");
560             free(buff);
561             return false;
562         } else {
563             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
564         }
565     }
566     free(buff);
567
568     // example of adding an control port:
569 //    asprintf(&buff,"%s_cap_%s",id.c_str(),"myportnamehere");
570 //    p=new Streaming::MotuControlPort(
571 //            buff,
572 //            Streaming::Port::E_Capture,
573 //            0 // you can add all other port specific stuff you
574 //              // need to pass by extending MotuXXXPort and MotuPortInfo
575 //    );
576 //    free(buff);
577 //
578 //    if (!p) {
579 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
580 //    } else {
581 //
582 //        if (!m_receiveProcessor->addPort(p)) {
583 //            debugWarning("Could not register port with stream processor\n");
584 //            return false;
585 //        } else {
586 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
587 //        }
588 //    }
589
590     // Do the same for the transmit processor
591     m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor(
592         get1394Service().getPort(), event_size_out);
593
594     m_transmitProcessor->setVerboseLevel(getDebugLevel());
595
596     if(!m_transmitProcessor->init()) {
597         debugFatal("Could not initialize transmit processor!\n");
598         return false;
599     }
600
601     // Now we add ports to the processor
602     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
603
604     // Add audio playback ports
605     if (!addDirPorts(Streaming::Port::E_Playback, samp_freq, optical_out_mode)) {
606         return false;
607     }
608
609     // Add MIDI port.  The MOTU only has one output MIDI port, with each
610     // MIDI byte transmitted using a 3 byte sequence starting at byte 4
611     // of the event data.
612     asprintf(&buff,"%s_pbk_MIDI0",id.c_str());
613     p = new Streaming::MotuMidiPort(buff,
614         Streaming::Port::E_Capture, 4);
615     if (!p) {
616         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
617     } else {
618         if (!m_receiveProcessor->addPort(p)) {
619             debugWarning("Could not register port with stream processor\n");
620             free(buff);
621             return false;
622         } else {
623             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
624         }
625     }
626     free(buff);
627
628     // example of adding an control port:
629 //    asprintf(&buff,"%s_pbk_%s",id.c_str(),"myportnamehere");
630 //
631 //    p=new Streaming::MotuControlPort(
632 //            buff,
633 //            Streaming::Port::E_Playback,
634 //            0 // you can add all other port specific stuff you
635 //              // need to pass by extending MotuXXXPort and MotuPortInfo
636 //    );
637 //    free(buff);
638 //
639 //    if (!p) {
640 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
641 //    } else {
642 //        if (!m_transmitProcessor->addPort(p)) {
643 //            debugWarning("Could not register port with stream processor\n");
644 //            return false;
645 //        } else {
646 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
647 //        }
648 //    }
649
650     return true;
651 }
652
653 int
654 MotuDevice::getStreamCount() {
655      return 2; // one receive, one transmit
656 }
657
658 Streaming::StreamProcessor *
659 MotuDevice::getStreamProcessorByIndex(int i) {
660     switch (i) {
661     case 0:
662         return m_receiveProcessor;
663     case 1:
664          return m_transmitProcessor;
665     default:
666         return NULL;
667     }
668     return 0;
669 }
670
671 bool
672 MotuDevice::startStreamByIndex(int i) {
673
674 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
675
676     // NOTE: this assumes that you have two streams
677     switch (i) {
678     case 0:
679         // TODO: do the stuff that is nescessary to make the device
680         // receive a stream
681
682         // Set the streamprocessor channel to the one obtained by
683         // the connection management
684         m_receiveProcessor->setChannel(m_iso_recv_channel);
685
686         // Mask out current transmit settings of the MOTU and replace
687         // with new ones.  Turn bit 24 on to enable changes to the
688         // MOTU's iso transmit settings when the iso control register
689         // is written.  Bit 23 enables iso transmit from the MOTU.
690         isoctrl &= 0xff00ffff;
691         isoctrl |= (m_iso_recv_channel << 16);
692         isoctrl |= 0x00c00000;
693         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
694         break;
695     case 1:
696         // TODO: do the stuff that is nescessary to make the device
697         // transmit a stream
698
699         // Set the streamprocessor channel to the one obtained by
700         // the connection management
701         m_transmitProcessor->setChannel(m_iso_send_channel);
702
703         // Mask out current receive settings of the MOTU and replace
704         // with new ones.  Turn bit 31 on to enable changes to the
705         // MOTU's iso receive settings when the iso control register
706         // is written.  Bit 30 enables iso receive by the MOTU.
707         isoctrl &= 0x00ffffff;
708         isoctrl |= (m_iso_send_channel << 24);
709         isoctrl |= 0xc0000000;
710         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
711         break;
712
713     default: // Invalid stream index
714         return false;
715     }
716
717     return true;
718 }
719
720 bool
721 MotuDevice::stopStreamByIndex(int i) {
722
723 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
724
725     // TODO: connection management: break connection
726     // cfr the start function
727
728     // NOTE: this assumes that you have two streams
729     switch (i) {
730     case 0:
731         // Turn bit 22 off to disable iso send by the MOTU.  Turn
732         // bit 23 on to enable changes to the MOTU's iso transmit
733         // settings when the iso control register is written.
734         isoctrl &= 0xffbfffff;
735         isoctrl |= 0x00800000;
736         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
737         break;
738     case 1:
739         // Turn bit 30 off to disable iso receive by the MOTU.  Turn
740         // bit 31 on to enable changes to the MOTU's iso receive
741         // settings when the iso control register is written.
742         isoctrl &= 0xbfffffff;
743         isoctrl |= 0x80000000;
744         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
745         break;
746
747     default: // Invalid stream index
748         return false;
749     }
750
751     return true;
752 }
753
754 signed int MotuDevice::getIsoRecvChannel(void) {
755     return m_iso_recv_channel;
756 }
757
758 signed int MotuDevice::getIsoSendChannel(void) {
759     return m_iso_send_channel;
760 }
761
762 unsigned int MotuDevice::getOpticalMode(unsigned int dir) {
763     unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
764
765 debugOutput(DEBUG_LEVEL_VERBOSE, "optical mode: %x %x %x %x\n",dir, reg, reg & MOTUFW_OPTICAL_IN_MODE_MASK,
766 reg & MOTUFW_OPTICAL_OUT_MODE_MASK);
767
768     if (dir == MOTUFW_DIR_IN)
769         return (reg & MOTUFW_OPTICAL_IN_MODE_MASK) >> 8;
770     else
771         return (reg & MOTUFW_OPTICAL_OUT_MODE_MASK) >> 10;
772 }
773
774 signed int MotuDevice::setOpticalMode(unsigned int dir, unsigned int mode) {
775     unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
776     unsigned int opt_ctrl = 0x0000002;
777
778     // Set up the optical control register value according to the current
779     // optical port modes.  At this stage it's not completely understood
780     // what the "Optical control" register does, so the values it's set to
781     // are more or less "magic" numbers.
782     if (reg & MOTUFW_OPTICAL_IN_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<8))
783         opt_ctrl |= 0x00000080;
784     if (reg & MOTUFW_OPTICAL_OUT_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<10))
785         opt_ctrl |= 0x00000040;
786
787     if (mode & MOTUFW_DIR_IN) {
788         reg &= ~MOTUFW_OPTICAL_IN_MODE_MASK;
789         reg |= (mode << 8) & MOTUFW_OPTICAL_IN_MODE_MASK;
790         if (mode != MOTUFW_OPTICAL_MODE_ADAT)
791             opt_ctrl |= 0x00000080;
792         else
793             opt_ctrl &= ~0x00000080;
794     }
795     if (mode & MOTUFW_DIR_OUT) {
796         reg &= ~MOTUFW_OPTICAL_OUT_MODE_MASK;
797         reg |= (mode <<10) & MOTUFW_OPTICAL_OUT_MODE_MASK;
798         if (mode != MOTUFW_OPTICAL_MODE_ADAT)
799             opt_ctrl |= 0x00000040;
800         else
801             opt_ctrl &= ~0x00000040;
802     }
803
804     // FIXME: there seems to be more to it than this, but for
805     // the moment at least this seems to work.
806     WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg);
807     return WriteRegister(MOTUFW_REG_OPTICAL_CTRL, opt_ctrl);
808 }
809
810 signed int MotuDevice::getEventSize(unsigned int direction) {
811 //
812 // Return the size in bytes of a single event sent to (dir==MOTUFW_OUT) or
813 // from (dir==MOTUFW_IN) the MOTU as part of an iso data packet.
814 //
815 // FIXME: for performance it may turn out best to calculate the event
816 // size in setOpticalMode and cache the result in a data field.  However,
817 // as it stands this will not adapt to dynamic changes in sample rate - we'd
818 // need a setFrameRate() for that.
819 //
820 // At the very least an event consists of the SPH (4 bytes) and the control/MIDI
821 // bytes (6 bytes).
822 // Note that all audio channels are sent using 3 bytes.
823 signed int sample_rate = getSamplingFrequency();
824 signed int optical_mode = getOpticalMode(direction);
825 signed int size = 4+6;
826
827 unsigned int i;
828 unsigned int dir = direction==Streaming::Port::E_Capture?MOTUFW_DIR_IN:MOTUFW_DIR_OUT;
829 unsigned int flags = (1 << ( optical_mode + 4 ));
830
831     if ( sample_rate > 96000 )
832         flags |= MOTUFW_PA_RATE_4x;
833     else if ( sample_rate > 48000 )
834         flags |= MOTUFW_PA_RATE_2x;
835     else
836         flags |= MOTUFW_PA_RATE_1x;
837
838     for (i=0; i < ( DevicesProperty[m_motu_model-1].PortsListLength /sizeof( PortEntry ) ); i++) {
839         if (( DevicesProperty[m_motu_model-1].PortsList[i].port_dir & dir ) &&
840            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_RATE_MASK & flags ) &&
841            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_OPTICAL_MASK & flags )) {
842             size += 3;
843         }
844     }
845
846     // Finally round size up to the next quadlet boundary
847     return ((size+3)/4)*4;
848 }
849 /* ======================================================================= */
850
851 bool MotuDevice::addPort(Streaming::StreamProcessor *s_processor,
852   char *name, enum Streaming::Port::E_Direction direction,
853   int position, int size) {
854 /*
855  * Internal helper function to add a MOTU port to a given stream processor.
856  * This just saves the unnecessary replication of what is essentially
857  * boilerplate code.  Note that the port name is freed by this function
858  * prior to exit.
859  */
860 Streaming::Port *p=NULL;
861
862     p = new Streaming::MotuAudioPort(name, direction, position, size);
863
864     if (!p) {
865         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
866     } else {
867         if (!s_processor->addPort(p)) {
868             debugWarning("Could not register port with stream processor\n");
869             free(name);
870             return false;
871         } else {
872             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",name);
873         }
874         p->enable();
875     }
876     free(name);
877     return true;
878 }
879 /* ======================================================================= */
880
881 bool MotuDevice::addDirPorts(
882   enum Streaming::Port::E_Direction direction,
883   unsigned int sample_rate, unsigned int optical_mode) {
884 /*
885  * Internal helper method: adds all required ports for the given direction
886  * based on the indicated sample rate and optical mode.
887  *
888  * Notes: currently ports are not created if they are disabled due to sample
889  * rate or optical mode.  However, it might be better to unconditionally
890  * create all ports and just disable those which are not active.
891  */
892 const char *mode_str = direction==Streaming::Port::E_Capture?"cap":"pbk";
893 Streaming::StreamProcessor *s_processor;
894 unsigned int i;
895 char *buff;
896 unsigned int dir = direction==Streaming::Port::E_Capture?MOTUFW_DIR_IN:MOTUFW_DIR_OUT;
897 unsigned int flags = (1 << ( optical_mode + 4 ));
898
899     if ( sample_rate > 96000 )
900         flags |= MOTUFW_PA_RATE_4x;
901     else if ( sample_rate > 48000 )
902         flags |= MOTUFW_PA_RATE_2x;
903     else
904         flags |= MOTUFW_PA_RATE_1x;
905
906     // retrieve the ID
907     std::string id=std::string("dev?");
908     if(!getOption("id", id)) {
909         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
910     }
911
912     if (direction == Streaming::Port::E_Capture) {
913         s_processor = m_receiveProcessor;
914     } else {
915         s_processor = m_transmitProcessor;
916     }
917
918     for (i=0; i < ( DevicesProperty[m_motu_model-1].PortsListLength /sizeof( PortEntry ) ); i++) {
919         if (( DevicesProperty[m_motu_model-1].PortsList[i].port_dir & dir ) &&
920            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_RATE_MASK & flags ) &&
921            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_OPTICAL_MASK & flags )) {
922             asprintf(&buff,"%s_%s_%s" , id.c_str(), mode_str,
923               DevicesProperty[m_motu_model-1].PortsList[i].port_name);
924             if (!addPort(s_processor, buff, direction, DevicesProperty[m_motu_model-1].PortsList[i].port_offset, 0))
925                 return false;
926         }
927     }
928    
929     return true;
930 }
931 /* ======================================================================== */
932
933 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
934 /*
935  * Attempts to read the requested register from the MOTU.
936  */
937
938   quadlet_t quadlet;
939
940   quadlet = 0;
941   // Note: 1394Service::read() expects a physical ID, not the node id
942   if (get1394Service().read(0xffc0 | getNodeId(), MOTUFW_BASE_ADDR+reg, 1, &quadlet) < 0) {
943     debugError("Error doing motu read from register 0x%06x\n",reg);
944   }
945
946   return ntohl(quadlet);
947 }
948
949 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
950 /*
951  * Attempts to write the given data to the requested MOTU register.
952  */
953
954   unsigned int err = 0;
955   data = htonl(data);
956
957   // Note: 1394Service::write() expects a physical ID, not the node id
958   if (get1394Service().write(0xffc0 | getNodeId(), MOTUFW_BASE_ADDR+reg, 1, &data) < 0) {
959     err = 1;
960     debugError("Error doing motu write to register 0x%06x\n",reg);
961   }
962
963   usleep(100);
964   return (err==0)?0:-1;
965 }
966
967 }
Note: See TracBrowser for help on using the browser.