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

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

MOTU: fix a long-standing typo bug which tripped things up with the new port cache. Clearly the port mode isn't checked all that often, or this would never have worked.

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