--- /dev/null
+/* Quick-and-dirt MDF file parser
+ * (c) 2011 Michal Sojka
+ * License: GPLv2+
+ *
+ * MDF Specification: http://www.vector.com/vi_mdf_en.html or
+ * https://www.vector.com/vi_downloadcenter_en.html?busprot=MDF&formular_treffer_submit=1&sprachumschaltung=1
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <error.h>
+
+typedef uint32_t link;
+
+struct idblock {
+ char file_identifier[8];
+ char format_identifier[8];
+ char program_identifier[8];
+ uint16_t default_byte_order;
+ uint16_t version_number;
+ uint16_t code_page_number;
+ char res1[2];
+ char res2[30];
+} __attribute__((packed));
+
+struct hdblock {
+ char hd[2];
+ uint16_t block_size;
+ link data_group_block;
+ link file_comment;
+ link program_block;
+ uint16_t number_of_data_groups;
+ char date[10];
+ char time[8];
+ char author[32];
+ char organization[32];
+ char project[32];
+ char subject[32];
+ uint64_t timestamp;
+ int16_t utc_time_offset;
+ uint16_t time_quality_class;
+ char timer_ident[32];
+} __attribute__((packed));
+
+struct dgblock {
+ char dg[2];
+ uint16_t block_size;
+ link next_dgblock;
+ link first_channel_group_block;
+ link trigger_block;
+ link data_block;
+ uint16_t num_chn_groups;
+ uint16_t num_rec_ids;
+ uint32_t res;
+} __attribute__((packed));
+
+struct cgblock {
+ char cg[2];
+ uint16_t block_size;
+ link next_channel_group_block;
+ link first_channel_block;
+ link comment;
+ uint16_t record_id;
+ uint16_t num_channels;
+ uint16_t size_of_data_record;
+ uint32_t num_records;
+ link first_sample_reduction_block;
+} __attribute__((packed));
+
+struct cnblock {
+ char cn[2];
+ uint16_t block_size;
+ link next_channel_block;
+ link conversion_formula;
+ link source_dep_ext;
+ link dependency_block;
+ link comment;
+ uint16_t channel_type;
+ char short_signal_name[32];
+ char signal_description[128];
+ uint16_t start_offset_in_bits;
+ uint16_t number_of_bits;
+ uint16_t signal_data_type;
+} __attribute__((packed));
+
+int main(int argc, char *argv[])
+{
+ FILE *f;
+ struct idblock id;
+ struct hdblock hd;
+ struct dgblock dg;
+ struct cgblock cg;
+ unsigned i, cnidx;
+ struct cnblock *cn[20];
+ link cglink;
+ char *rec;
+
+ if (argc != 2) {
+ error(1, 0, "Usage: %s <mdf_log_file>", argv[0]);
+ }
+ f = fopen(argv[1], "r");
+ fread(&id, sizeof(id), 1, f);
+ fseek(f, 64, SEEK_SET);
+ fread(&hd, sizeof(hd), 1, f);
+ fseek(f, hd.data_group_block, SEEK_SET);
+ fread(&dg, sizeof(dg), 1, f);
+
+ cglink = dg.first_channel_group_block;
+ while (cglink) {
+ link cnlink;
+ fseek(f, cglink, SEEK_SET);
+ fread(&cg, sizeof(cg), 1, f);
+ cnlink = cg.first_channel_block;
+ cnidx = 0;
+ while (cnlink) {
+ fseek(f, cnlink, SEEK_SET);
+ cn[cnidx] = malloc(sizeof(struct cnblock));
+ fread(cn[cnidx], sizeof(struct cnblock), 1, f);
+ cnlink = cn[cnidx]->next_channel_block;
+ cnidx++;
+ }
+ cglink = cg.next_channel_group_block;
+ }
+
+ printf("#");
+ for (i=0; i<cnidx; i++) {
+ struct cnblock *c = cn[i];
+ printf("%s ", c->short_signal_name);
+ }
+ printf("\n");
+
+ rec = malloc(cg.size_of_data_record);
+
+ fseek(f, dg.data_block, SEEK_SET);
+ int j;
+ for (j=0; j<cg.num_records; j++) {
+ uint8_t rec_id;
+ switch (dg.num_rec_ids) {
+ case 0: rec_id = 0; break;
+ case 1: fread(&rec_id, sizeof(rec_id), 1, f); break;
+ default: printf("Unsupported num_rec_ids\n");
+ }
+ if (rec_id == cg.record_id) {
+ fread(rec, cg.size_of_data_record, 1, f);
+ for (i=0; i<cnidx; i++) {
+ struct cnblock *c = cn[i];
+ switch (c->signal_data_type) {
+ case 0:
+ switch(c->number_of_bits) {
+ case 8: printf("%hhu", rec[c->start_offset_in_bits/8]); break;
+ case 16: printf("%hu", *(uint16_t*)&rec[c->start_offset_in_bits/8]); break;
+ case 32: printf("%u", *(uint32_t*)&rec[c->start_offset_in_bits/8]); break;
+ default: printf("?size%d", c->number_of_bits);
+ }
+ break;
+ case 1:
+ switch(c->number_of_bits) {
+ case 8: printf("%hhd", rec[c->start_offset_in_bits/8]); break;
+ case 16: printf("%hd", *(int16_t*)&rec[c->start_offset_in_bits/8]); break;
+ case 32: printf("%d", *(int32_t*)&rec[c->start_offset_in_bits/8]); break;
+ default: printf("?size%d", c->number_of_bits);
+ }
+ break;
+ default:
+ printf("?type%d", c->signal_data_type);
+ }
+ printf(" ");
+ }
+ printf("\n");
+ } else
+ error(1, 0, "Unknown record id %d\n", rec_id);
+ }
+ return 0;
+}