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

Revision 658, 36.3 kB (checked in by f.ernoult, 15 years ago)

MotU: Preliminary implementation of UltraLite and 8pre support

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