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"); }
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); }