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 "config.h"
  2 
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <unistd.h>
  7 #include <errno.h>
  8 #include <ctype.h>
  9 #include <locale.h>
 10 #include <fcntl.h>
 11 #include <inttypes.h>
 12 #include <time.h>
 13 
 14 #ifndef PRId64
 15 # define PRId64 "lld"
 16 # define PRIx64 "llx"
 17 #endif
 18 
 19 #if BYTE_ORDER == LITTLE_ENDIAN
 20 # define SWAP2(x) ((((uint16_t)x>>8)  & (uint16_t)0x00ff) |\
 21                    (((uint16_t)x<<8)  & (uint16_t)0xff00))
 22 
 23 # define SWAP4(x) ((((uint32_t)x>>24) & (uint32_t)0x000000ff) |\
 24                    (((uint32_t)x>>8)  & (uint32_t)0x0000ff00) |\
 25                    (((uint32_t)x<<8)  & (uint32_t)0x00ff0000) |\
 26                    (((uint32_t)x<<24) & (uint32_t)0xff000000))
 27 
 28 # define SWAP8(x) ((((uint64_t)x>>56) & (uint64_t)0x00000000000000ff) |\
 29                    (((uint64_t)x>>40) & (uint64_t)0x000000000000ff00) |\
 30                    (((uint64_t)x>>24) & (uint64_t)0x0000000000ff0000) |\
 31                    (((uint64_t)x>> 8) & (uint64_t)0x00000000ff000000) |\
 32                    (((uint64_t)x<< 8) & (uint64_t)0x000000ff00000000) |\
 33                    (((uint64_t)x<<24) & (uint64_t)0x0000ff0000000000) |\
 34                    (((uint64_t)x<<40) & (uint64_t)0x00ff000000000000) |\
 35                    (((uint64_t)x<<56) & (uint64_t)0xff00000000000000))
 36 #else
 37 # define SWAP2(a) (a)
 38 # define SWAP4(a) (a)
 39 # define SWAP8(a) (a)
 40 #endif
 41 
 42 #define MAKEFOURCC(a,b,c,d) ((((uint32_t)a)<<24) | (((uint32_t)b)<<16) | \
 43                              (((uint32_t)c)<< 8) | ( (uint32_t)d)      )
 44 
 45 #define a_clip MAKEFOURCC('c','l','i','p')
 46 #define a_co64 MAKEFOURCC('c','o','6','4')
 47 #define a_dinf MAKEFOURCC('d','i','n','f')
 48 #define a_dref MAKEFOURCC('d','r','e','f')
 49 #define a_free MAKEFOURCC('f','r','e','e')
 50 #define a_edts MAKEFOURCC('e','d','t','s')
 51 #define a_elst MAKEFOURCC('e','l','s','t')
 52 #define a_hdlr MAKEFOURCC('h','d','l','r')
 53 #define a_mdat MAKEFOURCC('m','d','a','t')
 54 #define a_mdhd MAKEFOURCC('m','d','h','d')
 55 #define a_mdia MAKEFOURCC('m','d','i','a')
 56 #define a_minf MAKEFOURCC('m','i','n','f')
 57 #define a_moov MAKEFOURCC('m','o','o','v')
 58 #define a_mvhd MAKEFOURCC('m','v','h','d')
 59 #define a_skip MAKEFOURCC('s','k','i','p')
 60 #define a_smhd MAKEFOURCC('s','m','h','d')
 61 #define a_stbl MAKEFOURCC('s','t','b','l')
 62 #define a_stco MAKEFOURCC('s','t','c','o')
 63 #define a_stsc MAKEFOURCC('s','t','s','c')
 64 #define a_stsd MAKEFOURCC('s','t','s','d')
 65 #define a_stsh MAKEFOURCC('s','t','s','h')
 66 #define a_stss MAKEFOURCC('s','t','s','s')
 67 #define a_stsz MAKEFOURCC('s','t','s','z')
 68 #define a_stts MAKEFOURCC('s','t','t','s')
 69 #define a_tkhd MAKEFOURCC('t','k','h','d')
 70 #define a_trak MAKEFOURCC('t','r','a','k')
 71 #define a_udta MAKEFOURCC('u','d','t','a')
 72 #define a_vmhd MAKEFOURCC('v','m','h','d')
 73 #define a_wide MAKEFOURCC('w','i','d','e')
 74 
 75 /* ------------------------------------------------------------------ */
 76 
 77 struct classic_atom {
 78     uint32_t  size;
 79     uint32_t  type;
 80     uint64_t  extsize;
 81 };
 82 
 83 struct qt_atom {
 84     uint32_t  size;
 85     uint32_t  type;
 86     uint64_t  extsize;
 87 };
 88 
 89 enum field_type {
 90     END_OF_LIST = 0,
 91     INT16,
 92     INT32,
 93     INT64,
 94     FIX16,
 95     FIX32,
 96     FOURCC,
 97     VER,
 98     FLAGS3,
 99     TIME,
100     LANG,
101     COLOR,
102     COUNT,
103     RES2,
104     RES4,
105     RES6,
106     RES8,
107     RES10,
108     MATRIX,
109 };
110 
111 struct field_list {
112     enum field_type type;
113     char            *name;
114 };
115 
116 struct atom_list {
117     uint32_t          type;
118     struct field_list *fields;
119 };
120 
121 struct fcc_names {
122     uint32_t          type;
123     char              *name;
124 };
125 
126 static int handle_classic_atom(int fh, off_t pos, off_t size, int depth);
127 #if 0
128 static int handle_qt_atom(int fh, off_t pos, off_t size, int depth);
129 #endif
130 
131 /* ------------------------------------------------------------------ */
132 
133 static struct field_list l_co64[] = {
134     { VER,    "version"                },
135     { FLAGS3, "flags"                  },
136     { COUNT,  "number of entries"      },
137     /* FIXME: loop */
138     { INT64,  "offset64"               },
139     { END_OF_LIST }
140 };
141 
142 static struct field_list l_dref[] = {
143     { VER,    "version"            },
144     { FLAGS3, "flags"              },
145     { INT32,  "number of entries"  },
146     /* FIXME: loop */
147     { INT32,  "size"               },
148     { FOURCC, "type"               },
149     { VER,    "version"            },
150     { FLAGS3, "flags"              },
151     { END_OF_LIST }
152 };
153 
154 static struct field_list l_elst[] = {
155     { VER,    "version"            },
156     { FLAGS3, "flags"              },
157     { COUNT,  "number of entries"  },
158     /* FIXME: loop */
159     { INT32,  "track duration"     },
160     { INT32,  "media time"         },
161     { FIX32,  "media rate"         },
162     { END_OF_LIST }
163 };
164 
165 static struct field_list l_hdlr[] = {
166     { VER,    "version"                },
167     { FLAGS3, "flags"                  },
168     { FOURCC, "component type"         },
169     { FOURCC, "component subtype"      },
170     { RES4,   "component manufacturer" },
171     { RES4,   "component flags"        },
172     { RES4,   "component flags mask"   },
173     /* FIXME: name */
174     { END_OF_LIST }
175 };
176 
177 static struct field_list l_mdhd[] = {
178     { VER,    "version"                },
179     { FLAGS3, "flags"                  },
180     { TIME,   "ctime"                  },
181     { TIME,   "mtime"                  },
182     { INT32,  "time scale"             },
183     { INT32,  "duration"               },
184     { LANG,   "language"               },
185     { INT16,  "quality"                },
186     { END_OF_LIST }
187 };
188 
189 static struct field_list l_mvhd[] = {
190     { VER,    "version"                },
191     { FLAGS3, "flags"                  },
192     { TIME,   "ctime"                  },
193     { TIME,   "mtime"                  },
194     { INT32,  "time scale"             },
195     { INT32,  "duration"               },
196     { FIX32,  "preferred rate"         },
197     { FIX16,  "preferred volume"       },
198     { RES10,  "reserved"               },
199     { MATRIX, "matrix"                 },
200     { INT32,  "preview time"           },
201     { INT32,  "preview duration"       },
202     { INT32,  "poster time"            },
203     { INT32,  "selection time"         },
204     { INT32,  "selection duration"     },
205     { INT32,  "current time"           },
206     { INT32,  "next track id"          },
207     { END_OF_LIST }
208 };
209 
210 static struct field_list l_smhd[] = {
211     { VER,    "version"                },
212     { FLAGS3, "flags"                  },
213     { INT16,  "balance"                },
214     { RES2,   "reserved"               },
215     { END_OF_LIST }
216 };
217 
218 static struct field_list l_stco[] = {
219     { VER,    "version"                },
220     { FLAGS3, "flags"                  },
221     { COUNT,  "number of entries"      },
222     /* FIXME: loop */
223     { INT32,  "offset"                 },
224     { END_OF_LIST }
225 };
226 
227 static struct field_list l_stsc[] = {
228     { VER,    "version"                },
229     { FLAGS3, "flags"                  },
230     { COUNT,  "number of entries"      },
231     /* FIXME: loop */
232     { INT32,  "first chunk"            },
233     { INT32,  "samples per chunk"      },
234     { INT32,  "sample description id"  },
235     { END_OF_LIST }
236 };
237 
238 static struct field_list l_stsd[] = {
239     { VER,    "version"                },
240     { FLAGS3, "flags"                  },
241     { COUNT,  "number of entries"      },
242     /* FIXME: loop */
243     { INT32,  "size"                   },
244     { FOURCC, "format"                 },
245     { RES6,   "reserved"               },
246     { INT16,  "data reference index"   },
247     { END_OF_LIST }
248 };
249 
250 static struct field_list l_stts[] = {
251     { VER,    "version"                },
252     { FLAGS3, "flags"                  },
253     { COUNT,  "number of entries"      },
254     /* FIXME: loop */
255     { INT32,  "sample count"           },
256     { INT32,  "sample duration"        },
257     { END_OF_LIST }
258 };
259 
260 static struct field_list l_stsz[] = {
261     { VER,    "version"                },
262     { FLAGS3, "flags"                  },
263     { INT32,  "sample size"            },
264     { COUNT,  "number of entries"      },
265     /* FIXME: loop if "sample size is 0" */
266 #if 0
267     { INT32,  "sample size"            },
268 #endif
269     { END_OF_LIST }
270 };
271 
272 static struct field_list l_tkhd[] = {
273     { VER,    "version"                },
274     { FLAGS3, "flags"                  },
275     { TIME,   "ctime"                  },
276     { TIME,   "mtime"                  },
277     { INT32,  "track id"               },
278     { RES4,   "reserved"               },
279     { INT32,  "duration"               },
280     { RES8,   "reserved"               },
281     { INT16,  "layer"                  },
282     { INT16,  "alternate group"        },
283     { INT16,  "volume"                 },
284     { RES2,   "reserved"               },
285     { MATRIX, "matrix"                 },
286     { FIX32,  "width"                  },
287     { FIX32,  "height"                 },
288     { END_OF_LIST }
289 };
290 
291 static struct field_list l_vmhd[] = {
292     { VER,    "version"                },
293     { FLAGS3, "flags"                  },
294     { INT16,  "graphics mode"          },
295     { COLOR,  "opcolor"                },
296     { END_OF_LIST }
297 };
298 
299 static struct atom_list alist[] = {
300     { a_co64, l_co64 },
301     { a_dref, l_dref },
302     { a_elst, l_elst },
303     { a_hdlr, l_hdlr },
304     { a_mdhd, l_mdhd },
305     { a_mvhd, l_mvhd },
306     { a_smhd, l_smhd },
307     { a_stco, l_stco },
308     { a_stsc, l_stsc },
309     { a_stsd, l_stsd },
310     { a_stsz, l_stsz },
311     { a_stts, l_stts },
312     { a_tkhd, l_tkhd },
313     { a_vmhd, l_vmhd },
314     { /* end of list */}
315 };
316 
317 /* ------------------------------------------------------------------ */
318 
319 static struct fcc_names flist[] = {
320     { a_co64, "chunk offset64 atom" },
321     { a_clip, "movie clipping atom" },
322     { a_dinf, "data information atom" },
323     { a_dref, "data reference atom" },
324     { a_edts, "edit atom" },
325     { a_elst, "edit list atom" },
326     { a_free, "unused space" },
327     { a_hdlr, "handler reference atom" },
328     { a_mdat, "movie data atom" },
329     { a_mdhd, "media header atom" },
330     { a_mdia, "media atom" },
331     { a_minf, "media information atom" },
332     { a_moov, "movie atom" },
333     { a_mvhd, "movie header atom" },
334     { a_skip, "unused space" },
335     { a_smhd, "sound media information header atom" },
336     { a_stbl, "sample table atom" },
337     { a_stco, "chunk offset atom" },
338     { a_stsc, "sample-to-chunk atom" },
339     { a_stsd, "sample description atom" },
340     { a_stsz, "sample size atom" },
341     { a_stts, "time-to-sample atom" },
342     { a_tkhd, "track header atom" },
343     { a_trak, "track atom" },
344     { a_udta, "user data atom" },
345     { a_vmhd, "video media information header atom"  },
346     { a_wide, "reserved space for extsize field" },
347     { /* end of list */}
348 };
349 
350 /* ------------------------------------------------------------------ */
351 
352 static int verbose=0;
353 
354 static void swap_classic_atom(struct classic_atom *a)
355 {
356     a->size    = SWAP4(a->size);
357     a->type    = SWAP4(a->type);
358     a->extsize = SWAP8(a->extsize);
359 }
360 
361 #if 0
362 static void swap_qt_atom(struct qt_atom *a)
363 {
364 }
365 #endif
366 
367 static int xisprint(int c)
368 {
369     switch (c) {
370     case 169: /* copyright */
371         return 1;
372     default:
373         return isprint(c);
374     }
375 }
376 
377 static char* strfcc(uint32_t type)
378 {
379     static char retval[64];
380     int i,l;
381 
382     if (xisprint((type >> 24) & 0xff) &&
383         xisprint((type >> 16) & 0xff) &&
384         xisprint((type >>  8) & 0xff) &&
385         xisprint( type        & 0xff)) {
386         l = sprintf(retval,"%c%c%c%c",
387                 (type >> 24) & 0xff,
388                 (type >> 16) & 0xff,
389                 (type >>  8) & 0xff,
390                 type         & 0xff);
391     } else {
392         l = sprintf(retval,"0x%08x",type);
393     }
394     for (i = 0; flist[i].type != 0; i++)
395         if (flist[i].type == type)
396             break;
397     if (flist[i].type != 0)
398         sprintf(retval+l," [%s]",flist[i].name);
399     return retval;
400 }
401 
402 #define FIELD_NAME "\t%s%-20s = "
403 static void dump_fields(int fh, off_t pos, struct field_list *list)
404 {
405     char dummy[64],si[8];
406     int  i,loop,cpos;
407     int8_t   int8;
408     int16_t  int16;
409     int32_t  int32, fcc, count;
410     int64_t  int64;
411     uint16_t color[3];
412     uint32_t uint32;
413     time_t   t;
414 
415     if (0 == verbose)
416         return;
417     if (-1 == lseek(fh,pos,SEEK_SET)) {
418         perror("lseek");
419         exit(1);
420     }
421     si[0] = 0;
422     count = 0;
423     cpos  = 0;
424     loop  = 0;
425     for (i = 0; list[i].type != END_OF_LIST || loop < count-1; i++) {
426         switch (list[i].type) {
427         case FOURCC:
428             read(fh,&fcc,sizeof(fcc));
429             printf(FIELD_NAME "%s\n",si,list[i].name,strfcc(SWAP4(fcc)));
430             break;
431         case VER:
432             read(fh,&int8,sizeof(int8));
433             if (verbose > 1 || int8 > 0)
434                 printf(FIELD_NAME "%d\n",si,list[i].name,(int)int8);
435             break;
436         case LANG:
437         case INT16:
438             read(fh,&int16,sizeof(int16));
439             printf(FIELD_NAME "%d\n",si,list[i].name,(int)SWAP2(int16));
440             break;
441         case INT32:
442             read(fh,&int32,sizeof(int32));
443             printf(FIELD_NAME "%d\n",si,list[i].name,SWAP4(int32));
444             break;
445         case INT64:
446             read(fh,&int64,sizeof(int64));
447             printf(FIELD_NAME "%" PRId64 "\n",si,list[i].name,SWAP8(int64));
448             break;
449         case FIX16:
450             read(fh,&int16,sizeof(int16));
451             printf(FIELD_NAME "%f\n",si,list[i].name,
452                    SWAP2(int16) / 256.0);
453             break;
454         case FIX32:
455             read(fh,&int32,sizeof(int32));
456             printf(FIELD_NAME "%f\n",si,list[i].name,
457                    SWAP4(int32) / 65536.0);
458             break;
459         case FLAGS3:
460             read(fh,dummy,3);
461             int32 = dummy[0] << 16 | dummy[1] << 8 | dummy[2];
462             if (verbose > 1 || int32 > 0)
463                 printf(FIELD_NAME "0x%06x\n",si,list[i].name,int32);
464             break;
465         case TIME:
466             read(fh,&uint32,sizeof(uint32));
467             t = SWAP4(uint32) - 2082848400;
468             strftime(dummy,sizeof(dummy),"%d. %b %Y - %H:%M:%S",localtime(&t));
469             printf(FIELD_NAME "%s\n",si,list[i].name,dummy);
470             break;
471         case COLOR:
472             read(fh,&color,sizeof(color));
473             printf(FIELD_NAME "%d/%d/%d (rgb)\n",si,list[i].name,
474                    (int)SWAP2(color[0]),
475                    (int)SWAP2(color[0]),
476                    (int)SWAP2(color[0]));
477             break;
478         case RES2:
479             read(fh,dummy,2);
480             break;
481         case RES4:
482             read(fh,dummy,4);
483             break;
484         case RES6:
485             read(fh,dummy,6);
486             break;
487         case RES8:
488             read(fh,dummy,8);
489             break;
490         case RES10:
491             read(fh,dummy,10);
492             break;
493         case MATRIX:
494             read(fh,dummy,36);
495             break;
496         case COUNT:
497             read(fh,&count,sizeof(count));
498             count = SWAP4(count);
499             cpos  = i;
500             if (verbose < 2) {
501                 printf("\t[list follows]\n");
502                 return;
503             }
504             printf(FIELD_NAME "%d\n",si,list[i].name,count);
505             sprintf(si,"[%d] ",loop);
506             break;
507         case END_OF_LIST:
508             i = cpos;
509             loop++;
510             sprintf(si,"[%d] ",loop);
511             break;
512         }
513     }
514 }
515 
516 static void dump_string(int fh, off_t pos, off_t size)
517 {
518     off_t off;
519     uint16_t ssize,stype;
520     char *str;
521     
522     if (0 == verbose)
523         return;
524     if (-1 == lseek(fh,pos,SEEK_SET)) {
525         perror("lseek");
526         exit(1);
527     }
528     /* FIXME: specs say size is _including_ size+type */
529     for (off = 0; off < size; off += ssize+4) {
530         read(fh,&ssize,sizeof(ssize));
531         read(fh,&stype,sizeof(stype));
532         ssize = SWAP2(ssize);
533         stype = SWAP2(stype);
534         str = malloc(ssize+1);
535         read(fh,str,ssize);
536         str[ssize] = 0;
537         printf("\t%d[%d] = %s\n",(int)stype,(int)ssize,str);
538         free(str);
539     }
540     if (off != size) {
541         fprintf(stderr,"Huh?  string size mismatch!\n");
542         exit(1);
543     }
544 }
545 
546 static int handle_classic_atom(int fh, off_t pos, off_t size, int depth)
547 {
548     struct classic_atom a;
549     uint64_t asize;
550     size_t off;
551     int i;
552 
553     if (-1 == lseek(fh,pos,SEEK_SET)) {
554         perror("lseek");
555         exit(1);
556     }
557     if (sizeof(a) != read(fh,&a,sizeof(a))) {
558         perror("read");
559         exit(1);
560     }
561     swap_classic_atom(&a);
562     switch (a.size) {
563     case 0:
564         asize = size;
565         off   = 8;
566         break;
567     case 1:
568         asize = a.extsize;
569         off   = 16;
570         break;
571     default:
572         asize = a.size;
573         off   = 8;
574     }
575     printf("0x%08" PRIx64 " 0x%08" PRIx64 " %*s%s\n",
576            (int64_t)pos,(int64_t)asize,depth,"",strfcc(a.type));
577     switch (a.type) {
578     case a_dinf:
579     case a_edts:
580     case a_mdia:
581     case a_minf:
582     case a_moov:
583     case a_stbl:
584     case a_trak:
585     case a_udta:
586         while (off < asize)
587             off += handle_classic_atom(fh,pos+off,asize-off,depth+3);
588         if (off != asize) {
589             fprintf(stderr,"Huh?  atom size mismatch!\n");
590             exit(1);
591         }
592         break;
593     default:
594         if (169 == ((a.type >> 24) & 0xff)) {
595             dump_string(fh,pos+off,asize-off);
596         } else {
597             for (i = 0; alist[i].type != 0; i++)
598                 if (alist[i].type == a.type)
599                     break;
600             if (alist[i].type != 0)
601                 dump_fields(fh,pos+off,alist[i].fields);
602         }
603     }
604     return asize;
605 }
606 
607 #if 0
608 static int handle_qt_atom(int fh, off_t pos, off_t size, int depth)
609 {
610     return 0;
611 }
612 #endif
613 
614 /* ------------------------------------------------------------------ */
615 
616 static void
617 usage(char *prog)
618 {
619     char *h;
620 
621     if (NULL != (h = strrchr(prog,'/')))
622         prog = h+1;
623     fprintf(stderr,
624             "%s - dump structure of quicktime files\n"
625             "\n"
626             "usage:  %s [ -j ] [ -e ] filename\n"
627             "options:\n"
628             "  -h  this text\n"
629             "  -v  increase verbose level\n"
630             "\n",
631             prog,prog);
632 }
633 
634 int main(int argc, char *argv[])
635 {
636     int   fh;
637     off_t off,size;
638 
639     int c;
640 
641     /* parse options */
642     for (;;) {
643         if (-1 == (c = getopt(argc, argv, "hv")))
644             break;
645         switch (c) {
646         case 'v':
647             verbose++;
648             break;
649         case 'h':
650         default:
651             usage(argv[0]);
652             exit(1);
653         }
654     }
655     
656     if (optind == argc) {
657         usage(argv[0]);
658         exit(1);
659     }
660 
661     setlocale(LC_ALL,NULL);
662     fh = open(argv[optind],O_RDONLY);
663     if (-1 == fh) {
664         fprintf(stderr,"open %s: %s\n",argv[optind],strerror(errno));
665         exit(1);
666     }
667     size = lseek(fh,0,SEEK_END);
668     for (off = 0; off < size;)
669         off += handle_classic_atom(fh,off,size,0);
670     if (off != size) {
671         fprintf(stderr,"Huh?  File size mismatch!\n");
672         exit(1);
673     }
674     return 0;
675 }
676 
  This page was automatically generated by the LXR engine.