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

Revision 1509, 72.3 kB (checked in by jwoithe, 12 years ago)

- MOTU: Refactor mixer control logic to make things clearer. Please test to ensure the changes haven't caused regressions for suppoted devices.
- MOTU: Implement buttons for the Ultralite's phase inversion controls. Connect Ultralite trimgain mixer controls to their respective dbus paths. These additional Ultralite controls have a much greater chance of working now - please test.

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