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

Revision 1425, 71.3 kB (checked in by jwoithe, 15 years ago)

MOTU: fix a NULL pointer dereference for devices without mixer definitions which I thought I fixed some months ago (thanks to Peter Peter McCormick? for spotting this)

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