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

Revision 1064, 52.8 kB (checked in by jwoithe, 16 years ago)

* MOTU: disable optical SPDIF mode if device doesn't support it.
* MOTU: update protocol documentation.
* MOTU: rearrange mixer to put the channel pair switches in a more intelligent position (note that pairing functionality is still to be implemented).

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "motu/motu_avdevice.h"
26
27 #include "libieee1394/configrom.h"
28 #include "libieee1394/ieee1394service.h"
29
30 #include "libavc/avc_definitions.h"
31
32 #include "debugmodule/debugmodule.h"
33
34 #include "libstreaming/motu/MotuReceiveStreamProcessor.h"
35 #include "libstreaming/motu/MotuTransmitStreamProcessor.h"
36 #include "libstreaming/motu/MotuPort.h"
37
38 #include "libutil/DelayLockedLoop.h"
39 #include "libutil/Time.h"
40
41 #include "libcontrol/BasicElements.h"
42
43 #include <string>
44 #include <stdint.h>
45 #include <assert.h>
46 #include <netinet/in.h>
47 #include <iostream>
48 #include <sstream>
49
50 #include <libraw1394/csr.h>
51
52 namespace Motu {
53
54 // Define the supported devices.  Device ordering is arbitary here.
55 static VendorModelEntry supportedDeviceList[] =
56 {
57 //  {vendor_id, model_id, unit_version, unit_specifier_id, model, vendor_name,model_name}
58     {FW_VENDORID_MOTU, 0, 0x00000003, 0x000001f2, MOTU_MODEL_828mkII, "MOTU", "828MkII"},
59     {FW_VENDORID_MOTU, 0, 0x00000009, 0x000001f2, MOTU_MODEL_TRAVELER, "MOTU", "Traveler"},
60     {FW_VENDORID_MOTU, 0, 0x0000000d, 0x000001f2, MOTU_MODEL_ULTRALITE, "MOTU", "UltraLite"},
61     {FW_VENDORID_MOTU, 0, 0x0000000f, 0x000001f2, MOTU_MODEL_8PRE, "MOTU", "8pre"},
62     {FW_VENDORID_MOTU, 0, 0x00000001, 0x000001f2, MOTU_MODEL_828MkI, "MOTU", "828MkI"},
63     {FW_VENDORID_MOTU, 0, 0x00000005, 0x000001f2, MOTU_MODEL_896HD, "MOTU", "896HD"},
64 };
65
66 // Ports declarations
67 const PortEntry Ports_828MKI[] =
68 {
69     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
70     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
71     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
72     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
73     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
74     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
75     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
76     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
77     {"SPDIF1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
78     {"SPDIF2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
79     {"ADAT1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
80     {"ADAT2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
81     {"ADAT3", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 46},
82     {"ADAT4", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 49},
83     {"ADAT5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 52},
84     {"ADAT6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 55},
85     {"ADAT7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 58},
86     {"ADAT8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 61},
87 };
88
89 const PortEntry Ports_896HD[] =
90 {
91     {"Mix-L", MOTU_DIR_IN, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
92     {"Mix-R", MOTU_DIR_IN, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
93     {"Phones-L", MOTU_DIR_OUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
94     {"Phones-R", MOTU_DIR_OUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
95     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 16},
96     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 10},
97     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 19},
98     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 13},
99     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 22},
100     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 16},
101     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 25},
102     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 19},
103     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 28},
104     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 22},
105     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 31},
106     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 25},
107     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 34},
108     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 28},
109     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 37},
110     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 31},
111     {"MainOut-L", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
112     {"MainOut-R", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
113     {"AES/EBU1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 46},
114     {"AES/EBU2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 49},
115     {"ADAT1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 52},
116     {"ADAT2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 55},
117     {"ADAT3", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 58},
118     {"ADAT4", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 61},
119     {"ADAT5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
120     {"ADAT6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
121     {"ADAT7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
122     {"ADAT8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
123 };
124
125 const PortEntry Ports_828MKII[] =
126 {
127     {"Main-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
128     {"Main-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
129     {"Mix-L", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
130     {"Mix-R", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
131     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
132     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
133     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
134     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
135     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
136     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
137     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
138     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
139     {"Phones-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
140     {"Phones-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
141     {"Mic1", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
142     {"Mic2", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
143     {"SPDIF1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 46},
144     {"SPDIF2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 49},
145     {"ADAT1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 52},
146     {"ADAT2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 55},
147     {"ADAT3", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 58},
148     {"ADAT4", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 61},
149     {"ADAT5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
150     {"ADAT6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
151     {"ADAT7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
152     {"ADAT8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
153 };
154
155 const PortEntry Ports_TRAVELER[] =
156 {
157     {"Mix-L", MOTU_DIR_IN, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
158     {"Mix-R", MOTU_DIR_IN, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
159     {"Phones-L", MOTU_DIR_OUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
160     {"Phones-R", MOTU_DIR_OUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
161     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 16},
162     {"Analog1", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 10},
163     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 19},
164     {"Analog2", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 13},
165     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 22},
166     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 16},
167     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 25},
168     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 19},
169     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 28},
170     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 22},
171     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 31},
172     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 25},
173     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 34},
174     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 28},
175     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 37},
176     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 31},
177     {"AES/EBU1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
178     {"AES/EBU2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
179     {"SPDIF1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_OPTICAL_ADAT, 46},
180     {"SPDIF2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_OPTICAL_ADAT, 49},
181     {"Toslink1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_TOSLINK, 46},
182     {"Toslink2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_TOSLINK, 49},
183     {"ADAT1", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 52},
184     {"ADAT2", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 55},
185     {"ADAT3", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 58},
186     {"ADAT4", MOTU_DIR_INOUT, MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 61},
187     {"ADAT5", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
188     {"ADAT6", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
189     {"ADAT7", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
190     {"ADAT8", MOTU_DIR_INOUT, MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
191 };
192
193 const PortEntry Ports_ULTRALITE[] =
194 {
195     {"Main-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
196     {"Main-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
197     {"Mix-L", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
198     {"Mix-R", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
199     {"Mic1", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
200     {"Mic2", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
201     {"Analog1", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
202     {"Analog2", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
203     {"Analog3", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
204     {"Analog4", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
205     {"Analog5", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
206     {"Analog6", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
207     {"Analog7", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
208     {"Analog8", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
209     {"Phones-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
210     {"Phones-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
211     {"SPDIF1", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 46},
212     {"SPDIF2", MOTU_DIR_INOUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 49},
213 };
214
215 const PortEntry Ports_8PRE[] =
216 {
217     {"Analog1", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
218     {"Analog2", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
219     {"Analog3", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
220     {"Analog4", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
221     {"Analog5", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
222     {"Analog6", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
223     {"Analog7", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
224     {"Analog8", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
225     {"Mix-L", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
226     {"Mix-R", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
227     {"Main-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
228     {"Main-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
229     {"Phones-L", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
230     {"Phones-R", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
231     {"ADAT1", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
232     {"ADAT1", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 22},
233     {"ADAT2", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
234     {"ADAT2", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 25},
235     {"ADAT3", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 46},
236     {"ADAT3", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 28},
237     {"ADAT4", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 49},
238     {"ADAT4", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 31},
239     {"ADAT5", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 52},
240     {"ADAT5", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 34},
241     {"ADAT6", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 55},
242     {"ADAT6", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 37},
243     {"ADAT7", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 58},
244     {"ADAT7", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
245     {"ADAT8", MOTU_DIR_IN, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 61},
246     {"ADAT8", MOTU_DIR_OUT, MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
247 };
248
249 // Mixer registers
250 const MixerCtrl MixerCtrls_Traveler[] = {
251     {"Mix1/Ana1_", "Mix 1 analog 1 ", "", MOTU_CTRL_STD_CHANNEL, 0x4000, },
252     {"Mix1/Ana2_", "Mix 1 analog 2 ", "", MOTU_CTRL_STD_CHANNEL, 0x4004, },
253     {"Mix1/Ana3_", "Mix 1 analog 3 ", "", MOTU_CTRL_STD_CHANNEL, 0x4008, },
254     {"Mix1/Ana4_", "Mix 1 analog 4 ", "", MOTU_CTRL_STD_CHANNEL, 0x400c, },
255     {"Mix1/Ana5_", "Mix 1 analog 5 ", "", MOTU_CTRL_STD_CHANNEL, 0x4010, },
256     {"Mix1/Ana6_", "Mix 1 analog 6 ", "", MOTU_CTRL_STD_CHANNEL, 0x4014, },
257     {"Mix1/Ana7_", "Mix 1 analog 7 ", "", MOTU_CTRL_STD_CHANNEL, 0x4018, },
258     {"Mix1/Ana8_", "Mix 1 analog 8 ", "", MOTU_CTRL_STD_CHANNEL, 0x401c, },
259
260     {"Mix1/Mix_", "Mix 1 ", "", MOTU_CTRL_STD_MIX, 0x0c20, },
261
262     /* For mic/line input controls, the "register" is the zero-based channel number */
263     {"Control/Ana1_", "Analog 1 input ", "", MOTU_CTRL_TRAVELER_MIC_INPUT_CTRLS, 0},
264     {"Control/Ana2_", "Analog 2 input ", "", MOTU_CTRL_TRAVELER_MIC_INPUT_CTRLS, 1},
265     {"Control/Ana3_", "Analog 3 input ", "", MOTU_CTRL_TRAVELER_MIC_INPUT_CTRLS, 2},
266     {"Control/Ana4_", "Analog 4 input ", "", MOTU_CTRL_TRAVELER_MIC_INPUT_CTRLS, 3},
267     {"Control/Ana5_", "Analog 5 input ", "", MOTU_CTRL_TRAVELER_LINE_INPUT_CTRLS, 4},
268     {"Control/Ana6_", "Analog 6 input ", "", MOTU_CTRL_TRAVELER_LINE_INPUT_CTRLS, 5},
269     {"Control/Ana7_", "Analog 7 input ", "", MOTU_CTRL_TRAVELER_LINE_INPUT_CTRLS, 6},
270     {"Control/Ana8_", "Analog 8 input ", "", MOTU_CTRL_TRAVELER_LINE_INPUT_CTRLS, 7},
271
272     {"Control/Phones_", "Phones source", "", MOTU_CTRL_PHONES_SRC, 0},
273
274     {"Control/OpticalIn_mode", "Optical input mode ", "", MOTU_CTRL_OPTICAL_MODE, MOTU_DIR_IN},
275     {"Control/OpticalOut_mode", "Optical output mode ", "", MOTU_CTRL_OPTICAL_MODE, MOTU_DIR_OUT},
276 };
277
278 // For convenience during initial testing, just make the 828MkII and 896HD
279 // use the Traveler's mixer definition.  Separate definitions for these
280 // models will come once the final mixer structure is in place.  For now
281 // it's in a state of flux and subject to significant change.
282 #define MixerCtrls_828MkII MixerCtrls_Traveler
283 #define MixerCtrls_896HD   MixerCtrls_Traveler
284
285 /* The order of DevicesProperty entries must match the numeric order of the
286  * MOTU model enumeration (EMotuModel).
287  */
288 const DevicePropertyEntry DevicesProperty[] = {
289 //  { Ports_map,       N_ELEMENTS( Ports_map ),        MaxSR },
290     { Ports_828MKII,   N_ELEMENTS( Ports_828MKII ),    96000, MixerCtrls_828MkII, N_ELEMENTS(MixerCtrls_828MkII), },
291     { Ports_TRAVELER,  N_ELEMENTS( Ports_TRAVELER ),  192000, MixerCtrls_Traveler, N_ELEMENTS(MixerCtrls_Traveler), },
292     { Ports_ULTRALITE, N_ELEMENTS( Ports_ULTRALITE ),  96000 },
293     { Ports_8PRE,      N_ELEMENTS( Ports_8PRE ),       96000 },
294     { Ports_828MKI,    N_ELEMENTS( Ports_828MKI ),     48000 },
295     { Ports_896HD,     N_ELEMENTS( Ports_896HD ),     192000, MixerCtrls_896HD, N_ELEMENTS(MixerCtrls_896HD),  },
296 };
297
298 MotuDevice::MotuDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
299     : FFADODevice( d, configRom )
300     , m_motu_model( MOTU_MODEL_NONE )
301     , m_iso_recv_channel ( -1 )
302     , m_iso_send_channel ( -1 )
303     , m_rx_bandwidth ( -1 )
304     , m_tx_bandwidth ( -1 )
305     , m_receiveProcessor ( 0 )
306     , m_transmitProcessor ( 0 )
307     , m_MixerContainer ( NULL )
308     , m_ControlContainer ( NULL )
309 {
310     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
311                  getConfigRom().getNodeId() );
312 }
313
314 MotuDevice::~MotuDevice()
315 {
316     delete m_receiveProcessor;
317     delete m_transmitProcessor;
318
319     // Free ieee1394 bus resources if they have been allocated
320     if (m_iso_recv_channel>=0 && !get1394Service().freeIsoChannel(m_iso_recv_channel)) {
321         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
322     }
323     if (m_iso_send_channel>=0 && !get1394Service().freeIsoChannel(m_iso_send_channel)) {
324         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
325     }
326
327     destroyMixer();
328 }
329
330 bool
331 MotuDevice::buildMixer() {
332     unsigned int i;
333     bool result = true;
334     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a MOTU mixer...\n");
335
336     destroyMixer();
337        
338     // create the mixer object container
339     m_MixerContainer = new Control::Container("Mixer");
340     if (!m_MixerContainer) {
341         debugError("Could not create mixer container...\n");
342         return false;
343     }
344
345     // Mixer controls get added here
346     for (i=0; i<DevicesProperty[m_motu_model-1].n_mixer_ctrls; i++) {
347         unsigned int type = DevicesProperty[m_motu_model-1].mixer_ctrl[i].type;
348         char name[100];
349         char label[100];
350         if (type & MOTU_CTRL_CHANNEL_FADER) {
351             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "fader");
352             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"fader");
353             result &= m_MixerContainer->addElement(
354                 new ChannelFader(*this,
355                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
356                     name, label,
357                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
358             type &= ~MOTU_CTRL_CHANNEL_FADER;
359         }
360         if (type & MOTU_CTRL_CHANNEL_PAN) {
361             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "pan");
362             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"pan");
363             result &= m_MixerContainer->addElement(
364                 new ChannelPan(*this,
365                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
366                     name, label,
367                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
368             type &= ~MOTU_CTRL_CHANNEL_PAN;
369         }
370         if (type & MOTU_CTRL_CHANNEL_MUTE) {
371             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "mute");
372             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"mute");
373             result &= m_MixerContainer->addElement(
374                 new MotuBinarySwitch(*this,
375                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
376                     MOTU_CTRL_MASK_MUTE_VALUE, MOTU_CTRL_MASK_MUTE_SETENABLE,
377                     name, label,
378                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
379             type &= ~MOTU_CTRL_CHANNEL_MUTE;
380         }
381         if (type & MOTU_CTRL_CHANNEL_SOLO) {
382             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "solo");
383             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"solo");
384             result &= m_MixerContainer->addElement(
385                 new MotuBinarySwitch(*this,
386                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
387                     MOTU_CTRL_MASK_SOLO_VALUE, MOTU_CTRL_MASK_SOLO_SETENABLE,
388                     name, label,
389                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
390             type &= ~MOTU_CTRL_CHANNEL_SOLO;
391         }
392
393         if (type & MOTU_CTRL_MIX_FADER) {
394             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "fader");
395             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"fader");
396             result &= m_MixerContainer->addElement(
397                 new MixFader(*this,
398                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
399                     name, label,
400                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
401             type &= ~MOTU_CTRL_MIX_FADER;
402         }
403         if (type & MOTU_CTRL_MIX_MUTE) {
404             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "mute");
405             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"mute");
406             result &= m_MixerContainer->addElement(
407                 new MixMute(*this,
408                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
409                     name, label,
410                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
411             type &= ~MOTU_CTRL_MIX_MUTE;
412         }
413         if (type & MOTU_CTRL_MIX_DEST) {
414             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "dest");
415             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"dest");
416             result &= m_MixerContainer->addElement(
417                 new MixDest(*this,
418                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
419                     name, label,
420                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
421             type &= ~MOTU_CTRL_MIX_DEST;
422         }
423
424         if (type & MOTU_CTRL_INPUT_TRIMGAIN) {
425             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "trimgain");
426             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"trimgain");
427             result &= m_MixerContainer->addElement(
428                 new InputGainPad(*this,
429                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register, MOTU_CTRL_MODE_TRIMGAIN,
430                     name, label,
431                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
432             type &= ~MOTU_CTRL_INPUT_TRIMGAIN;
433         }
434         if (type & MOTU_CTRL_INPUT_PAD) {
435             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "pad");
436             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"pad");
437             result &= m_MixerContainer->addElement(
438                 new InputGainPad(*this,
439                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register, MOTU_CTRL_MODE_PAD,
440                     name, label,
441                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
442             type &= ~MOTU_CTRL_INPUT_PAD;
443         }
444
445         if (type & MOTU_CTRL_INPUT_LEVEL) {
446             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "level");
447             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"level");
448             result &= m_MixerContainer->addElement(
449                 new MotuBinarySwitch(*this,
450                     MOTU_REG_INPUT_LEVEL,
451                     1<<DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register, 0,
452                     name, label,
453                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
454             type &= ~MOTU_CTRL_INPUT_LEVEL;
455         }
456         if (type & MOTU_CTRL_INPUT_BOOST) {
457             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "boost");
458             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"boost");
459             result &= m_MixerContainer->addElement(
460                 new MotuBinarySwitch(*this,
461                     MOTU_REG_INPUT_BOOST,
462                     1<<DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register, 0,
463                     name, label,
464                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
465             type &= ~MOTU_CTRL_INPUT_BOOST;
466         }
467         if (type & MOTU_CTRL_PHONES_SRC) {
468             snprintf(name, 100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].name, "src");
469             snprintf(label,100, "%s%s", DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,"src");
470             result &= m_MixerContainer->addElement(
471                 new PhonesSrc(*this,
472                     name, label,
473                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
474             type &= ~MOTU_CTRL_PHONES_SRC;
475         }
476         if (type & MOTU_CTRL_OPTICAL_MODE) {
477             result &= m_MixerContainer->addElement(
478                 new OpticalMode(*this, DevicesProperty[m_motu_model-1].mixer_ctrl[i].dev_register,
479                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].name,
480                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].label,
481                     DevicesProperty[m_motu_model-1].mixer_ctrl[i].desc));
482             type &= ~MOTU_CTRL_OPTICAL_MODE;
483         }
484
485         if (type) {
486             debugOutput(DEBUG_LEVEL_VERBOSE, "Unknown mixer control type flag bits 0x%08x\n", DevicesProperty[m_motu_model-1].mixer_ctrl[i].type);
487         }
488     }
489
490     /* Now add some general device information controls.  These may yet
491      * become device-specific if it turns out to be easier that way.
492      */
493     result &= m_MixerContainer->addElement(
494         new InfoElement(*this, MOTU_INFO_IS_STREAMING, "Info/IsStreaming", "Is device streaming", ""));
495     result &= m_MixerContainer->addElement(
496         new InfoElement(*this, MOTU_INFO_SAMPLE_RATE, "Info/SampleRate", "Device sample rate", ""));
497     result &= m_MixerContainer->addElement(
498         new InfoElement(*this, MOTU_INFO_HAS_MIC_INPUTS, "Info/HasMicInputs", "Device has mic inputs", ""));
499     result &= m_MixerContainer->addElement(
500         new InfoElement(*this, MOTU_INFO_HAS_AESEBU_INPUTS, "Info/HasAESEBUInputs", "Device has AES/EBU inputs", ""));
501     result &= m_MixerContainer->addElement(
502         new InfoElement(*this, MOTU_INFO_HAS_SPDIF_INPUTS, "Info/HasSPDIFInputs", "Device has SPDIF inputs", ""));
503     result &= m_MixerContainer->addElement(
504         new InfoElement(*this, MOTU_INFO_HAS_OPTICAL_SPDIF, "Info/HasOpticalSPDIF", "Device has Optical SPDIF", ""));
505
506     if (!addElement(m_MixerContainer)) {
507         debugWarning("Could not register mixer to device\n");
508         // clean up
509         destroyMixer();
510         return false;
511     }
512
513     // Special controls
514     m_ControlContainer = new Control::Container("Control");
515     if (!m_ControlContainer) {
516         debugError("Could not create control container...\n");
517         return false;
518     }
519
520     // Special controls get added here
521
522     if (!result) {
523         debugWarning("One or more device control elements could not be created.");
524         // clean up those that couldn't be created
525         destroyMixer();
526         return false;
527     }
528     if (!addElement(m_ControlContainer)) {
529         debugWarning("Could not register controls to device\n");
530         // clean up
531         destroyMixer();
532         return false;
533     }
534
535     return true;
536 }
537
538
539 bool
540 MotuDevice::destroyMixer() {
541     debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
542
543     if (m_MixerContainer == NULL) {
544         debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
545         return true;
546     }
547    
548     if (!deleteElement(m_MixerContainer)) {
549         debugError("Mixer present but not registered to the avdevice\n");
550         return false;
551     }
552
553     // remove and delete (as in free) child control elements
554     m_MixerContainer->clearElements(true);
555     delete m_MixerContainer;
556     m_MixerContainer = NULL;
557
558     // remove control container
559     if (m_ControlContainer == NULL) {
560         debugOutput(DEBUG_LEVEL_VERBOSE, "no controls to destroy...\n");
561         return true;
562     }
563    
564     if (!deleteElement(m_ControlContainer)) {
565         debugError("Controls present but not registered to the avdevice\n");
566         return false;
567     }
568    
569     // remove and delete (as in free) child control elements
570     m_ControlContainer->clearElements(true);
571     delete m_ControlContainer;
572     m_ControlContainer = NULL;
573
574     return true;
575 }
576
577 bool
578 MotuDevice::probe( ConfigRom& configRom )
579 {
580     unsigned int vendorId = configRom.getNodeVendorId();
581     unsigned int unitVersion = configRom.getUnitVersion();
582     unsigned int unitSpecifierId = configRom.getUnitSpecifierId();
583
584     for ( unsigned int i = 0;
585           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
586           ++i )
587     {
588         if ( ( supportedDeviceList[i].vendor_id == vendorId )
589              && ( supportedDeviceList[i].unit_version == unitVersion )
590              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
591            )
592         {
593             return true;
594         }
595     }
596
597     return false;
598 }
599
600 FFADODevice *
601 MotuDevice::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
602 {
603     return new MotuDevice(d, configRom);
604 }
605
606 bool
607 MotuDevice::discover()
608 {
609     unsigned int vendorId = getConfigRom().getNodeVendorId();
610     unsigned int unitVersion = getConfigRom().getUnitVersion();
611     unsigned int unitSpecifierId = getConfigRom().getUnitSpecifierId();
612
613     for ( unsigned int i = 0;
614           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
615           ++i )
616     {
617         if ( ( supportedDeviceList[i].vendor_id == vendorId )
618              && ( supportedDeviceList[i].unit_version == unitVersion )
619              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
620            )
621         {
622             m_model = &(supportedDeviceList[i]);
623             m_motu_model=supportedDeviceList[i].model;
624         }
625     }
626
627     if (m_model == NULL) {
628         return false;
629     }
630
631     debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
632         m_model->vendor_name, m_model->model_name);
633
634     if (!buildMixer()) {
635         debugWarning("Could not build mixer\n");
636     }
637
638     return true;
639 }
640
641 int
642 MotuDevice::getSamplingFrequency( ) {
643 /*
644  * Retrieve the current sample rate from the MOTU device.
645  */
646     quadlet_t q = ReadRegister(MOTU_REG_CLK_CTRL);
647     int rate = 0;
648
649     switch (q & MOTU_RATE_BASE_MASK) {
650         case MOTU_RATE_BASE_44100:
651             rate = 44100;
652             break;
653         case MOTU_RATE_BASE_48000:
654             rate = 48000;
655             break;
656     }
657     switch (q & MOTU_RATE_MULTIPLIER_MASK) {
658         case MOTU_RATE_MULTIPLIER_2X:
659             rate *= 2;
660             break;
661         case MOTU_RATE_MULTIPLIER_4X:
662             rate *= 4;
663             break;
664     }
665     return rate;
666 }
667
668 int
669 MotuDevice::getConfigurationId()
670 {
671     return 0;
672 }
673
674 bool
675 MotuDevice::setSamplingFrequency( int samplingFrequency )
676 {
677 /*
678  * Set the MOTU device's samplerate.
679  */
680     char *src_name;
681     quadlet_t q, new_rate=0;
682     int i, supported=true, cancel_adat=false;
683
684     if ( samplingFrequency > DevicesProperty[m_motu_model-1].MaxSampleRate )
685        return false;
686
687     switch ( samplingFrequency ) {
688         case 22050:
689         case 24000:
690         case 32000:
691             supported=false;
692             break;
693         case 44100:
694             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_1X;
695             break;
696         case 48000:
697             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_1X;
698             break;
699         case 88200:
700             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_2X;
701             break;
702         case 96000:
703             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_2X;
704             break;
705         case 176400:
706             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_4X;
707             cancel_adat = true;  // current ADAT protocol doesn't support sample rate > 96000
708             break;
709         case 192000:
710             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_4X;
711             cancel_adat = true;
712             break;
713         default:
714             supported=false;
715     }
716
717     // Update the clock control register.  FIXME: while this is now rather
718     // comprehensive there may still be a need to manipulate MOTU_REG_CLK_CTRL
719     // a little more than we do.
720     if (supported) {
721         quadlet_t value=ReadRegister(MOTU_REG_CLK_CTRL);
722
723         // If optical port must be disabled (because a 4x sample rate has
724         // been selected) then do so before changing the sample rate.  At
725         // this stage it will be up to the user to re-enable the optical
726         // port if the sample rate is set to a 1x or 2x rate later.
727         if (cancel_adat) {
728             setOpticalMode(MOTU_DIR_INOUT, MOTU_OPTICAL_MODE_OFF);
729         }
730
731         value &= ~(MOTU_RATE_BASE_MASK|MOTU_RATE_MULTIPLIER_MASK);
732         value |= new_rate;
733
734         // In other OSes bit 26 of MOTU_REG_CLK_CTRL always seems
735         // to be set when this register is written to although the
736         // reason isn't currently known.  When we set it, it appears
737         // to prevent output being produced so we'll leave it unset
738         // until we work out what's going on.  Other systems write
739         // to MOTU_REG_CLK_CTRL multiple times, so that may be
740         // part of the mystery.
741         //   value |= 0x04000000;
742         if (WriteRegister(MOTU_REG_CLK_CTRL, value) == 0) {
743             supported=true;
744         } else {
745             supported=false;
746         }
747         // A write to the rate/clock control register requires the
748         // textual name of the current clock source be sent to the
749         // clock source name registers.
750         switch (value & MOTU_CLKSRC_MASK) {
751             case MOTU_CLKSRC_INTERNAL:
752                 src_name = "Internal        ";
753                 break;
754             case MOTU_CLKSRC_ADAT_OPTICAL:
755                 src_name = "ADAT Optical    ";
756                 break;
757             case MOTU_CLKSRC_SPDIF_TOSLINK:
758                 if (getOpticalMode(MOTU_DIR_IN)  == MOTU_OPTICAL_MODE_TOSLINK)
759                     src_name = "TOSLink         ";
760                 else
761                     src_name = "SPDIF           ";
762                 break;
763             case MOTU_CLKSRC_SMTPE:
764                 src_name = "SMPTE           ";
765                 break;
766             case MOTU_CLKSRC_WORDCLOCK:
767                 src_name = "Word Clock In   ";
768                 break;
769             case MOTU_CLKSRC_ADAT_9PIN:
770                 src_name = "ADAT 9-pin      ";
771                 break;
772             case MOTU_CLKSRC_AES_EBU:
773                 src_name = "AES-EBU         ";
774                 break;
775             default:
776                 src_name = "Unknown         ";
777         }
778         for (i=0; i<16; i+=4) {
779             q = (src_name[i]<<24) | (src_name[i+1]<<16) |
780                 (src_name[i+2]<<8) | src_name[i+3];
781             WriteRegister(MOTU_REG_CLKSRC_NAME0+i, q);
782         }
783     }
784     return supported;
785 }
786
787 FFADODevice::ClockSourceVector
788 MotuDevice::getSupportedClockSources() {
789     FFADODevice::ClockSourceVector r;
790     return r;
791 }
792
793 bool
794 MotuDevice::setActiveClockSource(ClockSource s) {
795     return false;
796 }
797
798 FFADODevice::ClockSource
799 MotuDevice::getActiveClockSource() {
800     ClockSource s;
801     return s;
802 }
803
804 bool
805 MotuDevice::lock() {
806
807     return true;
808 }
809
810
811 bool
812 MotuDevice::unlock() {
813
814     return true;
815 }
816
817 void
818 MotuDevice::showDevice()
819 {
820     debugOutput(DEBUG_LEVEL_VERBOSE,
821         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
822         getNodeId());
823 }
824
825 bool
826 MotuDevice::prepare() {
827
828     int samp_freq = getSamplingFrequency();
829     unsigned int optical_in_mode = getOpticalMode(MOTU_DIR_IN);
830     unsigned int optical_out_mode = getOpticalMode(MOTU_DIR_OUT);
831     unsigned int event_size_in = getEventSize(MOTU_DIR_IN);
832     unsigned int event_size_out= getEventSize(MOTU_DIR_OUT);
833
834     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
835
836     // Allocate bandwidth if not previously done.
837     // FIXME: The bandwidth allocation calculation can probably be
838     // refined somewhat since this is currently based on a rudimentary
839     // understanding of the ieee1394 iso protocol.
840     // Currently we assume the following.
841     //   * Ack/iso gap = 0.05 us
842     //   * DATA_PREFIX = 0.16 us
843     //   * DATA_END    = 0.26 us
844     // These numbers are the worst-case figures given in the ieee1394
845     // standard.  This gives approximately 0.5 us of overheads per packet -
846     // around 25 bandwidth allocation units (from the ieee1394 standard 1
847     // bandwidth allocation unit is 125/6144 us).  We further assume the
848     // MOTU is running at S400 (which it should be) so one allocation unit
849     // is equivalent to 1 transmitted byte; thus the bandwidth allocation
850     // required for the packets themselves is just the size of the packet.
851     // We used to allocate based on the maximum packet size (1160 bytes at
852     // 192 kHz for the traveler) but now do this based on the actual device
853     // state by utilising the result from getEventSize() and remembering
854     // that each packet has an 8 byte CIP header.  Note that bandwidth is
855     // allocated on a *per stream* basis - it must be allocated for both the
856     // transmit and receive streams.  While most MOTU modules are close to
857     // symmetric in terms of the number of in/out channels there are
858     // exceptions, so we deal with receive and transmit bandwidth separately.
859     signed int n_events_per_packet = samp_freq<=48000?8:(samp_freq<=96000?16:32);
860     m_rx_bandwidth = 25 + (n_events_per_packet*event_size_in);
861     m_tx_bandwidth = 25 + (n_events_per_packet*event_size_out);
862
863     // Assign iso channels if not already done
864     if (m_iso_recv_channel < 0)
865         m_iso_recv_channel = get1394Service().allocateIsoChannelGeneric(m_rx_bandwidth);
866
867     if (m_iso_send_channel < 0)
868         m_iso_send_channel = get1394Service().allocateIsoChannelGeneric(m_tx_bandwidth);
869
870     debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
871         m_iso_recv_channel, m_iso_send_channel);
872
873     if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
874         // be nice and deallocate
875         if (m_iso_recv_channel >= 0)
876             get1394Service().freeIsoChannel(m_iso_recv_channel);
877         if (m_iso_send_channel >= 0)
878             get1394Service().freeIsoChannel(m_iso_send_channel);
879
880         debugFatal("Could not allocate iso channels!\n");
881         return false;
882     }
883
884     m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor(*this, event_size_in);
885
886     // The first thing is to initialize the processor.  This creates the
887     // data structures.
888     if(!m_receiveProcessor->init()) {
889         debugFatal("Could not initialize receive processor!\n");
890         return false;
891     }
892     m_receiveProcessor->setVerboseLevel(getDebugLevel());
893
894     // Now we add ports to the processor
895     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
896
897     char *buff;
898     Streaming::Port *p=NULL;
899
900     // retrieve the ID
901     std::string id=std::string("dev?");
902     if(!getOption("id", id)) {
903         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
904     }
905
906     // Add audio capture ports
907     if (!addDirPorts(Streaming::Port::E_Capture, samp_freq, optical_in_mode)) {
908         return false;
909     }
910
911     // Add MIDI port.  The MOTU only has one MIDI input port, with each
912     // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
913     // event data.
914     asprintf(&buff,"%s_cap_MIDI0",id.c_str());
915     p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff,
916         Streaming::Port::E_Capture, 4);
917     if (!p) {
918         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
919     }
920     free(buff);
921
922     // example of adding an control port:
923 //    asprintf(&buff,"%s_cap_%s",id.c_str(),"myportnamehere");
924 //    p=new Streaming::MotuControlPort(
925 //            buff,
926 //            Streaming::Port::E_Capture,
927 //            0 // you can add all other port specific stuff you
928 //              // need to pass by extending MotuXXXPort and MotuPortInfo
929 //    );
930 //    free(buff);
931 //
932 //    if (!p) {
933 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
934 //    } else {
935 //
936 //        if (!m_receiveProcessor->addPort(p)) {
937 //            debugWarning("Could not register port with stream processor\n");
938 //            return false;
939 //        } else {
940 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
941 //        }
942 //    }
943
944     // Do the same for the transmit processor
945     m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor(*this, event_size_out);
946
947     m_transmitProcessor->setVerboseLevel(getDebugLevel());
948
949     if(!m_transmitProcessor->init()) {
950         debugFatal("Could not initialize transmit processor!\n");
951         return false;
952     }
953
954     // Now we add ports to the processor
955     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
956
957     // Add audio playback ports
958     if (!addDirPorts(Streaming::Port::E_Playback, samp_freq, optical_out_mode)) {
959         return false;
960     }
961
962     // Add MIDI port.  The MOTU only has one output MIDI port, with each
963     // MIDI byte transmitted using a 3 byte sequence starting at byte 4
964     // of the event data.
965     asprintf(&buff,"%s_pbk_MIDI0",id.c_str());
966     p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff,
967         Streaming::Port::E_Capture, 4);
968     if (!p) {
969         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
970     }
971     free(buff);
972
973     // example of adding an control port:
974 //    asprintf(&buff,"%s_pbk_%s",id.c_str(),"myportnamehere");
975 //
976 //    p=new Streaming::MotuControlPort(
977 //            buff,
978 //            Streaming::Port::E_Playback,
979 //            0 // you can add all other port specific stuff you
980 //              // need to pass by extending MotuXXXPort and MotuPortInfo
981 //    );
982 //    free(buff);
983 //
984 //    if (!p) {
985 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
986 //    } else {
987 //        if (!m_transmitProcessor->addPort(p)) {
988 //            debugWarning("Could not register port with stream processor\n");
989 //            return false;
990 //        } else {
991 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
992 //        }
993 //    }
994
995     return true;
996 }
997
998 int
999 MotuDevice::getStreamCount() {
1000      return 2; // one receive, one transmit
1001 }
1002
1003 Streaming::StreamProcessor *
1004 MotuDevice::getStreamProcessorByIndex(int i) {
1005     switch (i) {
1006     case 0:
1007         return m_receiveProcessor;
1008     case 1:
1009          return m_transmitProcessor;
1010     default:
1011         return NULL;
1012     }
1013     return 0;
1014 }
1015
1016 bool
1017 MotuDevice::startStreamByIndex(int i) {
1018
1019 quadlet_t isoctrl = ReadRegister(MOTU_REG_ISOCTRL);
1020
1021     // NOTE: this assumes that you have two streams
1022     switch (i) {
1023     case 0:
1024         // TODO: do the stuff that is nescessary to make the device
1025         // receive a stream
1026
1027         // Set the streamprocessor channel to the one obtained by
1028         // the connection management
1029         m_receiveProcessor->setChannel(m_iso_recv_channel);
1030
1031         // Mask out current transmit settings of the MOTU and replace
1032         // with new ones.  Turn bit 24 on to enable changes to the
1033         // MOTU's iso transmit settings when the iso control register
1034         // is written.  Bit 23 enables iso transmit from the MOTU.
1035         isoctrl &= 0xff00ffff;
1036         isoctrl |= (m_iso_recv_channel << 16);
1037         isoctrl |= 0x00c00000;
1038         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1039         break;
1040     case 1:
1041         // TODO: do the stuff that is nescessary to make the device
1042         // transmit a stream
1043
1044         // Set the streamprocessor channel to the one obtained by
1045         // the connection management
1046         m_transmitProcessor->setChannel(m_iso_send_channel);
1047
1048         // Mask out current receive settings of the MOTU and replace
1049         // with new ones.  Turn bit 31 on to enable changes to the
1050         // MOTU's iso receive settings when the iso control register
1051         // is written.  Bit 30 enables iso receive by the MOTU.
1052         isoctrl &= 0x00ffffff;
1053         isoctrl |= (m_iso_send_channel << 24);
1054         isoctrl |= 0xc0000000;
1055         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1056         break;
1057
1058     default: // Invalid stream index
1059         return false;
1060     }
1061
1062     return true;
1063 }
1064
1065 bool
1066 MotuDevice::stopStreamByIndex(int i) {
1067
1068 quadlet_t isoctrl = ReadRegister(MOTU_REG_ISOCTRL);
1069
1070     // TODO: connection management: break connection
1071     // cfr the start function
1072
1073     // NOTE: this assumes that you have two streams
1074     switch (i) {
1075     case 0:
1076         // Turn bit 22 off to disable iso send by the MOTU.  Turn
1077         // bit 23 on to enable changes to the MOTU's iso transmit
1078         // settings when the iso control register is written.
1079         isoctrl &= 0xffbfffff;
1080         isoctrl |= 0x00800000;
1081         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1082         break;
1083     case 1:
1084         // Turn bit 30 off to disable iso receive by the MOTU.  Turn
1085         // bit 31 on to enable changes to the MOTU's iso receive
1086         // settings when the iso control register is written.
1087         isoctrl &= 0xbfffffff;
1088         isoctrl |= 0x80000000;
1089         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1090         break;
1091
1092     default: // Invalid stream index
1093         return false;
1094     }
1095
1096     return true;
1097 }
1098
1099 signed int MotuDevice::getIsoRecvChannel(void) {
1100     return m_iso_recv_channel;
1101 }
1102
1103 signed int MotuDevice::getIsoSendChannel(void) {
1104     return m_iso_send_channel;
1105 }
1106
1107 unsigned int MotuDevice::getOpticalMode(unsigned int dir) {
1108     unsigned int reg = ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
1109
1110 debugOutput(DEBUG_LEVEL_VERBOSE, "optical mode: %x %x %x %x\n",dir, reg, reg & MOTU_OPTICAL_IN_MODE_MASK,
1111 reg & MOTU_OPTICAL_OUT_MODE_MASK);
1112
1113     if (dir == MOTU_DIR_IN)
1114         return (reg & MOTU_OPTICAL_IN_MODE_MASK) >> 8;
1115     else
1116         return (reg & MOTU_OPTICAL_OUT_MODE_MASK) >> 10;
1117 }
1118
1119 signed int MotuDevice::setOpticalMode(unsigned int dir, unsigned int mode) {
1120     unsigned int reg = ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
1121     unsigned int opt_ctrl = 0x0000002;
1122
1123     /* THe 896HD doesn't have an SPDIF/TOSLINK optical mode, so don't try to
1124      * set it
1125      */
1126     if (m_motu_model==MOTU_MODEL_896HD && mode==MOTU_OPTICAL_MODE_TOSLINK)
1127         return -1;
1128
1129     // Set up the optical control register value according to the current
1130     // optical port modes.  At this stage it's not completely understood
1131     // what the "Optical control" register does, so the values it's set to
1132     // are more or less "magic" numbers.
1133     if (reg & MOTU_OPTICAL_IN_MODE_MASK != (MOTU_OPTICAL_MODE_ADAT<<8))
1134         opt_ctrl |= 0x00000080;
1135     if (reg & MOTU_OPTICAL_OUT_MODE_MASK != (MOTU_OPTICAL_MODE_ADAT<<10))
1136         opt_ctrl |= 0x00000040;
1137
1138     if (mode & MOTU_DIR_IN) {
1139         reg &= ~MOTU_OPTICAL_IN_MODE_MASK;
1140         reg |= (mode << 8) & MOTU_OPTICAL_IN_MODE_MASK;
1141         if (mode != MOTU_OPTICAL_MODE_ADAT)
1142             opt_ctrl |= 0x00000080;
1143         else
1144             opt_ctrl &= ~0x00000080;
1145     }
1146     if (mode & MOTU_DIR_OUT) {
1147         reg &= ~MOTU_OPTICAL_OUT_MODE_MASK;
1148         reg |= (mode <<10) & MOTU_OPTICAL_OUT_MODE_MASK;
1149         if (mode != MOTU_OPTICAL_MODE_ADAT)
1150             opt_ctrl |= 0x00000040;
1151         else
1152             opt_ctrl &= ~0x00000040;
1153     }
1154
1155     // FIXME: there seems to be more to it than this, but for
1156     // the moment at least this seems to work.
1157     WriteRegister(MOTU_REG_ROUTE_PORT_CONF, reg);
1158     return WriteRegister(MOTU_REG_OPTICAL_CTRL, opt_ctrl);
1159 }
1160
1161 signed int MotuDevice::getEventSize(unsigned int direction) {
1162 //
1163 // Return the size in bytes of a single event sent to (dir==MOTU_OUT) or
1164 // from (dir==MOTU_IN) the MOTU as part of an iso data packet.
1165 //
1166 // FIXME: for performance it may turn out best to calculate the event
1167 // size in setOpticalMode and cache the result in a data field.  However,
1168 // as it stands this will not adapt to dynamic changes in sample rate - we'd
1169 // need a setFrameRate() for that.
1170 //
1171 // At the very least an event consists of the SPH (4 bytes) and the control/MIDI
1172 // bytes (6 bytes).
1173 // Note that all audio channels are sent using 3 bytes.
1174 signed int sample_rate = getSamplingFrequency();
1175 signed int optical_mode = getOpticalMode(direction);
1176 signed int size = 4+6;
1177
1178 unsigned int i;
1179 unsigned int dir = direction==Streaming::Port::E_Capture?MOTU_DIR_IN:MOTU_DIR_OUT;
1180 unsigned int flags = (1 << ( optical_mode + 4 ));
1181
1182     if ( sample_rate > 96000 )
1183         flags |= MOTU_PA_RATE_4x;
1184     else if ( sample_rate > 48000 )
1185         flags |= MOTU_PA_RATE_2x;
1186     else
1187         flags |= MOTU_PA_RATE_1x;
1188
1189     for (i=0; i < DevicesProperty[m_motu_model-1].n_port_entries; i++) {
1190         if (( DevicesProperty[m_motu_model-1].port_entry[i].port_dir & dir ) &&
1191            ( DevicesProperty[m_motu_model-1].port_entry[i].port_flags & MOTU_PA_RATE_MASK & flags ) &&
1192            ( DevicesProperty[m_motu_model-1].port_entry[i].port_flags & MOTU_PA_OPTICAL_MASK & flags )) {
1193             size += 3;
1194         }
1195     }
1196
1197     // Finally round size up to the next quadlet boundary
1198     return ((size+3)/4)*4;
1199 }
1200 /* ======================================================================= */
1201
1202 bool MotuDevice::addPort(Streaming::StreamProcessor *s_processor,
1203   char *name, enum Streaming::Port::E_Direction direction,
1204   int position, int size) {
1205 /*
1206  * Internal helper function to add a MOTU port to a given stream processor.
1207  * This just saves the unnecessary replication of what is essentially
1208  * boilerplate code.  Note that the port name is freed by this function
1209  * prior to exit.
1210  */
1211 Streaming::Port *p=NULL;
1212
1213     p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size);
1214
1215     if (!p) {
1216         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
1217     }
1218     free(name);
1219     return true;
1220 }
1221 /* ======================================================================= */
1222
1223 bool MotuDevice::addDirPorts(
1224   enum Streaming::Port::E_Direction direction,
1225   unsigned int sample_rate, unsigned int optical_mode) {
1226 /*
1227  * Internal helper method: adds all required ports for the given direction
1228  * based on the indicated sample rate and optical mode.
1229  *
1230  * Notes: currently ports are not created if they are disabled due to sample
1231  * rate or optical mode.  However, it might be better to unconditionally
1232  * create all ports and just disable those which are not active.
1233  */
1234 const char *mode_str = direction==Streaming::Port::E_Capture?"cap":"pbk";
1235 Streaming::StreamProcessor *s_processor;
1236 unsigned int i;
1237 char *buff;
1238 unsigned int dir = direction==Streaming::Port::E_Capture?MOTU_DIR_IN:MOTU_DIR_OUT;
1239 unsigned int flags = (1 << ( optical_mode + 4 ));
1240
1241     if ( sample_rate > 96000 )
1242         flags |= MOTU_PA_RATE_4x;
1243     else if ( sample_rate > 48000 )
1244         flags |= MOTU_PA_RATE_2x;
1245     else
1246         flags |= MOTU_PA_RATE_1x;
1247
1248     // retrieve the ID
1249     std::string id=std::string("dev?");
1250     if(!getOption("id", id)) {
1251         debugWarning("Could not retrieve id parameter, defaulting to 'dev?'\n");
1252     }
1253
1254     if (direction == Streaming::Port::E_Capture) {
1255         s_processor = m_receiveProcessor;
1256     } else {
1257         s_processor = m_transmitProcessor;
1258     }
1259
1260     for (i=0; i < DevicesProperty[m_motu_model-1].n_port_entries; i++) {
1261         if (( DevicesProperty[m_motu_model-1].port_entry[i].port_dir & dir ) &&
1262            ( DevicesProperty[m_motu_model-1].port_entry[i].port_flags & MOTU_PA_RATE_MASK & flags ) &&
1263            ( DevicesProperty[m_motu_model-1].port_entry[i].port_flags & MOTU_PA_OPTICAL_MASK & flags )) {
1264             asprintf(&buff,"%s_%s_%s" , id.c_str(), mode_str,
1265               DevicesProperty[m_motu_model-1].port_entry[i].port_name);
1266             if (!addPort(s_processor, buff, direction, DevicesProperty[m_motu_model-1].port_entry[i].port_offset, 0))
1267                 return false;
1268         }
1269     }
1270    
1271     return true;
1272 }
1273 /* ======================================================================== */
1274
1275 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
1276 /*
1277  * Attempts to read the requested register from the MOTU.
1278  */
1279
1280   quadlet_t quadlet;
1281
1282   quadlet = 0;
1283   // Note: 1394Service::read() expects a physical ID, not the node id
1284   if (get1394Service().read(0xffc0 | getNodeId(), MOTU_BASE_ADDR+reg, 1, &quadlet) < 0) {
1285     debugError("Error doing motu read from register 0x%06x\n",reg);
1286   }
1287
1288   return ntohl(quadlet);
1289 }
1290
1291 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
1292 /*
1293  * Attempts to write the given data to the requested MOTU register.
1294  */
1295
1296   unsigned int err = 0;
1297   data = htonl(data);
1298
1299   // Note: 1394Service::write() expects a physical ID, not the node id
1300   if (get1394Service().write(0xffc0 | getNodeId(), MOTU_BASE_ADDR+reg, 1, &data) < 0) {
1301     err = 1;
1302     debugError("Error doing motu write to register 0x%06x\n",reg);
1303   }
1304
1305   SleepRelativeUsec(100);
1306   return (err==0)?0:-1;
1307 }
1308
1309 }
Note: See TracBrowser for help on using the browser.