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

Revision 981, 39.6 kB (checked in by jwoithe, 16 years ago)

config.h.in: reworked MOTU_* constants to get "nearly correct" timestamps in outgoing packets. This makes playback at 2x and 4x samplerates work. More fine-tuning may be needed.

motu_avdevice.cpp: account for different port locations in packet data at 4x rates.

motu_avdevice.cpp: MotuDevice::probe(), MotuDevice::createDevice(): remove commented out references to the ConfigRom? ModelID field; with MOTUs this is useless for differentiating models.

motu_avdevice.cpp: MotuDevice::setOpticalMode(): the 896HD doesn't have an SPDIF/TOSLINK optical mode, so don't try to set it.

RME: implemented first cut at sample rate control. This has about a 50% chance of working as it currently stands.

MOTU: minor whitespace fixes for consistency.

MOTU: start implementation of device status tracking.

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/DelayLockedLoop.h"
39 #include "libutil/Time.h"
40
41 #include <string>
42 #include <stdint.h>
43 #include <assert.h>
44 #include <netinet/in.h>
45 #include <iostream>
46 #include <sstream>
47
48 #include <libraw1394/csr.h>
49
50 namespace Motu {
51
52 // Define the supported devices.  Device ordering is arbitary here.
53 static VendorModelEntry supportedDeviceList[] =
54 {
55 //  {vendor_id, model_id, unit_version, unit_specifier_id, model, vendor_name,model_name}
56     {FW_VENDORID_MOTU, 0, 0x00000003, 0x000001f2, MOTUFW_MODEL_828mkII, "MOTU", "828MkII"},
57     {FW_VENDORID_MOTU, 0, 0x00000009, 0x000001f2, MOTUFW_MODEL_TRAVELER, "MOTU", "Traveler"},
58     {FW_VENDORID_MOTU, 0, 0x0000000d, 0x000001f2, MOTUFW_MODEL_ULTRALITE, "MOTU", "UltraLite"},
59     {FW_VENDORID_MOTU, 0, 0x0000000f, 0x000001f2, MOTUFW_MODEL_8PRE, "MOTU", "8pre"},
60     {FW_VENDORID_MOTU, 0, 0x00000001, 0x000001f2, MOTUFW_MODEL_828MkI, "MOTU", "828MkI"},
61     {FW_VENDORID_MOTU, 0, 0x00000005, 0x000001f2, MOTUFW_MODEL_896HD, "MOTU", "896HD"},
62 };
63
64 // Ports declarations
65 const PortEntry Ports_828MKI[] =
66 {
67     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
68     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
69     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
70     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
71     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
72     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
73     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
74     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
75     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
76     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
77     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 40},
78     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 43},
79     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 46},
80     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 49},
81     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 52},
82     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 55},
83     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 58},
84     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 61},
85 };
86
87 const PortEntry Ports_896HD[] =
88 {
89     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
90     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
91     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
92     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
93     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
94     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
95     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
96     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
97     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
98     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
99     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
100     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
101     {"MainOut-L", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 40},
102     {"MainOut-R", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 43},
103     {"AES/EBU1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 46},
104     {"AES/EBU2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 49},
105     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 52},
106     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 55},
107     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 58},
108     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 61},
109     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 64},
110     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 67},
111     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 70},
112     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 73},
113 };
114
115 const PortEntry Ports_828MKII[] =
116 {
117     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
118     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
119     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
120     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
121     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
122     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
123     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
124     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
125     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
126     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
127     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
128     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
129     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
130     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
131     {"Mic1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
132     {"Mic2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
133     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 46},
134     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 49},
135     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 52},
136     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 55},
137     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 58},
138     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 61},
139     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 64},
140     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 67},
141     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 70},
142     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 73},
143 };
144
145 const PortEntry Ports_TRAVELER[] =
146 {
147     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
148     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
149     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 10},
150     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 13},
151     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 16},
152     {"Analog1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 10},
153     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 19},
154     {"Analog2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 13},
155     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 22},
156     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 16},
157     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 25},
158     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 19},
159     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 28},
160     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 22},
161     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 31},
162     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 25},
163     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 34},
164     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 28},
165     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 37},
166     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_4x|MOTUFW_PA_OPTICAL_ANY, 31},
167     {"AES/EBU1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 40},
168     {"AES/EBU2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ANY, 43},
169     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_OFF|MOTUFW_PA_OPTICAL_ADAT, 46},
170     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_OFF|MOTUFW_PA_OPTICAL_ADAT, 49},
171     {"Toslink1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_TOSLINK, 46},
172     {"Toslink2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_TOSLINK, 49},
173     {"ADAT1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 52},
174     {"ADAT2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 55},
175     {"ADAT3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 58},
176     {"ADAT4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x2x|MOTUFW_PA_OPTICAL_ADAT, 61},
177     {"ADAT5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 64},
178     {"ADAT6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 67},
179     {"ADAT7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 70},
180     {"ADAT8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_1x|MOTUFW_PA_OPTICAL_ADAT, 73},
181 };
182
183 const PortEntry Ports_ULTRALITE[] =
184 {
185     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 40},
186     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 43},
187     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
188     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
189     {"Mic1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
190     {"Mic2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
191     {"Analog1", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
192     {"Analog2", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
193     {"Analog3", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
194     {"Analog4", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
195     {"Analog5", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
196     {"Analog6", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
197     {"Analog7", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
198     {"Analog8", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
199     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
200     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
201     {"SPDIF1", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 46},
202     {"SPDIF2", MOTUFW_DIR_INOUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 49},
203 };
204
205 const PortEntry Ports_8PRE[] =
206 {
207     {"Analog1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
208     {"Analog2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
209     {"Analog3", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 22},
210     {"Analog4", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 25},
211     {"Analog5", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 28},
212     {"Analog6", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 31},
213     {"Analog7", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 34},
214     {"Analog8", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 37},
215     {"Mix-L", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
216     {"Mix-R", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
217     {"Main-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 16},
218     {"Main-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 19},
219     {"Phones-L", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 10},
220     {"Phones-R", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ANY, 13},
221     {"ADAT1", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 40},
222     {"ADAT1", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 22},
223     {"ADAT2", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 43},
224     {"ADAT2", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 25},
225     {"ADAT3", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 46},
226     {"ADAT3", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 28},
227     {"ADAT4", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 49},
228     {"ADAT4", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 31},
229     {"ADAT5", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 52},
230     {"ADAT5", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 34},
231     {"ADAT6", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 55},
232     {"ADAT6", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 37},
233     {"ADAT7", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 58},
234     {"ADAT7", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 40},
235     {"ADAT8", MOTUFW_DIR_IN, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 61},
236     {"ADAT8", MOTUFW_DIR_OUT, MOTUFW_PA_RATE_ANY|MOTUFW_PA_OPTICAL_ADAT, 43},
237 };
238
239 /* The order of DevicesProperty entries must match the numeric order of the
240  * MOTU model enumeration (EMotuModel).
241  */
242 const DevicePropertyEntry DevicesProperty[] = {
243 //  { Ports_map,       sizeof( Ports_map ),        MaxSR },
244     { Ports_828MKII,   sizeof( Ports_828MKII ),    96000 },
245     { Ports_TRAVELER,  sizeof( Ports_TRAVELER ),  192000 },
246     { Ports_ULTRALITE, sizeof( Ports_ULTRALITE ),  96000 },
247     { Ports_8PRE,      sizeof( Ports_8PRE ),       96000 },
248     { Ports_828MKI,    sizeof( Ports_828MKI ),     48000 },
249     { Ports_896HD,     sizeof( Ports_896HD ),     192000 },
250 };
251
252 MotuDevice::MotuDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
253     : FFADODevice( d, configRom )
254     , m_motu_model( MOTUFW_MODEL_NONE )
255     , m_iso_recv_channel ( -1 )
256     , m_iso_send_channel ( -1 )
257     , m_rx_bandwidth ( -1 )
258     , m_tx_bandwidth ( -1 )
259     , m_receiveProcessor ( 0 )
260     , m_transmitProcessor ( 0 )
261
262 {
263     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
264                  getConfigRom().getNodeId() );
265 }
266
267 MotuDevice::~MotuDevice()
268 {
269     delete m_receiveProcessor;
270     delete m_transmitProcessor;
271
272     // Free ieee1394 bus resources if they have been allocated
273     if (m_iso_recv_channel>=0 && !get1394Service().freeIsoChannel(m_iso_recv_channel)) {
274         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
275     }
276     if (m_iso_send_channel>=0 && !get1394Service().freeIsoChannel(m_iso_send_channel)) {
277         debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
278     }
279 }
280
281 bool
282 MotuDevice::probe( ConfigRom& configRom )
283 {
284     unsigned int vendorId = configRom.getNodeVendorId();
285     unsigned int unitVersion = configRom.getUnitVersion();
286     unsigned int unitSpecifierId = configRom.getUnitSpecifierId();
287
288     for ( unsigned int i = 0;
289           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
290           ++i )
291     {
292         if ( ( supportedDeviceList[i].vendor_id == vendorId )
293              && ( supportedDeviceList[i].unit_version == unitVersion )
294              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
295            )
296         {
297             return true;
298         }
299     }
300
301     return false;
302 }
303
304 FFADODevice *
305 MotuDevice::createDevice(DeviceManager& d, std::auto_ptr<ConfigRom>( configRom ))
306 {
307     return new MotuDevice(d, configRom);
308 }
309
310 bool
311 MotuDevice::discover()
312 {
313     unsigned int vendorId = getConfigRom().getNodeVendorId();
314     unsigned int unitVersion = getConfigRom().getUnitVersion();
315     unsigned int unitSpecifierId = getConfigRom().getUnitSpecifierId();
316
317     for ( unsigned int i = 0;
318           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
319           ++i )
320     {
321         if ( ( supportedDeviceList[i].vendor_id == vendorId )
322              && ( supportedDeviceList[i].unit_version == unitVersion )
323              && ( supportedDeviceList[i].unit_specifier_id == unitSpecifierId )
324            )
325         {
326             m_model = &(supportedDeviceList[i]);
327             m_motu_model=supportedDeviceList[i].model;
328         }
329     }
330
331     if (m_model != NULL) {
332         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
333                 m_model->vendor_name, m_model->model_name);
334         return true;
335     }
336
337     return false;
338 }
339
340 int
341 MotuDevice::getSamplingFrequency( ) {
342 /*
343  * Retrieve the current sample rate from the MOTU device.
344  */
345     quadlet_t q = ReadRegister(MOTUFW_REG_CLK_CTRL);
346     int rate = 0;
347
348     switch (q & MOTUFW_RATE_BASE_MASK) {
349         case MOTUFW_RATE_BASE_44100:
350             rate = 44100;
351             break;
352         case MOTUFW_RATE_BASE_48000:
353             rate = 48000;
354             break;
355     }
356     switch (q & MOTUFW_RATE_MULTIPLIER_MASK) {
357         case MOTUFW_RATE_MULTIPLIER_2X:
358             rate *= 2;
359             break;
360         case MOTUFW_RATE_MULTIPLIER_4X:
361             rate *= 4;
362             break;
363     }
364     return rate;
365 }
366
367 int
368 MotuDevice::getConfigurationId()
369 {
370     return 0;
371 }
372
373 bool
374 MotuDevice::setSamplingFrequency( int samplingFrequency )
375 {
376 /*
377  * Set the MOTU device's samplerate.
378  */
379     char *src_name;
380     quadlet_t q, new_rate=0;
381     int i, supported=true, cancel_adat=false;
382
383     if ( samplingFrequency > DevicesProperty[m_motu_model-1].MaxSampleRate )
384        return false;
385
386     switch ( samplingFrequency ) {
387         case 22050:
388         case 24000:
389         case 32000:
390             supported=false;
391             break;
392         case 44100:
393             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_1X;
394             break;
395         case 48000:
396             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_1X;
397             break;
398         case 88200:
399             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_2X;
400             break;
401         case 96000:
402             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_2X;
403             break;
404         case 176400:
405             new_rate = MOTUFW_RATE_BASE_44100 | MOTUFW_RATE_MULTIPLIER_4X;
406             cancel_adat = true;  // current ADAT protocol doesn't support sample rate > 96000
407             break;
408         case 192000:
409             new_rate = MOTUFW_RATE_BASE_48000 | MOTUFW_RATE_MULTIPLIER_4X;
410             cancel_adat = true;
411             break;
412         default:
413             supported=false;
414     }
415
416     // Update the clock control register.  FIXME: while this is now rather
417     // comprehensive there may still be a need to manipulate MOTUFW_REG_CLK_CTRL
418     // a little more than we do.
419     if (supported) {
420         quadlet_t value=ReadRegister(MOTUFW_REG_CLK_CTRL);
421
422         // If optical port must be disabled (because a 4x sample rate has
423         // been selected) then do so before changing the sample rate.  At
424         // this stage it will be up to the user to re-enable the optical
425         // port if the sample rate is set to a 1x or 2x rate later.
426         if (cancel_adat) {
427             setOpticalMode(MOTUFW_DIR_INOUT, MOTUFW_OPTICAL_MODE_OFF);
428         }
429
430         value &= ~(MOTUFW_RATE_BASE_MASK|MOTUFW_RATE_MULTIPLIER_MASK);
431         value |= new_rate;
432
433         // In other OSes bit 26 of MOTUFW_REG_CLK_CTRL always seems
434         // to be set when this register is written to although the
435         // reason isn't currently known.  When we set it, it appears
436         // to prevent output being produced so we'll leave it unset
437         // until we work out what's going on.  Other systems write
438         // to MOTUFW_REG_CLK_CTRL multiple times, so that may be
439         // part of the mystery.
440         //   value |= 0x04000000;
441         if (WriteRegister(MOTUFW_REG_CLK_CTRL, value) == 0) {
442             supported=true;
443         } else {
444             supported=false;
445         }
446         // A write to the rate/clock control register requires the
447         // textual name of the current clock source be sent to the
448         // clock source name registers.
449         switch (value & MOTUFW_CLKSRC_MASK) {
450             case MOTUFW_CLKSRC_INTERNAL:
451                 src_name = "Internal        ";
452                 break;
453             case MOTUFW_CLKSRC_ADAT_OPTICAL:
454                 src_name = "ADAT Optical    ";
455                 break;
456             case MOTUFW_CLKSRC_SPDIF_TOSLINK:
457                 if (getOpticalMode(MOTUFW_DIR_IN)  == MOTUFW_OPTICAL_MODE_TOSLINK)
458                     src_name = "TOSLink         ";
459                 else
460                     src_name = "SPDIF           ";
461                 break;
462             case MOTUFW_CLKSRC_SMTPE:
463                 src_name = "SMPTE           ";
464                 break;
465             case MOTUFW_CLKSRC_WORDCLOCK:
466                 src_name = "Word Clock In   ";
467                 break;
468             case MOTUFW_CLKSRC_ADAT_9PIN:
469                 src_name = "ADAT 9-pin      ";
470                 break;
471             case MOTUFW_CLKSRC_AES_EBU:
472                 src_name = "AES-EBU         ";
473                 break;
474             default:
475                 src_name = "Unknown         ";
476         }
477         for (i=0; i<16; i+=4) {
478             q = (src_name[i]<<24) | (src_name[i+1]<<16) |
479                 (src_name[i+2]<<8) | src_name[i+3];
480             WriteRegister(MOTUFW_REG_CLKSRC_NAME0+i, q);
481         }
482     }
483     return supported;
484 }
485
486 FFADODevice::ClockSourceVector
487 MotuDevice::getSupportedClockSources() {
488     FFADODevice::ClockSourceVector r;
489     return r;
490 }
491
492 bool
493 MotuDevice::setActiveClockSource(ClockSource s) {
494     return false;
495 }
496
497 FFADODevice::ClockSource
498 MotuDevice::getActiveClockSource() {
499     ClockSource s;
500     return s;
501 }
502
503 bool
504 MotuDevice::lock() {
505
506     return true;
507 }
508
509
510 bool
511 MotuDevice::unlock() {
512
513     return true;
514 }
515
516 void
517 MotuDevice::showDevice()
518 {
519     debugOutput(DEBUG_LEVEL_VERBOSE,
520         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
521         getNodeId());
522 }
523
524 bool
525 MotuDevice::prepare() {
526
527     int samp_freq = getSamplingFrequency();
528     unsigned int optical_in_mode = getOpticalMode(MOTUFW_DIR_IN);
529     unsigned int optical_out_mode = getOpticalMode(MOTUFW_DIR_OUT);
530     unsigned int event_size_in = getEventSize(MOTUFW_DIR_IN);
531     unsigned int event_size_out= getEventSize(MOTUFW_DIR_OUT);
532
533     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
534
535     // Allocate bandwidth if not previously done.
536     // FIXME: The bandwidth allocation calculation can probably be
537     // refined somewhat since this is currently based on a rudimentary
538     // understanding of the ieee1394 iso protocol.
539     // Currently we assume the following.
540     //   * Ack/iso gap = 0.05 us
541     //   * DATA_PREFIX = 0.16 us
542     //   * DATA_END    = 0.26 us
543     // These numbers are the worst-case figures given in the ieee1394
544     // standard.  This gives approximately 0.5 us of overheads per packet -
545     // around 25 bandwidth allocation units (from the ieee1394 standard 1
546     // bandwidth allocation unit is 125/6144 us).  We further assume the
547     // MOTU is running at S400 (which it should be) so one allocation unit
548     // is equivalent to 1 transmitted byte; thus the bandwidth allocation
549     // required for the packets themselves is just the size of the packet.
550     // We used to allocate based on the maximum packet size (1160 bytes at
551     // 192 kHz for the traveler) but now do this based on the actual device
552     // state by utilising the result from getEventSize() and remembering
553     // that each packet has an 8 byte CIP header.  Note that bandwidth is
554     // allocated on a *per stream* basis - it must be allocated for both the
555     // transmit and receive streams.  While most MOTU modules are close to
556     // symmetric in terms of the number of in/out channels there are
557     // exceptions, so we deal with receive and transmit bandwidth separately.
558     signed int n_events_per_packet = samp_freq<=48000?8:(samp_freq<=96000?16:32);
559     m_rx_bandwidth = 25 + (n_events_per_packet*event_size_in);
560     m_tx_bandwidth = 25 + (n_events_per_packet*event_size_out);
561
562     // Assign iso channels if not already done
563     if (m_iso_recv_channel < 0)
564         m_iso_recv_channel = get1394Service().allocateIsoChannelGeneric(m_rx_bandwidth);
565
566     if (m_iso_send_channel < 0)
567         m_iso_send_channel = get1394Service().allocateIsoChannelGeneric(m_tx_bandwidth);
568
569     debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
570         m_iso_recv_channel, m_iso_send_channel);
571
572     if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
573         // be nice and deallocate
574         if (m_iso_recv_channel >= 0)
575             get1394Service().freeIsoChannel(m_iso_recv_channel);
576         if (m_iso_send_channel >= 0)
577             get1394Service().freeIsoChannel(m_iso_send_channel);
578
579         debugFatal("Could not allocate iso channels!\n");
580         return false;
581     }
582
583     m_receiveProcessor=new Streaming::MotuReceiveStreamProcessor(*this, event_size_in);
584
585     // The first thing is to initialize the processor.  This creates the
586     // data structures.
587     if(!m_receiveProcessor->init()) {
588         debugFatal("Could not initialize receive processor!\n");
589         return false;
590     }
591     m_receiveProcessor->setVerboseLevel(getDebugLevel());
592
593     // Now we add ports to the processor
594     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
595
596     char *buff;
597     Streaming::Port *p=NULL;
598
599     // retrieve the ID
600     std::string id=std::string("dev?");
601     if(!getOption("id", id)) {
602         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
603     }
604
605     // Add audio capture ports
606     if (!addDirPorts(Streaming::Port::E_Capture, samp_freq, optical_in_mode)) {
607         return false;
608     }
609
610     // Add MIDI port.  The MOTU only has one MIDI input port, with each
611     // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
612     // event data.
613     asprintf(&buff,"%s_cap_MIDI0",id.c_str());
614     p = new Streaming::MotuMidiPort(*m_receiveProcessor, buff,
615         Streaming::Port::E_Capture, 4);
616     if (!p) {
617         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
618     }
619     free(buff);
620
621     // example of adding an control port:
622 //    asprintf(&buff,"%s_cap_%s",id.c_str(),"myportnamehere");
623 //    p=new Streaming::MotuControlPort(
624 //            buff,
625 //            Streaming::Port::E_Capture,
626 //            0 // you can add all other port specific stuff you
627 //              // need to pass by extending MotuXXXPort and MotuPortInfo
628 //    );
629 //    free(buff);
630 //
631 //    if (!p) {
632 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
633 //    } else {
634 //
635 //        if (!m_receiveProcessor->addPort(p)) {
636 //            debugWarning("Could not register port with stream processor\n");
637 //            return false;
638 //        } else {
639 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
640 //        }
641 //    }
642
643     // Do the same for the transmit processor
644     m_transmitProcessor=new Streaming::MotuTransmitStreamProcessor(*this, event_size_out);
645
646     m_transmitProcessor->setVerboseLevel(getDebugLevel());
647
648     if(!m_transmitProcessor->init()) {
649         debugFatal("Could not initialize transmit processor!\n");
650         return false;
651     }
652
653     // Now we add ports to the processor
654     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
655
656     // Add audio playback ports
657     if (!addDirPorts(Streaming::Port::E_Playback, samp_freq, optical_out_mode)) {
658         return false;
659     }
660
661     // Add MIDI port.  The MOTU only has one output MIDI port, with each
662     // MIDI byte transmitted using a 3 byte sequence starting at byte 4
663     // of the event data.
664     asprintf(&buff,"%s_pbk_MIDI0",id.c_str());
665     p = new Streaming::MotuMidiPort(*m_transmitProcessor, buff,
666         Streaming::Port::E_Capture, 4);
667     if (!p) {
668         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
669     }
670     free(buff);
671
672     // example of adding an control port:
673 //    asprintf(&buff,"%s_pbk_%s",id.c_str(),"myportnamehere");
674 //
675 //    p=new Streaming::MotuControlPort(
676 //            buff,
677 //            Streaming::Port::E_Playback,
678 //            0 // you can add all other port specific stuff you
679 //              // need to pass by extending MotuXXXPort and MotuPortInfo
680 //    );
681 //    free(buff);
682 //
683 //    if (!p) {
684 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
685 //    } else {
686 //        if (!m_transmitProcessor->addPort(p)) {
687 //            debugWarning("Could not register port with stream processor\n");
688 //            return false;
689 //        } else {
690 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
691 //        }
692 //    }
693
694     return true;
695 }
696
697 int
698 MotuDevice::getStreamCount() {
699      return 2; // one receive, one transmit
700 }
701
702 Streaming::StreamProcessor *
703 MotuDevice::getStreamProcessorByIndex(int i) {
704     switch (i) {
705     case 0:
706         return m_receiveProcessor;
707     case 1:
708          return m_transmitProcessor;
709     default:
710         return NULL;
711     }
712     return 0;
713 }
714
715 bool
716 MotuDevice::startStreamByIndex(int i) {
717
718 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
719
720     // NOTE: this assumes that you have two streams
721     switch (i) {
722     case 0:
723         // TODO: do the stuff that is nescessary to make the device
724         // receive a stream
725
726         // Set the streamprocessor channel to the one obtained by
727         // the connection management
728         m_receiveProcessor->setChannel(m_iso_recv_channel);
729
730         // Mask out current transmit settings of the MOTU and replace
731         // with new ones.  Turn bit 24 on to enable changes to the
732         // MOTU's iso transmit settings when the iso control register
733         // is written.  Bit 23 enables iso transmit from the MOTU.
734         isoctrl &= 0xff00ffff;
735         isoctrl |= (m_iso_recv_channel << 16);
736         isoctrl |= 0x00c00000;
737         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
738         break;
739     case 1:
740         // TODO: do the stuff that is nescessary to make the device
741         // transmit a stream
742
743         // Set the streamprocessor channel to the one obtained by
744         // the connection management
745         m_transmitProcessor->setChannel(m_iso_send_channel);
746
747         // Mask out current receive settings of the MOTU and replace
748         // with new ones.  Turn bit 31 on to enable changes to the
749         // MOTU's iso receive settings when the iso control register
750         // is written.  Bit 30 enables iso receive by the MOTU.
751         isoctrl &= 0x00ffffff;
752         isoctrl |= (m_iso_send_channel << 24);
753         isoctrl |= 0xc0000000;
754         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
755         break;
756
757     default: // Invalid stream index
758         return false;
759     }
760
761     return true;
762 }
763
764 bool
765 MotuDevice::stopStreamByIndex(int i) {
766
767 quadlet_t isoctrl = ReadRegister(MOTUFW_REG_ISOCTRL);
768
769     // TODO: connection management: break connection
770     // cfr the start function
771
772     // NOTE: this assumes that you have two streams
773     switch (i) {
774     case 0:
775         // Turn bit 22 off to disable iso send by the MOTU.  Turn
776         // bit 23 on to enable changes to the MOTU's iso transmit
777         // settings when the iso control register is written.
778         isoctrl &= 0xffbfffff;
779         isoctrl |= 0x00800000;
780         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
781         break;
782     case 1:
783         // Turn bit 30 off to disable iso receive by the MOTU.  Turn
784         // bit 31 on to enable changes to the MOTU's iso receive
785         // settings when the iso control register is written.
786         isoctrl &= 0xbfffffff;
787         isoctrl |= 0x80000000;
788         WriteRegister(MOTUFW_REG_ISOCTRL, isoctrl);
789         break;
790
791     default: // Invalid stream index
792         return false;
793     }
794
795     return true;
796 }
797
798 signed int MotuDevice::getIsoRecvChannel(void) {
799     return m_iso_recv_channel;
800 }
801
802 signed int MotuDevice::getIsoSendChannel(void) {
803     return m_iso_send_channel;
804 }
805
806 unsigned int MotuDevice::getOpticalMode(unsigned int dir) {
807     unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
808
809 debugOutput(DEBUG_LEVEL_VERBOSE, "optical mode: %x %x %x %x\n",dir, reg, reg & MOTUFW_OPTICAL_IN_MODE_MASK,
810 reg & MOTUFW_OPTICAL_OUT_MODE_MASK);
811
812     if (dir == MOTUFW_DIR_IN)
813         return (reg & MOTUFW_OPTICAL_IN_MODE_MASK) >> 8;
814     else
815         return (reg & MOTUFW_OPTICAL_OUT_MODE_MASK) >> 10;
816 }
817
818 signed int MotuDevice::setOpticalMode(unsigned int dir, unsigned int mode) {
819     unsigned int reg = ReadRegister(MOTUFW_REG_ROUTE_PORT_CONF);
820     unsigned int opt_ctrl = 0x0000002;
821
822     /* THe 896HD doesn't have an SPDIF/TOSLINK optical mode, so don't try to
823      * set it
824      */
825     if (m_motu_model==MOTUFW_MODEL_896HD && mode==MOTUFW_OPTICAL_MODE_TOSLINK)
826         return -1;
827
828     // Set up the optical control register value according to the current
829     // optical port modes.  At this stage it's not completely understood
830     // what the "Optical control" register does, so the values it's set to
831     // are more or less "magic" numbers.
832     if (reg & MOTUFW_OPTICAL_IN_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<8))
833         opt_ctrl |= 0x00000080;
834     if (reg & MOTUFW_OPTICAL_OUT_MODE_MASK != (MOTUFW_OPTICAL_MODE_ADAT<<10))
835         opt_ctrl |= 0x00000040;
836
837     if (mode & MOTUFW_DIR_IN) {
838         reg &= ~MOTUFW_OPTICAL_IN_MODE_MASK;
839         reg |= (mode << 8) & MOTUFW_OPTICAL_IN_MODE_MASK;
840         if (mode != MOTUFW_OPTICAL_MODE_ADAT)
841             opt_ctrl |= 0x00000080;
842         else
843             opt_ctrl &= ~0x00000080;
844     }
845     if (mode & MOTUFW_DIR_OUT) {
846         reg &= ~MOTUFW_OPTICAL_OUT_MODE_MASK;
847         reg |= (mode <<10) & MOTUFW_OPTICAL_OUT_MODE_MASK;
848         if (mode != MOTUFW_OPTICAL_MODE_ADAT)
849             opt_ctrl |= 0x00000040;
850         else
851             opt_ctrl &= ~0x00000040;
852     }
853
854     // FIXME: there seems to be more to it than this, but for
855     // the moment at least this seems to work.
856     WriteRegister(MOTUFW_REG_ROUTE_PORT_CONF, reg);
857     return WriteRegister(MOTUFW_REG_OPTICAL_CTRL, opt_ctrl);
858 }
859
860 signed int MotuDevice::getEventSize(unsigned int direction) {
861 //
862 // Return the size in bytes of a single event sent to (dir==MOTUFW_OUT) or
863 // from (dir==MOTUFW_IN) the MOTU as part of an iso data packet.
864 //
865 // FIXME: for performance it may turn out best to calculate the event
866 // size in setOpticalMode and cache the result in a data field.  However,
867 // as it stands this will not adapt to dynamic changes in sample rate - we'd
868 // need a setFrameRate() for that.
869 //
870 // At the very least an event consists of the SPH (4 bytes) and the control/MIDI
871 // bytes (6 bytes).
872 // Note that all audio channels are sent using 3 bytes.
873 signed int sample_rate = getSamplingFrequency();
874 signed int optical_mode = getOpticalMode(direction);
875 signed int size = 4+6;
876
877 unsigned int i;
878 unsigned int dir = direction==Streaming::Port::E_Capture?MOTUFW_DIR_IN:MOTUFW_DIR_OUT;
879 unsigned int flags = (1 << ( optical_mode + 4 ));
880
881     if ( sample_rate > 96000 )
882         flags |= MOTUFW_PA_RATE_4x;
883     else if ( sample_rate > 48000 )
884         flags |= MOTUFW_PA_RATE_2x;
885     else
886         flags |= MOTUFW_PA_RATE_1x;
887
888     for (i=0; i < ( DevicesProperty[m_motu_model-1].PortsListLength /sizeof( PortEntry ) ); i++) {
889         if (( DevicesProperty[m_motu_model-1].PortsList[i].port_dir & dir ) &&
890            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_RATE_MASK & flags ) &&
891            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_OPTICAL_MASK & flags )) {
892             size += 3;
893         }
894     }
895
896     // Finally round size up to the next quadlet boundary
897     return ((size+3)/4)*4;
898 }
899 /* ======================================================================= */
900
901 bool MotuDevice::addPort(Streaming::StreamProcessor *s_processor,
902   char *name, enum Streaming::Port::E_Direction direction,
903   int position, int size) {
904 /*
905  * Internal helper function to add a MOTU port to a given stream processor.
906  * This just saves the unnecessary replication of what is essentially
907  * boilerplate code.  Note that the port name is freed by this function
908  * prior to exit.
909  */
910 Streaming::Port *p=NULL;
911
912     p = new Streaming::MotuAudioPort(*s_processor, name, direction, position, size);
913
914     if (!p) {
915         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",name);
916     }
917     free(name);
918     return true;
919 }
920 /* ======================================================================= */
921
922 bool MotuDevice::addDirPorts(
923   enum Streaming::Port::E_Direction direction,
924   unsigned int sample_rate, unsigned int optical_mode) {
925 /*
926  * Internal helper method: adds all required ports for the given direction
927  * based on the indicated sample rate and optical mode.
928  *
929  * Notes: currently ports are not created if they are disabled due to sample
930  * rate or optical mode.  However, it might be better to unconditionally
931  * create all ports and just disable those which are not active.
932  */
933 const char *mode_str = direction==Streaming::Port::E_Capture?"cap":"pbk";
934 Streaming::StreamProcessor *s_processor;
935 unsigned int i;
936 char *buff;
937 unsigned int dir = direction==Streaming::Port::E_Capture?MOTUFW_DIR_IN:MOTUFW_DIR_OUT;
938 unsigned int flags = (1 << ( optical_mode + 4 ));
939
940     if ( sample_rate > 96000 )
941         flags |= MOTUFW_PA_RATE_4x;
942     else if ( sample_rate > 48000 )
943         flags |= MOTUFW_PA_RATE_2x;
944     else
945         flags |= MOTUFW_PA_RATE_1x;
946
947     // retrieve the ID
948     std::string id=std::string("dev?");
949     if(!getOption("id", id)) {
950         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
951     }
952
953     if (direction == Streaming::Port::E_Capture) {
954         s_processor = m_receiveProcessor;
955     } else {
956         s_processor = m_transmitProcessor;
957     }
958
959     for (i=0; i < ( DevicesProperty[m_motu_model-1].PortsListLength /sizeof( PortEntry ) ); i++) {
960         if (( DevicesProperty[m_motu_model-1].PortsList[i].port_dir & dir ) &&
961            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_RATE_MASK & flags ) &&
962            ( DevicesProperty[m_motu_model-1].PortsList[i].port_flags & MOTUFW_PA_OPTICAL_MASK & flags )) {
963             asprintf(&buff,"%s_%s_%s" , id.c_str(), mode_str,
964               DevicesProperty[m_motu_model-1].PortsList[i].port_name);
965             if (!addPort(s_processor, buff, direction, DevicesProperty[m_motu_model-1].PortsList[i].port_offset, 0))
966                 return false;
967         }
968     }
969    
970     return true;
971 }
972 /* ======================================================================== */
973
974 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
975 /*
976  * Attempts to read the requested register from the MOTU.
977  */
978
979   quadlet_t quadlet;
980
981   quadlet = 0;
982   // Note: 1394Service::read() expects a physical ID, not the node id
983   if (get1394Service().read(0xffc0 | getNodeId(), MOTUFW_BASE_ADDR+reg, 1, &quadlet) < 0) {
984     debugError("Error doing motu read from register 0x%06x\n",reg);
985   }
986
987   return ntohl(quadlet);
988 }
989
990 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
991 /*
992  * Attempts to write the given data to the requested MOTU register.
993  */
994
995   unsigned int err = 0;
996   data = htonl(data);
997
998   // Note: 1394Service::write() expects a physical ID, not the node id
999   if (get1394Service().write(0xffc0 | getNodeId(), MOTUFW_BASE_ADDR+reg, 1, &data) < 0) {
1000     err = 1;
1001     debugError("Error doing motu write to register 0x%06x\n",reg);
1002   }
1003
1004   SleepRelativeUsec(100);
1005   return (err==0)?0:-1;
1006 }
1007
1008 }
Note: See TracBrowser for help on using the browser.