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

Revision 1605, 76.1 kB (checked in by jwoithe, 13 years ago)

RME: implement the beginnings of a device control interface via the ffado dbus framework.
MOTU: fix error handling code paths in buildMixer() and destroyMixer().

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