/* CAROUSEL_ID_DESCRIPTOR parser */ int descriptor_0x13_parser(const char *payload, int len, struct dentry *parent, struct demuxfs_data *priv) { struct dentry *dentry; struct formatted_descriptor f; if (! descriptor_is_parseable(parent, payload[0], 6, len)) return -ENODATA; dentry = CREATE_DIRECTORY(parent, "Carousel_Identifier"); f.carousel_id = CONVERT_TO_32(payload[2], payload[3], payload[4], payload[5]); CREATE_FILE_NUMBER(dentry, &f, carousel_id); /* * TODO: MHP contains a different spec for this descriptor. * See Table B.36 on page 505 of MHP Specification 1.1.3. */ if (len > 6) { size_t file_size = len-6; f.private_data = malloc(file_size * sizeof(char)); memcpy(f.private_data, &payload[6], file_size); CREATE_FILE_BIN(dentry, &f, private_data, file_size); free(f.private_data); } return 0; }
static int ForceCreatePath(TCHAR * szFullPath) { TCHAR * szPlainName = (TCHAR *)GetPlainFileName(szFullPath) - 1; TCHAR * szPathPart = szFullPath; TCHAR chSaveChar; // Skip disk drive and root directory if(szPathPart[0] != 0 && szPathPart[1] == _T(':')) szPathPart += 3; while(szPathPart <= szPlainName) { // If there is a delimiter, create the path fragment if(szPathPart[0] == _T('\\') || szPathPart[0] == _T('/')) { chSaveChar = szPathPart[0]; szPathPart[0] = 0; CREATE_DIRECTORY(szFullPath); szPathPart[0] = chSaveChar; } // Move to the next character szPathPart++; } return ERROR_SUCCESS; }
/* LOCAL_TIME_OFFSET_DESCRIPTOR parser */ int descriptor_0x58_parser(const char *payload, int len, struct dentry *parent, struct demuxfs_data *priv) { struct formatted_descriptor f; if (! descriptor_is_parseable(parent, payload[0], 15, len)) return -ENODATA; memset(&f, 0, sizeof(f)); sprintf(f.country_code, "%c%c%c [0x%x%x%x]", payload[2], payload[3], payload[4], payload[2], payload[3], payload[4]); f.country_region_id = payload[5] >> 2; f.reserved = (payload[5] >> 6) & 0x01; f.local_time_offset_polarity = (payload[5] >> 7) & 0x01; f.local_time_offset = CONVERT_TO_16(payload[6], payload[7]); f.time_of_change = CONVERT_TO_40(payload[8], payload[9], payload[10], payload[11], payload[12]) & 0xffffffffff; f.next_time_offset = CONVERT_TO_16(payload[13], payload[14]); struct dentry *dentry = CREATE_DIRECTORY(parent, "Local_Time_Offset_Descriptor"); CREATE_FILE_STRING(dentry, &f, country_code, XATTR_FORMAT_STRING_AND_NUMBER); CREATE_FILE_NUMBER(dentry, &f, country_region_id); CREATE_FILE_NUMBER(dentry, &f, local_time_offset_polarity); CREATE_FILE_NUMBER(dentry, &f, local_time_offset); CREATE_FILE_NUMBER(dentry, &f, time_of_change); CREATE_FILE_NUMBER(dentry, &f, next_time_offset); return 0; }
/* PARTIAL_RECEPTION_DESCRIPTOR parser */ int descriptor_0xfb_parser(const char *payload, int len, struct dentry *parent, struct demuxfs_data *priv) { uint8_t i; struct dentry *dentry, *subdir; if (! descriptor_is_parseable(parent, payload[0], 2, len)) return -ENODATA; dentry = CREATE_DIRECTORY(parent, "Partial_Reception_Descriptor"); for (i=2; i<len; i+=2) { struct formatted_descriptor f; f.service_id = CONVERT_TO_16(payload[i], payload[i+1]); subdir = CREATE_DIRECTORY(dentry, "Service_%02d", ((i-2)/2)+1); CREATE_FILE_NUMBER(subdir, &f, service_id); if (! pat_announces_service(f.service_id, priv)) TS_WARNING("service_id %#x not declared by the PAT", f.service_id); } return 0; }
static void ddb_create_directory(const struct ts_header *header, struct ddb_table *ddb, struct dentry **version_dentry, struct demuxfs_data *priv) { /* Create a directory named "DDB" at the root filesystem if it doesn't exist yet */ struct dentry *ddb_dir = CREATE_DIRECTORY(priv->root, FS_DDB_NAME); /* Create a directory named "<ddb_pid>" and populate it with files */ asprintf(&ddb->dentry->name, "%#04x", header->pid); ddb->dentry->mode = S_IFDIR | 0555; CREATE_COMMON(ddb_dir, ddb->dentry); /* Create the versioned dir and update the Current symlink */ *version_dentry = fsutils_create_version_dir(ddb->dentry, ddb->version_number); }
/* PARENTAL_RATING_DESCRIPTOR parser */ int descriptor_0x55_parser(const char *payload, int len, struct dentry *parent, struct demuxfs_data *priv) { int i, n, num_entries = (len-2) / 4; for (i=2, n=0; n<num_entries; ++n) { struct dentry *subdir = CREATE_DIRECTORY(parent, "Parental_Rating_Descriptor_%d", n+1); struct parental_rating_descriptor p; memset(&p, 0, sizeof(p)); sprintf(p.country_code, "%c%c%c [0x%x%x%x]", payload[i], payload[i+1], payload[i+2], payload[i], payload[i+1], payload[i+2]); p.rating = payload[i+3]; CREATE_FILE_STRING(subdir, &p, country_code, XATTR_FORMAT_STRING_AND_NUMBER); CREATE_FILE_NUMBER(subdir, &p, rating); i += 4; } return 0; }
/* VIDEO_DECODE_CONTROL_DESCRIPTOR parser */ int descriptor_0xc8_parser(const char *payload, int len, struct dentry *parent, struct demuxfs_data *priv) { struct dentry *dentry; struct formatted_descriptor f; char video_fmt[64]; if (! descriptor_is_parseable(parent, payload[0], 3, len)) return -ENODATA; dentry = CREATE_DIRECTORY(parent, "Video_Decode_Control_Descriptor"); f.still_picture_flag = (payload[2] & 0x80) ? 1 : 0; f.sequence_end_code_flag = (payload[2] & 0x40) ? 1 : 0; f._video_encode_format = (payload[2] >> 2) & 0x0f; f.reserved = payload[2] & 0x03; CREATE_FILE_NUMBER(dentry, &f, still_picture_flag); CREATE_FILE_NUMBER(dentry, &f, sequence_end_code_flag); switch (f._video_encode_format) { case 0: sprintf(video_fmt, "1080p"); break; case 1: sprintf(video_fmt, "1080i"); break; case 2: sprintf(video_fmt, "720p"); break; case 3: sprintf(video_fmt, "480p"); break; case 4: sprintf(video_fmt, "480i"); break; case 5: sprintf(video_fmt, "240p"); break; case 6: sprintf(video_fmt, "120p"); break; default: sprintf(video_fmt, "Reserved"); } sprintf(f.video_encode_format, "%s [%#x]", video_fmt, f._video_encode_format); CREATE_FILE_STRING(dentry, &f, video_encode_format, XATTR_FORMAT_STRING_AND_NUMBER); return 0; }
static void ait_parse_descriptor(uint8_t tag, uint8_t len, const char *payload, struct dentry *parent, struct demuxfs_data *priv) { struct dentry *dentry; switch (tag) { case 0x00: /* Application descriptor */ { uint8_t i; struct application_descriptor desc; dentry = CREATE_DIRECTORY(parent, "Application_Descriptor"); desc.application_profiles_length = payload[2]; for (i=3; i<desc.application_profiles_length+3; i+=5) { struct dentry *prof_dentry; struct app_profile *profile = &desc.app_profile; profile->application_profile = CONVERT_TO_16(payload[i], payload[i+1]); profile->version_major = payload[i+2]; profile->version_minor = payload[i+3]; profile->version_micro = payload[i+4]; prof_dentry = CREATE_DIRECTORY(dentry, "Application_Profile_%02d", profile->application_profile); CREATE_FILE_NUMBER(prof_dentry, profile, version_major); CREATE_FILE_NUMBER(prof_dentry, profile, version_minor); CREATE_FILE_NUMBER(prof_dentry, profile, version_micro); } desc.service_bound_flag = payload[i] >> 7; desc._visibility = (payload[i] >> 5) & 0x03; desc.application_priority = payload[i+1]; if (desc._visibility == 0x00) desc.visibility = strdup("Not visible to users or other applications through API, except for logout information errors and such [0x00]"); else if (desc._visibility == 0x01) desc.visibility = strdup("Not visible to users but visible to other applications through API [0x01]"); else if (desc._visibility == 0x02) desc.visibility = strdup("Reserved for future use [0x02]"); else /* if (desc._visibility == 0x03) */ desc.visibility = strdup("Visible to users and to other applications through API [0x03]"); CREATE_FILE_NUMBER(dentry, &desc, service_bound_flag); CREATE_FILE_STRING(dentry, &desc, visibility, XATTR_FORMAT_STRING_AND_NUMBER); CREATE_FILE_NUMBER(dentry, &desc, application_priority); free(desc.visibility); } break; case 0x01: /* Application name descriptor */ { struct application_name_descriptor desc; struct dentry *app_dentry; uint8_t i = 2, app_nr = 1; dentry = CREATE_DIRECTORY(parent, "Application_Name_Descriptor"); while (i < len) { app_dentry = CREATE_DIRECTORY(dentry, "Application_Name_%02d", app_nr++); desc.iso_639_language_code = CONVERT_TO_24(payload[i], payload[i+1], payload[i+2]) & 0x00ffffff; desc.application_name_length = payload[i+3]; desc.application_name = strndup(&payload[i+4], desc.application_name_length+1); desc.application_name[desc.application_name_length] = '\0'; CREATE_FILE_NUMBER(app_dentry, &desc, iso_639_language_code); CREATE_FILE_NUMBER(app_dentry, &desc, application_name_length); CREATE_FILE_STRING(app_dentry, &desc, application_name, XATTR_FORMAT_STRING); free(desc.application_name); i += 4 + desc.application_name_length; } } break; case 0x02: /* Transport protocol descriptor */ { struct transport_protocol_descriptor desc; memset(&desc, 0, sizeof(desc)); dentry = CREATE_DIRECTORY(parent, "Transport_Protocol_Descriptor"); desc._protocol_id = CONVERT_TO_16(payload[2], payload[3]); desc.transport_protocol_label = payload[4]; switch (desc._protocol_id) { case 0x0001: sprintf(desc.protocol_id, "Object carousel transport protocol [%#x]", desc._protocol_id); break; case 0x0002: sprintf(desc.protocol_id, "IP over multiprotocol DVB [%#x]", desc._protocol_id); break; case 0x0003: sprintf(desc.protocol_id, "Reserved / Data piping [%#x]", desc._protocol_id); break; case 0x0004: sprintf(desc.protocol_id, "Data carousel transport protocol [%#x]", desc._protocol_id); break; default: sprintf(desc.protocol_id, "Reserved for future use [%#x]", desc._protocol_id); break; } CREATE_FILE_STRING(dentry, &desc, protocol_id, XATTR_FORMAT_STRING_AND_NUMBER); CREATE_FILE_NUMBER(dentry, &desc, transport_protocol_label); if (((int) len - 3) > 0) { uint8_t i = 0; uint8_t url_number = 1; struct dentry *subdir; switch (desc._protocol_id) { case 0x0001: case 0x0004: subdir = CREATE_DIRECTORY(dentry, "Remote_Connection"); desc.carousel.remote_connection = payload[5] & 0x01; desc.carousel.reserved_future_use = (payload[5] >> 1) & 0x7f; CREATE_FILE_NUMBER(subdir, &desc.carousel, remote_connection); if (desc.carousel.remote_connection) { desc.carousel.original_network_id = CONVERT_TO_16(payload[6], payload[7]); desc.carousel.transport_stream_id = CONVERT_TO_16(payload[8], payload[9]); desc.carousel.service_id = CONVERT_TO_16(payload[10], payload[11]); CREATE_FILE_NUMBER(subdir, &desc.carousel, original_network_id); CREATE_FILE_NUMBER(subdir, &desc.carousel, transport_stream_id); CREATE_FILE_NUMBER(subdir, &desc.carousel, service_id); i = 6; } desc.carousel.component_tag = payload[6+i]; CREATE_FILE_NUMBER(subdir, &desc.carousel, component_tag); break; case 0x0002: subdir = CREATE_DIRECTORY(dentry, "IP_Transport"); desc.ip.remote_connection = payload[5] & 0x01; desc.ip.reserved_future_use = (payload[5] >> 1) & 0x7f; CREATE_FILE_NUMBER(subdir, &desc.ip, remote_connection); if (desc.ip.remote_connection) { desc.ip.original_network_id = CONVERT_TO_16(payload[6], payload[7]); desc.ip.transport_stream_id = CONVERT_TO_16(payload[8], payload[9]); desc.ip.service_id = CONVERT_TO_16(payload[10], payload[11]); CREATE_FILE_NUMBER(subdir, &desc.ip, original_network_id); CREATE_FILE_NUMBER(subdir, &desc.ip, transport_stream_id); CREATE_FILE_NUMBER(subdir, &desc.ip, service_id); i = 6; } desc.ip.alignment_indicator = payload[6+i] & 0x01; desc.ip.reserved = (payload[6+i] >> 1) & 0x7f; CREATE_FILE_NUMBER(subdir, &desc.ip, alignment_indicator); i += 7; while (i < len) { char url_dirname[64]; struct dentry *url_dentry; sprintf(url_dirname, "URL_%02d", url_number++); url_dentry = CREATE_DIRECTORY(subdir, url_dirname); desc.ip.URL_length = payload[i++]; CREATE_FILE_NUMBER(url_dentry, &desc.ip, URL_length); if (desc.ip.URL_length) { desc.ip.URL_byte = calloc(desc.ip.URL_length + 1, sizeof(char)); memcpy(desc.ip.URL_byte, &payload[i], desc.ip.URL_length); CREATE_FILE_STRING(url_dentry, &desc.ip, URL_byte, XATTR_FORMAT_STRING); free(desc.ip.URL_byte); } i += desc.ip.URL_length; } break; default: desc.selector_byte = malloc((len-3) * sizeof(char)); for (i=0; i<len-3; ++i) desc.selector_byte[i] = payload[5+i]; CREATE_FILE_BIN(dentry, &desc, selector_byte, (len-3)); free(desc.selector_byte); } } } break; case 0x03: if (priv->options.standard == SBTVD_STANDARD) { /* Ginga-J application descriptor */ uint8_t param = 1; uint8_t i = 2; dentry = CREATE_DIRECTORY(parent, "Ginga-J_Application_Descriptor"); while (i < len) { struct dentry *param_dentry; struct ginga_j_application_descriptor desc; param_dentry = CREATE_DIRECTORY(dentry, "Parameter_%02d", param++); desc.parameter_length = payload[i]; CREATE_FILE_NUMBER(param_dentry, &desc, parameter_length); if (desc.parameter_length) { desc.parameter = strndup(&payload[i+1], desc.parameter_length+1); desc.parameter[desc.parameter_length] = '\0'; CREATE_FILE_STRING(param_dentry, &desc, parameter, XATTR_FORMAT_STRING); free(desc.parameter); } i += 2 + desc.parameter_length; } } else { /* DVB-J application descriptor */ dentry = CREATE_DIRECTORY(parent, "DVB-J_Application_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x04: if (priv->options.standard == SBTVD_STANDARD) { /* Ginga-J application location descriptor */ struct ginga_j_application_location_descriptor desc; uint8_t i; dentry = CREATE_DIRECTORY(parent, "Ginga-J_Application_Location"); desc.base_directory_length = payload[2]; desc.base_directory = strndup(&payload[3], desc.base_directory_length+1); desc.base_directory[desc.base_directory_length] = '\0'; i = 3 + desc.base_directory_length; desc.classpath_extension_length = payload[i]; desc.classpath_extension = strndup(&payload[i+1], desc.classpath_extension_length+1); desc.classpath_extension[desc.classpath_extension_length] = '\0'; i += 1 + desc.classpath_extension_length; desc.initial_class = strndup(&payload[i], len-i+2); desc.initial_class[len-i+2] = '\0'; CREATE_FILE_NUMBER(dentry, &desc, base_directory_length); CREATE_FILE_STRING(dentry, &desc, base_directory, XATTR_FORMAT_STRING); CREATE_FILE_NUMBER(dentry, &desc, classpath_extension_length); CREATE_FILE_STRING(dentry, &desc, classpath_extension, XATTR_FORMAT_STRING); CREATE_FILE_STRING(dentry, &desc, initial_class, XATTR_FORMAT_STRING); free(desc.base_directory); free(desc.classpath_extension); free(desc.initial_class); } else { /* DVB-J application location descriptor */ dentry = CREATE_DIRECTORY(parent, "DVB-J_Application_Location_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x05: /* External application authorization descriptor */ { uint8_t i = 2; uint8_t app = 1; dentry = CREATE_DIRECTORY(parent, "External_Application_Authorization_Descriptor"); while (i < len) { struct dentry *app_dentry; struct external_application_authorization_descriptor desc; desc.id.organization_id = CONVERT_TO_32(payload[i], payload[i+1], payload[i+2], payload[i+3]); desc.id.application_id = CONVERT_TO_16(payload[i+4], payload[i+5]); desc.application_priority = payload[i+6]; i += 7; app_dentry = CREATE_DIRECTORY(dentry, "Application_%02d", app++); CREATE_FILE_NUMBER(app_dentry, &desc.id, organization_id); CREATE_FILE_NUMBER(app_dentry, &desc.id, application_id); CREATE_FILE_NUMBER(app_dentry, &desc, application_priority); } } break; case 0x06: if (priv->options.standard == SBTVD_STANDARD) { /* Ginga-NCL application descriptor */ dentry = CREATE_DIRECTORY(parent, "Ginga-NCL_Application_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } else { /* Routing Descriptor IPv4 */ dentry = CREATE_DIRECTORY(parent, "IPv4_Routing_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x07: if (priv->options.standard == SBTVD_STANDARD) { /* Ginga-NCL application location descriptor */ dentry = CREATE_DIRECTORY(parent, "Ginga-NCL_Application_Location_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } else { /* Routing Descriptor IPv6 */ dentry = CREATE_DIRECTORY(parent, "IPv6_Routing_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x08: if (priv->options.standard == SBTVD_STANDARD) { /* NCL-HTML (reserved by MHP) */ dentry = CREATE_DIRECTORY(parent, "NCL-HTML_Application_Descriptor"); } else if (priv->options.standard == DVB_STANDARD) { /* DVB-HTML application descriptor */ dentry = CREATE_DIRECTORY(parent, "DVB-HTML_Application_Descriptor"); } dprintf("Parser for AIT descriptor %#x not implemented", tag); break; case 0x09: if (priv->options.standard == SBTVD_STANDARD) { /* NCL-HTML (reserved by MHP) */ dentry = CREATE_DIRECTORY(parent, "NCL-HTML_Application_Location_Descriptor"); } else if (priv->options.standard == DVB_STANDARD) { /* DVB-HTML application location descriptor */ dentry = CREATE_DIRECTORY(parent, "DVB-HTML_Application_Location_Descriptor"); } dprintf("Parser for AIT descriptor %#x not implemented", tag); break; case 0x0a: if (priv->options.standard == SBTVD_STANDARD) { /* NCL-HTML (reserved by MHP) */ dentry = CREATE_DIRECTORY(parent, "NCL-HTML_Application_Boundary_Descriptor"); } else if (priv->options.standard == DVB_STANDARD) { /* DVB-HTML application boundary descriptor */ dentry = CREATE_DIRECTORY(parent, "DVB-HTML_Application_Boundary_Descriptor"); } dprintf("Parser for AIT descriptor %#x not implemented", tag); break; case 0x0b: /* Application icons descriptor */ { struct application_icons_descriptor desc; uint8_t i; dentry = CREATE_DIRECTORY(parent, "Application_Icons_Descriptor"); desc.icon_locator_length = payload[2]; CREATE_FILE_NUMBER(dentry, &desc, icon_locator_length); if (desc.icon_locator_length) { desc.icon_locator = malloc(desc.icon_locator_length); memcpy(desc.icon_locator, &payload[3], desc.icon_locator_length); CREATE_FILE_BIN(dentry, &desc, icon_locator, desc.icon_locator_length); } i = 3 + desc.icon_locator_length; desc._icon_flags = CONVERT_TO_16(payload[i], payload[i+1]); switch (desc._icon_flags) { case 0x01: sprintf(desc.icon_flags, "32x32 for presentation on squared pixel screens [%#x]", desc._icon_flags); break; case 0x02: sprintf(desc.icon_flags, "32x32 for presentation on 4:3 screens [%#x]", desc._icon_flags); break; case 0x04: sprintf(desc.icon_flags, "24x32 for presentation on 16:9 screens [%#x]", desc._icon_flags); break; case 0x08: sprintf(desc.icon_flags, "64x64 for presentation on squared pixel screens [%#x]", desc._icon_flags); break; case 0x10: sprintf(desc.icon_flags, "64x64 for presentation on 4:3 screens [%#x]", desc._icon_flags); break; case 0x20: sprintf(desc.icon_flags, "48x64 for presentation on 16:9 screens [%#x]", desc._icon_flags); break; case 0x40: sprintf(desc.icon_flags, "128x128 for presentation on squared pixel screens [%#x]", desc._icon_flags); break; case 0x80: sprintf(desc.icon_flags, "128x128 for presentation on 4:3 screens [%#x]", desc._icon_flags); break; case 0x100: sprintf(desc.icon_flags, "96x128 for presentation on 16:9 screens [%#x]", desc._icon_flags); break; default: sprintf(desc.icon_flags, "reserved for future use [%#x]", desc._icon_flags); } CREATE_FILE_STRING(dentry, &desc, icon_flags, XATTR_FORMAT_STRING_AND_NUMBER); } break; case 0x0c: /* Prefetch descriptor */ { dentry = CREATE_DIRECTORY(parent, "Prefetch_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x0d: /* DII location descriptor */ { uint8_t i = 3; uint8_t label_number = 1; struct prefetch_descriptor desc; dentry = CREATE_DIRECTORY(parent, "DII_Location_Descriptor"); desc.transport_protocol_label = payload[2]; CREATE_FILE_NUMBER(dentry, &desc, transport_protocol_label); while (i < len) { char label_name[32]; struct dentry *label_dentry; sprintf(label_name, "Label_%02d", label_number++); label_dentry = CREATE_DIRECTORY(dentry, label_name); desc.label_length = payload[i++]; CREATE_FILE_NUMBER(label_dentry, &desc, label_length); if (desc.label_length) { desc.label = calloc(desc.label_length + 1, sizeof(char)); memcpy(desc.label, &payload[i], desc.label_length); CREATE_FILE_STRING(label_dentry, &desc, label, XATTR_FORMAT_STRING); } i += desc.label_length; desc.prefetch_priority = payload[i++]; if (desc.prefetch_priority <= 0 || desc.prefetch_priority > 100) TS_WARNING("prefetch_priority not in range 1..100 (%d)", desc.prefetch_priority); CREATE_FILE_NUMBER(label_dentry, &desc, prefetch_priority); } } break; case 0x0e: if (priv->options.standard == SBTVD_STANDARD) { /* Reserved by MHP */ dprintf("Parser for AIT descriptor %#x not implemented for it's reserved for future use by MHP", tag); } else if (priv->options.standard == DVB_STANDARD) { /* Delegated application descriptor */ dentry = CREATE_DIRECTORY(parent, "Delegated_Application_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x0f: if (priv->options.standard == SBTVD_STANDARD) { /* Reserved by MHP */ dprintf("Parser for AIT descriptor %#x not implemented for it's reserved for future use by MHP", tag); } else if (priv->options.standard == DVB_STANDARD) { /* Plugin descriptor */ dentry = CREATE_DIRECTORY(parent, "Plugin_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x10: if (priv->options.standard == SBTVD_STANDARD) { /* Reserved by MHP */ dprintf("Parser for AIT descriptor %#x not implemented for it's reserved for future use by MHP", tag); } else if (priv->options.standard == DVB_STANDARD) { /* APplication storage descriptor */ dentry = CREATE_DIRECTORY(parent, "Application_Storage_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x11: /* IP signalling descriptor */ if (priv->options.standard == SBTVD_STANDARD) { struct ip_signalling_descriptor desc; desc.platform_id = CONVERT_TO_24(payload[2], payload[3], payload[4]); dentry = CREATE_DIRECTORY(parent, "IP_Signalling_Descriptor"); CREATE_FILE_NUMBER(dentry, &desc, platform_id); } else { /* Reserved by MHP */ dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x12 ... 0x5e: /* Reserved for future use by MHP */ { dprintf("Parser for AIT descriptor %#x not implemented for it's reserved for future use by MHP", tag); } break; case 0x5f: /* Private data specifier descriptor */ { dentry = CREATE_DIRECTORY(parent, "Private_Data_Specifier_Descriptor"); dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; case 0x60 ... 0x7f: /* Reserved for future use by MHP */ { dprintf("Parser for AIT descriptor %#x not implemented for it's reserved for future use by MHP", tag); } break; case 0x80 ... 0xff: /* User defined */ { dprintf("Parser for AIT descriptor %#x not implemented", tag); } break; }
int ddb_parse(const struct ts_header *header, const char *payload, uint32_t payload_len, struct demuxfs_data *priv) { struct ddb_table *current_ddb = NULL; struct ddb_table *ddb = (struct ddb_table *) calloc(1, sizeof(struct ddb_table)); assert(ddb); ddb->dentry = (struct dentry *) calloc(1, sizeof(struct dentry)); assert(ddb->dentry); /* Copy data up to the first loop entry */ int ret = psi_parse((struct psi_common_header *) ddb, payload, payload_len); if (ret < 0) { ddb_free(ddb); return 0; } ddb_check_header(ddb); /* Set hash key and check if there's already one version of this table in the hash */ ddb->dentry->inode = TS_PACKET_HASH_KEY(header, ddb); current_ddb = hashtable_get(priv->psi_tables, ddb->dentry->inode); /* Check whether we should keep processing this packet or not */ if (! ddb->current_next_indicator) { dprintf("ddb doesn't have current_next_indicator bit set, skipping it"); ddb_free(ddb); return 0; } /** DSM-CC Download Data Header */ struct dsmcc_download_data_header *data_header = &ddb->dsmcc_download_data_header; int j = dsmcc_parse_download_data_header(data_header, payload, 8); if (data_header->_dsmcc_type != 0x03 || data_header->_message_id != 0x1003) { ddb_free(ddb); return 0; } if (data_header->message_length < 5) { // XXX: expose header in the fs? if (data_header->message_length) dprintf("skipping message with len=%d", data_header->message_length); ddb_free(ddb); return 0; } /** DDB bits */ ddb->module_id = CONVERT_TO_16(payload[j], payload[j+1]); ddb->module_version = payload[j+2]; ddb->reserved = payload[j+3]; ddb->block_number = CONVERT_TO_16(payload[j+4], payload[j+5]); ddb->_block_data_size = data_header->message_length - data_header->adaptation_length - 6; if (! ddb->_block_data_size) { ddb_free(ddb); return 0; } if (ddb_block_number_already_parsed(current_ddb, ddb->module_id, ddb->block_number)) { ddb_free(ddb); return 0; } // TS_INFO("DDB parser: pid=%d, table_id=%#x, ddb->version_number=%#x, ddb->block_number=%d, module_id=%d, current=%p", // header->pid, ddb->table_id, ddb->version_number, ddb->block_number, ddb->module_id, current_ddb); /* Create filesystem entries for this table */ struct dentry *version_dentry = NULL; if (current_ddb) version_dentry = fsutils_get_current(current_ddb->dentry); else ddb_create_directory(header, ddb, &version_dentry, priv); uint16_t this_block_size = payload_len - (j+6) - 4; uint16_t this_block_start = j+6; if (this_block_size != ddb->_block_data_size) TS_WARNING("ddb->block_data_size=%d != this_block_size=%d", ddb->_block_data_size, this_block_size); /* Create individual block file */ struct dentry *module_dir = CREATE_DIRECTORY(version_dentry, "module_%02d", ddb->module_id); struct dentry *block_dentry = (struct dentry *) calloc(1, sizeof(struct dentry)); block_dentry->size = this_block_size; block_dentry->mode = S_IFREG | 0444; block_dentry->obj_type = OBJ_TYPE_FILE; block_dentry->contents = malloc(this_block_size); memcpy(block_dentry->contents, &payload[this_block_start], this_block_size); asprintf(&block_dentry->name, "block_%02d.bin", ddb->block_number); CREATE_COMMON(module_dir, block_dentry); xattr_add(block_dentry, XATTR_FORMAT, XATTR_FORMAT_BIN, strlen(XATTR_FORMAT_BIN), false); if (current_ddb) ddb_free(ddb); else hashtable_add(priv->psi_tables, ddb->dentry->inode, ddb, (hashtable_free_function_t) ddb_free); return 0; }