root/branches/libffado-2.0/src/motu/motu_avdevice.cpp

Revision 1518, 73.6 kB (checked in by jwoithe, 15 years ago)

MOTU: tweak jack port layout for the 896HD.

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