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

Revision 660, 36.3 kB (checked in by jwoithe, 16 years ago)

MOTU: allow receive and transmit streams to have different bandwidth requirements, since not all interfaces have about the same number of input and output channels.

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