mirror of
				https://github.com/DigitalDevices/dddvb.git
				synced 2025-03-01 10:35:23 +00:00 
			
		
		
		
	add modulator MCI commands
This commit is contained in:
		
							
								
								
									
										268
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								apps/modconfig.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <linux/types.h> | ||||
| #include <getopt.h> | ||||
| #include <ctype.h> | ||||
|  | ||||
| typedef uint8_t u8; | ||||
| typedef uint16_t u16; | ||||
| typedef int16_t s16; | ||||
| typedef uint32_t u32; | ||||
| typedef uint64_t u64; | ||||
|  | ||||
| #include "../ddbridge/ddbridge-mci.h" | ||||
| #include "../ddbridge/ddbridge-ioctl.h" | ||||
|  | ||||
| struct mconf { | ||||
| 	int set_output; | ||||
| 	int set_channels; | ||||
| 	int fd; | ||||
| 	 | ||||
| 	struct mci_command channels; | ||||
| 	struct mci_command stream; | ||||
| 	struct mci_command output; | ||||
| }; | ||||
|  | ||||
| void strim(char *s) | ||||
| { | ||||
| 	int l = strlen(s); | ||||
|  | ||||
| 	while (l && isspace(s[l-1])) | ||||
| 		l--; | ||||
| 	s[l] = 0; | ||||
| } | ||||
|  | ||||
| void parse(char *fname, char *sec, void *priv, void (*cb)(void *, char *, char *)) | ||||
| { | ||||
| 	char line[256], csec[80], par[80], val[80], *p; | ||||
| 	FILE *f; | ||||
|  | ||||
| 	if ((f = fopen(fname, "r")) == NULL) | ||||
| 		return; | ||||
| 	while ((p = fgets(line, sizeof(line), f))) { | ||||
| 		if (*p == '\r' || *p == '\n' || *p == '#') | ||||
| 			continue; | ||||
| 		if (*p == '[') { | ||||
| 			if ((p = strtok(line + 1, "]")) == NULL) | ||||
| 				continue; | ||||
| 			strncpy(csec, p, sizeof(csec)); | ||||
| 			if (!strcmp(sec, csec) && cb) | ||||
| 				cb(priv, NULL, NULL); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if (!(p = strtok(line, "="))) | ||||
| 			continue; | ||||
| 		while (isspace(*p)) | ||||
| 			p++; | ||||
| 		strncpy(par, p, sizeof(par)); | ||||
| 		strim(par); | ||||
| 		if (!(p = strtok(NULL, "="))) | ||||
| 			continue; | ||||
| 		while (isspace(*p)) | ||||
| 			p++; | ||||
| 		strncpy (val, p, sizeof(val)); | ||||
| 		strim(val); | ||||
| 		if (!strcmp(sec, csec) && cb) | ||||
| 			cb(priv, par, val); | ||||
| 	} | ||||
| 	if (!strcmp(sec, csec) && cb) | ||||
| 		cb(priv, NULL, NULL); | ||||
| 	fclose(f); | ||||
| } | ||||
|  | ||||
| int mci_cmd(int dev, struct mci_command *cmd) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct ddb_mci_msg msg; | ||||
|  | ||||
| 	msg.link = 0; | ||||
| 	memcpy(&msg.cmd, cmd, sizeof(msg.cmd)); | ||||
| 	ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg); | ||||
| 	if (ret < 0) { | ||||
| 		printf("mci_cmd error %d\n", errno); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| struct mci_command msg_channels = { | ||||
| 	.mod_command = MOD_SETUP_CHANNELS,	 | ||||
| 	.mod_channel = 0, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_channels[0] = { | ||||
| 		.flags = MOD_SETUP_FLAG_FIRST|MOD_SETUP_FLAG_LAST|MOD_SETUP_FLAG_VALID, | ||||
| 		.standard = MOD_STANDARD_DVBT_8, | ||||
| 		.num_channels = 25, | ||||
| 		.frequency = 474000000, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| struct mci_command msg_stream = { | ||||
| 	.mod_command = MOD_SETUP_STREAM,	 | ||||
| 	.mod_channel = 1, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_stream = { | ||||
| 		.standard = MOD_STANDARD_DVBT_8, | ||||
| 		.fft_size = 1, | ||||
| 		.guard_interval = 0, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| struct mci_command msg_output = { | ||||
| 	.mod_command = MOD_SETUP_OUTPUT, | ||||
| 	.mod_channel = 0, | ||||
| 	.mod_stream = 0, | ||||
| 	.mod_setup_output = { | ||||
| 		.connector = MOD_CONNECTOR_F, | ||||
| 		.num_channels = 16, | ||||
| 		.unit = MOD_UNIT_DBUV, | ||||
| 		.channel_power = 5000, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| void output_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		mc->set_output = 1; | ||||
| 		return; | ||||
| 	}		 | ||||
| 	if (!strcasecmp(par, "connector")) { | ||||
| 		if (!strcasecmp(val, "F")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_F; | ||||
| 		} else if (!strcasecmp(val, "SMA")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_SMA; | ||||
| 		} else if (!strcasecmp(val, "OFF")) { | ||||
| 			mc->output.mod_setup_output.connector = MOD_CONNECTOR_OFF; | ||||
| 		} else | ||||
| 			printf("invalid connector\n"); | ||||
| 	} else if (!strcasecmp(par, "power")) { | ||||
| 		mc->output.mod_setup_output.channel_power = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "channels")) { | ||||
| 		mc->output.mod_setup_output.num_channels = strtol(val, NULL, 10); | ||||
| 	}else if (!strcasecmp(par, "unit")) { | ||||
| 		if (!strcasecmp(val, "DBUV")) { | ||||
| 			mc->output.mod_setup_output.unit = MOD_UNIT_DBUV; | ||||
| 		} else if (!strcasecmp(val, "DBM")) { | ||||
| 			mc->output.mod_setup_output.unit = MOD_UNIT_DBM; | ||||
| 		} else | ||||
| 			printf("invalid unit\n"); | ||||
| 	} else | ||||
| 		printf("invalid output parameter: %s\n", par); | ||||
| } | ||||
|  | ||||
| void channels_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		mc->set_channels = 1; | ||||
| 		return; | ||||
| 	}		 | ||||
| 	if (!strcasecmp(par, "frequency")) { | ||||
| 		mc->channels.mod_setup_channels[0].frequency = strtol(val, NULL, 10); | ||||
| 		printf("frequency = %u\n", mc->channels.mod_setup_channels[0].frequency); | ||||
| 	} else if (!strcasecmp(par, "channels")) { | ||||
| 		mc->channels.mod_setup_channels[0].num_channels = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "standard")) { | ||||
| 		mc->channels.mod_setup_channels[0].standard = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "offset")) { | ||||
| 		mc->channels.mod_setup_channels[0].offset = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "bandwidth")) { | ||||
| 		mc->channels.mod_setup_channels[0].bandwidth = strtol(val, NULL, 10); | ||||
| 		mc->channels.mod_setup_channels[0].offset = | ||||
| 			mc->channels.mod_setup_channels[0].bandwidth / 2; | ||||
| 	} else | ||||
| 		printf("invalid channels parameter: %s\n", par); | ||||
| } | ||||
|  | ||||
| void streams_cb(void *priv, char *par, char *val) | ||||
| { | ||||
| 	struct mconf *mc = (struct mconf *) priv; | ||||
|  | ||||
| 	if (!par && !val) { | ||||
| 		return; | ||||
| 	}		 | ||||
| 	if (!strcasecmp(par, "fft_size")) { | ||||
| 		mc->stream.mod_setup_stream.fft_size = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "guard_interval")) { | ||||
| 		mc->stream.mod_setup_stream.guard_interval = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "standard")) { | ||||
| 		mc->stream.mod_setup_stream.standard = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "stream_format")) { | ||||
| 		mc->stream.mod_setup_stream.stream_format = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "symbol_rate")) { | ||||
| 		mc->stream.mod_setup_stream.symbol_rate = strtol(val, NULL, 10); | ||||
| 	} else if (!strcasecmp(par, "stream")) { | ||||
| 		mc->stream.mod_stream = strtol(val, NULL, 10); | ||||
| 		printf("set stream %u to channel %u\n", mc->stream.mod_stream, mc->stream.mod_channel); | ||||
| 		mci_cmd(mc->fd, &mc->stream); | ||||
| 	} else if (!strcasecmp(par, "channel")) { | ||||
| 		mc->stream.mod_channel = strtol(val, NULL, 10); | ||||
| 	} else | ||||
| 		printf("invalid streams parameter: %s\n", par); | ||||
| } | ||||
|  | ||||
| int main(int argc, char*argv[]) | ||||
| { | ||||
| 	int fd = -1; | ||||
| 	char fn[128]; | ||||
| 	uint32_t device = 0; | ||||
| 	uint32_t frequency = 0; | ||||
| 	char *configname = "modulator.conf"; | ||||
| 	struct mconf mc; | ||||
|  | ||||
| 	memset(&mc, 0, sizeof(mc)); | ||||
| 	mc.channels = msg_channels; | ||||
| 	mc.stream = msg_stream; | ||||
| 	mc.output = msg_output; | ||||
| 	 | ||||
| 	while (1) { | ||||
| 		int cur_optind = optind ? optind : 1; | ||||
| 		int option_index = 0; | ||||
| 		int c; | ||||
| 		static struct option long_options[] = { | ||||
| 			{"device", required_argument, 0, 'd'}, | ||||
| 			{"config", required_argument, 0, 'c'}, | ||||
| 			{0, 0, 0, 0} | ||||
| 		}; | ||||
|                 c = getopt_long(argc, argv, "d:c:", | ||||
| 				long_options, &option_index); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
| 		switch (c) { | ||||
| 		case 'd': | ||||
| 			device = strtoul(optarg, NULL, 0); | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			configname = optarg; | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) { | ||||
| 		printf("too many arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	snprintf(fn, 127, "/dev/ddbridge/card%u", device); | ||||
| 	fd = open(fn, O_RDWR); | ||||
| 	if (fd < 0) | ||||
| 		return -1; | ||||
| 	mc.fd = fd; | ||||
| 	parse(configname, "output", (void *) &mc, output_cb); | ||||
| 	if (mc.set_output) | ||||
| 		mci_cmd(fd, &mc.output); | ||||
| 	parse(configname, "channels", (void *) &mc, channels_cb); | ||||
| 	if (mc.set_channels) | ||||
| 		mci_cmd(fd, &mc.channels); | ||||
| 	parse(configname, "streams", (void *) &mc, streams_cb); | ||||
| } | ||||
| @@ -185,6 +185,60 @@ | ||||
|  | ||||
| #define MCI_SUCCESS(status)     ((status & MCI_STATUS_UNSUPPORTED) == 0) | ||||
|  | ||||
| /********************************************************/ | ||||
|  | ||||
| #define MOD_SETUP_CHANNELS      (0x60) | ||||
| #define MOD_SETUP_OUTPUT        (0x61) | ||||
| #define MOD_SETUP_STREAM        (0x62) | ||||
|  | ||||
| #define MOD_SETUP_FLAG_FIRST    (0x01) | ||||
| #define MOD_SETUP_FLAG_LAST     (0x02) | ||||
| #define MOD_SETUP_FLAG_VALID    (0x80) | ||||
|  | ||||
| #define MOD_STANDARD_GENERIC    (0x00) | ||||
| #define MOD_STANDARD_DVBT_8     (0x01) | ||||
| #define MOD_STANDARD_DVBT_7     (0x02) | ||||
| #define MOD_STANDARD_DVBT_6     (0x03) | ||||
|  | ||||
| #define MOD_CONNECTOR_OFF       (0x00) | ||||
| #define MOD_CONNECTOR_F         (0x01) | ||||
| #define MOD_CONNECTOR_SMA       (0x02) | ||||
|  | ||||
| #define MOD_UNIT_DBUV           (0x00) | ||||
| #define MOD_UNIT_DBM            (0x01) | ||||
|  | ||||
| #define MOD_FORMAT_DEFAULT      (0x00) | ||||
| #define MOD_FORMAT_IQ16         (0x01) | ||||
| #define MOD_FORMAT_IQ8          (0x02) | ||||
| #define MOD_FORMAT_IDX8         (0x03) | ||||
| #define MOD_FORMAT_TS           (0x04) | ||||
|  | ||||
| struct mod_setup_channels { | ||||
| 	u8   flags; | ||||
| 	u8   standard; | ||||
| 	u8   num_channels; | ||||
| 	u8   rsvd; | ||||
| 	u32  frequency; | ||||
| 	u32  offset;            /* used only when Standard == 0 */ | ||||
| 	u32  bandwidth;         /* used only when Standard == 0 */    | ||||
| }; | ||||
|  | ||||
| struct mod_setup_stream { | ||||
| 	u8   standard; | ||||
| 	u8   stream_format; | ||||
| 	u8   rsvd[2]; | ||||
| 	u32  symbol_rate;        /* only used when Standard doesn't define a fixed symbol rate */ | ||||
| 	u8   fft_size;           /* 0 = 2K, 1 = 8K  (2K yet supported) */ | ||||
| 	u8   guard_interval;     /* 0 = 1/32, 1 = 1/16, 2 = 1/8, 3 = 1/4  (DVB-T Encoding) */ | ||||
| }; | ||||
|  | ||||
| struct mod_setup_output { | ||||
| 	u8   connector;         /* 0 = OFF, 1 = F, 2 = SMA */  | ||||
| 	u8   num_channels;      /* max active channels, determines max power for each channel. */ | ||||
| 	u8   unit;              /* 0 = dBµV, 1 = dBm, */ | ||||
| 	u8   rsvd; | ||||
| 	s16  channel_power; | ||||
| }; | ||||
|  | ||||
| /********************************************************/ | ||||
|  | ||||
| @@ -197,6 +251,12 @@ struct mci_command { | ||||
| 			u8 demod; | ||||
| 			u8 output; | ||||
| 		}; | ||||
| 		struct { | ||||
| 			u8 mod_command; | ||||
| 			u8 mod_channel; | ||||
| 			u8 mod_stream; | ||||
| 			u8 mod_rsvd1; | ||||
| 		}; | ||||
| 	}; | ||||
| 	union { | ||||
| 		u32 params[31]; | ||||
| @@ -344,6 +404,10 @@ struct mci_command { | ||||
| 		struct { | ||||
| 			u8   select;        // 0 = Data PLP, 1 = Common PLP, only DVB-T2 and DVB-C2 | ||||
| 		} get_bb_header; | ||||
|  | ||||
| 		struct mod_setup_channels mod_setup_channels[4]; | ||||
| 		struct mod_setup_stream mod_setup_stream; | ||||
| 		struct mod_setup_output mod_setup_output; | ||||
| 	}; | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user