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

Revision 734, 36.3 kB (checked in by ppalmers, 15 years ago)

merge ppalmers-streaming branch

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