OSDN Git Service

add bit parser
[rec10/rec10-git.git] / epgdump / dsmcc.c
1 // -*- tab-width:4 -*-
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "dsmcc.h"
8 #include "ts_ctl.h"
9 #include "clt2png.h"
10
11 // STD-B21 p130 (144)
12 // a_90-with-att.pdf p24 (29/99)
13 int parseDSMCChead(unsigned char *data, DSMCChead *dsmh) {
14         int boff = 0;
15
16         memset(dsmh, 0, sizeof(DSMCChead));
17
18         dsmh->table_id = getBit(data, &boff, 8);
19         dsmh->section_syntax_indicator = getBit(data, &boff, 1);
20         dsmh->complement_indicator = getBit(data, &boff,1);
21         dsmh->reserved1 = getBit(data, &boff, 2);
22         dsmh->section_length = getBit(data, &boff, 12);
23         dsmh->table_id_extension = getBit(data, &boff, 16);
24         dsmh->reserved2 = getBit(data, &boff, 2);
25         dsmh->version_number = getBit(data, &boff, 5);
26         dsmh->current_next_indicator = getBit(data, &boff, 1);
27         dsmh->section_number = getBit(data, &boff, 8);
28         dsmh->last_section_number = getBit(data, &boff, 8);
29
30         return 8;
31 }
32
33 // a_90-with-att.pdf p29 (34/99)
34 // 2-STD-B24v5_4-3p3.pdf p16 (30/125)
35 int parseDSMCCbodyDII(unsigned char *data, DSMCCbodyDII *dsmbdii) {
36         int boff = 0, i;
37         DSMCCbodyDIIModule *module;
38
39         memset(dsmbdii, 0, sizeof(DSMCCbodyDII));
40
41         // header
42         dsmbdii->protocolDiscriminator = getBit(data, &boff, 8);
43         dsmbdii->dsmccType = getBit(data, &boff, 8);
44         dsmbdii->messageId = getBit(data, &boff, 16);
45         dsmbdii->transaction_id = getBit(data, &boff, 32);
46         dsmbdii->reserved = getBit(data, &boff, 8);
47         dsmbdii->adaptationLength = getBit(data, &boff, 8);
48         dsmbdii->messageLength = getBit(data, &boff, 16);
49         if ( dsmbdii->adaptationLength > 0 ) {
50                 dsmbdii->dsmccAdaptationHeader = allocCopy(data, &boff, dsmbdii->adaptationLength);
51         }
52
53         // body
54         dsmbdii->downloadId = getBit(data, &boff, 32);
55         dsmbdii->blockSize = getBit(data, &boff, 16);
56         dsmbdii->windowSize = getBit(data, &boff, 8);
57         dsmbdii->ackPeriod = getBit(data, &boff, 8);
58         dsmbdii->tCDownloadWindow = getBit(data, &boff, 32);
59         dsmbdii->tCDownloadScenario = getBit(data, &boff, 32);
60         dsmbdii->compatibilityDescriptor = getBit(data, &boff, 16);
61 /*
62         see http://www.atsc.org/cms/standards/a_90-with-att.pdf
63
64         compatibilityDescriptorLength   16
65         descriptorCount 16
66         for(i=0;i<descriptorCount;i++) {
67                 descriptorType          8
68                 descriptorLength        8
69                 specifierType           8
70                 specifierData           24
71                 model                           16
72                 version                         16
73                 subDescriptorCount      8
74                 for(j=0;j<subDescriptorCount;j++) {
75                         subDescriptor() {
76                                 subDescriptorType       8
77                                 subDescriptorLength     8
78                                 for(k=0;k<subDescriptorLength;k++) {
79                                         additionalInformation   8
80                 }
81         }
82 */
83         boff += dsmbdii->compatibilityDescriptor * 8;
84         dsmbdii->numberOfModules = getBit(data, &boff, 16);
85
86         if ( dsmbdii->numberOfModules > 0 ) {
87                 dsmbdii->modules = calloc(1, sizeof(DSMCCbodyDIIModule) * dsmbdii->numberOfModules + 1000);
88
89                 for (i=0; i<dsmbdii->numberOfModules; i++) {
90                         module = dsmbdii->modules + sizeof(DSMCCbodyDIIModule) * i;
91                         module->moduleId = getBit(data, &boff, 16);
92                         module->moduleSize = getBit(data, &boff, 32);
93                         module->moduleVersion = getBit(data, &boff, 8);
94                         module->moduleInfoLength = getBit(data, &boff, 8);
95
96                         if ( *(data + boff / 8) == 0x01 ) {
97                                 /* Type 記述子 モジュールの型(MIME 形式等) */
98                                 module->descriptor_tag = getBit(data, &boff, 8);
99                                 module->descriptor_length = getBit(data, &boff, 8);
100                                 module->Type = allocCopy(data, &boff, module->descriptor_length + 1);
101                                 module->Type[module->descriptor_length] = '\0';
102                                 // +1 byte for null-terminated
103                         }
104                         else if ( *(data + boff / 8) == 0x02 ) {
105                                 /* Name 記述子 モジュール名(ファイル名) */
106                                 module->descriptor_tag = getBit(data, &boff, 8);
107                                 module->descriptor_length = getBit(data, &boff, 8);
108                                 module->Name = allocCopy(data, &boff, module->descriptor_length + 1);
109                                 module->Name[module->descriptor_length] = '\0';
110                         }
111                         else if ( *(data + boff / 8) == 0x03 ) {
112                                 /* Info 記述子 モジュール情報(文字型) */
113                                 module->descriptor_tag = getBit(data, &boff, 8);
114                                 module->descriptor_length = getBit(data, &boff, 8);
115                                 boff += 24; // ISO_639_language_code
116                                 module->Info = allocCopy(data, &boff, module->descriptor_length - 3 + 1);
117                                 module->Info[module->descriptor_length] = '\0';
118                         }
119                         else {
120                                 module->moduleInfo = allocCopy(data, &boff, module->moduleInfoLength);
121                         }
122                 }
123         }
124
125         dsmbdii->privateDataLength = getBit(data, &boff, 8);
126         dsmbdii->privateData = allocCopy(data, &boff, dsmbdii->privateDataLength);
127
128         return boff / 8;
129 }
130
131 // a_90-with-att.pdf p35 (40/99)
132 int parseDSMCCbodyDDB(unsigned char *data, DSMCCbodyDDB *dsmbddb) {
133         int boff = 0;
134
135         memset(dsmbddb, 0, sizeof(DSMCCbodyDDB));
136
137         // header
138         dsmbddb->protocolDiscriminator = getBit(data, &boff, 8);
139         dsmbddb->dsmccType = getBit(data, &boff, 8);
140         dsmbddb->messageId = getBit(data, &boff, 16);
141         dsmbddb->downloadId = getBit(data, &boff, 32);
142         dsmbddb->reserved1 = getBit(data, &boff, 8);
143         dsmbddb->adaptationLength = getBit(data, &boff, 8);
144         dsmbddb->messageLength = getBit(data, &boff, 16);
145         if ( dsmbddb->adaptationLength > 0 ) {
146                 dsmbddb->dsmccAdaptationHeader = allocCopy(data, &boff, dsmbddb->adaptationLength);
147         }
148
149         // body
150         dsmbddb->moduleId = getBit(data, &boff, 16);
151         dsmbddb->moduleVersion = getBit(data, &boff, 8);
152         dsmbddb->reserved2 = getBit(data, &boff, 8);
153         dsmbddb->blockNumber = getBit(data, &boff, 16);
154         dsmbddb->blockData = allocCopy(data, &boff, dsmbddb->messageLength);
155
156         return boff / 8;
157 }
158
159 void dumpDSMCC(unsigned char *ptr, int * downloadDataId, DSM_CONTROL *dsmctl)
160 {
161         DSMCChead  dsmh;
162         DSMCCbodyDII  dsmbdii;
163         DSMCCbodyDDB  dsmbddb;
164         DSMCCbodyDIIModule *module;
165
166         int len = 0;
167         int i = 0;
168
169         /* DSMCC */
170         len = parseDSMCChead(ptr, &dsmh);
171         ptr += len;
172         //loop_len = dsmh.section_length - (len - 3 + 4); // 3は共通ヘッダ長 4はCRC
173 /*
174         printf("DSMCChead=(%d:%d:%d:%d)\n",
175                 dsmh.table_id, dsmh.section_length, 
176                 dsmh.table_id_extension, dsmh.section_number);
177 */
178         if ( dsmh.table_id == 0x3B ) {
179                 len = parseDSMCCbodyDII(ptr, &dsmbdii);
180 #if 0
181                 printf("DSMCCbDII=(%d:%d:%d:%d:%d:%d) (%d:%d:%d:%d)\n",
182                         dsmbdii.protocolDiscriminator, dsmbdii.dsmccType, 
183                         dsmbdii.messageId, dsmbdii.transaction_id, 
184                         dsmbdii.adaptationLength, dsmbdii.messageLength, 
185
186                         dsmbdii.downloadId , dsmbdii.blockSize , dsmbdii.compatibilityDescriptor , 
187                         dsmbdii.numberOfModules);
188 #endif
189                 for (i=0; i<dsmbdii.numberOfModules; i++) {
190                         module = dsmbdii.modules + sizeof(DSMCCbodyDIIModule) * i;
191                         // 0x01 Type 記述子
192                         // 0x02 Name 記述子
193                         // 0x03 Info 記述子
194                         if ( module->descriptor_tag == 0x01 ) {
195                                 //printf("1 %s\n", module->Type);
196                         }
197                         else if ( module->descriptor_tag == 0x02 ) {
198                                 //printf("2 %s\n", module->Name);
199                                 // is_bs_cs == 1 && 
200                                 if ( !strncmp( module->Name, "LOGO", 4 ) ) {
201                                         //printf("%s(%d) : id = %d\n", module->Name, is_bs_cs, dsmbdii.downloadId);
202                                         *downloadDataId = dsmbdii.downloadId;
203                                 }
204                                 // なぜかBSにCSのロゴも載ってるため
205                                 // is_bs_cs == 2 && 
206                                 else if ( !strncmp( module->Name, "CS_LOGO", 7 ) ) {
207                                         //printf("%s(%d) : id = %d\n", module->Name, is_bs_cs, dsmbdii.downloadId);
208                                         *downloadDataId = dsmbdii.downloadId;
209                                 }
210                         }
211                         else if ( module->descriptor_tag == 0x03 ) {
212                                 //printf("3 %s\n", module->Info);
213                         }
214                 }
215         }
216         else if ( dsmh.table_id == 0x3C ) {
217                 len = parseDSMCCbodyDDB(ptr, &dsmbddb);
218                 if ( *downloadDataId == dsmbddb.downloadId ) {
219 //              if ( 33882368 == dsmbddb.downloadId ) {
220 //              {
221 #if 0
222                         printf("DSMCCbDDB=(%d:%d:%d:%d:%d:%d) (%d:%d:%d)\n",
223                                 dsmbddb.protocolDiscriminator, dsmbddb.dsmccType, 
224                                 dsmbddb.messageId, dsmbddb.downloadId, 
225                                 dsmbddb.adaptationLength, dsmbddb.messageLength, 
226
227                                 dsmbddb.moduleId , dsmbddb.moduleVersion , dsmbddb.blockNumber);
228 #endif
229
230                         for (i = 0; i < 1024; i++) {
231                                 if ( dsmctl[i].isUsed == 0 ) {
232                                         // リストの終端まで来たので
233                                         //printf("moduleId=%d as dsmctl[%d]\n", dsmbddb.moduleId, i);
234                                         dsmctl[i].moduleId = dsmbddb.moduleId;
235                                         dsmctl[i].lastBlockNumber = -1;
236                                         dsmctl[i].isUsed = 1;
237                                 }
238                                 if ( dsmctl[i].moduleId == dsmbddb.moduleId ) {
239                                         if ( dsmctl[i].lastBlockNumber + 1 == dsmbddb.blockNumber ) {
240                                                 dsmbddb.messageLength -= 6; // length of moduleId, moduleVersion, reserved, blockNumber
241                                                 //printf("moduleId=%d as dsmctl[%d] size %d += %d\n", dsmbddb.moduleId, i, dsmctl[i].blockSize, dsmbddb.messageLength);
242                                                 dsmctl[i].blockData = realloc( dsmctl[i].blockData, dsmctl[i].blockSize + dsmbddb.messageLength );
243                                                 memcpy( dsmctl[i].blockData + dsmctl[i].blockSize, dsmbddb.blockData, dsmbddb.messageLength );
244                                                 dsmctl[i].blockSize += dsmbddb.messageLength;
245                                                 dsmctl[i].lastBlockNumber++;
246                                         }
247                                         else {
248                                                 //printf("ignoring %d(max %d)\n", dsmbddb.blockNumber, dsmctl[i].lastBlockNumber);
249                                         }
250                                         break;
251                                 }
252                         }
253                 }
254         }
255
256         return;
257 }
258