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

Revision 1835, 80.8 kB (checked in by jwoithe, 11 years ago)

MOTU:

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