Exemplo n.º 1
0
static void do_a_print(const sensors_chip_name *name)
{
    printf("%s\n", sprintf_chip_name(name));
    if (!hide_adapter) {
        const char *adap = sensors_get_adapter_name(&name->bus);
        if (adap)
            printf("Adapter: %s\n", adap);
        else
            fprintf(stderr, "Can't get adapter name\n");
    }
    if (do_raw)
        print_chip_raw(name);
    else
        print_chip(name);
    printf("\n");
}
Exemplo n.º 2
0
int main(int argc, char **argv)
{
	char *value, *subs;
	int i, forcedstride = 0;

	int fd = -1;

	/* command args */
	int ch;
	const char *device = "/dev/video0";	/* -d device */
	struct v4l2_capability vcap;	/* list_cap */
	struct v4l2_dbg_register set_reg;
	struct v4l2_dbg_register get_reg;
	struct v4l2_dbg_chip_ident chip_id;
	const struct board_list *curr_bd = NULL;
	char short_options[26 * 2 * 2 + 1];
	int idx = 0;
	std::string reg_min_arg, reg_max_arg;
	std::string reg_set_arg;
	unsigned long long reg_min = 0, reg_max = 0;
	std::vector<std::string> get_regs;
	struct v4l2_dbg_match match;

	match.type = V4L2_CHIP_MATCH_HOST;
	match.addr = 0;
	memset(&set_reg, 0, sizeof(set_reg));
	memset(&get_reg, 0, sizeof(get_reg));
	memset(&chip_id, 0, sizeof(chip_id));

	if (argc == 1) {
		usage();
		return 0;
	}
	for (i = 0; long_options[i].name; i++) {
		if (!isalpha(long_options[i].val))
			continue;
		short_options[idx++] = long_options[i].val;
		if (long_options[i].has_arg == required_argument)
			short_options[idx++] = ':';
	}
	while (1) {
		int option_index = 0;

		short_options[idx] = 0;
		ch = getopt_long(argc, argv, short_options,
				 long_options, &option_index);
		if (ch == -1)
			break;

		options[(int)ch] = 1;
		switch (ch) {
		case OptHelp:
			usage();
			return 0;

		case OptSetDevice:
			device = optarg;
			if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
				static char newdev[20];
				char dev = device[0];

				sprintf(newdev, "/dev/video%c", dev);
				device = newdev;
			}
			break;

		case OptChip:
			if (isdigit(optarg[0])) {
				match.type = V4L2_CHIP_MATCH_I2C_ADDR;
				match.addr = strtoul(optarg, NULL, 0);
				break;
			}
			if (!memcmp(optarg, "host", 4)) {
				match.type = V4L2_CHIP_MATCH_HOST;
				match.addr = strtoul(optarg + 4, NULL, 0);
				break;
			}
			if (!strcasecmp(optarg, "ac97")) {
				match.type = V4L2_CHIP_MATCH_AC97;
				match.addr = 0;
				break;
			}
			match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
			strncpy(match.name, optarg, sizeof(match.name));
			match.name[sizeof(match.name) - 1] = '\0';
			break;

		case OptSetRegister:
			reg_set_arg = optarg;
			break;

		case OptGetRegister:
			get_regs.push_back(optarg);
			break;

		case OptSetStride:
			forcedstride = strtoull(optarg, 0L, 0);
			break;

		case OptListRegisters:
			subs = optarg;
			if (subs == NULL)
				break;

			while (*subs != '\0') {
				static const char * const subopts[] = {
					"min",
					"max",
					NULL
				};

				switch (parse_subopt(&subs, subopts, &value)) {
				case 0:
					reg_min_arg = value;
					//if (reg_max == 0)
					//	reg_max = reg_min + 0xff;
					break;
				case 1:
					reg_max_arg = value;
					break;
				}
			}
			break;

		case OptGetChipIdent:
		case OptListSymbols:
			break;

		case ':':
			fprintf(stderr, "Option `%s' requires a value\n",
				argv[optind]);
			usage();
			return 1;

		case '?':
			fprintf(stderr, "Unknown argument `%s'\n",
				argv[optind]);
			usage();
			return 1;
		}
	}

	if ((fd = open(device, O_RDWR)) < 0) {
		fprintf(stderr, "Failed to open %s: %s\n", device,
			strerror(errno));
		exit(1);
	}

	doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
	capabilities = vcap.capabilities;

	/* Information Opts */

	if (options[OptGetDriverInfo]) {
		printf("Driver info:\n");
		printf("\tDriver name   : %s\n", vcap.driver);
		printf("\tCard type     : %s\n", vcap.card);
		printf("\tBus info      : %s\n", vcap.bus_info);
		printf("\tDriver version: %d.%d.%d\n",
				vcap.version >> 16,
				(vcap.version >> 8) & 0xff,
				vcap.version & 0xff);
		printf("\tCapabilities  : 0x%08X\n", vcap.capabilities);
		printf("%s", cap2s(vcap.capabilities).c_str());
	}

	if (match.type == V4L2_CHIP_MATCH_AC97) {
		curr_bd = &boards[AC97_BOARD];
	} else if (match.type == V4L2_CHIP_MATCH_HOST) {
		for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
			if (!strcasecmp((char *)vcap.driver, boards[board].name)) {
				curr_bd = &boards[board];
				break;
			}
		}
	} else if (match.type == V4L2_CHIP_MATCH_I2C_DRIVER) {
		for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
			if (!strcasecmp(match.name, boards[board].name)) {
				curr_bd = &boards[board];
				break;
			}
		}
	}

	/* Set options */

	if (options[OptSetRegister]) {
		set_reg.match = match;
		if (optind >= argc)
			usage();
		set_reg.reg = parse_reg(curr_bd, reg_set_arg);
		while (optind < argc) {
			set_reg.val = strtoull(argv[optind++], NULL, 0);
			if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
						"VIDIOC_DBG_S_REGISTER") >= 0) {
				const char *name = reg_name(curr_bd, set_reg.reg);

				printf("Register ");

				if (name)
					printf("%s (0x%08llx)", name, set_reg.reg);
				else
					printf("0x%08llx", set_reg.reg);

				printf(" set to 0x%llx\n", set_reg.val);
			} else {
				printf("Failed to set register 0x%08llx value 0x%llx: %s\n",
					set_reg.reg, set_reg.val, strerror(errno));
			}
			set_reg.reg++;
		}
	}

	if (options[OptGetChipIdent]) {
		chip_id.match = match;
		if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0)
			print_chip(&chip_id);
	}

	if (options[OptScanChipIdents]) {
		int i;

		chip_id.match.type = V4L2_CHIP_MATCH_HOST;
		chip_id.match.addr = 0;

		while (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) {
			printf("host%d: ", chip_id.match.addr);
			print_chip(&chip_id);
			chip_id.match.addr++;
		}

		chip_id.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
		for (i = 0; i < 128; i++) {
			chip_id.match.addr = i;
			if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) {
				printf("i2c 0x%02x: ", i);
				print_chip(&chip_id);
			}
		}
	}

	if (options[OptGetRegister]) {
		get_reg.match = match;
		printf("ioctl: VIDIOC_DBG_G_REGISTER\n");

		for (std::vector<std::string>::iterator iter = get_regs.begin();
				iter != get_regs.end(); ++iter) {
			get_reg.reg = parse_reg(curr_bd, *iter);
			if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
				fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
						"failed for 0x%llx\n", get_reg.reg);
			else {
				const char *name = reg_name(curr_bd, get_reg.reg);

				printf("Register ");

				if (name)
					printf("%s (0x%08llx)", name, get_reg.reg);
				else
					printf("0x%08llx", get_reg.reg);

				printf(" = %llxh (%lldd  %sb)\n",
					get_reg.val, get_reg.val, binary(get_reg.val));
			}
		}
	}

	if (options[OptListRegisters]) {
		std::string name;
		int stride = 1;

		get_reg.match = match;
		if (forcedstride) {
			stride = forcedstride;
		} else if (get_reg.match.type == V4L2_CHIP_MATCH_HOST) {
			stride = 4;
		}
		printf("ioctl: VIDIOC_DBG_G_REGISTER\n");

		if (curr_bd) {
			if (reg_min_arg.empty())
				reg_min = 0;
			else
				reg_min = parse_reg(curr_bd, reg_min_arg);


			if (reg_max_arg.empty())
				reg_max = (1ll << 32) - 1;
			else
				reg_max = parse_reg(curr_bd, reg_max_arg);

			for (int i = 0; i < curr_bd->regs_size; i++) {
				if (reg_min_arg.empty() || ((curr_bd->regs[i].reg >= reg_min) && curr_bd->regs[i].reg <= reg_max)) {
					get_reg.reg = curr_bd->regs[i].reg;

					if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
						fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
								"failed for 0x%llx\n", get_reg.reg);
					else {
						const char *name = reg_name(curr_bd, get_reg.reg);

						printf("Register ");

						if (name)
							printf("%s (0x%08llx)", name, get_reg.reg);
						else
							printf("0x%08llx", get_reg.reg);

						printf(" = %llxh (%lldd  %sb)\n",
							get_reg.val, get_reg.val, binary(get_reg.val));
					}
				}
			}
			goto list_done;
		}

		if (!reg_min_arg.empty()) {
			reg_min = parse_reg(curr_bd, reg_min_arg);
			if (reg_max_arg.empty())
				reg_max = reg_min + 0xff;
			else
				reg_max = parse_reg(curr_bd, reg_max_arg);
			/* Explicit memory range: just do it */
			print_regs(fd, &get_reg, reg_min, reg_max, stride);
			goto list_done;
		}

		/* try to figure out which chip it is */
		chip_id.match = match;
		if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") != 0) {
			chip_id.ident = V4L2_IDENT_NONE;
		}
		switch (chip_id.ident) {
		case V4L2_IDENT_CX23415:
		case V4L2_IDENT_CX23416:
			name = "cx23416";
			break;
		case V4L2_IDENT_CX23418:
			name = "cx23418";
			break;
		case V4L2_IDENT_CAFE:
			name = "cafe";
			break;
		default:
			if (get_reg.match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
				name = get_reg.match.name;
			break;
		}

		if (name == "saa7115") {
			print_regs(fd, &get_reg, 0, 0xff, stride);
		} else if (name == "saa717x") {
			// FIXME: use correct reg regions
			print_regs(fd, &get_reg, 0, 0xff, stride);
		} else if (name == "saa7127") {
			print_regs(fd, &get_reg, 0, 0x7f, stride);
		} else if (name == "ov7670") {
			print_regs(fd, &get_reg, 0, 0x89, stride);
		} else if (name == "cx25840") {
			print_regs(fd, &get_reg, 0, 2, stride);
			print_regs(fd, &get_reg, 0x100, 0x15f, stride);
			print_regs(fd, &get_reg, 0x200, 0x23f, stride);
			print_regs(fd, &get_reg, 0x400, 0x4bf, stride);
			print_regs(fd, &get_reg, 0x800, 0x9af, stride);
		} else if (name == "cs5345") {
			print_regs(fd, &get_reg, 1, 0x10, stride);
		} else if (name == "cx23416") {
			print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride);
		} else if (name == "cx23418") {
			print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride);
		} else if (name == "cafe") {
			print_regs(fd, &get_reg, 0, 0x43, stride);
			print_regs(fd, &get_reg, 0x88, 0x8f, stride);
			print_regs(fd, &get_reg, 0xb4, 0xbb, stride);
			print_regs(fd, &get_reg, 0x3000, 0x300c, stride);
		} else {
			/* unknown chip, dump 0-0xff by default */
			print_regs(fd, &get_reg, 0, 0xff, stride);
		}
	}
list_done:

	if (options[OptLogStatus]) {
		static char buf[40960];
		int len;

		if (doioctl(fd, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS") == 0) {
			printf("\nStatus Log:\n\n");
			len = klogctl(3, buf, sizeof(buf) - 1);
			if (len >= 0) {
				char *p = buf;
				char *q;

				buf[len] = 0;
				while ((q = strstr(p, "START STATUS CARD #"))) {
					p = q + 1;
				}
				if (p) {
					while (p > buf && *p != '<') p--;
					q = p;
					while ((q = strstr(q, "<6>"))) {
						memcpy(q, "   ", 3);
					}
					printf("%s", p);
				}
			}
		}
	}

	if (options[OptListSymbols]) {
		if (curr_bd == NULL) {
			printf("No symbols found for driver %s\n", vcap.driver);
		}
		else {
			printf("Symbols for driver %s:\n", curr_bd->name);
			for (int i = 0; i < curr_bd->regs_size; i++)
				printf("0x%08x: %s\n", curr_bd->regs[i].reg, curr_bd->regs[i].name);
			for (int i = 0; i < curr_bd->alt_regs_size; i++)
				printf("0x%08x: %s\n", curr_bd->alt_regs[i].reg, curr_bd->alt_regs[i].name);
		}
	}

	close(fd);
	exit(0);
}