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

Revision 1879, 88.1 kB (checked in by jwoithe, 14 years ago)

MOTU: fix a typo affecting the correct detection of G3 optical port modes.

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