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

Revision 1837, 81.0 kB (checked in by jwoithe, 11 years ago)

MOTU: 8pre: disable the phones / main fader mixer widgets because these controls are not software controllable on the 8pre and thus aren't accessible via the dbus interface.
MOTU: 8pre: add pad controls to the channel matrix mixers so the ADAT controls show up at the same place in the matrix mixers as they do on other devices. See also r1384 where a similar issue was addressed for the Ultralite.
MOTU: 8pre: add some pad channels to enlarge the 1x rate data packets to the sizes seen under other systems.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2009 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 "config.h"
26
27 #include "motu/motu_avdevice.h"
28 #include "motu/motu_mixerdefs.h"
29 #include "motu/motu_mark3_mixerdefs.h"
30
31 #include "devicemanager.h"
32
33 #include "libieee1394/configrom.h"
34 #include "libieee1394/ieee1394service.h"
35
36 #include "libavc/avc_definitions.h"
37
38 #include "debugmodule/debugmodule.h"
39
40 #include "libstreaming/motu/MotuReceiveStreamProcessor.h"
41 #include "libstreaming/motu/MotuTransmitStreamProcessor.h"
42 #include "libstreaming/motu/MotuPort.h"
43
44 #include "libutil/Time.h"
45 #include "libutil/Configuration.h"
46
47 #include "libcontrol/BasicElements.h"
48
49 #include <string>
50 #include <stdint.h>
51 #include <assert.h>
52 #include "libutil/ByteSwap.h"
53 #include <iostream>
54 #include <sstream>
55
56 #include <libraw1394/csr.h>
57
58 namespace Motu {
59
60 // Define the supported devices.  Device ordering is arbitary here.
61 static VendorModelEntry supportedDeviceList[] =
62 {
63 //  {vendor_id, model_id, unit_version, unit_specifier_id, model, vendor_name,model_name}
64     {FW_VENDORID_MOTU, 0, 0x00000003, 0x000001f2, MOTU_MODEL_828mkII, "MOTU", "828MkII"},
65     {FW_VENDORID_MOTU, 0, 0x00000009, 0x000001f2, MOTU_MODEL_TRAVELER, "MOTU", "Traveler"},
66     {FW_VENDORID_MOTU, 0, 0x0000000d, 0x000001f2, MOTU_MODEL_ULTRALITE, "MOTU", "UltraLite"},
67     {FW_VENDORID_MOTU, 0, 0x0000000f, 0x000001f2, MOTU_MODEL_8PRE, "MOTU", "8pre"},
68     {FW_VENDORID_MOTU, 0, 0x00000001, 0x000001f2, MOTU_MODEL_828MkI, "MOTU", "828MkI"},
69     {FW_VENDORID_MOTU, 0, 0x00000005, 0x000001f2, MOTU_MODEL_896HD, "MOTU", "896HD"},
70     {FW_VENDORID_MOTU, 0, 0x00000015, 0x000001f2, MOTU_MODEL_828mk3, "MOTU", "828Mk3"},
71     {FW_VENDORID_MOTU, 0, 0x00000019, 0x000001f2, MOTU_MODEL_ULTRALITEmk3, "MOTU", "UltraLineMk3"},
72 };
73
74 // Ports declarations
75 const PortEntry Ports_828MKI[] =
76 {
77     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
78     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
79     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
80     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
81     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
82     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
83     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
84     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
85     {"SPDIF1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
86     {"SPDIF2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
87     {"ADAT1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
88     {"ADAT2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
89     {"ADAT3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 46},
90     {"ADAT4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 49},
91     {"ADAT5", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 52},
92     {"ADAT6", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 55},
93     {"ADAT7", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 58},
94     {"ADAT8", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 61},
95 };
96
97 const PortEntry Ports_896HD[] =
98 {
99     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
100     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
101     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
102     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
103     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 16},
104     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 10},
105     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 19},
106     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 13},
107     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 22},
108     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 16},
109     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 25},
110     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 19},
111     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 28},
112     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 22},
113     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 31},
114     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 25},
115     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 34},
116     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 28},
117     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 37},
118     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 31},
119     {"MainOut-L", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
120     {"MainOut-R", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
121     {"unknown-1", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
122     {"unknown-2", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
123     {"ADAT1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 46},
124     {"ADAT2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 49},
125     {"ADAT3", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 52},
126     {"ADAT4", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 55},
127     {"ADAT5", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 58},
128     {"ADAT6", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 61},
129     {"ADAT7", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
130     {"ADAT8", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
131     // AES/EBU location with ADAT active
132     {"AES/EBU1", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
133     {"AES/EBU2", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
134     {"AES/EBU1", MOTU_PA_INOUT | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT, 58},
135     {"AES/EBU2", MOTU_PA_INOUT | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT, 61},
136     // AES/EBU location with no ADAT active
137     {"AES/EBU1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF, 46},
138     {"AES/EBU2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF, 49},
139 };
140
141 const PortEntry Ports_828MKII[] =
142 {
143     {"Main-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
144     {"Main-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
145     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
146     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
147     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
148     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
149     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
150     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
151     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
152     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
153     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
154     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
155     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
156     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
157     {"Mic1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
158     {"Mic2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
159     {"SPDIF1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 46},
160     {"SPDIF2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 49},
161     {"ADAT1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 52},
162     {"ADAT2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 55},
163     {"ADAT3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 58},
164     {"ADAT4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 61},
165     {"ADAT5", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
166     {"ADAT6", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
167     {"ADAT7", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
168     {"ADAT8", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
169 };
170
171 const PortEntry Ports_TRAVELER[] =
172 {
173     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
174     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
175     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 10},
176     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 13},
177     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 16},
178     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 10},
179     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 19},
180     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 13},
181     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 22},
182     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 16},
183     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 25},
184     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 19},
185     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 28},
186     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 22},
187     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 31},
188     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 25},
189     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 34},
190     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 28},
191     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 37},
192     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_4x|MOTU_PA_OPTICAL_ANY, 31},
193     {"AES/EBU1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
194     {"AES/EBU2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
195     {"SPDIF1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_OPTICAL_ADAT, 46},
196     {"SPDIF2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_OPTICAL_ADAT, 49},
197     {"Toslink1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_TOSLINK, 46},
198     {"Toslink2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_TOSLINK, 49},
199     {"ADAT1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 52},
200     {"ADAT2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 55},
201     {"ADAT3", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 58},
202     {"ADAT4", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ADAT, 61},
203     {"ADAT5", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 64},
204     {"ADAT6", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 67},
205     {"ADAT7", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 70},
206     {"ADAT8", MOTU_PA_INOUT | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT, 73},
207 };
208
209 const PortEntry Ports_ULTRALITE[] =
210 {
211     {"Main-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
212     {"Main-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
213     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
214     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
215     {"Mic1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
216     {"Mic2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
217     {"Analog1", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
218     {"Analog2", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
219     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
220     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
221     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
222     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
223     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
224     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
225     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
226     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
227     {"SPDIF1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
228     {"SPDIF2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
229     {"Padding1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY|MOTU_PA_PADDING, 46},
230     {"Padding2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY|MOTU_PA_PADDING, 49},
231     {"SPDIF1", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 46},
232     {"SPDIF2", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 49},
233 };
234
235 const PortEntry Ports_8PRE[] =
236 {
237     {"Analog1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
238     {"Analog2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
239     {"Analog3", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
240     {"Analog4", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
241     {"Analog5", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
242     {"Analog6", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
243     {"Analog7", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
244     {"Analog8", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
245     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
246     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
247     {"Main-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
248     {"Main-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
249     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
250     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
251     {"Padding1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_PADDING, 22},
252     {"Padding2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_PADDING, 25},
253     {"ADAT1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
254     {"ADAT1", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 22},
255     {"ADAT2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
256     {"ADAT2", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 25},
257     {"ADAT3", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 46},
258     {"ADAT3", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 28},
259     {"ADAT4", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 49},
260     {"ADAT4", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 31},
261     {"ADAT5", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 52},
262     {"ADAT5", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 34},
263     {"ADAT6", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 55},
264     {"ADAT6", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 37},
265     {"ADAT7", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 58},
266     {"ADAT7", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 40},
267     {"ADAT8", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 61},
268     {"ADAT8", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ADAT, 43},
269 };
270
271 const PortEntry Ports_828mk3[] =
272 {
273     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 10},
274     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 13},
275     {"Unknown-L", MOTU_PA_OUT | MOTU_PA_RATE_4x|MOTU_PA_MK3_OPT_ANY, 10},
276     {"Unknown-R", MOTU_PA_OUT | MOTU_PA_RATE_4x|MOTU_PA_MK3_OPT_ANY, 13},
277     {"Mic-1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 10},
278     {"Mic-2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 13},
279     {"Analog1", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 16},
280     {"Analog2", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 19},
281     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 22},
282     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 25},
283     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 28},
284     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 31},
285     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 34},
286     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 37},
287     {"MainOut-L", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 40},
288     {"MainOut-R", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 43},
289     {"Return-1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 40},
290     {"Return-2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_MK3_OPT_ANY, 43},
291     {"SPDIF1", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 46},
292     {"SPDIF2", MOTU_PA_INOUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 49},
293     {"Unknown-1", MOTU_PA_OUT | MOTU_PA_RATE_4x|MOTU_PA_MK3_OPT_ANY, 46},
294     {"Unknown-2", MOTU_PA_OUT | MOTU_PA_RATE_4x|MOTU_PA_MK3_OPT_ANY, 49},
295     {"Reverb-1", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 52},
296     {"Reverb-2", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_ANY, 55},
297     //
298     // Optical port locations are a bit messy with the Mark 3 devices since
299     // there are two optical ports whose modes can be independently set.
300     // First take care of the output direction.
301     //
302     {"Toslink-A1", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 52},
303     {"Toslink-A2", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 55},
304     {"ADAT-A1", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 52},
305     {"ADAT-A2", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 55},
306     {"ADAT-A3", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 58},
307     {"ADAT-A4", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 61},
308     {"ADAT-A5", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 64},
309     {"ADAT-A6", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 67},
310     {"ADAT-A7", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 70},
311     {"ADAT-A8", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ANY, 73},
312     //
313     {"Toslink-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 52},
314     {"Toslink-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 55},
315     {"Toslink-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 58},
316     {"Toslink-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 61},
317     {"Toslink-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 76},
318     {"Toslink-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 79},
319     {"Toslink-B1", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 64},
320     {"Toslink-B2", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 67},
321     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 76},
322     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 79},
323     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 82},
324     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 85},
325     {"ADAT-B5", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 88},
326     {"ADAT-B6", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 91},
327     {"ADAT-B7", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 94},
328     {"ADAT-B8", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 97},
329     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 64},
330     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 67},
331     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 70},
332     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 73},
333     //
334     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 58},
335     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 61},
336     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 64},
337     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 67},
338     {"ADAT-B5", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 70},
339     {"ADAT-B6", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 73},
340     {"ADAT-B7", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 76},
341     {"ADAT-B8", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 79},
342     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 58},
343     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 61},
344     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 64},
345     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 67},
346     //
347     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 52},
348     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 55},
349     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 58},
350     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 61},
351     {"ADAT-B5", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 64},
352     {"ADAT-B6", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 67},
353     {"ADAT-B7", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 70},
354     {"ADAT-B8", MOTU_PA_OUT | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 73},
355     {"ADAT-B1", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 52},
356     {"ADAT-B2", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 55},
357     {"ADAT-B3", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 58},
358     {"ADAT-B4", MOTU_PA_OUT | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_ADAT, 61},
359
360     // Now deal with the input side of things.  Firstly comes two channels
361     // which are yet to be identified at 1x rates.
362     {"Unknown-1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_ANY, 58},
363     {"Unknown-2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_ANY, 61},
364
365     // Follow up with the optical input port details.
366     //
367     {"Toslink-A1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 64},
368     {"Toslink-A2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 67},
369     {"Toslink-A1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 58},
370     {"Toslink-A2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_ANY, 61},
371     {"ADAT-A1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 64},
372     {"ADAT-A2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 67},
373     {"ADAT-A3", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 70},
374     {"ADAT-A4", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 73},
375     {"ADAT-A5", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 76},
376     {"ADAT-A6", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 79},
377     {"ADAT-A7", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 82},
378     {"ADAT-A8", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 85},
379     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 88},
380     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 91},
381     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 94},
382     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 97},
383     {"ADAT-B5", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 100},
384     {"ADAT-B6", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 103},
385     {"ADAT-B7", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 106},
386     {"ADAT-B8", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 109},
387     {"ADAT-A1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 58},
388     {"ADAT-A2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 61},
389     {"ADAT-A3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 64},
390     {"ADAT-A4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ANY, 67},
391     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 70},
392     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 73},
393     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 76},
394     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 79},
395     {"Unknown-3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 82},
396     {"Unknown-4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_ADAT|MOTU_PA_MK3_OPT_B_ADAT, 85},
397     //
398     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 64},
399     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 67},
400     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 58},
401     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_OFF|MOTU_PA_MK3_OPT_B_TOSLINK, 61},
402     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 70},
403     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 73},
404     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 64},
405     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_TOSLINK|MOTU_PA_MK3_OPT_B_TOSLINK, 67},
406     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 88},
407     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 91},
408     {"Toslink-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 70},
409     {"Toslink-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_MK3_OPT_A_ADAT|MOTU_PA_MK3_OPT_B_TOSLINK, 73},
410     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 64},
411     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 67},
412     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 70},
413     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 73},
414     {"ADAT-B5", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 76},
415     {"ADAT-B6", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 79},
416     {"ADAT-B7", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 82},
417     {"ADAT-B8", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 85},
418     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 58},
419     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 61},
420     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 64},
421     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 67},
422     {"Unknown-3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 70},
423     {"Unknown-4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_OFF|MOTU_PA_MK3_OPT_B_ADAT, 73},
424     //
425     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 70},
426     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 73},
427     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 76},
428     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 79},
429     {"ADAT-B5", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 82},
430     {"ADAT-B6", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 85},
431     {"ADAT-B7", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 88},
432     {"ADAT-B8", MOTU_PA_IN | MOTU_PA_RATE_1x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 91},
433     {"ADAT-B1", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 64},
434     {"ADAT-B2", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 67},
435     {"ADAT-B3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 70},
436     {"ADAT-B4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 73},
437     {"Unknown-3", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 76},
438     {"Unknown-4", MOTU_PA_IN | MOTU_PA_RATE_2x|MOTU_PA_OPTICAL_TOSLINK|MOTU_PA_MK3_OPT_B_ADAT, 79},
439
440 };
441
442 const PortEntry Ports_ULTRALITEmk3[] =
443 {
444     {"Main-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 40},
445     {"Main-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 43},
446     {"Mix-L", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
447     {"Mix-R", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
448     {"Mic1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
449     {"Mic2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
450     {"Analog1", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 16},
451     {"Analog2", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 19},
452     {"Analog3", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 22},
453     {"Analog4", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 25},
454     {"Analog5", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 28},
455     {"Analog6", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 31},
456     {"Analog7", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 34},
457     {"Analog8", MOTU_PA_INOUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 37},
458     {"Phones-L", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 10},
459     {"Phones-R", MOTU_PA_OUT | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY, 13},
460     {"SPDIF1", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 40},
461     {"SPDIF2", MOTU_PA_IN | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 43},
462     {"Padding1", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY|MOTU_PA_PADDING, 46},
463     {"Padding2", MOTU_PA_IN | MOTU_PA_RATE_ANY|MOTU_PA_OPTICAL_ANY|MOTU_PA_PADDING, 49},
464     {"SPDIF1", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 46},
465     {"SPDIF2", MOTU_PA_OUT | MOTU_PA_RATE_1x2x|MOTU_PA_OPTICAL_ANY, 49},
466 };
467
468 /* The order of DevicesProperty entries must match the numeric order of the
469  * MOTU model enumeration (EMotuModel).
470  */
471 const DevicePropertyEntry DevicesProperty[] = {
472 //  { Ports_map,          N_ELEMENTS( Ports_map ),        MaxSR, MixerDescrPtr, Mark3MixerDescrPtr },
473     { Ports_828MKII,      N_ELEMENTS( Ports_828MKII ),       96000, &Mixer_828Mk2, NULL, },
474     { Ports_TRAVELER,     N_ELEMENTS( Ports_TRAVELER ),     192000, &Mixer_Traveler, NULL, },
475     { Ports_ULTRALITE,    N_ELEMENTS( Ports_ULTRALITE ),     96000, &Mixer_Ultralite, NULL, },
476     { Ports_8PRE,         N_ELEMENTS( Ports_8PRE ),          96000, &Mixer_8pre, NULL, },
477     { Ports_828MKI,       N_ELEMENTS( Ports_828MKI ),        48000 },
478     { Ports_896HD,        N_ELEMENTS( Ports_896HD ),        192000, &Mixer_896HD, NULL, },
479     { Ports_828mk3,       N_ELEMENTS( Ports_828mk3 ),       192000 },
480     { Ports_ULTRALITEmk3, N_ELEMENTS( Ports_ULTRALITEmk3 ), 192000 },
481 };
482
483 MotuDevice::MotuDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
484     : FFADODevice( d, configRom )
485     , m_motu_model( MOTU_MODEL_NONE )
486     , m_iso_recv_channel ( -1 )
487     , m_iso_send_channel ( -1 )
488     , m_rx_bandwidth ( -1 )
489     , m_tx_bandwidth ( -1 )
490     , m_receiveProcessor ( 0 )
491     , m_transmitProcessor ( 0 )
492     , m_MixerContainer ( NULL )
493     , m_ControlContainer ( NULL )
494 {
495     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
496                  getConfigRom().getNodeId() );
497 }
498
499 MotuDevice::~MotuDevice()
500 {
501     delete m_receiveProcessor;
502     delete m_transmitProcessor;
503
504     // Free ieee1394 bus resources if they have been allocated
505     if (m_iso_recv_channel>=0 && !get1394Service().freeIsoChannel(m_iso_recv_channel)) {
506         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
507     }
508     if (m_iso_send_channel>=0 && !get1394Service().freeIsoChannel(m_iso_send_channel)) {
509         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
510     }
511
512     destroyMixer();
513 }
514
515 bool
516 MotuDevice::probe( Util::Configuration& c, ConfigRom& configRom, bool generic)
517 {
518     if(generic) return false;
519
520     unsigned int vendorId = configRom.getNodeVendorId();
521     unsigned int unitVersion = configRom.getUnitVersion();
522     unsigned int unitSpecifierId = configRom.getUnitSpecifierId();
523
524     for ( unsigned int i = 0;
525           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
526           ++i )
527     {
528         if ( ( supportedDeviceList[i].vendor_id == vendorId )
529              && ( supportedDeviceList[i].unit_version == unitVersion )
530              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
531            )
532         {
533             return true;
534         }
535     }
536
537     return false;
538 }
539
540 FFADODevice *
541 MotuDevice::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
542 {
543     return new MotuDevice(d, configRom);
544 }
545
546 bool
547 MotuDevice::discover()
548 {
549     unsigned int vendorId = getConfigRom().getNodeVendorId();
550     unsigned int unitVersion = getConfigRom().getUnitVersion();
551     unsigned int unitSpecifierId = getConfigRom().getUnitSpecifierId();
552
553     for ( unsigned int i = 0;
554           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
555           ++i )
556     {
557         if ( ( supportedDeviceList[i].vendor_id == vendorId )
558              && ( supportedDeviceList[i].unit_version == unitVersion )
559              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
560            )
561         {
562             m_model = &(supportedDeviceList[i]);
563             m_motu_model=supportedDeviceList[i].model;
564         }
565     }
566
567     if (m_model == NULL) {
568         return false;
569     }
570
571     debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
572         m_model->vendor_name, m_model->model_name);
573
574     if (!buildMixer()) {
575         debugWarning("Could not build mixer\n");
576     }
577
578     return true;
579 }
580
581 enum FFADODevice::eStreamingState
582 MotuDevice::getStreamingState()
583 {
584     unsigned int val = ReadRegister(MOTU_REG_ISOCTRL);
585     /* Streaming is active if either bit 22 (Motu->PC streaming
586      * enable) or bit 30 (PC->Motu streaming enable) is set.
587      */
588     debugOutput(DEBUG_LEVEL_VERBOSE, "MOTU_REG_ISOCTRL: %08x\n", val);
589
590     if((val & 0x40400000) != 0) {
591         return eSS_Both;
592     } else if ((val & 0x40000000) != 0) {
593         return eSS_Receiving;
594     } else if ((val & 0x00400000) != 0) {
595         return eSS_Sending;
596     } else {
597         return eSS_Idle;
598     }
599 }
600
601 int
602 MotuDevice::getSamplingFrequency( ) {
603 /*
604  * Retrieve the current sample rate from the MOTU device.
605  */
606     quadlet_t q = 0;
607     int rate = 0;
608
609     if (m_motu_model == MOTU_MODEL_828MkI) {
610         /* The original MOTU interfaces did things rather differently */
611         q = ReadRegister(MOTU_G1_REG_CONFIG);
612         if ((q & MOTU_G1_RATE_MASK) == MOTU_G1_RATE_44100)
613             rate = 44100;
614         else
615             rate = 48000;
616         return rate;
617     }
618
619     q = ReadRegister(MOTU_REG_CLK_CTRL);
620     switch (q & MOTU_RATE_BASE_MASK) {
621         case MOTU_RATE_BASE_44100:
622             rate = 44100;
623             break;
624         case MOTU_RATE_BASE_48000:
625             rate = 48000;
626             break;
627     }
628     switch (q & MOTU_RATE_MULTIPLIER_MASK) {
629         case MOTU_RATE_MULTIPLIER_2X:
630             rate *= 2;
631             break;
632         case MOTU_RATE_MULTIPLIER_4X:
633             rate *= 4;
634             break;
635     }
636     return rate;
637 }
638
639 int
640 MotuDevice::getConfigurationId()
641 {
642     return 0;
643 }
644
645 unsigned int
646 MotuDevice::getHwClockSource()
647 {
648     unsigned int reg;
649
650     if (m_motu_model == MOTU_MODEL_828MkI) {
651         reg = ReadRegister(MOTU_G1_REG_CONFIG);
652         switch (reg & MOTU_G1_CLKSRC_MASK) {
653             case MOTU_G1_CLKSRC_INTERNAL: return MOTU_CLKSRC_INTERNAL;
654             case MOTU_G1_CLKSRC_ADAT_9PIN: return MOTU_CLKSRC_ADAT_9PIN;
655             case MOTU_G1_CLKSRC_SPDIF: return MOTU_CLKSRC_SPDIF_TOSLINK;
656         }
657         return MOTU_CLKSRC_NONE;
658     }
659
660     reg = ReadRegister(MOTU_REG_CLK_CTRL);
661     if (getDeviceGeneration() == MOTU_DEVICE_G2) {
662         switch (reg & MOTU_G2_CLKSRC_MASK) {
663             case MOTU_G2_CLKSRC_INTERNAL: return MOTU_CLKSRC_INTERNAL;
664             case MOTU_G2_CLKSRC_ADAT_OPTICAL: return MOTU_CLKSRC_ADAT_OPTICAL;
665             case MOTU_G2_CLKSRC_SPDIF_TOSLINK: return MOTU_CLKSRC_SPDIF_TOSLINK;
666             case MOTU_G2_CLKSRC_SMPTE: return MOTU_CLKSRC_SMPTE;
667             case MOTU_G2_CLKSRC_WORDCLOCK: return MOTU_CLKSRC_WORDCLOCK;
668             case MOTU_G2_CLKSRC_ADAT_9PIN: return MOTU_CLKSRC_ADAT_9PIN;
669             case MOTU_G2_CLKSRC_AES_EBU: return MOTU_CLKSRC_AES_EBU;
670         }
671     } else {
672         /* Handle G3 devices */
673         switch (reg & MOTU_G3_CLKSRC_MASK) {
674             case MOTU_G3_CLKSRC_INTERNAL: return MOTU_CLKSRC_INTERNAL;
675             case MOTU_G3_CLKSRC_SPDIF: return MOTU_CLKSRC_SPDIF_TOSLINK;
676             case MOTU_G3_CLKSRC_SMPTE: return MOTU_CLKSRC_SMPTE;
677             case MOTU_G3_CLKSRC_WORDCLOCK: return MOTU_CLKSRC_WORDCLOCK;
678             case MOTU_G3_CLKSRC_OPTICAL_A: return MOTU_CLKSRC_OPTICAL_A;
679             case MOTU_G3_CLKSRC_OPTICAL_B: return MOTU_CLKSRC_OPTICAL_B;
680         }
681     }
682     return MOTU_CLKSRC_NONE;
683 }
684
685 bool
686 MotuDevice::setClockCtrlRegister(signed int samplingFrequency, unsigned int clock_source)
687 {
688 /*
689  * Set the MOTU device's samplerate and/or clock source via the clock
690  * control register.  If samplingFrequency <= 0 it remains unchanged.  If
691  * clock_source is MOTU_CLKSRC_UNCHANGED the clock source remains unchanged.
692  */
693     const char *src_name;
694     quadlet_t q, new_rate=0xffffffff;
695     int i, supported=true, cancel_adat=false;
696     quadlet_t reg;
697     unsigned int old_clock_src = getHwClockSource();
698     signed int device_gen = getDeviceGeneration();
699
700     /* Don't touch anything if there's nothing to do */
701     if (samplingFrequency<=0 && clock_source==MOTU_CLKSRC_NONE)
702         return true;
703
704     if ( samplingFrequency > DevicesProperty[m_motu_model-1].MaxSampleRate )
705        return false;
706
707     /* The original MOTU devices do things differently; they are much
708      * simpler than the later interfaces.
709      */
710     if (m_motu_model == MOTU_MODEL_828MkI) {
711         reg = ReadRegister(MOTU_G1_REG_CONFIG);
712         if (samplingFrequency > 0) {
713             reg &= ~MOTU_G1_RATE_MASK;
714             switch (samplingFrequency) {
715                 case 44100:
716                     reg |= MOTU_G1_RATE_44100;
717                     break;
718                 case 48000:
719                     reg |= MOTU_G1_RATE_48000;
720                 default:
721                     // Unsupported rate
722                     return false;
723             }
724         }
725         if (clock_source != MOTU_CLKSRC_UNCHANGED) {
726             switch (clock_source) {
727                 case MOTU_CLKSRC_INTERNAL:
728                     clock_source = MOTU_G1_CLKSRC_INTERNAL; break;
729                 case MOTU_CLKSRC_SPDIF_TOSLINK:
730                     clock_source = MOTU_G1_CLKSRC_SPDIF; break;
731                 case MOTU_CLKSRC_ADAT_9PIN:
732                     clock_source = MOTU_G1_CLKSRC_ADAT_9PIN; break;
733                 default:
734                     // Unsupported clock source
735                     return false;
736             }
737             reg &= ~MOTU_G1_CLKSRC_MASK;
738             reg |= clock_source;
739         }
740         if (WriteRegister(MOTU_G1_REG_CONFIG, reg) != 0)
741             return false;
742         return true;
743     }
744
745     /* The rest of this function deals with later generation devices */
746
747     reg = ReadRegister(MOTU_REG_CLK_CTRL);
748
749     /* Control of sampling rate is the same for both G2 and G3 devices */
750     switch ( samplingFrequency ) {
751         case -1:
752             break;
753         case 44100:
754             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_1X;
755             break;
756         case 48000:
757             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_1X;
758             break;
759         case 88200:
760             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_2X;
761             break;
762         case 96000:
763             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_2X;
764             break;
765         case 176400:
766             new_rate = MOTU_RATE_BASE_44100 | MOTU_RATE_MULTIPLIER_4X;
767             cancel_adat = true;  // current ADAT protocol doesn't support sample rate > 96000
768             break;
769         case 192000:
770             new_rate = MOTU_RATE_BASE_48000 | MOTU_RATE_MULTIPLIER_4X;
771             cancel_adat = true;
772             break;
773         default:
774             supported=false;
775     }
776
777     // Sanity check the clock source
778     if (clock_source>MOTU_CLKSRC_LAST && clock_source!=MOTU_CLKSRC_UNCHANGED)
779         supported = false;
780
781     // Update the clock control register.  FIXME: while this is now rather
782     // comprehensive there may still be a need to manipulate MOTU_REG_CLK_CTRL
783     // a little more than we do.
784     if (supported) {
785
786         // If optical port must be disabled (because a 4x sample rate has
787         // been selected) then do so before changing the sample rate.  At
788         // this stage it will be up to the user to re-enable the optical
789         // port if the sample rate is set to a 1x or 2x rate later.
790         if (cancel_adat) {
791             setOpticalMode(MOTU_CTRL_DIR_INOUT, MOTU_OPTICAL_MODE_OFF, MOTU_OPTICAL_MODE_OFF);
792         }
793
794         // Set up new frequency if requested
795         if (new_rate != 0xffffffff) {
796             reg &= ~(MOTU_RATE_BASE_MASK|MOTU_RATE_MULTIPLIER_MASK);
797             reg |= new_rate;
798         }
799
800         // Set up new clock source if required
801         if (clock_source != MOTU_CLKSRC_UNCHANGED) {
802             if (device_gen == MOTU_DEVICE_G2) {
803                 reg &= ~MOTU_G2_CLKSRC_MASK;
804                 switch (clock_source) {
805                     case MOTU_CLKSRC_INTERNAL: reg |= MOTU_G2_CLKSRC_INTERNAL; break;
806                     case MOTU_CLKSRC_ADAT_OPTICAL: reg |= MOTU_G2_CLKSRC_ADAT_OPTICAL; break;
807                     case MOTU_CLKSRC_SPDIF_TOSLINK: reg |= MOTU_G2_CLKSRC_SPDIF_TOSLINK; break;
808                     case MOTU_CLKSRC_SMPTE: reg |= MOTU_G2_CLKSRC_SMPTE; break;
809                     case MOTU_CLKSRC_WORDCLOCK: reg |= MOTU_G2_CLKSRC_WORDCLOCK; break;
810                     case MOTU_CLKSRC_ADAT_9PIN: reg |= MOTU_G2_CLKSRC_ADAT_9PIN; break;
811                     case MOTU_CLKSRC_AES_EBU: reg |= MOTU_G2_CLKSRC_AES_EBU; break;
812                 }
813             } else {
814                 reg &= ~MOTU_G3_CLKSRC_MASK;
815                 switch (clock_source) {
816                     case MOTU_CLKSRC_INTERNAL: reg |= MOTU_G3_CLKSRC_INTERNAL; break;
817                     case MOTU_CLKSRC_SPDIF_TOSLINK: reg |= MOTU_G3_CLKSRC_SPDIF; break;
818                     case MOTU_CLKSRC_SMPTE: reg |= MOTU_G3_CLKSRC_SMPTE; break;
819                     case MOTU_CLKSRC_WORDCLOCK: reg |= MOTU_G3_CLKSRC_WORDCLOCK; break;
820                     case MOTU_CLKSRC_OPTICAL_A: reg |= MOTU_G3_CLKSRC_OPTICAL_A; break;
821                     case MOTU_CLKSRC_OPTICAL_B: reg |= MOTU_G3_CLKSRC_OPTICAL_B; break;
822                 }
823             }
824         } else {
825             /* Use the device's current clock source to set the clock
826              * source name registers, which must be done even if we aren't
827              * changing the clock source.
828              */
829             clock_source = old_clock_src;
830         }
831
832         // Bits 24-26 of MOTU_REG_CLK_CTRL behave a little differently
833         // depending on the model.  In addition, different bit patterns are
834         // written depending on whether streaming is enabled, disabled or is
835         // changing state.  For now we go with the combination used when
836         // streaming is enabled since it seems to work for the other states
837         // as well.  Since device muting can be effected by these bits, we
838         // may utilise this in future during streaming startup to prevent
839         // noises during stabilisation.
840         //
841         // For most models (possibly all except the Ultralite) all 3 bits
842         // can be zero and audio is still output.
843         //
844         // For the Traveler, if bit 26 is set (as it is under other OSes),
845         // bit 25 functions as a device mute bit: if set, audio is output
846         // while if 0 the entire device is muted.  If bit 26 is unset,
847         // setting bit 25 doesn't appear to be detrimental.
848         //
849         // For the Ultralite, other OSes leave bit 26 unset.  However, unlike
850         // other devices bit 25 seems to function as a mute bit in this case.
851         //
852         // The function of bit 24 is currently unknown.  Other OSes set it
853         // for all devices so we will too.
854         reg &= 0xf8ffffff;
855         if (m_motu_model == MOTU_MODEL_TRAVELER)
856             reg |= 0x04000000;
857         reg |= 0x03000000;
858         if (WriteRegister(MOTU_REG_CLK_CTRL, reg) == 0) {
859             supported=true;
860         } else {
861             supported=false;
862         }
863         // A write to the rate/clock control register requires the
864         // textual name of the current clock source be sent to the
865         // clock source name registers.  This appears to be the same for
866         // both G2 and G3 devices.
867         switch (clock_source) {
868             case MOTU_CLKSRC_INTERNAL:
869                 src_name = "Internal        ";
870                 break;
871             case MOTU_CLKSRC_ADAT_OPTICAL:
872                 src_name = "ADAT Optical    ";
873                 break;
874             case MOTU_CLKSRC_SPDIF_TOSLINK: {
875                 unsigned int p0_mode;
876                 if (device_gen < MOTU_DEVICE_G3) {
877                     getOpticalMode(MOTU_DIR_IN, &p0_mode, NULL);
878                 } else
879                     p0_mode = MOTU_OPTICAL_MODE_OFF;
880                 if (p0_mode == MOTU_OPTICAL_MODE_TOSLINK)
881                     src_name = "TOSLink         ";
882                 else
883                     src_name = "SPDIF           ";
884                 break;
885             }
886             case MOTU_CLKSRC_SMPTE:
887                 src_name = "SMPTE           ";
888                 break;
889             case MOTU_CLKSRC_WORDCLOCK:
890                 src_name = "Word Clock In   ";
891                 break;
892             case MOTU_CLKSRC_ADAT_9PIN:
893                 src_name = "ADAT 9-pin      ";
894                 break;
895             case MOTU_CLKSRC_AES_EBU:
896                 src_name = "AES-EBU         ";
897                 break;
898             case MOTU_CLKSRC_OPTICAL_A: {
899                 unsigned int p0_mode;
900                 getOpticalMode(MOTU_DIR_IN, &p0_mode, NULL);
901                 if (p0_mode == MOTU_OPTICAL_MODE_TOSLINK)
902                     src_name = "Toslink-A       ";
903                 else
904                     src_name = "ADAT-A Optical  ";
905                 break;
906             }
907             case MOTU_CLKSRC_OPTICAL_B: {
908                 unsigned int p1_mode;
909                 getOpticalMode(MOTU_DIR_IN, NULL, &p1_mode);
910                 if (p1_mode == MOTU_OPTICAL_MODE_TOSLINK)
911                     src_name = "Toslink-B       ";
912                 else
913                     src_name = "ADAT-B Optical  ";
914                 break;
915             }
916             default:
917                 src_name = "Unknown         ";
918         }
919         for (i=0; i<16; i+=4) {
920             q = (src_name[i]<<24) | (src_name[i+1]<<16) |
921                 (src_name[i+2]<<8) | src_name[i+3];
922             WriteRegister(MOTU_REG_CLKSRC_NAME0+i, q);
923         }
924     }
925     return supported;
926 }
927
928 bool
929 MotuDevice::setSamplingFrequency( int samplingFrequency )
930 {
931 /*
932  * Set the MOTU device's samplerate.
933  */
934     return setClockCtrlRegister(samplingFrequency, MOTU_CLKSRC_UNCHANGED);
935 }
936
937 std::vector<int>
938 MotuDevice::getSupportedSamplingFrequencies()
939 {
940     std::vector<int> frequencies;
941     signed int max_freq = DevicesProperty[m_motu_model-1].MaxSampleRate;
942
943     /* All MOTUs support 1x rates.  All others must be conditional. */
944     frequencies.push_back(44100);
945     frequencies.push_back(48000);
946
947     if (88200 <= max_freq)
948         frequencies.push_back(88200);
949     if (96000 <= max_freq)
950         frequencies.push_back(96000);
951     if (176400 <= max_freq)
952         frequencies.push_back(176400);
953     if (192000 <= max_freq)
954         frequencies.push_back(192000);
955     return frequencies;
956 }
957
958 FFADODevice::ClockSource
959 MotuDevice::clockIdToClockSource(unsigned int id) {
960     ClockSource s;
961     signed int device_gen = getDeviceGeneration();
962     s.id = id;
963
964     // Assume a clock source is valid/active unless otherwise overridden.
965     s.valid = true;
966     s.locked = true;
967     s.active = true;
968
969     switch (id) {
970         case MOTU_CLKSRC_INTERNAL:
971             s.type = eCT_Internal;
972             s.description = "Internal sync";
973             break;
974         case MOTU_CLKSRC_ADAT_OPTICAL:
975             s.type = eCT_ADAT;
976             s.description = "ADAT optical";
977             s.valid = s.active = s.locked = (device_gen!=MOTU_DEVICE_G1);
978             break;
979         case MOTU_CLKSRC_SPDIF_TOSLINK:
980             s.type = eCT_SPDIF;
981             if (device_gen < MOTU_DEVICE_G3)
982                 s.description = "SPDIF/Toslink";
983             else
984                 s.description = "SPDIF";
985             break;
986         case MOTU_CLKSRC_SMPTE:
987             s.type = eCT_SMPTE;
988             s.description = "SMPTE";
989             // Since we don't currently know how to deal with SMPTE on these
990             // devices make sure the SMPTE clock source is disabled.
991             s.valid = false;
992             s.active = false;
993             s.locked = false;
994             break;
995         case MOTU_CLKSRC_WORDCLOCK:
996             s.type = eCT_WordClock;
997             s.description = "Wordclock";
998             s.valid = s.active = s.locked = (device_gen!=MOTU_DEVICE_G1);
999             break;
1000         case MOTU_CLKSRC_ADAT_9PIN:
1001             s.type = eCT_ADAT;
1002             s.description = "ADAT 9-pin";
1003             break;
1004         case MOTU_CLKSRC_AES_EBU:
1005             s.type = eCT_AES;
1006             s.description = "AES/EBU";
1007             s.valid = s.active = s.locked = (device_gen!=MOTU_DEVICE_G1);
1008             break;
1009         case MOTU_CLKSRC_OPTICAL_A:
1010             s.type = eCT_ADAT;
1011             s.description = "ADAT/Toslink port A";
1012             break;
1013         case MOTU_CLKSRC_OPTICAL_B:
1014             s.type = eCT_ADAT;
1015             s.description = "ADAT/Toslink port B";
1016             break;
1017         default:
1018             s.type = eCT_Invalid;
1019     }
1020
1021     s.slipping = false;
1022     return s;
1023 }
1024
1025 FFADODevice::ClockSourceVector
1026 MotuDevice::getSupportedClockSources() {
1027     FFADODevice::ClockSourceVector r;
1028     ClockSource s;
1029     signed int device_gen = getDeviceGeneration();
1030
1031     /* Form a list of clocks supported by MOTU interfaces */
1032
1033     /* All interfaces support an internal clock */
1034     s = clockIdToClockSource(MOTU_CLKSRC_INTERNAL);
1035     r.push_back(s);
1036
1037     if (device_gen == MOTU_DEVICE_G2) {
1038         s = clockIdToClockSource(MOTU_CLKSRC_ADAT_OPTICAL);
1039         r.push_back(s);
1040     }
1041
1042     s = clockIdToClockSource(MOTU_CLKSRC_SPDIF_TOSLINK);
1043     r.push_back(s);
1044     s = clockIdToClockSource(MOTU_CLKSRC_SMPTE);
1045     r.push_back(s);
1046     s = clockIdToClockSource(MOTU_CLKSRC_WORDCLOCK);
1047     r.push_back(s);
1048
1049     if (device_gen < MOTU_DEVICE_G3) {
1050         s = clockIdToClockSource(MOTU_CLKSRC_ADAT_9PIN);
1051         r.push_back(s);
1052     }
1053     s = clockIdToClockSource(MOTU_CLKSRC_AES_EBU);
1054     r.push_back(s);
1055
1056     if (device_gen == MOTU_DEVICE_G3) {
1057         s = clockIdToClockSource(MOTU_CLKSRC_OPTICAL_A);
1058         r.push_back(s);
1059         s = clockIdToClockSource(MOTU_CLKSRC_OPTICAL_B);
1060         r.push_back(s);
1061     }
1062
1063     return r;
1064 }
1065
1066 bool
1067 MotuDevice::setActiveClockSource(ClockSource s) {
1068     debugOutput(DEBUG_LEVEL_VERBOSE, "setting clock source to id: %d\n",s.id);
1069
1070     // FIXME: this could do with some error checking
1071     return setClockCtrlRegister(-1, s.id);
1072 }
1073
1074 FFADODevice::ClockSource
1075 MotuDevice::getActiveClockSource() {
1076     ClockSource s;
1077     quadlet_t clock_id = getHwClockSource();
1078     s = clockIdToClockSource(clock_id);
1079     s.active = true;
1080     return s;
1081 }
1082
1083 bool
1084 MotuDevice::lock() {
1085
1086     return true;
1087 }
1088
1089
1090 bool
1091 MotuDevice::unlock() {
1092
1093     return true;
1094 }
1095
1096 void
1097 MotuDevice::showDevice()
1098 {
1099     debugOutput(DEBUG_LEVEL_VERBOSE,
1100         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
1101         getNodeId());
1102 }
1103
1104 bool
1105 MotuDevice::prepare() {
1106
1107     int samp_freq = getSamplingFrequency();
1108     unsigned int optical_in_mode_a, optical_out_mode_a;
1109     unsigned int optical_in_mode_b, optical_out_mode_b;
1110     unsigned int event_size_in = getEventSize(MOTU_DIR_IN);
1111     unsigned int event_size_out= getEventSize(MOTU_DIR_OUT);
1112
1113     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
1114
1115     getOpticalMode(MOTU_DIR_IN, &optical_in_mode_a, &optical_in_mode_b);
1116     getOpticalMode(MOTU_DIR_OUT, &optical_out_mode_a, &optical_out_mode_b);
1117
1118     // Explicitly set the optical mode, primarily to ensure that the
1119     // MOTU_REG_OPTICAL_CTRL register is initialised.  We need to do this to
1120     // because some interfaces (the Ultralite for example) appear to power
1121     // up without this set to anything sensible.  In this case, writes to
1122     // MOTU_REG_ISOCTRL fail more often than not, which is bad.
1123     setOpticalMode(MOTU_DIR_IN, optical_in_mode_a, optical_in_mode_b);
1124     setOpticalMode(MOTU_DIR_OUT, optical_out_mode_a, optical_out_mode_b);
1125
1126     // Allocate bandwidth if not previously done.
1127     // FIXME: The bandwidth allocation calculation can probably be
1128     // refined somewhat since this is currently based on a rudimentary
1129     // understanding of the ieee1394 iso protocol.
1130     // Currently we assume the following.
1131     //   * Ack/iso gap = 0.05 us
1132     //   * DATA_PREFIX = 0.16 us
1133     //   * DATA_END    = 0.26 us
1134     // These numbers are the worst-case figures given in the ieee1394
1135     // standard.  This gives approximately 0.5 us of overheads per packet -
1136     // around 25 bandwidth allocation units (from the ieee1394 standard 1
1137     // bandwidth allocation unit is 125/6144 us).  We further assume the
1138     // MOTU is running at S400 (which it should be) so one allocation unit
1139     // is equivalent to 1 transmitted byte; thus the bandwidth allocation
1140     // required for the packets themselves is just the size of the packet.
1141     // We used to allocate based on the maximum packet size (1160 bytes at
1142     // 192 kHz for the traveler) but now do this based on the actual device
1143     // state by utilising the result from getEventSize() and remembering
1144     // that each packet has an 8 byte CIP header.  Note that bandwidth is
1145     // allocated on a *per stream* basis - it must be allocated for both the
1146     // transmit and receive streams.  While most MOTU modules are close to
1147     // symmetric in terms of the number of in/out channels there are
1148     // exceptions, so we deal with receive and transmit bandwidth separately.
1149     signed int n_events_per_packet = samp_freq<=48000?8:(samp_freq<=96000?16:32);
1150     m_rx_bandwidth = 25 + (n_events_per_packet*event_size_in);
1151     m_tx_bandwidth = 25 + (n_events_per_packet*event_size_out);
1152
1153     // Assign iso channels if not already done
1154     if (m_iso_recv_channel < 0)
1155         m_iso_recv_channel = get1394Service().allocateIsoChannelGeneric(m_rx_bandwidth);
1156
1157     if (m_iso_send_channel < 0)
1158         m_iso_send_channel = get1394Service().allocateIsoChannelGeneric(m_tx_bandwidth);
1159
1160     debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
1161         m_iso_recv_channel, m_iso_send_channel);
1162
1163     if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
1164         // be nice and deallocate
1165         if (m_iso_recv_channel >= 0)
1166             get1394Service().freeIsoChannel(m_iso_recv_channel);
1167         if (m_iso_send_channel >= 0)
1168             get1394Service().freeIsoChannel(m_iso_send_channel);
1169
1170         debugFatal("Could not allocate iso channels!\n");
1171         return false;
1172     }
1173
1174     // get the device specific and/or global SP configuration
1175     Util::Configuration &config = getDeviceManager().getConfiguration();
1176     // base value is the config.h value
1177     float recv_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
1178     float xmit_sp_dll_bw = STREAMPROCESSOR_DLL_BW_HZ;
1179
1180     // we can override that globally
1181     config.getValueForSetting("streaming.spm.recv_sp_dll_bw", recv_sp_dll_bw);
1182     config.getValueForSetting("streaming.spm.xmit_sp_dll_bw", xmit_sp_dll_bw);
1183
1184     // or override in the device section
1185     config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "recv_sp_dll_bw", recv_sp_dll_bw);
1186     config.getValueForDeviceSetting(getConfigRom().getNodeVendorId(), getConfigRom().getModelId(), "xmit_sp_dll_bw", xmit_sp_dll_bw);
1187
1188     m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor(*this, event_size_in);
1189     m_receiveProcessor->setVerboseLevel(getDebugLevel());
1190
1191     // The first thing is to initialize the processor.  This creates the
1192     // data structures.
1193     if(!m_receiveProcessor->init()) {
1194         debugFatal("Could not initialize receive processor!\n");
1195         return false;
1196     }
1197
1198     if(!m_receiveProcessor->setDllBandwidth(recv_sp_dll_bw)) {
1199         debugFatal("Could not set DLL bandwidth\n");
1200         delete m_receiveProcessor;
1201         m_receiveProcessor = NULL;
1202         return false;
1203     }
1204
1205     // Now we add ports to the processor
1206     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
1207
1208     char *buff;
1209     Streaming::Port *p=NULL;
1210
1211     // retrieve the ID
1212     std::string id=std::string("dev?");
1213     if(!getOption("id", id)) {
1214         debugWarning("Could not retrieve id parameter, defaulting to 'dev?'\n");
1215     }
1216
1217     // Add audio capture ports
1218     if (!addDirPorts(Streaming::Port::E_Capture, samp_freq, optical_in_mode_a, optical_in_mode_b)) {
1219         return false;
1220     }
1221
1222     // Add MIDI port.  The MOTU only has one MIDI input port, with each
1223     // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
1224     // event data.
1225     asprintf(&buff,"%s_cap_MIDI0",id.c_str());
1226     p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff,
1227         Streaming::Port::E_Capture, 4);
1228     if (!p) {
1229         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
1230     }
1231     free(buff);
1232
1233     // example of adding an control port:
1234 //    asprintf(&buff,"%s_cap_%s",id.c_str(),"myportnamehere");
1235 //    p=new Streaming::MotuControlPort(
1236 //            buff,
1237 //            Streaming::Port::E_Capture,
1238 //            0 // you can add all other port specific stuff you
1239 //              // need to pass by extending MotuXXXPort and MotuPortInfo
1240 //    );
1241 //    free(buff);
1242 //
1243 //    if (!p) {
1244 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
1245 //    } else {
1246 //
1247 //        if (!m_receiveProcessor->addPort(p)) {
1248 //            debugWarning("Could not register port with stream processor\n");
1249 //            return false;
1250 //        } else {
1251 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
1252 //        }
1253 //    }
1254
1255     // Do the same for the transmit processor
1256     m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor(*this, event_size_out);
1257
1258     m_transmitProcessor->setVerboseLevel(getDebugLevel());
1259
1260     if(!m_transmitProcessor->init()) {
1261         debugFatal("Could not initialize transmit processor!\n");
1262         return false;
1263     }
1264
1265     if(!m_transmitProcessor->setDllBandwidth(xmit_sp_dll_bw)) {
1266         debugFatal("Could not set DLL bandwidth\n");
1267         delete m_transmitProcessor;
1268         m_transmitProcessor = NULL;
1269         return false;
1270     }
1271
1272     // Now we add ports to the processor
1273     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
1274
1275     // Add audio playback ports
1276     if (!addDirPorts(Streaming::Port::E_Playback, samp_freq, optical_out_mode_a, optical_out_mode_b)) {
1277         return false;
1278     }
1279
1280     // Add MIDI port.  The MOTU only has one output MIDI port, with each
1281     // MIDI byte transmitted using a 3 byte sequence starting at byte 4
1282     // of the event data.
1283     asprintf(&buff,"%s_pbk_MIDI0",id.c_str());
1284     p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff,
1285         Streaming::Port::E_Playback, 4);
1286     if (!p) {
1287         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
1288     }
1289     free(buff);
1290
1291     // example of adding an control port:
1292 //    asprintf(&buff,"%s_pbk_%s",id.c_str(),"myportnamehere");
1293 //
1294 //    p=new Streaming::MotuControlPort(
1295 //            buff,
1296 //            Streaming::Port::E_Playback,
1297 //            0 // you can add all other port specific stuff you
1298 //              // need to pass by extending MotuXXXPort and MotuPortInfo
1299 //    );
1300 //    free(buff);
1301 //
1302 //    if (!p) {
1303 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
1304 //    } else {
1305 //        if (!m_transmitProcessor->addPort(p)) {
1306 //            debugWarning("Could not register port with stream processor\n");
1307 //            return false;
1308 //        } else {
1309 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
1310 //        }
1311 //    }
1312
1313     return true;
1314 }
1315
1316 int
1317 MotuDevice::getStreamCount() {
1318      return 2; // one receive, one transmit
1319 }
1320
1321 Streaming::StreamProcessor *
1322 MotuDevice::getStreamProcessorByIndex(int i) {
1323     switch (i) {
1324     case 0:
1325         return m_receiveProcessor;
1326     case 1:
1327          return m_transmitProcessor;
1328     default:
1329         return NULL;
1330     }
1331     return 0;
1332 }
1333
1334 bool
1335 MotuDevice::startStreamByIndex(int i) {
1336
1337 quadlet_t isoctrl = ReadRegister(MOTU_REG_ISOCTRL);
1338
1339     if (m_motu_model == MOTU_MODEL_828MkI) {
1340         // The 828MkI device does this differently.
1341         // To be implemented
1342         return false;
1343     }
1344
1345     // NOTE: this assumes that you have two streams
1346     switch (i) {
1347     case 0:
1348         // TODO: do the stuff that is nescessary to make the device
1349         // receive a stream
1350
1351         // Set the streamprocessor channel to the one obtained by
1352         // the connection management
1353         m_receiveProcessor->setChannel(m_iso_recv_channel);
1354
1355         // Mask out current transmit settings of the MOTU and replace
1356         // with new ones.  Turn bit 24 on to enable changes to the
1357         // MOTU's iso transmit settings when the iso control register
1358         // is written.  Bit 23 enables iso transmit from the MOTU.
1359         isoctrl &= 0xff00ffff;
1360         isoctrl |= (m_iso_recv_channel << 16);
1361         isoctrl |= 0x00c00000;
1362         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1363         break;
1364     case 1:
1365         // TODO: do the stuff that is nescessary to make the device
1366         // transmit a stream
1367
1368         // Set the streamprocessor channel to the one obtained by
1369         // the connection management
1370         m_transmitProcessor->setChannel(m_iso_send_channel);
1371
1372         // Mask out current receive settings of the MOTU and replace
1373         // with new ones.  Turn bit 31 on to enable changes to the
1374         // MOTU's iso receive settings when the iso control register
1375         // is written.  Bit 30 enables iso receive by the MOTU.
1376         isoctrl &= 0x00ffffff;
1377         isoctrl |= (m_iso_send_channel << 24);
1378         isoctrl |= 0xc0000000;
1379         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1380         break;
1381
1382     default: // Invalid stream index
1383         return false;
1384     }
1385
1386     return true;
1387 }
1388
1389 bool
1390 MotuDevice::stopStreamByIndex(int i) {
1391
1392 quadlet_t isoctrl = ReadRegister(MOTU_REG_ISOCTRL);
1393
1394     // TODO: connection management: break connection
1395     // cfr the start function
1396
1397     if (m_motu_model == MOTU_MODEL_828MkI) {
1398         // The 828MkI device does this differently.
1399         // To be implemented
1400         return false;
1401     }
1402
1403     // NOTE: this assumes that you have two streams
1404     switch (i) {
1405     case 0:
1406         // Turn bit 22 off to disable iso send by the MOTU.  Turn
1407         // bit 23 on to enable changes to the MOTU's iso transmit
1408         // settings when the iso control register is written.
1409         isoctrl &= 0xffbfffff;
1410         isoctrl |= 0x00800000;
1411         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1412         break;
1413     case 1:
1414         // Turn bit 30 off to disable iso receive by the MOTU.  Turn
1415         // bit 31 on to enable changes to the MOTU's iso receive
1416         // settings when the iso control register is written.
1417         isoctrl &= 0xbfffffff;
1418         isoctrl |= 0x80000000;
1419         WriteRegister(MOTU_REG_ISOCTRL, isoctrl);
1420         break;
1421
1422     default: // Invalid stream index
1423         return false;
1424     }
1425
1426     return true;
1427 }
1428
1429 signed int MotuDevice::getIsoRecvChannel(void) {
1430     return m_iso_recv_channel;
1431 }
1432
1433 signed int MotuDevice::getIsoSendChannel(void) {
1434     return m_iso_send_channel;
1435 }
1436
1437 signed int MotuDevice::getDeviceGeneration(void) {
1438     if (m_motu_model == MOTU_MODEL_828MkI)
1439         return MOTU_DEVICE_G1;
1440     if (m_motu_model==MOTU_MODEL_828mk3 ||
1441         m_motu_model==MOTU_MODEL_ULTRALITEmk3)
1442         return MOTU_DEVICE_G3;
1443     return MOTU_DEVICE_G2;
1444 }
1445
1446 unsigned int MotuDevice::getOpticalMode(unsigned int dir,
1447   unsigned int *port_a_mode, unsigned int *port_b_mode) {
1448     // Only the "Mark 3" (aka G3) MOTU devices had more than one optical
1449     // port.  Therefore the "port_b_mode" parameter is unused by all
1450     // devices other than the Mark 3 devices.
1451     //
1452     // If a mode parameter pointer is NULL it will not be returned.
1453     unsigned int reg;
1454     unsigned int mask, shift;
1455
1456     if (port_b_mode != NULL)
1457         *port_b_mode = MOTU_OPTICAL_MODE_NONE;
1458     if (getDeviceGeneration()!=MOTU_DEVICE_G3 && port_a_mode==NULL)
1459         return 0;
1460
1461     if (m_motu_model == MOTU_MODEL_828MkI) {
1462         // The early devices used a different register layout. 
1463         reg = ReadRegister(MOTU_G1_REG_CONFIG);
1464         mask = (dir==MOTU_DIR_IN)?MOTU_G1_OPT_IN_MODE_MASK:MOTU_G1_OPT_OUT_MODE_MASK;
1465         shift = (dir==MOTU_DIR_IN)?MOTU_G1_OPT_IN_MODE_BIT0:MOTU_G1_OPT_OUT_MODE_BIT0;
1466         switch ((reg & mask) >> shift) {
1467             case MOTU_G1_OPTICAL_OFF: *port_a_mode = MOTU_OPTICAL_MODE_OFF; break;
1468             case MOTU_G1_OPTICAL_TOSLINK: *port_a_mode = MOTU_OPTICAL_MODE_TOSLINK; break;
1469             // MOTU_G1_OPTICAL_OFF and MOTU_G1_OPTICAL_ADAT seem to be
1470             // identical, so currently we don't know how to differentiate
1471             // these two modes.
1472             // case MOTU_G1_OPTICAL_ADAT: return MOTU_OPTICAL_MODE_ADAT;
1473         }
1474         return 0;
1475     }
1476
1477     if (getDeviceGeneration() == MOTU_DEVICE_G3) {
1478         unsigned int mask, enable, toslink;
1479         reg = ReadRegister(MOTU_G3_REG_OPTICAL_CTRL);
1480         if (port_a_mode != NULL) {
1481             mask = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_A_IN_MASK:MOTU_G3_OPT_A_OUT_MASK;
1482             enable = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_A_IN_ENABLE:MOTU_G3_OPT_A_OUT_ENABLE;
1483             toslink = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_A_IN_TOSLINK:MOTU_G3_OPT_A_OUT_TOSLINK;
1484             if ((reg & enable) == 0)
1485               *port_a_mode = MOTU_OPTICAL_MODE_OFF;
1486             else
1487             if ((reg * toslink) == 0)
1488               *port_a_mode = MOTU_OPTICAL_MODE_TOSLINK;
1489             else
1490               *port_a_mode = MOTU_OPTICAL_MODE_ADAT;
1491         }
1492         if (port_b_mode != NULL) {
1493             mask = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_B_IN_MASK:MOTU_G3_OPT_B_OUT_MASK;
1494             enable = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_B_IN_ENABLE:MOTU_G3_OPT_B_OUT_ENABLE;
1495             toslink = (dir==MOTU_DIR_IN)?MOTU_G3_OPT_B_IN_TOSLINK:MOTU_G3_OPT_B_OUT_TOSLINK;
1496             if ((reg & enable) == 0)
1497               *port_b_mode = MOTU_OPTICAL_MODE_OFF;
1498             else
1499             if ((reg * toslink) == 0)
1500               *port_b_mode = MOTU_OPTICAL_MODE_TOSLINK;
1501             else
1502               *port_b_mode = MOTU_OPTICAL_MODE_ADAT;
1503         }
1504         return 0;
1505     }
1506
1507     reg = ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
1508     mask = (dir==MOTU_DIR_IN)?MOTU_G2_OPTICAL_IN_MODE_MASK:MOTU_G2_OPTICAL_OUT_MODE_MASK;
1509     shift = (dir==MOTU_DIR_IN)?MOTU_G2_OPTICAL_IN_MODE_BIT0:MOTU_G2_OPTICAL_OUT_MODE_BIT0;
1510     switch ((reg & mask) >> shift) {
1511         case MOTU_G2_OPTICAL_MODE_OFF: *port_a_mode = MOTU_OPTICAL_MODE_OFF; break;
1512         case MOTU_G2_OPTICAL_MODE_ADAT: *port_a_mode = MOTU_OPTICAL_MODE_ADAT; break;
1513         case MOTU_G2_OPTICAL_MODE_TOSLINK: *port_a_mode = MOTU_OPTICAL_MODE_TOSLINK; break;
1514     }
1515     return 0;
1516 }
1517
1518 signed int MotuDevice::setOpticalMode(unsigned int dir,
1519   unsigned int port_a_mode, unsigned int port_b_mode) {
1520     // Only the "Mark 3" (aka G3) MOTU devices had more than one optical port.
1521     // Therefore the "port B" mode is ignored for all devices other than
1522     // the Mark 3 devices.
1523     unsigned int reg, g2mode;
1524     unsigned int opt_ctrl = 0x0000002;
1525
1526     /* THe 896HD doesn't have an SPDIF/TOSLINK optical mode, so don't try to
1527      * set it
1528      */
1529     if (m_motu_model==MOTU_MODEL_896HD && port_a_mode==MOTU_OPTICAL_MODE_TOSLINK)
1530         return -1;
1531
1532     if (getDeviceGeneration()!=MOTU_DEVICE_G3 && port_a_mode==MOTU_OPTICAL_MODE_KEEP)
1533         return 0;
1534
1535     if (m_motu_model == MOTU_MODEL_828MkI) {
1536         // The earlier MOTUs handle this differently.
1537         unsigned int mask, shift, g1mode = 0;
1538         reg = ReadRegister(MOTU_G1_REG_CONFIG);
1539         mask = (dir==MOTU_DIR_IN)?MOTU_G1_OPT_IN_MODE_MASK:MOTU_G1_OPT_OUT_MODE_MASK;
1540         shift = (dir==MOTU_DIR_IN)?MOTU_G1_OPT_IN_MODE_BIT0:MOTU_G1_OPT_OUT_MODE_BIT0;
1541         switch (port_a_mode) {
1542             case MOTU_OPTICAL_MODE_OFF: g1mode = MOTU_G1_OPTICAL_OFF; break;
1543             case MOTU_OPTICAL_MODE_ADAT: g1mode = MOTU_G1_OPTICAL_ADAT; break;
1544             // See comment in getOpticalMode() about mode ambiguity
1545             // case MOTU_OPTICAL_MODE_TOSLINK: g1mode = MOTU_G1_OPTICAL_TOSLINK; break;
1546         }
1547         reg = (reg & ~mask) | (g1mode << shift);
1548         return WriteRegister(MOTU_G1_REG_CONFIG, reg);
1549     }
1550
1551     /* The G3 devices are also quite a bit different to the G2 units */
1552     if (getDeviceGeneration() == MOTU_DEVICE_G3) {
1553         unsigned int mask, enable, toslink;
1554         reg = ReadRegister(MOTU_G3_REG_OPTICAL_CTRL);
1555         if (port_a_mode != MOTU_OPTICAL_MODE_KEEP) {
1556             mask = enable = toslink = 0;
1557             if (dir & MOTU_DIR_IN) {
1558                  mask |= MOTU_G3_OPT_A_IN_MASK;
1559                  enable |= MOTU_G3_OPT_A_IN_ENABLE;
1560                  toslink |= MOTU_G3_OPT_A_IN_TOSLINK;
1561             }
1562             if (dir & MOTU_DIR_OUT) {
1563                  mask |= MOTU_G3_OPT_A_OUT_MASK;
1564                  enable |= MOTU_G3_OPT_A_OUT_ENABLE;
1565                  toslink |= MOTU_G3_OPT_A_OUT_TOSLINK;
1566             }
1567             reg = (reg & ~mask) | enable;
1568             switch (port_a_mode) {
1569                 case MOTU_OPTICAL_MODE_OFF: reg &= ~enable; break;
1570                 case MOTU_OPTICAL_MODE_TOSLINK: reg |= toslink; break;
1571             }
1572         }
1573         if (port_b_mode != MOTU_OPTICAL_MODE_KEEP) {
1574             mask = enable = toslink = 0;
1575             if (dir & MOTU_DIR_IN) {
1576                  mask |= MOTU_G3_OPT_B_IN_MASK;
1577                  enable |= MOTU_G3_OPT_B_IN_ENABLE;
1578                  toslink |= MOTU_G3_OPT_B_IN_TOSLINK;
1579             }
1580             if (dir & MOTU_DIR_OUT) {
1581                  mask |= MOTU_G3_OPT_B_OUT_MASK;
1582                  enable |= MOTU_G3_OPT_B_OUT_ENABLE;
1583                  toslink |= MOTU_G3_OPT_B_OUT_TOSLINK;
1584             }
1585             reg = (reg & ~mask) | enable;
1586             switch (port_a_mode) {
1587                 case MOTU_OPTICAL_MODE_OFF: reg &= ~enable; break;
1588                 case MOTU_OPTICAL_MODE_TOSLINK: reg |= toslink; break;
1589             }
1590             reg = (reg & ~mask) | enable;
1591             switch (port_b_mode) {
1592                 case MOTU_OPTICAL_MODE_OFF: reg &= ~enable; break;
1593                 case MOTU_OPTICAL_MODE_TOSLINK: reg |= toslink; break;
1594             }
1595         }
1596         return WriteRegister(MOTU_G3_REG_OPTICAL_CTRL, reg);
1597     }
1598
1599     reg = ReadRegister(MOTU_REG_ROUTE_PORT_CONF);
1600
1601     // Map from user mode to values sent to the device registers.
1602     g2mode = 0;
1603     switch (port_a_mode) {
1604         case MOTU_OPTICAL_MODE_OFF: g2mode = MOTU_G2_OPTICAL_MODE_OFF; break;
1605         case MOTU_OPTICAL_MODE_ADAT: g2mode = MOTU_G2_OPTICAL_MODE_ADAT; break;
1606         case MOTU_OPTICAL_MODE_TOSLINK: g2mode = MOTU_G2_OPTICAL_MODE_TOSLINK; break;
1607     }
1608
1609     // Set up the optical control register value according to the current
1610     // optical port modes.  At this stage it's not completely understood
1611     // what the "Optical control" register does, so the values it's set to
1612     // are more or less "magic" numbers.
1613     if ((reg & MOTU_G2_OPTICAL_IN_MODE_MASK) != (MOTU_G2_OPTICAL_MODE_ADAT<<MOTU_G2_OPTICAL_IN_MODE_BIT0))
1614         opt_ctrl |= 0x00000080;
1615     if ((reg & MOTU_G2_OPTICAL_OUT_MODE_MASK) != (MOTU_G2_OPTICAL_MODE_ADAT<<MOTU_G2_OPTICAL_OUT_MODE_BIT0))
1616         opt_ctrl |= 0x00000040;
1617
1618     if (dir & MOTU_DIR_IN) {
1619         reg &= ~MOTU_G2_OPTICAL_IN_MODE_MASK;
1620         reg |= (g2mode << MOTU_G2_OPTICAL_IN_MODE_BIT0) & MOTU_G2_OPTICAL_IN_MODE_MASK;
1621         if (g2mode != MOTU_G2_OPTICAL_MODE_ADAT)
1622             opt_ctrl |= 0x00000080;
1623         else
1624             opt_ctrl &= ~0x00000080;
1625     }
1626     if (dir & MOTU_DIR_OUT) {
1627         reg &= ~MOTU_G2_OPTICAL_OUT_MODE_MASK;
1628         reg |= (g2mode << MOTU_G2_OPTICAL_OUT_MODE_BIT0) & MOTU_G2_OPTICAL_OUT_MODE_MASK;
1629         if (g2mode != MOTU_G2_OPTICAL_MODE_ADAT)
1630             opt_ctrl |= 0x00000040;
1631         else
1632             opt_ctrl &= ~0x00000040;
1633     }
1634
1635     /* Setting bit 25 in the route/port configuration register enables the
1636      * setting of the optical mode.  Bit 24 allows the phones assign to be
1637      * set using the lower 8 bits of the register.  This function has no
1638      * business setting that, so make sure bit 24 is masked off.
1639      */
1640     reg |= 0x02000000;
1641     reg &= ~0x01000000;
1642
1643     // FIXME: there seems to be more to it than this, but for
1644     // the moment at least this seems to work.
1645     WriteRegister(MOTU_REG_ROUTE_PORT_CONF, reg);
1646     return WriteRegister(MOTU_REG_OPTICAL_CTRL, opt_ctrl);
1647 }
1648
1649 signed int MotuDevice::getEventSize(unsigned int direction) {
1650 //
1651 // Return the size in bytes of a single event sent to (dir==MOTU_OUT) or
1652 // from (dir==MOTU_IN) the MOTU as part of an iso data packet.
1653 //
1654 // FIXME: for performance it may turn out best to calculate the event
1655 // size in setOpticalMode and cache the result in a data field.  However,
1656 // as it stands this will not adapt to dynamic changes in sample rate - we'd
1657 // need a setFrameRate() for that.
1658 //
1659 // At the very least an event consists of the SPH (4 bytes) and the control/MIDI
1660 // bytes (6 bytes).
1661 // Note that all audio channels are sent using 3 bytes.
1662 signed int sample_rate = getSamplingFrequency();
1663 unsigned int optical_mode_a, optical_mode_b;
1664 signed int size = 4+6;
1665
1666 unsigned int i;
1667 unsigned int dir = direction==Streaming::Port::E_Capture?MOTU_PA_IN:MOTU_PA_OUT;
1668 unsigned int flags = 0;
1669 unsigned int port_flags;
1670
1671     getOpticalMode(direction, &optical_mode_a, &optical_mode_b);
1672
1673     if ( sample_rate > 96000 )
1674         flags |= MOTU_PA_RATE_4x;
1675     else if ( sample_rate > 48000 )
1676         flags |= MOTU_PA_RATE_2x;
1677     else
1678         flags |= MOTU_PA_RATE_1x;
1679
1680     switch (optical_mode_a) {
1681         case MOTU_OPTICAL_MODE_OFF: flags |= MOTU_PA_OPTICAL_OFF; break;
1682         case MOTU_OPTICAL_MODE_ADAT: flags |= MOTU_PA_OPTICAL_ADAT; break;
1683         case MOTU_OPTICAL_MODE_TOSLINK: flags |= MOTU_PA_OPTICAL_TOSLINK; break;
1684     }
1685     switch (optical_mode_b) {
1686         case MOTU_OPTICAL_MODE_NONE: flags |= MOTU_PA_MK3_OPT_B_ANY; break;
1687         case MOTU_OPTICAL_MODE_OFF: flags |= MOTU_PA_MK3_OPT_B_OFF; break;
1688         case MOTU_OPTICAL_MODE_ADAT: flags |= MOTU_PA_MK3_OPT_B_ADAT; break;
1689         case MOTU_OPTICAL_MODE_TOSLINK: flags |= MOTU_PA_MK3_OPT_B_TOSLINK; break;
1690     }
1691
1692     // Don't test for padding port flag here since we need to include such
1693     // pseudo-ports when calculating the event size.
1694     for (i=0; i < DevicesProperty[m_motu_model-1].n_port_entries; i++) {
1695         port_flags = DevicesProperty[m_motu_model-1].port_entry[i].port_flags;
1696         /* Make sure the "port B" test returns true for devices without
1697          * a port B.
1698          */
1699         if (optical_mode_b == MOTU_OPTICAL_MODE_NONE) {
1700             port_flags |= MOTU_PA_MK3_OPT_B_ANY;
1701         }
1702         if (( port_flags & dir ) &&
1703            ( port_flags & MOTU_PA_RATE_MASK & flags ) &&
1704            ( port_flags & MOTU_PA_MK3_OPT_B_MASK & flags ) &&
1705            ( port_flags & MOTU_PA_OPTICAL_MASK & flags )) {
1706             size += 3;
1707         }
1708     }
1709
1710     // Finally round size up to the next quadlet boundary
1711     return ((size+3)/4)*4;
1712 }
1713 /* ======================================================================= */
1714
1715 bool MotuDevice::addPort(Streaming::StreamProcessor *s_processor,
1716   char *name, enum Streaming::Port::E_Direction direction,
1717   int position, int size) {
1718 /*
1719  * Internal helper function to add a MOTU port to a given stream processor.
1720  * This just saves the unnecessary replication of what is essentially
1721  * boilerplate code.  Note that the port name is freed by this function
1722  * prior to exit.
1723  */
1724 Streaming::Port *p=NULL;
1725
1726     p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size);
1727
1728     if (!p) {
1729         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
1730     }
1731     free(name);
1732     return true;
1733 }
1734 /* ======================================================================= */
1735
1736 bool MotuDevice::addDirPorts(
1737   enum Streaming::Port::E_Direction direction, unsigned int sample_rate,
1738   unsigned int optical_a_mode, unsigned int optical_b_mode) {
1739 /*
1740  * Internal helper method: adds all required ports for the given direction
1741  * based on the indicated sample rate and optical mode.
1742  *
1743  * Notes: currently ports are not created if they are disabled due to sample
1744  * rate or optical mode.  However, it might be better to unconditionally
1745  * create all ports and just disable those which are not active.
1746  */
1747 const char *mode_str = direction==Streaming::Port::E_Capture?"cap":"pbk";
1748 Streaming::StreamProcessor *s_processor;
1749 unsigned int i;
1750 char *buff;
1751 unsigned int dir = direction==Streaming::Port::E_Capture?MOTU_PA_IN:MOTU_PA_OUT;
1752 unsigned int flags = 0;
1753 unsigned int port_flags;
1754
1755
1756     if ( sample_rate > 96000 )
1757         flags |= MOTU_PA_RATE_4x;
1758     else if ( sample_rate > 48000 )
1759         flags |= MOTU_PA_RATE_2x;
1760     else
1761         flags |= MOTU_PA_RATE_1x;
1762
1763     switch (optical_a_mode) {
1764         case MOTU_OPTICAL_MODE_OFF: flags |= MOTU_PA_OPTICAL_OFF; break;
1765         case MOTU_OPTICAL_MODE_ADAT: flags |= MOTU_PA_OPTICAL_ADAT; break;
1766         case MOTU_OPTICAL_MODE_TOSLINK: flags |= MOTU_PA_OPTICAL_TOSLINK; break;
1767     }
1768     switch (optical_b_mode) {
1769         case MOTU_OPTICAL_MODE_NONE: flags |= MOTU_PA_MK3_OPT_B_ANY; break;
1770         case MOTU_OPTICAL_MODE_OFF: flags |= MOTU_PA_MK3_OPT_B_OFF; break;
1771         case MOTU_OPTICAL_MODE_ADAT: flags |= MOTU_PA_MK3_OPT_B_ADAT; break;
1772         case MOTU_OPTICAL_MODE_TOSLINK: flags |= MOTU_PA_MK3_OPT_B_TOSLINK; break;
1773     }
1774
1775     // retrieve the ID
1776     std::string id=std::string("dev?");
1777     if(!getOption("id", id)) {
1778         debugWarning("Could not retrieve id parameter, defaulting to 'dev?'\n");
1779     }
1780
1781     if (direction == Streaming::Port::E_Capture) {
1782         s_processor = m_receiveProcessor;
1783     } else {
1784         s_processor = m_transmitProcessor;
1785     }
1786
1787     for (i=0; i < DevicesProperty[m_motu_model-1].n_port_entries; i++) {
1788         port_flags = DevicesProperty[m_motu_model-1].port_entry[i].port_flags;
1789         /* For devices without an optical port B ensure the test on the
1790          * optical port B mode always returns "true".
1791          */
1792         if (optical_b_mode == MOTU_OPTICAL_MODE_NONE)
1793             port_flags |= MOTU_PA_MK3_OPT_B_ANY;
1794
1795         if (( port_flags & dir ) &&
1796            ( port_flags & MOTU_PA_RATE_MASK & flags ) &&
1797            ( port_flags & MOTU_PA_OPTICAL_MASK & flags ) &&
1798            ( port_flags & MOTU_PA_MK3_OPT_B_MASK & flags ) &&
1799            !( port_flags & MOTU_PA_PADDING )) {
1800             asprintf(&buff,"%s_%s_%s" , id.c_str(), mode_str,
1801               DevicesProperty[m_motu_model-1].port_entry[i].port_name);
1802             if (!addPort(s_processor, buff, direction, DevicesProperty[m_motu_model-1].port_entry[i].port_offset, 0))
1803                 return false;
1804         }
1805     }
1806    
1807     return true;
1808 }
1809 /* ======================================================================== */
1810
1811 unsigned int MotuDevice::ReadRegister(fb_nodeaddr_t reg) {
1812 /*
1813  * Attempts to read the requested register from the MOTU.
1814  */
1815
1816     quadlet_t quadlet = 0;
1817
1818     /* If the supplied register has no upper bits set assume it's a G1/G2
1819      * register which is assumed to be relative to MOTU_REG_BASE_ADDR.
1820      */
1821     if ((reg & MOTU_REG_BASE_ADDR) == 0)
1822         reg |= MOTU_REG_BASE_ADDR;
1823
1824     // Note: 1394Service::read() expects a physical ID, not the node id
1825     if (get1394Service().read(0xffc0 | getNodeId(), reg, 1, &quadlet) <= 0) {
1826         debugError("Error doing motu read from register 0x%012llx\n",reg);
1827     }
1828
1829     return CondSwapFromBus32(quadlet);
1830 }
1831
1832 signed int MotuDevice::WriteRegister(fb_nodeaddr_t reg, quadlet_t data) {
1833 /*
1834  * Attempts to write the given data to the requested MOTU register.
1835  */
1836
1837     unsigned int err = 0;
1838     data = CondSwapToBus32(data);
1839
1840     /* If the supplied register has no upper bits set assume it's a G1/G2
1841      * register which is assumed to be relative to MOTU_REG_BASE_ADDR.
1842      */
1843     if ((reg & MOTU_REG_BASE_ADDR) == 0)
1844         reg |= MOTU_REG_BASE_ADDR;
1845
1846     // Note: 1394Service::write() expects a physical ID, not the node id
1847     if (get1394Service().write(0xffc0 | getNodeId(), reg, 1, &data) <= 0) {
1848         err = 1;
1849         debugError("Error doing motu write to register 0x%012llx\n",reg);
1850     }
1851
1852     SleepRelativeUsec(100);
1853     return (err==0)?0:-1;
1854 }
1855
1856 }
Note: See TracBrowser for help on using the browser.