1 /*****************************************************************************
2 * asi-deltacast.c: support for Deltacast ASI cards
3 *****************************************************************************
4 * Copyright (C) 2004, 2009, 2015 VideoLAN
6 * Authors: Simon Lockhart <simon@slimey.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 #ifdef HAVE_ASI_DELTACAST_SUPPORT
32 #include <sys/types.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
45 #include <bitstream/common.h>
47 #include <StreamMaster.h>
48 // #include <DeltacastErrors.h>
50 #include "asi-deltacast.h"
54 /*****************************************************************************
56 *****************************************************************************/
57 #define ASI_DELTACAST_PERIOD 1000 /* ms */
58 #define ASI_DELTACAST_LOCK_TIMEOUT 5000000 /* 5 s */
60 static HANDLE h_board
, h_channel
;
61 static struct ev_timer asi_watcher
, mute_watcher
;
62 static bool b_sync
= false;
64 static UCHAR
*p_asibuf
= NULL
;
65 static ULONG i_asibuf_len
;
67 /*****************************************************************************
69 *****************************************************************************/
70 void asi_deltacast_Open( void )
72 ASICHANNELCONFIG RXConfig
;
73 ULONG ApiVersion
, DrvVersion
, NbBoards
;
74 ASIBOARDINFOEX BoardInfoEx
;
77 /* Get API information */
78 res
= Asi_GetApiInfo(&ApiVersion
,&DrvVersion
,&NbBoards
);
81 msg_Err( NULL
, "couldn't get Deltacast API Info: 0x%08lX",
82 (unsigned long) Dc_GetLastError(NULL
) );
86 msg_Dbg( NULL
, "Deltacast StreamMaster DLL v%d.%d",
88 (int)ApiVersion
&0xFFFF);
89 msg_Dbg( NULL
, "Deltacast Driver v%d.%d.%d",
90 (DrvVersion
>> 24) & 0xFF,
91 (DrvVersion
>> 16) & 0xFF,
92 (DrvVersion
>> 8) & 0xFF);
93 msg_Dbg( NULL
, "Deltacast Board Count: %d", NbBoards
);
95 /* Get the board information */
96 res
= Asi_GetBoardInfoEx((int)(i_asi_adapter
/ 100), &BoardInfoEx
);
99 msg_Err( NULL
, "couldn't get Deltacast board Info: 0x%08lX",
100 (unsigned long) Dc_GetLastError(NULL
) );
104 msg_Dbg( NULL
, "Deltacast Board FPGA v%08lX",
105 (unsigned long)BoardInfoEx
.BaseInformation
.FPGAVersion
);
106 msg_Dbg( NULL
, "Deltacast Board PLD v%08lX",
107 (unsigned long)BoardInfoEx
.BaseInformation
.PLDVersion
);
108 msg_Dbg( NULL
, "Deltacast Board PLX v%08lX",
109 (unsigned long)BoardInfoEx
.BaseInformation
.PLXRevision
);
110 msg_Dbg( NULL
, "Deltacast Board Serial %08X%08X",
111 (ULONG
)(BoardInfoEx
.BaseInformation
.SerialNb
>>32),
112 (ULONG
)(BoardInfoEx
.BaseInformation
.SerialNb
&0xFFFFFFFF));
113 msg_Dbg( NULL
, "Deltacast Board Input Count: %d", BoardInfoEx
.NbRxChannels_i
);
114 msg_Dbg( NULL
, "Deltacast Board Output Count: %d", BoardInfoEx
.NbTxChannels_i
);
117 h_board
= Asi_SetupBoard((int)(i_asi_adapter
/ 100));
120 msg_Err( NULL
, "couldn't setup deltacast board %d: 0x%08lX",
121 (int)(i_asi_adapter
/ 100), (unsigned long) Dc_GetLastError(NULL
) );
125 /* Open the channel on the board */
126 memset(&RXConfig
,0,sizeof(ASICHANNELCONFIG
));
127 RXConfig
.DriverBufferSize
= 188 * 2400; /* Use a driver buffer size of 2400 packets */
128 RXConfig
.BoardBufferSize
= 1048576; /* Use 1MB of onboard buffer */
129 RXConfig
.TSPacketType
= ASI_PKT_188
; /* Use 188-bytes TS packets */
130 RXConfig
.NbPIDFilter
= 0; /* No PID filtering */
131 RXConfig
.pPIDFilterTable
= NULL
; /* No PID filtering */
132 RXConfig
.BitrateIntPeriod
= ASI_INTPER_100
; /* Integrate over 100 msec */
133 RXConfig
.AllowedBRDeviation
= 10000000; /* Allow 10Mbps of deviation */
134 RXConfig
.RXTimeStamp
= FALSE
; /* No timestamping */
136 /* Try to open RX0 channel on the board 0 */
137 h_channel
= Asi_OpenChannel(h_board
, ASI_CHN_RX0
+ (i_asi_adapter
% 100), &RXConfig
);
138 if (h_channel
== NULL
)
140 msg_Err( NULL
, "couldn't setup deltacast channel %d: 0x%08lX",
141 (i_asi_adapter
% 100), (unsigned long) Dc_GetLastError(NULL
) );
145 ev_timer_init(&asi_watcher
, asi_deltacast_Read
,
146 ASI_DELTACAST_PERIOD
/ 1000000.,
147 ASI_DELTACAST_PERIOD
/ 1000000.);
148 ev_timer_start(event_loop
, &asi_watcher
);
150 ev_timer_init(&mute_watcher
, asi_deltacast_MuteCb
,
151 ASI_DELTACAST_LOCK_TIMEOUT
/ 1000000.,
152 ASI_DELTACAST_LOCK_TIMEOUT
/ 1000000.);
155 /*****************************************************************************
156 * ASI deltacast events
157 *****************************************************************************/
158 static void asi_deltacast_Read(struct ev_loop
*loop
, struct ev_io
*w
, int revents
)
161 block_t
*p_ts
, **pp_current
= &p_ts
;
165 res
= Asi_GetInputBuffer(h_channel
, &p_asibuf
, &i_asibuf_len
,
166 ASI_DELTACAST_PERIOD
);
169 Err
= Dc_GetLastError(NULL
) & ~DC_ERRORCODE_MASK
;
171 if (Err
!= DCERR_TIMEOUT
)
173 msg_Warn( NULL
, "asi_deltacast_Read(): GetInputBuffer failed: 0x%08X!", Err
);
180 msg_Info( NULL
, "frontend has acquired lock" );
181 switch (i_print_type
) {
183 fprintf(print_fh
, "<STATUS type=\"lock\" status=\"1\"/>\n");
186 fprintf(print_fh
, "lock status: 1\n");
195 ev_timer_again(loop
, &mute_watcher
);
197 for (i
= 0; i
< i_asibuf_len
/ TS_SIZE
; i
++)
199 *pp_current
= block_New();
200 memcpy((*pp_current
)->p_ts
, p_asibuf
+ (i
* TS_SIZE
), TS_SIZE
);
201 pp_current
= &(*pp_current
)->p_next
;
205 res
= Asi_ReleaseInputBuffer(h_channel
);
207 // msg_Warn( NULL, "asi_deltacast_Read(): returning %d blocks", i_asibuf_len / TS_SIZE );
212 static void asi_deltacast_MuteCb(struct ev_loop
*loop
, struct ev_timer
*w
, int revents
)
214 msg_Warn( NULL
, "frontend has lost lock" );
215 ev_timer_stop(loop
, w
);
217 switch (i_print_type
) {
219 fprintf(print_fh
, "<STATUS type=\"lock\" status=\"0\"/>\n");
222 fprintf(print_fh
, "lock status: 0\n" );
229 /*****************************************************************************
230 * asi_deltacast_SetFilter
231 *****************************************************************************/
232 int asi_deltacast_SetFilter( uint16_t i_pid
)
234 /* TODO: Support PID filtering */
235 msg_Warn( NULL
, "asi_deltacast_SetFilter(%d) not yet implemented", i_pid
);
239 /*****************************************************************************
240 * asi_deltacast_UnsetFilter: normally never called
241 *****************************************************************************/
242 void asi_deltacast_UnsetFilter( int i_fd
, uint16_t i_pid
)
244 /* TODO: Support PID filtering */
245 msg_Warn( NULL
, "asi_deltacast_UnsetFilter() not yet implemented" );
248 /*****************************************************************************
249 * asi_deltacast_Reset
250 *****************************************************************************/
251 void asi_deltacast_Reset( void )
253 /* Called when retune required, so nothing required */
254 msg_Warn( NULL
, "asi_deltacast_Reset() do nothing" );