File: | asi.c |
Location: | line 267, column 14 |
Description: | Branch condition evaluates to a garbage value |
1 | /***************************************************************************** | |||
2 | * asi.c: support for Computer Modules ASI cards | |||
3 | ***************************************************************************** | |||
4 | * Copyright (C) 2004, 2009 VideoLAN | |||
5 | * | |||
6 | * Authors: Christophe Massiot <massiot@via.ecp.fr> | |||
7 | * | |||
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. | |||
12 | * | |||
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. | |||
17 | * | |||
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 | *****************************************************************************/ | |||
22 | #include "config.h" | |||
23 | ||||
24 | #ifdef HAVE_ASI_SUPPORT | |||
25 | ||||
26 | #include <stdlib.h> | |||
27 | #include <stdio.h> | |||
28 | #include <unistd.h> | |||
29 | #include <stdint.h> | |||
30 | #include <stdbool.h> | |||
31 | #include <string.h> | |||
32 | #include <sys/types.h> | |||
33 | #include <sys/stat.h> | |||
34 | #include <fcntl.h> | |||
35 | #include <sys/uio.h> | |||
36 | #include <sys/poll.h> | |||
37 | #include <sys/ioctl.h> | |||
38 | #include <sys/socket.h> | |||
39 | #include <netinet/in.h> | |||
40 | #include <arpa/inet.h> | |||
41 | #include <errno(*__errno_location ()).h> | |||
42 | ||||
43 | #include <bitstream/common.h> | |||
44 | ||||
45 | #include "asi.h" | |||
46 | ||||
47 | #include "dvblast.h" | |||
48 | ||||
49 | /* | |||
50 | * The problem with hardware filtering is that on startup, when you only | |||
51 | * set a filter on PID 0, it can take a very long time for a large buffer | |||
52 | * (typically ~100 TS packets) to fill up. And the buffer size cannot be | |||
53 | * adjusted afer startup. --Meuuh | |||
54 | */ | |||
55 | //#define USE_HARDWARE_FILTERING | |||
56 | ||||
57 | /***************************************************************************** | |||
58 | * Local declarations | |||
59 | *****************************************************************************/ | |||
60 | #define ASI_DEVICE"/dev/asirx%u" "/dev/asirx%u" | |||
61 | #define ASI_TIMESTAMPS_FILE"/sys/class/asi/asirx%u/timestamps" "/sys/class/asi/asirx%u/timestamps" | |||
62 | #define ASI_BUFSIZE_FILE"/sys/class/asi/asirx%u/bufsize" "/sys/class/asi/asirx%u/bufsize" | |||
63 | #define ASI_LOCK_TIMEOUT5000000 5000000 /* 5 s */ | |||
64 | ||||
65 | static int i_handle; | |||
66 | static int i_bufsize; | |||
67 | static uint8_t p_pid_filter[8192 / 8]; | |||
68 | static mtime_t i_last_packet = 0; | |||
69 | ||||
70 | /***************************************************************************** | |||
71 | * Local helpers | |||
72 | *****************************************************************************/ | |||
73 | #define MAXLEN256 256 | |||
74 | ||||
75 | static int ReadULSysfs( const char *psz_fmt, unsigned int i_link ) | |||
76 | { | |||
77 | char psz_file[MAXLEN256], psz_data[MAXLEN256]; | |||
78 | char *psz_tmp; | |||
79 | int i_fd; | |||
80 | ssize_t i_ret; | |||
81 | unsigned int i_data; | |||
82 | ||||
83 | snprintf( psz_file, sizeof(psz_file), psz_fmt, i_link ); | |||
84 | psz_file[sizeof(psz_file) - 1] = '\0'; | |||
85 | ||||
86 | if ( (i_fd = open( psz_file, O_RDONLY00 )) < 0 ) | |||
87 | return i_fd; | |||
88 | ||||
89 | i_ret = read( i_fd, psz_data, sizeof(psz_data) ); | |||
90 | close( i_fd ); | |||
91 | ||||
92 | if ( i_ret < 0 ) | |||
93 | return i_ret; | |||
94 | ||||
95 | i_data = strtoul( psz_data, &psz_tmp, 0 ); | |||
96 | if ( *psz_tmp != '\n' ) | |||
97 | return -1; | |||
98 | ||||
99 | return i_data; | |||
100 | } | |||
101 | ||||
102 | static ssize_t WriteULSysfs( const char *psz_fmt, unsigned int i_link, | |||
103 | unsigned int i_buf ) | |||
104 | { | |||
105 | char psz_file[MAXLEN256], psz_data[MAXLEN256]; | |||
106 | int i_fd; | |||
107 | ssize_t i_ret; | |||
108 | ||||
109 | snprintf( psz_file, sizeof(psz_file), psz_fmt, i_link ); | |||
110 | psz_file[sizeof(psz_file) - 1] = '\0'; | |||
111 | ||||
112 | snprintf( psz_data, sizeof(psz_data), "%u\n", i_buf ); | |||
113 | psz_file[sizeof(psz_data) - 1] = '\0'; | |||
114 | ||||
115 | if ( (i_fd = open( psz_file, O_WRONLY01 )) < 0 ) | |||
116 | return i_fd; | |||
117 | ||||
118 | i_ret = write( i_fd, psz_data, strlen(psz_data) + 1 ); | |||
119 | close( i_fd ); | |||
120 | return i_ret; | |||
121 | } | |||
122 | ||||
123 | /***************************************************************************** | |||
124 | * asi_Open | |||
125 | *****************************************************************************/ | |||
126 | void asi_Open( void ) | |||
127 | { | |||
128 | char psz_dev[MAXLEN256]; | |||
129 | ||||
130 | /* No timestamp - we wouldn't know what to do with them */ | |||
131 | if ( WriteULSysfs( ASI_TIMESTAMPS_FILE"/sys/class/asi/asirx%u/timestamps", i_asi_adapter, 0 ) < 0 ) | |||
132 | { | |||
133 | msg_Err( NULL((void*)0), "couldn't write file " ASI_TIMESTAMPS_FILE"/sys/class/asi/asirx%u/timestamps", | |||
134 | i_asi_adapter ); | |||
135 | exit(EXIT_FAILURE1); | |||
136 | } | |||
137 | ||||
138 | if ( (i_bufsize = ReadULSysfs( ASI_BUFSIZE_FILE"/sys/class/asi/asirx%u/bufsize", i_asi_adapter )) < 0 ) | |||
139 | { | |||
140 | msg_Err( NULL((void*)0), "couldn't read file " ASI_BUFSIZE_FILE"/sys/class/asi/asirx%u/bufsize", i_asi_adapter ); | |||
141 | exit(EXIT_FAILURE1); | |||
142 | } | |||
143 | ||||
144 | if ( i_bufsize % TS_SIZE188 ) | |||
145 | { | |||
146 | msg_Err( NULL((void*)0), ASI_BUFSIZE_FILE"/sys/class/asi/asirx%u/bufsize" " must be a multiple of 188", | |||
147 | i_asi_adapter ); | |||
148 | exit(EXIT_FAILURE1); | |||
149 | } | |||
150 | ||||
151 | snprintf( psz_dev, sizeof(psz_dev), ASI_DEVICE"/dev/asirx%u", i_asi_adapter ); | |||
152 | psz_dev[sizeof(psz_dev) - 1] = '\0'; | |||
153 | if ( (i_handle = open( psz_dev, O_RDONLY00, 0 )) < 0 ) | |||
154 | { | |||
155 | msg_Err( NULL((void*)0), "couldn't open device " ASI_DEVICE"/dev/asirx%u" " (%s)", | |||
156 | i_asi_adapter, strerror(errno(*__errno_location ())) ); | |||
157 | exit(EXIT_FAILURE1); | |||
158 | } | |||
159 | ||||
160 | #ifdef USE_HARDWARE_FILTERING | |||
161 | memset( p_pid_filter, 0x0, sizeof(p_pid_filter) ); | |||
162 | #else | |||
163 | memset( p_pid_filter, 0xff, sizeof(p_pid_filter) ); | |||
164 | p_pid_filter[8191 / 8] &= ~(0x01 << (8191 % 8)); /* padding */ | |||
165 | #endif | |||
166 | if ( ioctl( i_handle, ASI_IOC_RXSETPF(((1U) << (((0 +8)+8)+14)) | ((('?')) << (0 +8)) | (((76)) << 0) | ((((sizeof(unsigned int [256])))) << ((0 +8)+8))), p_pid_filter ) < 0 ) | |||
167 | { | |||
168 | msg_Warn( NULL((void*)0), "couldn't filter padding" ); | |||
169 | } | |||
170 | ||||
171 | fsync( i_handle ); | |||
172 | } | |||
173 | ||||
174 | /***************************************************************************** | |||
175 | * asi_Read : read packets from the device | |||
176 | *****************************************************************************/ | |||
177 | block_t *asi_Read( mtime_t i_poll_timeout ) | |||
178 | { | |||
179 | struct pollfd pfd[2]; | |||
180 | int i_ret, i_nb_fd = 1; | |||
181 | ||||
182 | pfd[0].fd = i_handle; | |||
183 | pfd[0].events = POLLIN0x001; | |||
184 | if ( i_comm_fd != -1 ) | |||
| ||||
185 | { | |||
186 | pfd[1].fd = i_comm_fd; | |||
187 | pfd[1].events = POLLIN0x001; | |||
188 | i_nb_fd++; | |||
189 | } | |||
190 | ||||
191 | i_ret = poll( pfd, i_nb_fd, (i_poll_timeout + 999) / 1000 ); | |||
192 | ||||
193 | i_wallclock = mdate(); | |||
194 | ||||
195 | if ( i_ret < 0 ) | |||
196 | { | |||
197 | if( errno(*__errno_location ()) != EINTR4 ) | |||
198 | msg_Err( NULL((void*)0), "couldn't poll from device " ASI_DEVICE"/dev/asirx%u" " (%s)", | |||
199 | i_asi_adapter, strerror(errno(*__errno_location ())) ); | |||
200 | return NULL((void*)0); | |||
201 | } | |||
202 | ||||
203 | if ( (pfd[0].revents & POLLPRI0x002) ) | |||
204 | { | |||
205 | unsigned int i_val; | |||
206 | ||||
207 | if ( ioctl(i_handle, ASI_IOC_RXGETEVENTS(((2U) << (((0 +8)+8)+14)) | ((('?')) << (0 +8)) | (((66)) << 0) | ((((sizeof(unsigned int)))) << ( (0 +8)+8))), &i_val) < 0 ) | |||
208 | msg_Err( NULL((void*)0), "couldn't RXGETEVENTS (%s)", strerror(errno(*__errno_location ())) ); | |||
209 | else | |||
210 | { | |||
211 | if ( i_val & ASI_EVENT_RX_BUFFER(1 << 0) ) | |||
212 | msg_Warn( NULL((void*)0), "driver receive buffer queue overrun" ); | |||
213 | if ( i_val & ASI_EVENT_RX_FIFO(1 << 1) ) | |||
214 | msg_Warn( NULL((void*)0), "onboard receive FIFO overrun" ); | |||
215 | if ( i_val & ASI_EVENT_RX_CARRIER(1 << 2) ) | |||
216 | msg_Warn( NULL((void*)0), "carrier status change" ); | |||
217 | if ( i_val & ASI_EVENT_RX_LOS(1 << 4) ) | |||
218 | msg_Warn( NULL((void*)0), "loss of packet synchronization" ); | |||
219 | if ( i_val & ASI_EVENT_RX_AOS(1 << 3) ) | |||
220 | msg_Warn( NULL((void*)0), "acquisition of packet synchronization" ); | |||
221 | if ( i_val & ASI_EVENT_RX_DATA(1 << 5) ) | |||
222 | msg_Warn( NULL((void*)0), "receive data status change" ); | |||
223 | } | |||
224 | } | |||
225 | ||||
226 | if ( (pfd[0].revents & POLLIN0x001) ) | |||
227 | { | |||
228 | struct iovec p_iov[i_bufsize / TS_SIZE188]; | |||
229 | block_t *p_ts, **pp_current = &p_ts; | |||
230 | int i, i_len; | |||
231 | ||||
232 | if ( !i_last_packet ) | |||
233 | { | |||
234 | switch (i_print_type) { | |||
235 | case PRINT_XML: | |||
236 | printf("<STATUS type=\"lock\" status=\"1\"/>\n"); | |||
237 | break; | |||
238 | default: | |||
239 | printf("frontend has acquired lock\n" ); | |||
240 | } | |||
241 | } | |||
242 | i_last_packet = i_wallclock; | |||
243 | ||||
244 | for ( i = 0; i < i_bufsize / TS_SIZE188; i++ ) | |||
245 | { | |||
246 | *pp_current = block_New(); | |||
247 | p_iov[i].iov_base = (*pp_current)->p_ts; | |||
248 | p_iov[i].iov_len = TS_SIZE188; | |||
249 | pp_current = &(*pp_current)->p_next; | |||
250 | } | |||
251 | ||||
252 | if ( (i_len = readv(i_handle, p_iov, i_bufsize / TS_SIZE188)) < 0 ) | |||
253 | { | |||
254 | msg_Err( NULL((void*)0), "couldn't read from device " ASI_DEVICE"/dev/asirx%u" " (%s)", | |||
255 | i_asi_adapter, strerror(errno(*__errno_location ())) ); | |||
256 | i_len = 0; | |||
257 | } | |||
258 | i_len /= TS_SIZE188; | |||
259 | ||||
260 | pp_current = &p_ts; | |||
261 | while ( i_len && *pp_current ) | |||
262 | { | |||
263 | pp_current = &(*pp_current)->p_next; | |||
264 | i_len--; | |||
265 | } | |||
266 | ||||
267 | if ( *pp_current ) | |||
| ||||
268 | msg_Dbg( NULL((void*)0), "partial buffer received" ); | |||
269 | block_DeleteChain( *pp_current ); | |||
270 | *pp_current = NULL((void*)0); | |||
271 | ||||
272 | return p_ts; | |||
273 | } | |||
274 | else if ( i_last_packet && i_last_packet + ASI_LOCK_TIMEOUT5000000 < i_wallclock ) | |||
275 | { | |||
276 | switch (i_print_type) { | |||
277 | case PRINT_XML: | |||
278 | printf("<STATUS type=\"lock\" status=\"0\"/>\n"); | |||
279 | break; | |||
280 | default: | |||
281 | printf("frontend has lost lock\n" ); | |||
282 | } | |||
283 | i_last_packet = 0; | |||
284 | } | |||
285 | ||||
286 | if ( i_comm_fd != -1 && pfd[1].revents ) | |||
287 | comm_Read(); | |||
288 | ||||
289 | return NULL((void*)0); | |||
290 | } | |||
291 | ||||
292 | /***************************************************************************** | |||
293 | * asi_SetFilter | |||
294 | *****************************************************************************/ | |||
295 | int asi_SetFilter( uint16_t i_pid ) | |||
296 | { | |||
297 | #ifdef USE_HARDWARE_FILTERING | |||
298 | p_pid_filter[ i_pid / 8 ] |= (0x01 << (i_pid % 8)); | |||
299 | if ( ioctl( i_handle, ASI_IOC_RXSETPF(((1U) << (((0 +8)+8)+14)) | ((('?')) << (0 +8)) | (((76)) << 0) | ((((sizeof(unsigned int [256])))) << ((0 +8)+8))), p_pid_filter ) < 0 ) | |||
300 | msg_Warn( NULL((void*)0), "couldn't add filter on PID %u", i_pid ); | |||
301 | ||||
302 | return 1; | |||
303 | #else | |||
304 | return -1; | |||
305 | #endif | |||
306 | } | |||
307 | ||||
308 | /***************************************************************************** | |||
309 | * asi_UnsetFilter: normally never called | |||
310 | *****************************************************************************/ | |||
311 | void asi_UnsetFilter( int i_fd, uint16_t i_pid ) | |||
312 | { | |||
313 | #ifdef USE_HARDWARE_FILTERING | |||
314 | p_pid_filter[ i_pid / 8 ] &= ~(0x01 << (i_pid % 8)); | |||
315 | if ( ioctl( i_handle, ASI_IOC_RXSETPF(((1U) << (((0 +8)+8)+14)) | ((('?')) << (0 +8)) | (((76)) << 0) | ((((sizeof(unsigned int [256])))) << ((0 +8)+8))), p_pid_filter ) < 0 ) | |||
316 | msg_Warn( NULL((void*)0), "couldn't remove filter on PID %u", i_pid ); | |||
317 | #endif | |||
318 | } | |||
319 | ||||
320 | /***************************************************************************** | |||
321 | * asi_Reset | |||
322 | *****************************************************************************/ | |||
323 | void asi_Reset( void ) | |||
324 | { | |||
325 | msg_Warn( NULL((void*)0), "asi_Reset() do nothing" ); | |||
326 | } | |||
327 | ||||
328 | #endif |