Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #include "dvb_filter.h"
  2 #include "av7110_ipack.h"
  3 #include <linux/string.h>       /* for memcpy() */
  4 #include <linux/vmalloc.h>
  5 
  6 
  7 void av7110_ipack_reset(struct ipack *p)
  8 {
  9         p->found = 0;
 10         p->cid = 0;
 11         p->plength = 0;
 12         p->flag1 = 0;
 13         p->flag2 = 0;
 14         p->hlength = 0;
 15         p->mpeg = 0;
 16         p->check = 0;
 17         p->which = 0;
 18         p->done = 0;
 19         p->count = 0;
 20 }
 21 
 22 
 23 int av7110_ipack_init(struct ipack *p, int size,
 24                       void (*func)(u8 *buf, int size, void *priv))
 25 {
 26         if (!(p->buf = vmalloc(size*sizeof(u8)))) {
 27                 printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
 28                 return -ENOMEM;
 29         }
 30         p->size = size;
 31         p->func = func;
 32         p->repack_subids = 0;
 33         av7110_ipack_reset(p);
 34         return 0;
 35 }
 36 
 37 
 38 void av7110_ipack_free(struct ipack *p)
 39 {
 40         vfree(p->buf);
 41 }
 42 
 43 
 44 static void send_ipack(struct ipack *p)
 45 {
 46         int off;
 47         struct dvb_audio_info ai;
 48         int ac3_off = 0;
 49         int streamid = 0;
 50         int nframes = 0;
 51         int f = 0;
 52 
 53         switch (p->mpeg) {
 54         case 2:
 55                 if (p->count < 10)
 56                         return;
 57                 p->buf[3] = p->cid;
 58                 p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
 59                 p->buf[5] = (u8)((p->count - 6) & 0x00ff);
 60                 if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
 61                         off = 9 + p->buf[8];
 62                         streamid = p->buf[off];
 63                         if ((streamid & 0xf8) == 0x80) {
 64                                 ai.off = 0;
 65                                 ac3_off = ((p->buf[off + 2] << 8)|
 66                                            p->buf[off + 3]);
 67                                 if (ac3_off < p->count)
 68                                         f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
 69                                                                    p->count - ac3_off, &ai, 0);
 70                                 if (!f) {
 71                                         nframes = (p->count - off - 3 - ac3_off) /
 72                                                 ai.framesize + 1;
 73                                         p->buf[off + 2] = (ac3_off >> 8) & 0xff;
 74                                         p->buf[off + 3] = (ac3_off) & 0xff;
 75                                         p->buf[off + 1] = nframes;
 76                                         ac3_off +=  nframes * ai.framesize - p->count;
 77                                 }
 78                         }
 79                 }
 80                 p->func(p->buf, p->count, p->data);
 81 
 82                 p->buf[6] = 0x80;
 83                 p->buf[7] = 0x00;
 84                 p->buf[8] = 0x00;
 85                 p->count = 9;
 86                 if (p->repack_subids && p->cid == PRIVATE_STREAM1
 87                     && (streamid & 0xf8) == 0x80) {
 88                         p->count += 4;
 89                         p->buf[9] = streamid;
 90                         p->buf[10] = (ac3_off >> 8) & 0xff;
 91                         p->buf[11] = (ac3_off) & 0xff;
 92                         p->buf[12] = 0;
 93                 }
 94                 break;
 95 
 96         case 1:
 97                 if (p->count < 8)
 98                         return;
 99                 p->buf[3] = p->cid;
100                 p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
101                 p->buf[5] = (u8)((p->count - 6) & 0x00ff);
102                 p->func(p->buf, p->count, p->data);
103 
104                 p->buf[6] = 0x0f;
105                 p->count = 7;
106                 break;
107         }
108 }
109 
110 
111 void av7110_ipack_flush(struct ipack *p)
112 {
113         if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
114                 return;
115         p->plength = p->found - 6;
116         p->found = 0;
117         send_ipack(p);
118         av7110_ipack_reset(p);
119 }
120 
121 
122 static void write_ipack(struct ipack *p, const u8 *data, int count)
123 {
124         u8 headr[3] = { 0x00, 0x00, 0x01 };
125 
126         if (p->count < 6) {
127                 memcpy(p->buf, headr, 3);
128                 p->count = 6;
129         }
130 
131         if (p->count + count < p->size){
132                 memcpy(p->buf+p->count, data, count);
133                 p->count += count;
134         } else {
135                 int rest = p->size - p->count;
136                 memcpy(p->buf+p->count, data, rest);
137                 p->count += rest;
138                 send_ipack(p);
139                 if (count - rest > 0)
140                         write_ipack(p, data + rest, count - rest);
141         }
142 }
143 
144 
145 int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
146 {
147         int l;
148         int c = 0;
149 
150         while (c < count && (p->mpeg == 0 ||
151                              (p->mpeg == 1 && p->found < 7) ||
152                              (p->mpeg == 2 && p->found < 9))
153                &&  (p->found < 5 || !p->done)) {
154                 switch (p->found) {
155                 case 0:
156                 case 1:
157                         if (buf[c] == 0x00)
158                                 p->found++;
159                         else
160                                 p->found = 0;
161                         c++;
162                         break;
163                 case 2:
164                         if (buf[c] == 0x01)
165                                 p->found++;
166                         else if (buf[c] == 0)
167                                 p->found = 2;
168                         else
169                                 p->found = 0;
170                         c++;
171                         break;
172                 case 3:
173                         p->cid = 0;
174                         switch (buf[c]) {
175                         case PROG_STREAM_MAP:
176                         case PRIVATE_STREAM2:
177                         case PROG_STREAM_DIR:
178                         case ECM_STREAM     :
179                         case EMM_STREAM     :
180                         case PADDING_STREAM :
181                         case DSM_CC_STREAM  :
182                         case ISO13522_STREAM:
183                                 p->done = 1;
184                                 /* fall through */
185                         case PRIVATE_STREAM1:
186                         case VIDEO_STREAM_S ... VIDEO_STREAM_E:
187                         case AUDIO_STREAM_S ... AUDIO_STREAM_E:
188                                 p->found++;
189                                 p->cid = buf[c];
190                                 c++;
191                                 break;
192                         default:
193                                 p->found = 0;
194                                 break;
195                         }
196                         break;
197 
198                 case 4:
199                         if (count-c > 1) {
200                                 p->plen[0] = buf[c];
201                                 c++;
202                                 p->plen[1] = buf[c];
203                                 c++;
204                                 p->found += 2;
205                                 p->plength = (p->plen[0] << 8) | p->plen[1];
206                         } else {
207                                 p->plen[0] = buf[c];
208                                 p->found++;
209                                 return count;
210                         }
211                         break;
212                 case 5:
213                         p->plen[1] = buf[c];
214                         c++;
215                         p->found++;
216                         p->plength = (p->plen[0] << 8) | p->plen[1];
217                         break;
218                 case 6:
219                         if (!p->done) {
220                                 p->flag1 = buf[c];
221                                 c++;
222                                 p->found++;
223                                 if ((p->flag1 & 0xc0) == 0x80)
224                                         p->mpeg = 2;
225                                 else {
226                                         p->hlength = 0;
227                                         p->which = 0;
228                                         p->mpeg = 1;
229                                         p->flag2 = 0;
230                                 }
231                         }
232                         break;
233 
234                 case 7:
235                         if (!p->done && p->mpeg == 2) {
236                                 p->flag2 = buf[c];
237                                 c++;
238                                 p->found++;
239                         }
240                         break;
241 
242                 case 8:
243                         if (!p->done && p->mpeg == 2) {
244                                 p->hlength = buf[c];
245                                 c++;
246                                 p->found++;
247                         }
248                         break;
249                 }
250         }
251 
252         if (c == count)
253                 return count;
254 
255         if (!p->plength)
256                 p->plength = MMAX_PLENGTH - 6;
257 
258         if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
259                         (p->mpeg == 1 && p->found >= 7))) {
260                 switch (p->cid) {
261                 case AUDIO_STREAM_S ... AUDIO_STREAM_E:
262                 case VIDEO_STREAM_S ... VIDEO_STREAM_E:
263                 case PRIVATE_STREAM1:
264                         if (p->mpeg == 2 && p->found == 9) {
265                                 write_ipack(p, &p->flag1, 1);
266                                 write_ipack(p, &p->flag2, 1);
267                                 write_ipack(p, &p->hlength, 1);
268                         }
269 
270                         if (p->mpeg == 1 && p->found == 7)
271                                 write_ipack(p, &p->flag1, 1);
272 
273                         if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
274                             p->found < 14) {
275                                 while (c < count && p->found < 14) {
276                                         p->pts[p->found - 9] = buf[c];
277                                         write_ipack(p, buf + c, 1);
278                                         c++;
279                                         p->found++;
280                                 }
281                                 if (c == count)
282                                         return count;
283                         }
284 
285                         if (p->mpeg == 1 && p->which < 2000) {
286 
287                                 if (p->found == 7) {
288                                         p->check = p->flag1;
289                                         p->hlength = 1;
290                                 }
291 
292                                 while (!p->which && c < count &&
293                                        p->check == 0xff){
294                                         p->check = buf[c];
295                                         write_ipack(p, buf + c, 1);
296                                         c++;
297                                         p->found++;
298                                         p->hlength++;
299                                 }
300 
301                                 if (c == count)
302                                         return count;
303 
304                                 if ((p->check & 0xc0) == 0x40 && !p->which) {
305                                         p->check = buf[c];
306                                         write_ipack(p, buf + c, 1);
307                                         c++;
308                                         p->found++;
309                                         p->hlength++;
310 
311                                         p->which = 1;
312                                         if (c == count)
313                                                 return count;
314                                         p->check = buf[c];
315                                         write_ipack(p, buf + c, 1);
316                                         c++;
317                                         p->found++;
318                                         p->hlength++;
319                                         p->which = 2;
320                                         if (c == count)
321                                                 return count;
322                                 }
323 
324                                 if (p->which == 1) {
325                                         p->check = buf[c];
326                                         write_ipack(p, buf + c, 1);
327                                         c++;
328                                         p->found++;
329                                         p->hlength++;
330                                         p->which = 2;
331                                         if (c == count)
332                                                 return count;
333                                 }
334 
335                                 if ((p->check & 0x30) && p->check != 0xff) {
336                                         p->flag2 = (p->check & 0xf0) << 2;
337                                         p->pts[0] = p->check;
338                                         p->which = 3;
339                                 }
340 
341                                 if (c == count)
342                                         return count;
343                                 if (p->which > 2){
344                                         if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
345                                                 while (c < count && p->which < 7) {
346                                                         p->pts[p->which - 2] = buf[c];
347                                                         write_ipack(p, buf + c, 1);
348                                                         c++;
349                                                         p->found++;
350                                                         p->which++;
351                                                         p->hlength++;
352                                                 }
353                                                 if (c == count)
354                                                         return count;
355                                         } else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
356                                                 while (c < count && p->which < 12) {
357                                                         if (p->which < 7)
358                                                                 p->pts[p->which - 2] = buf[c];
359                                                         write_ipack(p, buf + c, 1);
360                                                         c++;
361                                                         p->found++;
362                                                         p->which++;
363                                                         p->hlength++;
364                                                 }
365                                                 if (c == count)
366                                                         return count;
367                                         }
368                                         p->which = 2000;
369                                 }
370 
371                         }
372 
373                         while (c < count && p->found < p->plength + 6) {
374                                 l = count - c;
375                                 if (l + p->found > p->plength + 6)
376                                         l = p->plength + 6 - p->found;
377                                 write_ipack(p, buf + c, l);
378                                 p->found += l;
379                                 c += l;
380                         }
381                         break;
382                 }
383 
384 
385                 if (p->done) {
386                         if (p->found + count - c < p->plength + 6) {
387                                 p->found += count - c;
388                                 c = count;
389                         } else {
390                                 c += p->plength + 6 - p->found;
391                                 p->found = p->plength + 6;
392                         }
393                 }
394 
395                 if (p->plength && p->found == p->plength + 6) {
396                         send_ipack(p);
397                         av7110_ipack_reset(p);
398                         if (c < count)
399                                 av7110_ipack_instant_repack(buf + c, count - c, p);
400                 }
401         }
402         return count;
403 }
404 
  This page was automatically generated by the LXR engine.