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

Revision 659, 36.1 kB (checked in by f.ernoult, 15 years ago)

MotU: Centralize all device specific parameters in DeviceProperty?

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