Example #1
0
/* 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;
}
Example #2
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;
}
Example #3
0
/* 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;
}
Example #4
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;
}
Example #5
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);
}
Example #6
0
/* 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;
}
Example #7
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;
}
Example #8
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;
	}
Example #9
0
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;
}