root/branches/start/freebobstreaming/freebob_streaming.c

Revision 120, 45.8 kB (checked in by pieterpalmers, 18 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 /* freebob_streaming.c
30  *
31  * Implementation of the FreeBob Streaming API
32  *
33  */
34
35 #include "freebob_streaming.h"
36 #include "freebob_streaming_private.h"
37 #include "freebob_connections.h"
38 #include "freebob_debug.h"
39
40 /**
41  * Callbacks
42  */
43
44 static enum raw1394_iso_disposition
45 iso_slave_receive_handler(raw1394handle_t handle, unsigned char *data,
46         unsigned int length, unsigned char channel,
47         unsigned char tag, unsigned char sy, unsigned int cycle,
48         unsigned int dropped);
49        
50 static enum raw1394_iso_disposition
51 iso_master_receive_handler(raw1394handle_t handle, unsigned char *data,
52         unsigned int length, unsigned char channel,
53         unsigned char tag, unsigned char sy, unsigned int cycle,
54         unsigned int dropped);
55        
56 static enum raw1394_iso_disposition
57 iso_slave_transmit_handler(raw1394handle_t handle,
58                 unsigned char *data, unsigned int *length,
59                 unsigned char *tag, unsigned char *sy,
60                 int cycle, unsigned int dropped);
61                
62 static enum raw1394_iso_disposition
63 iso_master_transmit_handler(raw1394handle_t handle,
64                 unsigned char *data, unsigned int *length,
65                 unsigned char *tag, unsigned char *sy,
66                 int cycle, unsigned int dropped);
67                        
68
69 freebob_device_t *freebob_streaming_init (freebob_device_info_t *device_info, freebob_options_t options) {
70         int i;
71         int c;
72         int err=0;
73         freebob_device_t* dev=NULL;
74        
75         assert(device_info);
76        
77         printMessage("FreeBob Streaming Device Init\n");
78         printMessage(" Using FreeBobCtl lib version %s\n",freebobctl_get_version());
79         printMessage(" Device information:\n");
80        
81         switch (device_info->location_type) {
82         case freebob_osc:
83                 printMessage("  OSC URL: %s\n",device_info->xml_location);
84                 break;
85         case freebob_file:
86                 printMessage("  XML file: %s\n",device_info->xml_location);
87                 break;
88         default:
89                 printMessage("  Other location type.\n");
90         }
91        
92         printMessage(" Device options:\n");
93         /* driver related setup */
94         printMessage("  Samplerate  : %d\n",options.sample_rate);
95         printMessage("  Period Size : %d\n",options.period_size);
96         printMessage("  Nb Buffers  : %d\n",options.nb_buffers);
97         printMessage("  RAW1394 ISO Buffers      : %d\n",options.iso_buffers);
98         printMessage("  RAW1394 ISO Prebuffers   : %d\n",options.iso_prebuffers);
99         printMessage("  RAW1394 ISO IRQ Interval : %d\n",options.iso_irq_interval);
100         printMessage("\n");
101        
102         // initialize the freebob_device
103         // allocate memory
104         dev=calloc(1,sizeof(freebob_device_t));
105        
106         if(!dev) {
107                 printError("FREEBOB: cannot allocate memory for dev structure!\n");
108                 return NULL;
109         }
110        
111         // clear the device structure
112         memset(dev,0,sizeof(freebob_device_t));
113        
114         // copy the arguments to the device structure
115         memcpy(&dev->device_info, device_info, sizeof(freebob_device_info_t));
116         memcpy(&dev->options, &options, sizeof(freebob_options_t));
117        
118         // read in the device specification
119        
120         /* load the connections*/
121         /*
122          * This info should be provided by the Freebob CML application
123          *
124          */
125         freebob_connection_info_t *freebobctl_capture_connections=NULL;
126         freebob_connection_info_t *freebobctl_playback_connections=NULL;
127
128         switch (dev->device_info.location_type) {
129         case freebob_osc:
130                 printMessage("Reading from OSC URL: %s\n",dev->device_info.xml_location);
131                 freebobctl_capture_connections=freebobctl_get_connection_info_from_osc(dev->device_info.xml_location, 0);
132                 freebobctl_playback_connections=freebobctl_get_connection_info_from_osc(dev->device_info.xml_location, 1);
133                 break;
134         case freebob_file:
135                 printMessage("Reading from XML file: %s\n",dev->device_info.xml_location);
136                 freebobctl_capture_connections=freebobctl_get_connection_info_from_xml_file(dev->device_info.xml_location, 0);
137                 freebobctl_playback_connections=freebobctl_get_connection_info_from_xml_file(dev->device_info.xml_location, 1);
138                 break;
139         default:
140                 printError("Faulty location type!\n");
141                 free(dev);
142                 return NULL;
143                
144         }
145        
146         if (freebobctl_capture_connections) {
147                 dev->nb_connections_capture=freebobctl_capture_connections->nb_connections;
148                 // FIXME:
149                 //dev->nb_connections_capture=0;
150         } else {
151                 dev->nb_connections_capture=0;
152         }       
153        
154         if (freebobctl_playback_connections) {
155                 dev->nb_connections_playback=freebobctl_playback_connections->nb_connections;
156                 // FIXME:
157 //              dev->nb_connections_playback=0;
158         } else {
159                 dev->nb_connections_playback=0;
160         }
161        
162         dev->nb_connections=dev->nb_connections_playback+dev->nb_connections_capture;
163         /* see if there are any connections */
164         if (!dev->nb_connections) {
165                 printError("No connections specified, bailing out\n");
166                 if(freebobctl_capture_connections) { free(freebobctl_capture_connections); freebobctl_capture_connections=NULL; }
167                 if(freebobctl_playback_connections) { free(freebobctl_playback_connections); freebobctl_playback_connections=NULL; }
168                 free(dev);
169                
170                 return NULL;
171         }
172        
173         dev->connections=calloc(dev->nb_connections_playback+dev->nb_connections_capture, sizeof(freebob_connection_t));
174        
175        
176         for (c=0;c<dev->nb_connections_capture;c++) {
177                 memcpy(&dev->connections[c].spec, freebobctl_capture_connections->connections[c], sizeof(freebob_connection_spec_t));
178                 dev->connections[c].spec.direction=FREEBOB_CAPTURE;
179         }
180         for (c=0;c<dev->nb_connections_playback;c++) {
181                 memcpy(&dev->connections[c+dev->nb_connections_capture].spec, freebobctl_playback_connections->connections[c], sizeof(freebob_connection_spec_t));
182                 dev->connections[c+dev->nb_connections_capture].spec.direction=FREEBOB_PLAYBACK;
183         }
184        
185         if(freebobctl_capture_connections) { free(freebobctl_capture_connections); freebobctl_capture_connections=NULL; }
186         if(freebobctl_playback_connections) { free(freebobctl_playback_connections); freebobctl_playback_connections=NULL; }
187        
188         /* Figure out a master connection.
189          * Either it is given in the spec libfreebobctl
190          * Or it is the first connection defined (capture connections first)
191          */
192         int master_found=FALSE;
193        
194         for (c=0;c<dev->nb_connections_capture+dev->nb_connections_playback;c++) {
195                 if (dev->connections[c].spec.is_master==TRUE) {
196                         master_found=TRUE;
197                         break;
198                 }
199         }
200        
201         if((!master_found) && (dev->nb_connections_capture+dev->nb_connections_playback > 0)) {
202                 dev->connections[0].spec.is_master=TRUE;
203         }
204
205         // initialize all connections
206         for(i=0; i < dev->nb_connections; i++) {
207                 freebob_connection_t *connection= &(dev->connections[i]);
208                 if ((err=freebob_streaming_init_connection(dev, connection))<0) {
209                         printError("FREEBOB: failed to init connection %d\n",i);
210                         break;
211                 }
212         }
213        
214         if(err) {
215                 debugPrint(DEBUG_LEVEL_STARTUP, "Cleaning up connections\n");
216                
217                 // the connection that failed doesn't have to be cleaned
218                 i-=1;
219                
220                 for(; i >= 0; i--) {
221                         freebob_connection_t *connection= &(dev->connections[i]);
222                         debugPrint(DEBUG_LEVEL_STARTUP, "Cleaning up connection %d\n",i);
223                         if ((freebob_streaming_cleanup_connection(dev, connection))<0) {
224                                 printError( "Failed to clean connection %d\n",i);
225                         }
226                 }
227                 free(dev->connections);
228                 free(dev);
229                 return NULL;
230         }
231        
232         return dev;
233
234 }
235
236 void freebob_streaming_finish(freebob_device_t *dev) {
237         debugPrint(DEBUG_LEVEL_STARTUP,"Cleaning up connections\n");
238         unsigned int i;
239         int err=0;
240        
241         // cleanup all connections
242         for(i=0; i < dev->nb_connections; i++) {
243                 freebob_connection_t *connection= &(dev->connections[i]);
244                 if ((err=freebob_streaming_cleanup_connection(dev, connection))<0) {
245                         printError("Failed to cleanup connection %d\n",i);
246                         return;
247                 }
248         }
249        
250         // free stream structures
251         if(dev->capture_streams) {
252                 free(dev->capture_streams);
253         }
254         if(dev->playback_streams) {
255                 free(dev->playback_streams);
256         }
257         if(dev->synced_capture_streams) {
258                 free(dev->synced_capture_streams);
259         }
260         if(dev->synced_playback_streams) {
261                 free(dev->synced_playback_streams);
262         }
263        
264         // cleanup data structures
265         free(dev->connections);
266         free(dev);
267        
268         return;
269 }
270
271 int freebob_streaming_get_nb_capture_streams(freebob_device_t *dev) {
272         return dev->nb_capture_streams;
273 }
274
275 int freebob_streaming_get_nb_playback_streams(freebob_device_t *dev) {
276         return dev->nb_playback_streams;
277 }
278
279 int freebob_streaming_get_capture_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
280         freebob_stream_t *stream;
281         if(i<dev->nb_capture_streams) {
282                 stream=*(dev->capture_streams+i);
283                 return snprintf (buffer, buffersize, "%s_%d_%d_%d_%s",
284                                                 "cap", (int) stream->parent->spec.port, stream->parent->spec.node & 0x3F, stream->parent->spec.plug, stream->spec.name);               
285         } else {
286                 return -1;
287         }
288 }
289
290 int freebob_streaming_get_playback_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
291         freebob_stream_t *stream;
292         if(i<dev->nb_playback_streams) {
293                 stream=*(dev->playback_streams+i);
294                 return snprintf (buffer, buffersize, "%s_%d_%d_%d_%s",
295                                                 "pbk", (int) stream->parent->spec.port, stream->parent->spec.node & 0x3F, stream->parent->spec.plug, stream->spec.name);               
296         } else {
297                 return -1;
298         }
299 }
300
301 freebob_streaming_stream_type freebob_streaming_get_capture_stream_type(freebob_device_t *dev, int i) {
302         freebob_stream_t *stream;
303         if(i<dev->nb_capture_streams) {
304                 stream=*(dev->capture_streams+i);
305                 switch (stream->spec.format) {
306                 case IEC61883_STREAM_TYPE_MBLA:
307                         return freebob_audio;
308                 case IEC61883_STREAM_TYPE_MIDI:
309                         return freebob_midi;
310                 case IEC61883_STREAM_TYPE_SPDIF:
311                 default:
312                         return freebob_unknown;
313                 }
314         } else {
315                 return freebob_invalid;
316         }
317 }
318
319 freebob_streaming_stream_type freebob_streaming_get_playback_stream_type(freebob_device_t *dev, int i) {
320         freebob_stream_t *stream;
321         if(i<dev->nb_playback_streams) {
322                 stream=*(dev->playback_streams+i);
323                 switch (stream->spec.format) {
324                 case IEC61883_STREAM_TYPE_MBLA:
325                         return freebob_audio;
326                 case IEC61883_STREAM_TYPE_MIDI:
327                         return freebob_midi;
328                 case IEC61883_STREAM_TYPE_SPDIF:
329                 default:
330                         return freebob_unknown;
331                 }
332         } else {
333                 return freebob_invalid;
334         }
335 }
336
337 int freebob_streaming_start_thread(freebob_device_t *dev) {
338         int err;
339         // start the packetizer thread
340         // init the packetizer thread communication semaphores
341         if((err=sem_init(&dev->packetizer.transfer_boundary, 0, 0))) {
342                 printError( "Cannot init packet transfer semaphore\n");
343                 return err;
344         } else {
345                 debugPrint(DEBUG_LEVEL_STARTUP,"FREEBOB: successfull init of packet transfer semaphore\n");
346         }
347        
348         // FIXME: packetizer thread
349         dev->packetizer.run=1;
350        
351         if (freebob_streaming_create_thread(&dev->packetizer.transfer_thread, 10, 1, freebob_iso_packet_iterator, (void *)dev)) {
352                 printError("FREEBOB: cannot create packet transfer thread");
353                 return -1;
354         } else {
355                 debugPrint(DEBUG_LEVEL_STARTUP,"Created packet transfer thread\n");
356         }
357         return 0;
358 }
359
360 int freebob_streaming_stop_thread(freebob_device_t *dev) {
361         void *status;
362        
363         debugPrint(DEBUG_LEVEL_STARTUP," Stopping packetizer thread...\n");
364         dev->packetizer.run=0;
365        
366         //sem_post(&dev->packetizer.transfer_ack);
367        
368         pthread_join (dev->packetizer.transfer_thread, &status);
369        
370         // cleanup semaphores
371         sem_destroy(&dev->packetizer.transfer_boundary);
372
373         return 0;
374 }
375
376
377 int freebob_streaming_start(freebob_device_t *dev) {
378         int err;
379         int i;
380        
381         //SEGFAULT
382        
383         for(i=0; i < dev->nb_connections; i++) {
384                 err=0;
385                 freebob_connection_t *connection= &(dev->connections[i]);
386                
387                 //connection->plug=0;
388                 connection->iso.hostplug=-1;
389                
390                 // create the CCM PTP connection
391                 connection->iso.do_disconnect=0;
392
393                 // start receiving
394                 switch (connection->spec.direction) {
395                 case FREEBOB_CAPTURE:
396                
397                         debugPrint(DEBUG_LEVEL_STARTUP," creating capture connections...\n");
398                         if (connection->spec.iso_channel < 0) {
399                                 // we need to make the connection ourself
400                                 debugPrint(DEBUG_LEVEL_STARTUP, "Executing CMP procedure...\n");
401                                
402                                 connection->iso.iso_channel = iec61883_cmp_connect(
403                                         connection->raw_handle,
404                                         connection->spec.node | 0xffc0,
405                                         &connection->spec.plug,
406                                         raw1394_get_local_id (connection->raw_handle),
407                                         &connection->iso.hostplug,
408                                         &connection->iso.bandwidth);
409                                        
410                                 connection->iso.do_disconnect=1;
411                                
412                         } else {
413                                 connection->iso.iso_channel=connection->spec.iso_channel;
414                         }
415
416                         if (connection->spec.is_master) { //master connection
417                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master receive handler on channel %d...\n",connection->iso.iso_channel);
418                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
419                                 raw1394_iso_recv_init(
420                                         connection->raw_handle,
421                                         iso_master_receive_handler,
422                                         connection->iso.buffers,
423                                         AMDTP_MAX_PACKET_SIZE,
424                                         connection->iso.iso_channel,
425                                         RAW1394_DMA_BUFFERFILL,
426                                         connection->iso.irq_interval);
427                                                                                
428                                 dev->sync_master_connection=connection;
429                                 connection->status.master=NULL;
430                                
431                         } else {
432                                 //slave receive connection
433                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave receive handler on channel %d...\n",connection->iso.iso_channel);
434                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n", connection->iso.buffers, AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
435                                 raw1394_iso_recv_init( 
436                                         connection->raw_handle,
437                                         iso_slave_receive_handler,
438                                         connection->iso.buffers,
439                                         AMDTP_MAX_PACKET_SIZE,
440                                         connection->iso.iso_channel,
441                                         RAW1394_DMA_BUFFERFILL,
442                                         connection->iso.irq_interval);
443                         }
444                        
445                 break;
446                 case FREEBOB_PLAYBACK:
447                         debugPrint(DEBUG_LEVEL_STARTUP," creating playback connections...\n");
448                
449                         if (connection->spec.iso_channel < 0) { // we need to make the connection ourself
450                                 debugPrint(DEBUG_LEVEL_STARTUP, "Executing CMP procedure...\n");
451                                 connection->iso.iso_channel = iec61883_cmp_connect(
452                                 connection->raw_handle,
453                                 raw1394_get_local_id (connection->raw_handle),
454                                 &connection->iso.hostplug,
455                                 connection->spec.node | 0xffc0,
456                                 &connection->spec.plug,
457                                 &connection->iso.bandwidth);
458                                
459                                 connection->iso.do_disconnect=1;
460                         } else {
461                                 connection->iso.iso_channel=connection->spec.iso_channel;
462                         }
463
464                         if (connection->spec.is_master) { // master connection
465                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master transmit handler on channel %d...\n",connection->iso.iso_channel);
466                                 debugPrint(DEBUG_LEVEL_STARTUP, "   other mode (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
467                                
468                                 raw1394_iso_xmit_init(
469                                         connection->raw_handle,
470                                         iso_master_transmit_handler,
471                                         connection->iso.buffers,
472                                         AMDTP_MAX_PACKET_SIZE,
473                                         connection->iso.iso_channel,
474                                         RAW1394_ISO_SPEED_400,
475                                         connection->iso.irq_interval);
476
477                                 dev->sync_master_connection=connection;
478                                 connection->status.master=NULL;
479                        
480                         } else {
481                        
482                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave transmit handler on channel %d...\n",connection->iso.iso_channel);
483                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
484                                 raw1394_iso_xmit_init(
485                                         connection->raw_handle,
486                                         iso_slave_transmit_handler,
487                                         connection->iso.buffers,
488                                         AMDTP_MAX_PACKET_SIZE,
489                                         connection->iso.iso_channel,
490                                         RAW1394_ISO_SPEED_400,
491                                         connection->iso.irq_interval);
492                         }
493                        
494                         int fdf, syt_interval;
495 // FIXME:               
496                         int samplerate=dev->options.sample_rate;
497 //                      int samplerate=connection->spec.samplerate;
498
499                         switch (samplerate) {
500                         case 32000:
501                                 syt_interval = 8;
502                                 fdf = IEC61883_FDF_SFC_32KHZ;
503                                 break;
504                         case 44100:
505                                 syt_interval = 8;
506                                 fdf = IEC61883_FDF_SFC_44K1HZ;
507                                 break;
508                         default:
509                         case 48000:
510                                 syt_interval = 8;
511                                 fdf = IEC61883_FDF_SFC_48KHZ;
512                                 break;
513                         case 88200:
514                                 syt_interval = 16;
515                                 fdf = IEC61883_FDF_SFC_88K2HZ;
516                                 break;
517                         case 96000:
518                                 syt_interval = 16;
519                                 fdf = IEC61883_FDF_SFC_96KHZ;
520                                 break;
521                         case 176400:
522                                 syt_interval = 32;
523                                 fdf = IEC61883_FDF_SFC_176K4HZ;
524                                 break;
525                         case 192000:
526                                 syt_interval = 32;
527                                 fdf = IEC61883_FDF_SFC_192KHZ;
528                                 break;
529                         }
530                                                                
531                         iec61883_cip_init (
532                                 &connection->status.cip,
533                                 IEC61883_FMT_AMDTP,
534                                 fdf,
535                                 samplerate,
536                                 connection->spec.dimension,
537                                 syt_interval);
538                                
539                         iec61883_cip_set_transmission_mode (
540                                 &connection->status.cip,
541                                 IEC61883_MODE_BLOCKING_EMPTY);
542
543                 break;
544                 }
545                
546                 if(connection->iso.iso_channel<0) {
547                         printError("Could not do CMP for connection %d\n",i);
548                         i-=1;
549                         while(i>=0) {
550                                 connection= &(dev->connections[i]);
551                
552                                 debugPrint(DEBUG_LEVEL_STARTUP, "Shutdown connection %d on channel %d ...\n", i, connection->iso.iso_channel);
553                                
554                                 raw1394_iso_shutdown(connection->raw_handle);
555                
556                                 if (connection->iso.do_disconnect) {
557                                         // destroy the CCM PTP connection
558                                         switch (connection->spec.direction) {
559                                         case FREEBOB_CAPTURE:
560                                                 iec61883_cmp_disconnect(
561                                                         connection->raw_handle,
562                                                         connection->spec.node | 0xffc0,
563                                                         connection->spec.plug,
564                                                         raw1394_get_local_id (connection->raw_handle),
565                                                         connection->iso.hostplug,
566                                                         connection->iso.iso_channel,
567                                                         connection->iso.bandwidth);
568                                                
569                                         break;
570                                         case FREEBOB_PLAYBACK:
571                                                 iec61883_cmp_disconnect(
572                                                         connection->raw_handle,
573                                                         raw1394_get_local_id (connection->raw_handle),
574                                                         connection->iso.hostplug,
575                                                         connection->spec.node | 0xffc0,
576                                                         connection->spec.plug,
577                                                         connection->iso.iso_channel,
578                                                         connection->iso.bandwidth);
579                        
580                                         break;
581                                         }
582                                 }
583                                 i--;
584                         }
585                         return -1;
586                 }
587         }
588        
589         /* update the sync master pointer for all connections */
590         debugPrint(DEBUG_LEVEL_STARTUP,"Connection summary:\n");
591         int sync_masters_present=0;
592        
593         for(i=0; i < dev->nb_connections; i++) {
594                 err=0;
595                
596                 freebob_connection_t *connection= &(dev->connections[i]);
597                
598                 if (connection->spec.direction == FREEBOB_CAPTURE) {
599                         debugPrint(DEBUG_LEVEL_STARTUP,"  Capture : from node %02X.%02d to node %02X.%02d on channel %02d  {%p} ",
600                                 connection->spec.node & ~0xffc0, connection->spec.plug,
601                                 raw1394_get_local_id (connection->raw_handle) & ~0xffc0, connection->iso.hostplug,
602                                 connection->iso.iso_channel, connection);
603                 } else if (connection->spec.direction == FREEBOB_PLAYBACK) {
604                        
605                         debugPrint(DEBUG_LEVEL_STARTUP,"  Playback: from node %02X.%02d to node %02X.%02d on channel %02d  {%p} ",
606                                 raw1394_get_local_id (connection->raw_handle) & ~0xffc0, connection->iso.hostplug,
607                                 connection->spec.node & ~0xffc0, connection->spec.plug,
608                                 connection->iso.iso_channel, connection);
609                 }
610                
611                 if (connection->spec.is_master) {
612                         sync_masters_present++;
613                        
614                         debugPrintShort(DEBUG_LEVEL_STARTUP," [MASTER]");       
615                 } else {
616                         assert(dev->sync_master_connection);
617                         connection->status.master=&dev->sync_master_connection->status;
618                        
619                         debugPrintShort(DEBUG_LEVEL_STARTUP," [SLAVE]");
620                 }
621                 debugPrintShort(DEBUG_LEVEL_STARTUP,"\n");
622         }
623        
624         if (sync_masters_present == 0) {
625                 printError("FREEBOB: no sync master connection present!\n");
626                 // TODO: cleanup
627                 //freebob_streaming_stop(driver);
628                 return -1;
629         } else if (sync_masters_present > 1) {
630                 printError("FREEBOB: too many sync master connections present! (%d)\n",sync_masters_present);
631                 // TODO: cleanup
632                 //freebob_streaming_stop(driver);
633                 return -1;
634         }
635        
636         // put nb_periods*period_size of null frames into the playback buffers
637         if((err=freebob_streaming_prefill_playback_streams(dev))<0) {
638                 printError("Could not prefill playback streams.\n");
639                 return err;
640         }
641                
642         debugPrint(DEBUG_LEVEL_STARTUP,"Armed...\n");
643        
644         freebob_streaming_start_iso(dev);
645        
646         freebob_streaming_start_thread(dev);
647
648         return 0;
649
650 }
651
652 int freebob_streaming_stop(freebob_device_t *dev) {
653         unsigned int i;
654        
655
656         freebob_streaming_stop_thread(dev);
657        
658         freebob_streaming_stop_iso(dev);
659
660         // stop ISO xmit/receive
661         for(i=0; i < dev->nb_connections; i++) {
662                 freebob_connection_t *connection= &(dev->connections[i]);
663
664                 debugPrint(DEBUG_LEVEL_STARTUP, "Shutdown connection %d on channel %d ...\n", i, connection->iso.iso_channel);
665                
666                 raw1394_iso_shutdown(connection->raw_handle);
667
668                 if (connection->iso.do_disconnect) {
669                         // destroy the CCM PTP connection
670                         switch (connection->spec.direction) {
671                         case FREEBOB_CAPTURE:
672                                 iec61883_cmp_disconnect(
673                                         connection->raw_handle,
674                                         connection->spec.node | 0xffc0,
675                                         connection->spec.plug,
676                                         raw1394_get_local_id (connection->raw_handle),
677                                         connection->iso.hostplug,
678                                         connection->iso.iso_channel,
679                                         connection->iso.bandwidth);
680                                
681                         break;
682                         case FREEBOB_PLAYBACK:
683                                 iec61883_cmp_disconnect(
684                                         connection->raw_handle,
685                                         raw1394_get_local_id (connection->raw_handle),
686                                         connection->iso.hostplug,
687                                         connection->spec.node | 0xffc0,
688                                         connection->spec.plug,
689                                         connection->iso.iso_channel,
690                                         connection->iso.bandwidth);
691        
692                         break;
693                         }
694                 }
695                
696         }
697         return 0;
698 }
699
700 int freebob_streaming_prefill_playback_streams(freebob_device_t *dev) {
701         int i;
702         int err=0;
703        
704         for(i=0; i < dev->nb_playback_streams; i++) {
705                 freebob_stream_t *stream;
706
707                
708                 stream=*(dev->playback_streams+i);
709                
710                 assert(stream);
711                 err=freebob_streaming_prefill_stream(dev, stream);
712                 if (err) {
713                         printError("Could not prefill stream %d\n",i);
714                         return -1;
715                 }
716         }
717         return 0;
718        
719 }
720
721 int freebob_streaming_reset(freebob_device_t *dev) {
722         /*
723          * Reset means:
724          * 1) Stopping the packetizer thread
725          * 2) Bringing all buffers & connections into a know state
726          *    - Clear all capture buffers
727          *    - Put nb_periods*period_size of null frames into the playback buffers
728          * 3) Restarting the packetizer thread
729          */
730
731         unsigned long i;
732         int err;
733         assert(dev);
734        
735         if((err=freebob_streaming_stop_thread(dev))<0) {
736                 printError("Could not stop packetizer thread.\n");
737                 return err;
738         }
739
740         //freebob_streaming_stop_iso(dev);
741
742         // check if the packetizer is stopped
743         assert(!dev->packetizer.run);
744        
745         // reset all connections
746         for(i=0; i < dev->nb_connections; i++) {
747                 freebob_connection_t *connection= &(dev->connections[i]);
748                 freebob_streaming_reset_connection(dev,connection);
749         }
750        
751         // put nb_periods*period_size of null frames into the playback buffers
752         if((err=freebob_streaming_prefill_playback_streams(dev))<0) {
753                 printError("Could not prefill playback streams.\n");
754                 return err;
755         }
756        
757         // clear the xrun flag
758         dev->xrun_detected=FALSE;
759        
760         //freebob_streaming_start_iso(dev);
761        
762         if((err=freebob_streaming_start_thread(dev))<0) {
763                 printError("Could not start packetizer thread.\n");
764                 return err;
765         }
766        
767        
768         return 0;
769 }
770
771 int freebob_streaming_xrun_recovery(freebob_device_t *dev) {
772         freebob_streaming_reset(dev);
773         dev->xrun_count++;
774        
775         return 0;
776 }
777
778 int freebob_streaming_wait(freebob_device_t *dev) {
779         int ret;
780        
781         // Wait for packetizer thread to signal a period completion
782         sem_wait(&dev->packetizer.transfer_boundary);
783        
784         // acknowledge the reception of the period
785         //sem_post(&dev->packetizer.transfer_ack);
786        
787         if(dev->xrun_detected) {
788                 // notify the driver of the underrun and the delay
789                 ret=-freebob_streaming_xrun_recovery(dev);
790         } else {
791                 ret=dev->options.period_size;
792         }
793        
794         return ret;
795 }
796
797 int freebob_streaming_write(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
798         int retval;
799        
800         freebob_stream_t *stream;
801         assert(i<dev->nb_playback_streams);
802        
803         stream=*(dev->playback_streams+i);
804         assert(stream);
805        
806         retval=freebob_ringbuffer_write(stream->buffer,(char *)buffer,nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);
807                
808         return retval;
809 }
810
811 int freebob_streaming_read(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
812         int retval;
813        
814         freebob_stream_t *stream;
815         assert(i<dev->nb_capture_streams);
816        
817         stream=*(dev->capture_streams+i);
818         assert(stream);
819 //      fprintf(stderr,"rb read  [%02d: %08p %08p %08X, %d, %d]\n",stream->spec.position, stream, stream->buffer, *buffer, nsamples, retval);
820        
821         retval=freebob_ringbuffer_read(stream->buffer, (char *)buffer, nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);     
822        
823 //      fprintf(stderr,"rb read1 [%02d: %08p %08p %08X, %d, %d]\n",stream->spec.position, stream, stream->buffer, *buffer, nsamples, retval);
824        
825         return retval;
826 }
827
828 pthread_t freebob_streaming_get_packetizer_thread(freebob_device_t *dev) {
829         return dev->packetizer.transfer_thread;
830 }
831
832 /* --------------------- *
833  * PRIVATE STUFF         *
834  * --------------------- */
835  
836  
837 unsigned int freebob_streaming_register_generic_stream(freebob_stream_t *stream, freebob_stream_t ***oldset, unsigned int set_size) {
838         int i;
839         int found=0;
840         unsigned int new_set_size;
841        
842         freebob_stream_t **new_streams=calloc(set_size+1,sizeof(freebob_stream_t *));
843         freebob_stream_t **set=*oldset;
844        
845         for (i=0;i<set_size;i++) {
846                 *(new_streams+i)=*(set+i);
847                 if(*(set+i)==stream) {
848                         printError("FREEBOB: stream already registered\n");
849                         found=1;
850                 }
851         }
852         if (!found) {
853                 *(new_streams+set_size)=stream;
854                 new_set_size=set_size+1;
855                
856                 free(*oldset);
857                 *oldset=new_streams;
858         } else {
859                 free(new_streams);
860                 new_set_size=set_size;
861         }
862         return new_set_size;
863        
864 }
865
866 void freebob_streaming_register_capture_stream(freebob_device_t *dev, freebob_stream_t *stream) {
867         dev->nb_capture_streams=
868                 freebob_streaming_register_generic_stream(
869                         stream,
870                         &dev->capture_streams,
871                         dev->nb_capture_streams);
872         if (stream->spec.format==IEC61883_STREAM_TYPE_MBLA) {
873                 dev->nb_synced_capture_streams=
874                         freebob_streaming_register_generic_stream(
875                                 stream,
876                                 &dev->synced_capture_streams,
877                                 dev->nb_synced_capture_streams);
878         }
879 }
880
881 void freebob_streaming_register_playback_stream(freebob_device_t *dev, freebob_stream_t *stream) {
882         dev->nb_playback_streams=
883                 freebob_streaming_register_generic_stream(
884                         stream,
885                         &dev->playback_streams,
886                         dev->nb_playback_streams);
887         if (stream->spec.format==IEC61883_STREAM_TYPE_MBLA) {
888                 dev->nb_synced_playback_streams=
889                         freebob_streaming_register_generic_stream(
890                                 stream,
891                                 &dev->synced_playback_streams,
892                                 dev->nb_synced_playback_streams);
893         }
894 }
895
896 static inline int
897 freebob_streaming_period_complete (freebob_device_t *dev) {
898         unsigned long i;
899         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
900        
901         assert(dev);
902        
903         for(i=0; i < dev->nb_connections; i++) {
904                 freebob_connection_t *connection= &(dev->connections[i]);
905                 if (connection->status.frames_left > 0) {
906                         return FALSE;
907                 }
908         }
909         return TRUE;
910        
911 #if 0   
912         for(i=0; i < dev->nb_synced_capture_streams; i++) {
913                 assert(dev->synced_capture_streams);
914                 assert(dev->synced_capture_streams[i]);
915                
916                 /* We check if there is more than one period of samples in the buffer.
917                  * if not the period isn't complete yet.
918                  */
919                 if (freebob_ringbuffer_read_space(dev->synced_capture_streams[i]->buffer) < period_boundary_bytes) {
920                         return FALSE;
921                 }
922         }
923        
924         for(i=0; i < dev->nb_synced_playback_streams; i++) {
925                 assert(dev->synced_playback_streams);
926                 assert(dev->synced_playback_streams[i]);
927                 //FIXME: check this!
928                 /* We check if there is still one period of samples in the output buffer.
929                  * if so, the period isn't complete yet.
930                  */
931                 if (freebob_ringbuffer_read_space(dev->synced_playback_streams[i]->buffer) > period_boundary_bytes) {
932                         return FALSE;
933                 }
934         }
935         return TRUE;
936 #endif
937 }
938
939 static inline void
940 freebob_streaming_period_reset (freebob_device_t *dev) {
941 //      unsigned long i;
942         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
943         unsigned long i;
944         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
945         printEnter();
946         assert(dev);
947        
948         for(i=0; i < dev->nb_connections; i++) {
949                 freebob_connection_t *connection= &(dev->connections[i]);
950                 connection->status.frames_left+=dev->options.period_size;
951         }
952         printExit();
953         return;
954 }
955
956 static inline int
957 freebob_streaming_xrun_detected (freebob_device_t *dev, freebob_connection_t **connections, int nb_connections) {
958         int i;
959        
960         for(i=0; i < nb_connections; i++) {
961                 assert((connections[i]));
962                 if (connections[i]->status.xruns>0) {
963                         return TRUE;
964                 }
965         }
966         return FALSE;
967 }
968
969 int freebob_streaming_start_iso(freebob_device_t *dev) {
970         int err;
971         unsigned int c;
972
973         // start ISO xmit/receive
974         for(c=0; c < dev->nb_connections; c++) {
975                 err=0;
976                 freebob_connection_t *connection= &(dev->connections[c]);
977                 if (connection->spec.direction == FREEBOB_CAPTURE) {
978                         debugPrint(DEBUG_LEVEL_STARTUP, "Start ISO receive for connection %d on channel %d ...\n", c, connection->iso.iso_channel);
979                        
980                         err = raw1394_iso_recv_start(
981                                 connection->raw_handle,
982                                 0, // connection->iso.startcycle,
983                                 -1,//IEC61883_TAG_WITH_CIP,
984                                 0);
985
986                         if (err) {
987                                 printError("FREEBOB: couldn't start receiving: %s\n",
988                                             strerror (errno));
989                                 // TODO: cleanup
990                                 return err;
991                         }                                       
992                
993                 } else if (connection->spec.direction == FREEBOB_PLAYBACK) {
994                         debugPrintWithTimeStamp(DEBUG_LEVEL_STARTUP, "Start ISO transmit for connection %d on channel %d\n", c, connection->iso.iso_channel);
995                        
996                         err=raw1394_iso_xmit_start(
997                                 connection->raw_handle,
998                                 12, // connection->iso.startcycle,
999                                 connection->iso.prebuffers);
1000
1001                         if (err) {
1002                                 printError("FREEBOB: couldn't start transmitting: %s\n",
1003                                             strerror (errno));
1004                                 // TODO: cleanup
1005                                 return err;
1006                         }
1007                 }
1008         }       
1009         return 0;
1010 }
1011
1012 int freebob_streaming_stop_iso(freebob_device_t *dev) {
1013         unsigned int c;
1014         // stop ISO xmit/receive
1015         for(c=0; c < dev->nb_connections; c++) {
1016                 freebob_connection_t *connection= &(dev->connections[c]);
1017
1018                 debugPrintWithTimeStamp(DEBUG_LEVEL_STARTUP, "Stop connection %d on channel %d ...\n", c, connection->iso.iso_channel);
1019                
1020                 raw1394_iso_stop(connection->raw_handle);
1021         }
1022         return 0;
1023 }
1024
1025 /*
1026  * The thread responsible for packet iteration
1027  */
1028
1029 void * freebob_iso_packet_iterator(void *arg)
1030 {
1031
1032         freebob_device_t * dev=(freebob_device_t *) arg;
1033         int err;
1034         int cycle=0;
1035         unsigned int c;
1036         int underrun_detected=0;
1037        
1038         freebob_connection_t *connection=NULL;
1039        
1040         assert(dev);
1041         assert(dev->sync_master_connection);
1042         assert(dev->connections);
1043        
1044         debugPrint(DEBUG_LEVEL_STARTUP, "Entering packetizer thread...\n");
1045        
1046         //freebob_streaming_start_iso(dev);
1047        
1048         // when starting the thread, we should wait with iterating the slave connections
1049         // until the master connection has processed some samples, because the devices
1050         // tend to start with a stream of no-data packets, leading to xruns on slave
1051         // transmit, leading to multiple restarts of the thread, which doesn't work correctly (yet)
1052         debugPrint(DEBUG_LEVEL_STARTUP, "Waiting for the sync master...\n");
1053        
1054         connection=dev->sync_master_connection;
1055         while(connection->status.events==0) {
1056                 err=0;
1057                
1058                 // get a packet on the sync master connection
1059                 err=raw1394_loop_iterate(connection->raw_handle);
1060                
1061                 if (err == -1) {
1062                         printError("Possible raw1394 error: %s on sync master connection: %d\n",
1063                                 strerror (errno),connection->spec.id);
1064                                
1065                         dev->packetizer.status = -2;
1066                         dev->packetizer.retval = 0;
1067                         break;
1068                 }
1069                
1070                 // detect underruns on the sync master connection
1071                 if (freebob_streaming_xrun_detected(dev,&connection,1)) {
1072                         printError("Xrun on sync master connection %d\n", connection->spec.id);
1073                         underrun_detected=TRUE;
1074                         break; // we can exit as the underrun handler will flush the buffers anyway
1075                 }
1076         }
1077        
1078         debugPrint(DEBUG_LEVEL_STARTUP, "Go Go Go!!!\n");
1079        
1080         //sem_post(&dev->packetizer.transfer_ack);
1081
1082         while (dev->packetizer.run && !underrun_detected) {
1083                 //sem_wait(&dev->packetizer.transfer_ack);
1084                
1085                 freebob_streaming_period_reset(dev);
1086                
1087                 while(( !freebob_streaming_period_complete(dev)
1088                                 && !underrun_detected
1089                                 && (dev->packetizer.run))) {
1090                         err=0;
1091                        
1092                         // this makes sure the sync_master finishes before the others finish
1093                         connection=dev->sync_master_connection;
1094                         if (connection->status.frames_left > 0) {
1095                                 // process a packet on the sync master connection
1096                                 err=raw1394_loop_iterate(connection->raw_handle);
1097                                
1098                                 if (err == -1) {
1099                                         printError("Possible raw1394 error: %s on sync master connection: %d\n",
1100                                                 strerror (errno),connection->spec.id);
1101                                                
1102                                         dev->packetizer.status = -2;
1103                                         dev->packetizer.retval = 0;
1104                                         break;
1105                                 }
1106                                
1107                                 // detect underruns on the sync master connection
1108                                 if (freebob_streaming_xrun_detected(dev,&connection,1)) {
1109                                         printError("Xrun on sync master connection %d\n", connection->spec.id);
1110                                         underrun_detected=TRUE;
1111                                         break; // we can exit as the underrun handler will flush the buffers anyway
1112                                 }
1113                         }
1114                         // now iterate on the slave connections
1115                
1116                         for(c=0; c<dev->nb_connections; c++) {
1117
1118                                 connection = &(dev->connections[c]);
1119                                
1120                                 // skip the sync master and the connections that are finished
1121                                 if ((connection == dev->sync_master_connection) || (connection->status.frames_left <= 0))
1122                                         continue;
1123                                
1124                                 err=raw1394_loop_iterate(connection->raw_handle);
1125                                
1126                                 if (err == -1) {
1127                                         printError("Possible raw1394 error: %s on connection: %d\n",
1128                                                 strerror (errno),connection->spec.id);
1129                                         dev->packetizer.status = -2;
1130                                         dev->packetizer.retval = 0;
1131                                 }
1132                                
1133                                 // detect underruns
1134                                 if (freebob_streaming_xrun_detected(dev,&connection,1)) {
1135                                         printError("Xrun on slave connection %d\n", connection->spec.id);
1136                                         underrun_detected=TRUE;
1137                                         break; // we can exit as the underrun handler will flush the buffers anyway
1138                                 }
1139                         }
1140                        
1141                         cycle++;
1142                 }
1143                
1144                 if(underrun_detected) {
1145                         dev->xrun_detected=TRUE;
1146                         //underrun_detected=0;
1147                 }
1148                
1149                 // notify the waiting thread
1150 #ifdef DEBUG
1151                 debugPrint(DEBUG_LEVEL_HANDLERS, "Post semaphore ");
1152                 for(c=0; c<dev->nb_connections; c++) {
1153                         connection = &(dev->connections[c]);
1154                         debugPrintShort(DEBUG_LEVEL_HANDLERS,"[%d: %d]",c,connection->status.frames_left);
1155                 }
1156                 debugPrintShort(DEBUG_LEVEL_HANDLERS,"\n");
1157 #endif
1158                 sem_post(&dev->packetizer.transfer_boundary);
1159                
1160                
1161 #ifdef DEBUG
1162                         // update the packet counter
1163                 if((dev->sync_master_connection->status.packets - dev->sync_master_connection->status.total_packets_prev) > 1024*4) {
1164         //      if(1) {
1165                         unsigned int i;
1166                         debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER,"\r -> ");
1167                        
1168                         for(i=0; i < dev->nb_connections; i++) {
1169                                 freebob_connection_t *connection= &(dev->connections[i]);
1170                                 assert(connection);
1171                                
1172                                 /* Debug info format:
1173                                 * [direction, packetcount, bufferfill, packetdrop
1174                                 */
1175                                 debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER,"[%s, %02d, %12d, %4d, (%04d)]",
1176                                         (connection->spec.direction==FREEBOB_CAPTURE ? "C" : "P"),
1177                                         connection->status.fdf,
1178                                         connection->status.packets,
1179                                         connection->status.dropped,
1180                                         freebob_ringbuffer_read_space(connection->streams[0].buffer)/sizeof(freebob_sample_t)
1181                                         );
1182                         }
1183        
1184                         debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER," XRUNS (%4d)",dev->xrun_count);     
1185                         fflush (stderr);
1186                        
1187                         dev->sync_master_connection->status.total_packets_prev=dev->sync_master_connection->status.packets;
1188                 }
1189
1190 #endif
1191
1192         }
1193        
1194         //freebob_streaming_stop_iso(dev);
1195        
1196         debugPrint(DEBUG_LEVEL_STARTUP, "Exiting packetizer thread...\n");
1197        
1198        
1199         pthread_exit (0);       
1200 }
1201
1202 static int freebob_am824_recv(char *data,
1203                                int nevents, unsigned int dbc,
1204                                freebob_connection_t *connection);
1205
1206 static int freebob_am824_xmit(char *data,
1207                                int nevents, unsigned int dbc,
1208                                freebob_connection_t *connection);
1209                                
1210 /**
1211  * ISO send/receive callback handlers
1212  */
1213
1214 static enum raw1394_iso_disposition
1215 iso_master_receive_handler(raw1394handle_t handle, unsigned char *data,
1216         unsigned int length, unsigned char channel,
1217         unsigned char tag, unsigned char sy, unsigned int cycle,
1218         unsigned int dropped)
1219 {
1220     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
1221        
1222         int xrun=0;
1223
1224         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
1225         assert(connection);
1226        
1227         struct iec61883_packet *packet = (struct iec61883_packet *) data;
1228         assert(packet);
1229        
1230         // FIXME: dropped packets are very bad when transmitting and the other side is sync'ing on that!
1231         //connection->status.packets+=dropped;
1232         connection->status.dropped+=dropped;
1233        
1234         if((packet->fdf) != 0xFF && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
1235                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
1236                
1237                 // add the data payload to the ringbuffer
1238                 xrun= freebob_am824_recv(data + 8, nevents, packet->dbc, connection);
1239                
1240                 if(xrun) {
1241                         printError("MASTER RCV: Buffer overrun!\n");
1242                         connection->status.xruns++;
1243                         retval=RAW1394_ISO_DEFER;
1244                 } else {
1245                         retval=RAW1394_ISO_OK;
1246                 }
1247                
1248                 // keep track of the total amount of events received
1249                 connection->status.events+=nevents;
1250                
1251                 connection->status.fdf=packet->fdf;
1252                
1253         } else {
1254                 // discard packet
1255                 // can be important for sync though
1256         }
1257
1258         // one packet received
1259         connection->status.packets++;
1260         if(packet->dbs) {
1261                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
1262                         "MASTER RCV: %08d, CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %6d\n",
1263                         cycle,
1264                         channel, packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, length,
1265                         ((length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped);
1266         }
1267        
1268         if( (!(connection->status.packets % 4)) || (connection->status.frames_left<=0)) {
1269                 retval=RAW1394_ISO_DEFER;
1270         }
1271        
1272     return retval;
1273 }
1274
1275 static enum raw1394_iso_disposition
1276 iso_slave_transmit_handler(raw1394handle_t handle,
1277                 unsigned char *data, unsigned int *length,
1278                 unsigned char *tag, unsigned char *sy,
1279                 int cycle, unsigned int dropped)
1280 {
1281         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
1282         assert(connection);
1283        
1284         struct iec61883_packet *packet = (struct iec61883_packet *) data;
1285         assert(packet);
1286         assert(length);
1287         assert(tag);
1288         assert(sy);     
1289        
1290         // construct the packet cip
1291         int nevents = iec61883_cip_fill_header (handle, &connection->status.cip, packet);
1292         int xrun=0;
1293         int nsamples=0;
1294        
1295         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
1296                
1297 // debug
1298         if(packet->fdf != 0xFF) {
1299                 connection->status.fdf=packet->fdf;
1300         }
1301
1302         if (nevents > 0) {
1303                 nsamples = nevents;
1304         }
1305         else {
1306                 if (connection->status.cip.mode == IEC61883_MODE_BLOCKING_EMPTY) {
1307                         nsamples = 0;
1308                 }
1309                 else {
1310                         nsamples = connection->status.cip.syt_interval;
1311                 }
1312         }
1313        
1314         // dropped packets are very bad when transmitting and the other side is sync'ing on that!
1315         //connection->status.packets+=dropped;
1316         connection->status.dropped += dropped;
1317                
1318         if (nsamples > 0) {
1319                 // read the data payload from the ringbuffer
1320                 xrun=freebob_am824_xmit(data+8, nsamples, packet->dbc, connection);
1321         }
1322        
1323         if (xrun) {
1324                 printError("SLAVE XMT: Buffer underrun!\n");
1325                 connection->status.xruns++;
1326                 retval=RAW1394_ISO_DEFER;
1327                 nsamples=0;
1328         }
1329        
1330         *length = nsamples * connection->spec.dimension * sizeof (quadlet_t) + 8;
1331         *tag = IEC61883_TAG_WITH_CIP;
1332         *sy = 0;
1333        
1334         // keep track of the total amount of events transmitted
1335         connection->status.events+=nsamples;
1336                
1337         // one packet transmitted
1338         connection->status.packets++;
1339
1340         if(packet->dbs) {
1341                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
1342                         "SLAVE XMT: %08d, CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %4d, info->packets=%4d, events=%4d, %d, %d %d %d\n", cycle,
1343                         connection->iso.iso_channel,  packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, *length,((*length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped,
1344                         connection->status.packets, connection->status.events, connection->status.frames_left,
1345                         nevents, nsamples,xrun);
1346         }
1347                
1348         if( (!(connection->status.packets % 4)) || (connection->status.frames_left<=0)) {
1349                 retval=RAW1394_ISO_DEFER;
1350         }
1351         return retval;
1352
1353 }
1354
1355 /**
1356  * The master transmit handler.
1357  *
1358  * This is the most difficult, because we have to generate timing information ourselves.
1359  *
1360  */
1361
1362 /*
1363  Includes code from libiec61883
1364  */
1365 static enum raw1394_iso_disposition
1366 iso_master_transmit_handler(raw1394handle_t handle,
1367                 unsigned char *data, unsigned int *length,
1368                 unsigned char *tag, unsigned char *sy,
1369                 int cycle, unsigned int dropped)
1370 {
1371         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
1372         assert(connection);
1373        
1374         struct iec61883_packet *packet = (struct iec61883_packet *) data;
1375         assert(packet);
1376         assert(length);
1377         assert(tag);
1378         assert(sy);
1379        
1380         // construct the packet cip
1381         int nevents = iec61883_cip_fill_header (handle, &connection->status.cip, packet);
1382         int xrun=0;
1383         int nsamples=0;
1384        
1385         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
1386 // debug
1387         if(packet->fdf != 0xFF) {
1388                 connection->status.fdf=packet->fdf;
1389         }
1390        
1391         if (nevents > 0) {
1392                 nsamples = nevents;
1393         }
1394         else {
1395                 if (connection->status.cip.mode == IEC61883_MODE_BLOCKING_EMPTY) {
1396                         nsamples = 0;
1397                 }
1398                 else {
1399                         nsamples = connection->status.cip.syt_interval;
1400                 }
1401         }
1402        
1403         // dropped packets are very bad when transmitting and the other side is sync'ing on that!
1404         //connection->status.packets+=dropped;
1405         connection->status.dropped += dropped;
1406                
1407         if (nsamples > 0) {
1408                 // read the data payload from the ringbuffer
1409                 xrun=freebob_am824_xmit(data+8, nsamples, packet->dbc, connection);
1410         }
1411        
1412         if (xrun) {
1413                 printError("MASTER XMT: Buffer underrun!\n");
1414                 connection->status.xruns++;
1415                 retval=RAW1394_ISO_DEFER;
1416                 /* this is to make sure that the receiving device doesnt receive junk,
1417                    as part of the package wasn't filled.
1418                 */
1419                 nsamples=0;
1420         }
1421                
1422         *length = nsamples * connection->spec.dimension * sizeof (quadlet_t) + 8;
1423         *tag = IEC61883_TAG_WITH_CIP;
1424         *sy = 0;
1425        
1426         // keep track of the total amount of events transmitted
1427         connection->status.events+=nsamples;
1428                
1429         // one packet transmitted
1430         connection->status.packets++;
1431
1432         if(packet->dbs) {
1433                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
1434                         "MASTER XMT: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %4d, info->packets=%4d, events=%4d, %d, %d %d %d\n",
1435                         connection->iso.iso_channel,  packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, *length,((*length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped,
1436                         connection->status.packets, connection->status.events, connection->status.frames_left,
1437                         nevents, nsamples,xrun);
1438         }       
1439
1440         if( (!(connection->status.packets % 4)) || (connection->status.frames_left<=0)) {
1441                 retval=RAW1394_ISO_DEFER;
1442         }
1443                
1444         return retval;
1445
1446 }
1447
1448 static enum raw1394_iso_disposition
1449 iso_slave_receive_handler(raw1394handle_t handle, unsigned char *data,
1450         unsigned int length, unsigned char channel,
1451         unsigned char tag, unsigned char sy, unsigned int cycle,
1452         unsigned int dropped)
1453 {
1454         enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
1455         /* slave receive is easy if you assume that the connections are synced
1456          * Synced connections have matched data rates, so just receiving and calling the rcv handler would
1457          * suffice in this case. As the connection is externally matched to the master connection, the buffer fill
1458          * will be ok.
1459          */
1460                
1461         int xrun=0;
1462
1463         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
1464         assert(connection);
1465        
1466         struct iec61883_packet *packet = (struct iec61883_packet *) data;
1467         assert(packet);
1468        
1469         // FIXME: dropped packets are very bad when transmitting and the other side is sync'ing on that!
1470         //connection->status.packets+=dropped;
1471         connection->status.dropped+=dropped;
1472        
1473         if((packet->fdf) != 0xFF && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
1474                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
1475                 connection->status.fdf=packet->fdf;
1476                
1477                 // add the data payload to the ringbuffer
1478                 xrun= freebob_am824_recv(data + 8, nevents, packet->dbc, connection);
1479                
1480                 if(xrun) {
1481                         printError("SLAVE RCV: Buffer overrun!\n");
1482                         connection->status.xruns++;
1483                         retval=RAW1394_ISO_DEFER;
1484                 } else {
1485                         retval=RAW1394_ISO_OK;
1486                 }
1487                
1488                 // keep track of the total amount of events received
1489                 connection->status.events+=nevents;
1490         } else {
1491                 // discard packet
1492                 // can be important for sync though
1493         }
1494
1495         // one packet received
1496         connection->status.packets++;
1497        
1498         if(packet->dbs) {
1499                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
1500                         "SLAVE RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %6d\n",
1501                         channel, packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, length,
1502                         ((length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped);
1503         }
1504                
1505         if( (!(connection->status.packets % 4)) || (connection->status.frames_left<=0)) {
1506                 retval=RAW1394_ISO_DEFER;
1507         }
1508        
1509     return retval;
1510 }
1511
1512 /*
1513  * write received events to the stream ringbuffers.
1514  */
1515
1516 int freebob_am824_recv(char *data,
1517                                int nevents, unsigned int dbc,
1518                                freebob_connection_t *connection)
1519 {
1520         int xrun=0;
1521         unsigned int i=0;
1522        
1523         for(i = 0; i < connection->nb_streams; i++) {
1524                 freebob_stream_t *stream = &(connection->streams[i]);
1525                 size_t written=0;
1526                
1527                 assert(stream);
1528                
1529                 debugPrintShort(DEBUG_LEVEL_HANDLERS,"[%d: %d ",i,freebob_ringbuffer_write_space(stream->buffer));
1530
1531                 written = freebob_decode_events_to_stream(
1532                         connection,
1533                         stream,
1534                         (quadlet_t *)data,
1535                         nevents,
1536                         dbc
1537                         );
1538                        
1539                 if (written < nevents) {
1540                         xrun++;
1541                 }
1542                
1543                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "%d %d]",written,freebob_ringbuffer_write_space(stream->buffer));
1544         }
1545        
1546         connection->status.frames_left-=nevents;
1547                
1548         debugPrintShort(DEBUG_LEVEL_HANDLERS, "\n");
1549        
1550         return xrun;
1551 }
1552
1553 /*
1554  * get xmit events from ringbuffer
1555  */
1556
1557 int freebob_am824_xmit( char *data,
1558                                                 int nevents, unsigned int dbc,
1559                                                 freebob_connection_t *connection)
1560 {
1561         int xrun=0;
1562         unsigned int i=0;
1563        
1564         for(i = 0; i < connection->nb_streams; i++) {
1565                 freebob_stream_t *stream = &(connection->streams[i]);
1566                 size_t read=0;
1567                
1568                 assert(stream);
1569                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "[%d: %d ",i,freebob_ringbuffer_read_space(stream->buffer));
1570                
1571                 read = freebob_encode_stream_to_events(
1572                         connection,
1573                         stream,
1574                         (quadlet_t *)data,
1575                         nevents,
1576                         dbc
1577                         );
1578                
1579                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "%d %d]",read,freebob_ringbuffer_read_space(stream->buffer));
1580
1581                 if (read < nevents) {
1582                         xrun++;
1583                 }
1584                
1585         }
1586         debugPrintShort(DEBUG_LEVEL_HANDLERS, "\n");
1587        
1588         connection->status.frames_left-=nevents;
1589        
1590         return xrun;
1591 }
1592
1593 int
1594 freebob_streaming_create_thread (pthread_t* thread,
1595                            int priority,
1596                            int realtime,
1597                            void*(*start_routine)(void*),
1598                            void* arg)
1599 {
1600         int result = 0;
1601
1602         result = pthread_create (thread, 0, start_routine, arg);
1603         if (result) {
1604                 debugPrint(DEBUG_LEVEL_THREADS,"creating thread with default parameters");
1605         }
1606         return result;
1607 }
1608
Note: See TracBrowser for help on using the browser.