root/trunk/libfreebob/src/rme/rme_avdevice.cpp

Revision 374, 15.8 kB (checked in by jwoithe, 17 years ago)

More adjustments to make MOTU devices actually work again.
Make MOTU and RME work again now that ieee1394service's read/write functions interpret their length argument in quadlets rather than bytes.

Line 
1 /* rme_avdevice.cpp
2  * Copyright (C) 2006 by Jonathan Woithe
3  * Copyright (C) 2006 by Pieter Palmers
4  *
5  * This file is part of FreeBob.
6  *
7  * FreeBob is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  * FreeBob is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with FreeBob; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307 USA.
20  */
21
22 #include "rme/rme_avdevice.h"
23 #include "configrom.h"
24
25 #include "libfreebobavc/ieee1394service.h"
26 #include "libfreebobavc/avc_definitions.h"
27
28 #include "debugmodule/debugmodule.h"
29
30 //#include "libstreaming/MotuStreamProcessor.h"
31 //#include "libstreaming/MotuPort.h"
32
33 #include "libutil/DelayLockedLoop.h"
34
35 #include <string>
36 #include <stdint.h>
37 #include <assert.h>
38 #include <netinet/in.h>
39
40 #include <libraw1394/csr.h>
41
42 namespace Rme {
43
44 IMPL_DEBUG_MODULE( RmeDevice, RmeDevice, DEBUG_LEVEL_NORMAL );
45
46 char *rme_modelname[] = {"[unknown]","Fireface-800"};
47
48 /* ======================================================================= */
49 /* Provide a mechanism for allocating iso channels and bandwidth to MOTU
50  * interfaces.
51  */
52
53 static signed int allocate_iso_channel(raw1394handle_t handle) {
54 /*
55  * Allocates an iso channel for use by the interface in a similar way to
56  * libiec61883.  Returns -1 on error (due to there being no free channels)
57  * or an allocated channel number.
58  * FIXME: As in libiec61883, channel 63 is not requested; this is either a
59  * bug or it's omitted since that's the channel preferred by video devices.
60  */
61         int c = -1;
62         for (c = 0; c < 63; c++)
63                 if (raw1394_channel_modify (handle, c, RAW1394_MODIFY_ALLOC) == 0)
64                         break;
65         if (c < 63)
66                 return c;
67         return -1;
68 }
69
70 static signed int free_iso_channel(raw1394handle_t handle, signed int channel) {
71 /*
72  * Deallocates an iso channel.  Returns -1 on error or 0 on success.  Silently
73  * ignores a request to deallocate a negative channel number.
74  */
75         if (channel < 0)
76                 return 0;
77         if (raw1394_channel_modify (handle, channel, RAW1394_MODIFY_FREE)!=0)
78                 return -1;
79         return 0;
80 }
81
82 static signed int get_iso_bandwidth_avail(raw1394handle_t handle) {
83 /*
84  * Returns the current value of the `bandwidth available' register on
85  * the IRM, or -1 on error.
86  */
87 quadlet_t buffer;
88 signed int result = raw1394_read (handle, raw1394_get_irm_id (handle),
89         CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
90         sizeof (quadlet_t), &buffer);
91
92         if (result < 0)
93                 return -1;
94         return ntohl(buffer);
95 }
96 /* ======================================================================= */
97
98 RmeDevice::RmeDevice( std::auto_ptr< ConfigRom >( configRom ),
99                     Ieee1394Service& ieee1394service,
100                     int nodeId,
101                     int verboseLevel )
102     : m_configRom( configRom )
103     , m_1394Service( &ieee1394service )
104     , m_rme_model( RME_MODEL_NONE )
105     , m_nodeId( nodeId )
106     , m_verboseLevel( verboseLevel )
107     , m_id(0)
108     , m_iso_recv_channel ( -1 )
109     , m_iso_send_channel ( -1 )
110     , m_bandwidth ( -1 )
111 //    , m_receiveProcessor ( 0 )
112 //    , m_transmitProcessor ( 0 )
113    
114 {
115     setDebugLevel( verboseLevel );
116    
117     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Rme::RmeDevice (NodeID %d)\n",
118                  nodeId );
119
120 }
121
122 RmeDevice::~RmeDevice()
123 {
124         // Free ieee1394 bus resources if they have been allocated
125         if (m_1394Service != NULL) {
126                 raw1394handle_t handle = m_1394Service->getHandle();
127                 if (m_bandwidth >= 0)
128                         if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_FREE) < 0)
129                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free bandwidth of %d\n", m_bandwidth);
130                 if (m_iso_recv_channel >= 0)
131                         if (raw1394_channel_modify(handle, m_iso_recv_channel, RAW1394_MODIFY_FREE) < 0)
132                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free recv iso channel %d\n", m_iso_recv_channel);
133                 if (m_iso_send_channel >= 0)
134                         if (raw1394_channel_modify(handle, m_iso_send_channel, RAW1394_MODIFY_FREE) < 0)
135                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Could not free send iso channel %d\n", m_iso_send_channel);
136         }
137
138 }
139
140 ConfigRom&
141 RmeDevice::getConfigRom() const
142 {
143     return *m_configRom;
144 }
145
146 struct VendorModelEntry {
147     unsigned int vendor_id;
148     unsigned int model_id;
149 };
150
151 static VendorModelEntry supportedDeviceList[] =
152 {
153     {0x00000a35, 0x0001},  // RME Fireface-800
154
155 };
156
157 bool
158 RmeDevice::probe( ConfigRom& configRom )
159 {
160     unsigned int vendorId = configRom.getNodeVendorId();
161     unsigned int modelId = configRom.getModelId();
162
163     for ( unsigned int i = 0;
164           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
165           ++i )
166     {
167         if ( ( supportedDeviceList[i].vendor_id == vendorId )
168              && ( supportedDeviceList[i].model_id == modelId )
169            )
170         {
171             return true;
172         }
173     }
174
175     return false;
176 }
177
178 bool
179 RmeDevice::discover()
180 {
181         // Find out if this device is one we know about
182         if (m_configRom->getUnitSpecifierId() == RME_VENDOR_RME) {
183                 switch (m_configRom->getModelId()) {
184                     case RME_MODELID_FIREFACE800:
185                         m_rme_model = RME_MODEL_FIREFACE800;
186                         break;
187                 }
188         }
189         if (m_rme_model != RME_MODEL_NONE) {
190                 debugOutput( DEBUG_LEVEL_VERBOSE, "found RME %s\n",
191                         rme_modelname[m_rme_model]);
192                 return true;
193         }
194
195         return false;
196 }
197
198 int
199 RmeDevice::getSamplingFrequency( ) {
200 /*
201  * Retrieve the current sample rate from the RME device.
202  */
203         return 48000;
204 }
205
206 bool
207 RmeDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
208 {
209 /*
210  * Set the RME device's samplerate.
211  */
212         if (samplingFrequency == eSF_48000Hz)
213                 return true;
214         return false;
215 }
216
217 bool RmeDevice::setId( unsigned int id) {
218         debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id);
219         m_id=id;
220         return true;
221 }
222
223 void
224 RmeDevice::showDevice() const
225 {
226         debugOutput(DEBUG_LEVEL_VERBOSE,
227                 "RME %s at node %d\n", rme_modelname[m_rme_model],
228                 m_nodeId);
229 }
230
231 bool
232 RmeDevice::prepare() {
233
234         int samp_freq = getSamplingFrequency();
235
236         raw1394handle_t handle = m_1394Service->getHandle();
237
238         debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
239
240         // Assign iso channels if not already done
241 //      if (m_iso_recv_channel < 0)
242 //              m_iso_recv_channel = allocate_iso_channel(handle);
243 //      if (m_iso_send_channel < 0)
244 //              m_iso_send_channel = allocate_iso_channel(handle);
245 //
246 //      debugOutput(DEBUG_LEVEL_VERBOSE, "recv channel = %d, send channel = %d\n",
247 //              m_iso_recv_channel, m_iso_send_channel);
248 //
249 //      if (m_iso_recv_channel<0 || m_iso_send_channel<0) {
250 //              debugFatal("Could not allocate iso channels!\n");
251 //              return false;
252 //      }
253
254         // Allocate bandwidth if not previously done.
255         // FIXME: The bandwidth allocation calculation can probably be
256         // refined somewhat since this is currently based on a rudimentary
257         // understanding of the iso protocol.
258         // Currently we assume the following.
259         //   * Ack/iso gap = 0.05 us
260         //   * DATA_PREFIX = 0.16 us
261         //   * DATA_END    = 0.26 us
262         // These numbers are the worst-case figures given in the ieee1394
263         // standard.  This gives approximately 0.5 us of overheads per
264         // packet - around 25 bandwidth allocation units (from the ieee1394
265         // standard 1 bandwidth allocation unit is 125/6144 us).  We further
266         // assume the MOTU is running at S400 (which it should be) so one
267         // allocation unit is equivalent to 1 transmitted byte; thus the
268         // bandwidth allocation required for the packets themselves is just
269         // the size of the packet.  We allocate based on the maximum packet
270         // size (1160 bytes at 192 kHz) so the sampling frequency can be
271         // changed dynamically if this ends up being useful in future.
272 //      m_bandwidth = 25 + 1160;
273 //      debugOutput(DEBUG_LEVEL_VERBOSE, "Available bandwidth: %d\n",
274 //              get_iso_bandwidth_avail(handle));
275 //      if (raw1394_bandwidth_modify(handle, m_bandwidth, RAW1394_MODIFY_ALLOC) < 0) {
276 //              debugFatal("Could not allocate bandwidth of %d\n", m_bandwidth);
277 //              m_bandwidth = -1;
278 //              return false;
279 //      }
280 //      debugOutput(DEBUG_LEVEL_VERBOSE,
281 //              "allocated bandwidth of %d for MOTU device\n", m_bandwidth);
282 //      debugOutput(DEBUG_LEVEL_VERBOSE,
283 //              "remaining bandwidth: %d\n", get_iso_bandwidth_avail(handle));
284
285 //      m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor(
286 //              m_1394Service->getPort(), samp_freq, event_size_in);
287
288         // The first thing is to initialize the processor.  This creates the
289         // data structures.
290 //      if(!m_receiveProcessor->init()) {
291 //              debugFatal("Could not initialize receive processor!\n");
292 //              return false;
293 //      }
294 //      m_receiveProcessor->setVerboseLevel(getDebugLevel());
295
296         // Now we add ports to the processor
297 //      debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
298        
299 //      char *buff;
300 //      FreebobStreaming::Port *p=NULL;
301 //
302 //      // Add audio capture ports
303 //      if (!addDirPorts(FreebobStreaming::Port::E_Capture, samp_freq, optical_in_mode)) {
304 //              return false;
305 //      }
306
307         // Add MIDI port.  The MOTU only has one MIDI input port, with each
308         // MIDI byte sent using a 3 byte sequence starting at byte 4 of the
309         // event data.
310 //      asprintf(&buff,"dev%d_cap_MIDI0",m_id);
311 //      p = new FreebobStreaming::MotuMidiPort(buff,
312 //              FreebobStreaming::Port::E_Capture, 4);
313 //      if (!p) {
314 //              debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
315 //      } else {
316 //              if (!m_receiveProcessor->addPort(p)) {
317 //                      debugWarning("Could not register port with stream processor\n");
318 //                      free(buff);
319 //                      return false;
320 //              } else {
321 //                      debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
322 //              }
323 //      }
324 //      free(buff);
325
326         // example of adding an control port:
327 //    asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
328 //    p=new FreebobStreaming::MotuControlPort(
329 //            buff,
330 //            FreebobStreaming::Port::E_Capture,
331 //            0 // you can add all other port specific stuff you
332 //              // need to pass by extending MotuXXXPort and MotuPortInfo
333 //    );
334 //    free(buff);
335 //
336 //    if (!p) {
337 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
338 //    } else {
339 //
340 //        if (!m_receiveProcessor->addPort(p)) {
341 //            debugWarning("Could not register port with stream processor\n");
342 //            return false;
343 //        } else {
344 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
345 //        }
346 //    }
347
348         // Do the same for the transmit processor
349 //      m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor(
350 //              m_1394Service->getPort(), getSamplingFrequency(), event_size_out);
351 //
352 //      m_transmitProcessor->setVerboseLevel(getDebugLevel());
353 //     
354 //      if(!m_transmitProcessor->init()) {
355 //              debugFatal("Could not initialize transmit processor!\n");
356 //              return false;
357 //      }
358
359         // Connect the transmit stream ticks-per-frame hook to the
360         // ticks-per-frame DLL integrator in the receive stream.
361 //      m_transmitProcessor->setTicksPerFrameDLL(m_receiveProcessor->getTicksPerFrameDLL());
362
363         // Now we add ports to the processor
364 //      debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
365
366         // Add audio playback ports
367 //      if (!addDirPorts(FreebobStreaming::Port::E_Playback, samp_freq, optical_out_mode)) {
368 //              return false;
369 //      }
370
371         // Add MIDI port.  The MOTU only has one output MIDI port, with each
372         // MIDI byte transmitted using a 3 byte sequence starting at byte 4
373         // of the event data.
374 //      asprintf(&buff,"dev%d_pbk_MIDI0",m_id);
375 //      p = new FreebobStreaming::MotuMidiPort(buff,
376 //              FreebobStreaming::Port::E_Capture, 4);
377 //      if (!p) {
378 //              debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n", buff);
379 //      } else {
380 //              if (!m_receiveProcessor->addPort(p)) {
381 //                      debugWarning("Could not register port with stream processor\n");
382 //                      free(buff);
383 //                      return false;
384 //              } else {
385 //                      debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n", buff);
386 //              }
387 //      }
388 //      free(buff);
389
390         // example of adding an control port:
391 //    asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
392 //   
393 //    p=new FreebobStreaming::MotuControlPort(
394 //            buff,
395 //            FreebobStreaming::Port::E_Playback,
396 //            0 // you can add all other port specific stuff you
397 //              // need to pass by extending MotuXXXPort and MotuPortInfo
398 //    );
399 //    free(buff);
400 //
401 //    if (!p) {
402 //        debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
403 //    } else {
404 //        if (!m_transmitProcessor->addPort(p)) {
405 //            debugWarning("Could not register port with stream processor\n");
406 //            return false;
407 //        } else {
408 //            debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
409 //        }
410 //    }
411        
412         return true;
413 }
414
415 int
416 RmeDevice::getStreamCount() {
417         return 2; // one receive, one transmit
418 }
419
420 FreebobStreaming::StreamProcessor *
421 RmeDevice::getStreamProcessorByIndex(int i) {
422
423 //      switch (i) {
424 //      case 0:
425 //              return m_receiveProcessor;
426 //      case 1:
427 //              return m_transmitProcessor;
428 //      default:
429 //              return NULL;
430 //      }
431 //      return 0;
432         return NULL;
433 }
434
435 int
436 RmeDevice::startStreamByIndex(int i) {
437
438         // NOTE: this assumes that you have two streams
439         switch (i) {
440         case 0:
441                 // TODO: do the stuff that is nescessary to make the device
442                 // transmit a stream
443
444                 // Set the streamprocessor channel to the one obtained by
445                 // the connection management
446 //              m_receiveProcessor->setChannel(m_iso_recv_channel);
447
448                 // Mask out current transmit settings of the MOTU and replace
449                 // with new ones.  Turn bit 24 on to enable changes to the
450                 // MOTU's iso transmit settings when the iso control register
451                 // is written.  Bit 23 enables iso transmit from the MOTU.
452                 break;
453         case 1:
454                 // TODO: do the stuff that is nescessary to make the device
455                 // receive a stream
456
457                 // Set the streamprocessor channel to the one obtained by
458                 // the connection management
459 //              m_transmitProcessor->setChannel(m_iso_send_channel);
460
461                 // Mask out current receive settings of the MOTU and replace
462                 // with new ones.  Turn bit 31 on to enable changes to the
463                 // MOTU's iso receive settings when the iso control register
464                 // is written.  Bit 30 enables iso receive by the MOTU.
465                 break;
466                
467         default: // Invalid stream index
468                 return -1;
469         }
470
471         return 0;
472 }
473
474 int
475 RmeDevice::stopStreamByIndex(int i) {
476
477         // TODO: connection management: break connection
478         // cfr the start function
479
480         // NOTE: this assumes that you have two streams
481         switch (i) {
482         case 0:
483                 break;
484         case 1:
485                 break;
486                
487         default: // Invalid stream index
488                 return -1;
489         }
490
491         return 0;
492 }
493
494 signed int RmeDevice::getIsoRecvChannel(void) {
495         return m_iso_recv_channel;
496 }
497
498 signed int RmeDevice::getIsoSendChannel(void) {
499         return m_iso_send_channel;
500 }
501
502 signed int RmeDevice::getEventSize(unsigned int dir) {
503 //
504 // Return the size in bytes of a single event sent to (dir==MOTUFW_OUT) or
505 // from (dir==MOTUFW_IN) the MOTU as part of an iso data packet.
506
507         return 1;
508 }
509 /* ======================================================================= */
510
511 #if 0
512 unsigned int RmeDevice::ReadRegister(unsigned int reg) {
513 /*
514  * Attempts to read the requested register from the RME device.
515  */
516
517 quadlet_t quadlet;
518 assert(m_1394Service);
519        
520   quadlet = 0;
521   // Note: 1394Service::read() expects a physical ID, not the node id
522   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 1, &quadlet) < 0) {
523     debugError("Error doing rme read from register 0x%06x\n",reg);
524   }
525
526   return ntohl(quadlet);
527 }
528
529 signed int RmeDevice::WriteRegister(unsigned int reg, quadlet_t data) {
530 /*
531  * Attempts to write the given data to the requested RME register.
532  */
533
534   unsigned int err = 0;
535   data = htonl(data);
536
537   // Note: 1394Service::write() expects a physical ID, not the node id
538   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 1, &data) < 0) {
539     err = 1;
540     debugError("Error doing rme write to register 0x%06x\n",reg);
541   }
542
543   usleep(100);
544   return (err==0)?0:-1;
545 }
546 #endif
547
548 }
Note: See TracBrowser for help on using the browser.