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

Revision 739, 36.1 kB (checked in by ppalmers, 15 years ago)

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might work.

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 library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library 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 GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
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.