diff options
Diffstat (limited to 'v4l2-apps/util/v4l2-dbg.cpp')
-rw-r--r-- | v4l2-apps/util/v4l2-dbg.cpp | 301 |
1 files changed, 187 insertions, 114 deletions
diff --git a/v4l2-apps/util/v4l2-dbg.cpp b/v4l2-apps/util/v4l2-dbg.cpp index e0d6153fe..f427d4442 100644 --- a/v4l2-apps/util/v4l2-dbg.cpp +++ b/v4l2-apps/util/v4l2-dbg.cpp @@ -45,6 +45,8 @@ #include "v4l2-dbg-bttv.h" #include "v4l2-dbg-saa7134.h" #include "v4l2-dbg-em28xx.h" +#include "v4l2-dbg-ac97.h" +#include "v4l2-dbg-tvp5150.h" #define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0]))) @@ -58,6 +60,15 @@ struct board_list { }; static const struct board_list boards[] = { +#define AC97_BOARD 0 + { /* From ac97-dbg.h */ + AC97_IDENT, + sizeof(AC97_PREFIX) - 1, + ac97_regs, + ARRAY_SIZE(ac97_regs), + NULL, + 0, + }, { /* From bttv-dbg.h */ BTTV_IDENT, sizeof(BTTV_PREFIX) - 1, @@ -79,18 +90,19 @@ static const struct board_list boards[] = { sizeof(EM28XX_PREFIX) - 1, em28xx_regs, ARRAY_SIZE(em28xx_regs), + em28xx_alt_regs, + ARRAY_SIZE(em28xx_alt_regs), + }, + { /* From tvp5150-dbg.h */ + TVP5150_IDENT, + sizeof(TVP5150_PREFIX) - 1, + tvp5150_regs, + ARRAY_SIZE(tvp5150_regs), NULL, 0, }, }; -struct driverid { - const char *name; - unsigned id; -}; - -extern struct driverid driverids[]; - struct chipid { const char *name; unsigned id; @@ -119,7 +131,6 @@ enum Option { OptLogStatus = 128, OptVerbose, - OptListDriverIDs, OptListSymbols, OptLast = 256 }; @@ -136,11 +147,10 @@ static struct option long_options[] = { {"set-register", required_argument, 0, OptSetRegister}, {"chip", required_argument, 0, OptChip}, {"scan-chip-idents", no_argument, 0, OptScanChipIdents}, - {"get-chip-ident", required_argument, 0, OptGetChipIdent}, + {"get-chip-ident", no_argument, 0, OptGetChipIdent}, {"info", no_argument, 0, OptGetDriverInfo}, {"verbose", no_argument, 0, OptVerbose}, {"log-status", no_argument, 0, OptLogStatus}, - {"list-driverids", no_argument, 0, OptListDriverIDs}, {"list-symbols", no_argument, 0, OptListSymbols}, {"wide", required_argument, 0, OptSetStride}, {0, 0, 0, 0} @@ -156,8 +166,9 @@ static void usage(void) " --verbose Turn on verbose ioctl error reporting\n" " -c, --chip=<chip> The chip identifier to use with other commands\n" " It can be one of:\n" - " I2C driver ID (see --list-driverids)\n" + " I2C driver name\n" " I2C 7-bit address\n" + " AC97: for ac97 anciliary mixer\n" " host<num>: host chip number <num>\n" " host (default): same as host0\n" " -l, --list-registers[=min=<addr>[,max=<addr>]]\n" @@ -168,25 +179,16 @@ static void usage(void) " Set the register with the commandline arguments\n" " The register will autoincrement [VIDIOC_DBG_S_REGISTER]\n" " -S, --scan-chip-idents\n" - " Scan the available host and i2c chips [VIDIOC_G_CHIP_IDENT]\n" + " Scan the available host and i2c chips [VIDIOC_DBG_G_CHIP_IDENT]\n" " -i, --get-chip-ident\n" - " Get the chip identifier [VIDIOC_G_CHIP_IDENT]\n" + " Get the chip identifier [VIDIOC_DBG_G_CHIP_IDENT]\n" " -w, --wide=<reg length>\n" " Sets step between two registers\n" " --list-symbols List the symbolic register names you can use, if any\n" - " --log-status Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n" - " --list-driverids List the known I2C driver IDs for use with the i2cdrv type\n"); + " --log-status Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n"); exit(0); } -static unsigned parse_chip(const std::string &s) -{ - for (int i = 0; driverids[i].name; i++) - if (!strcasecmp(s.c_str(), driverids[i].name)) - return driverids[i].id; - return 0; -} - static std::string cap2s(unsigned cap) { std::string s; @@ -224,7 +226,7 @@ static std::string cap2s(unsigned cap) return s; } -static void print_regs(int fd, struct v4l2_register *reg, unsigned long min, unsigned long max, int stride) +static void print_regs(int fd, struct v4l2_dbg_register *reg, unsigned long min, unsigned long max, int stride) { unsigned long mask = stride > 1 ? 0x1f : 0x0f; unsigned long i; @@ -258,7 +260,7 @@ static void print_regs(int fd, struct v4l2_register *reg, unsigned long min, uns printf("\n"); } -static void print_chip(struct v4l2_chip_ident *chip) +static void print_chip(struct v4l2_dbg_chip_ident *chip) { const char *name = NULL; @@ -293,6 +295,21 @@ static unsigned long long parse_reg(const struct board_list *curr_bd, const std: return strtoull(reg.c_str(), NULL, 0); } +static const char *reg_name(const struct board_list *curr_bd, unsigned long long reg) +{ + if (curr_bd) { + for (int i = 0; i < curr_bd->regs_size; i++) { + if (reg == curr_bd->regs[i].reg) + return curr_bd->regs[i].name; + } + for (int i = 0; i < curr_bd->alt_regs_size; i++) { + if (reg == curr_bd->regs[i].reg) + return curr_bd->regs[i].name; + } + } + return NULL; +} + static const char *binary(unsigned long long val) { static char bin[80]; @@ -368,9 +385,9 @@ int main(int argc, char **argv) int ch; const char *device = "/dev/video0"; /* -d device */ struct v4l2_capability vcap; /* list_cap */ - struct v4l2_register set_reg; - struct v4l2_register get_reg; - struct v4l2_chip_ident chip_id; + 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; @@ -378,9 +395,10 @@ int main(int argc, char **argv) std::string reg_set_arg; unsigned long long reg_min = 0, reg_max = 0; std::vector<std::string> get_regs; - int match_type = V4L2_CHIP_MATCH_HOST; - int match_chip = 0; + 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)); @@ -424,21 +442,23 @@ int main(int argc, char **argv) case OptChip: if (isdigit(optarg[0])) { - match_type = V4L2_CHIP_MATCH_I2C_ADDR; - match_chip = strtoul(optarg, NULL, 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_chip = strtoul(optarg + 4, NULL, 0); + match.type = V4L2_CHIP_MATCH_HOST; + match.addr = strtoul(optarg + 4, NULL, 0); break; } - match_type = V4L2_CHIP_MATCH_I2C_DRIVER; - match_chip = parse_chip(optarg); - if (!match_chip) { - fprintf(stderr, "unknown driver ID %s\n", optarg); - exit(-1); + 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: @@ -457,6 +477,7 @@ int main(int argc, char **argv) subs = optarg; if (subs == NULL) break; + while (*subs != '\0') { static const char * const subopts[] = { "min", @@ -516,53 +537,75 @@ int main(int argc, char **argv) printf("%s", cap2s(vcap.capabilities).c_str()); } - for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) { - if (!strcasecmp((char *)vcap.driver, boards[board].name)) { - curr_bd = &boards[board]; - break; + 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_type = match_type; - set_reg.match_chip = match_chip; + 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) - printf("register 0x%llx set to 0x%llx\n", set_reg.reg, set_reg.val); + "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\n", + set_reg.reg, set_reg.val); + } set_reg.reg++; } } if (options[OptGetChipIdent]) { - chip_id.match_type = match_type; - chip_id.match_chip = match_chip; - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0) + 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_chip = 0; + chip_id.match.type = V4L2_CHIP_MATCH_HOST; + chip_id.match.addr = 0; - while (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) { - printf("host%d: ", chip_id.match_chip); + 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_chip++; + chip_id.match.addr++; } - chip_id.match_type = V4L2_CHIP_MATCH_I2C_ADDR; + chip_id.match.type = V4L2_CHIP_MATCH_I2C_ADDR; for (i = 0; i < 128; i++) { - chip_id.match_chip = i; - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") == 0 && chip_id.ident) { + 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); } @@ -572,8 +615,7 @@ int main(int argc, char **argv) if (options[OptGetRegister]) { int stride = 1; - get_reg.match_type = match_type; - get_reg.match_chip = match_chip; + get_reg.match = match; printf("ioctl: VIDIOC_DBG_G_REGISTER\n"); for (std::vector<std::string>::iterator iter = get_regs.begin(); @@ -582,25 +624,71 @@ int main(int argc, char **argv) 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 - printf("%llx = %llxh = %lldd = %sb\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_type = match_type; - get_reg.match_chip = match_chip; + get_reg.match = match; if (forcedstride) { stride = forcedstride; - } else { - if (get_reg.match_type == V4L2_CHIP_MATCH_HOST) - stride = 4; + } 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 = 1<<31 - 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()) @@ -611,57 +699,48 @@ int main(int argc, char **argv) print_regs(fd, &get_reg, reg_min, reg_max, stride); goto list_done; } - /* try to match the i2c chip */ - switch (get_reg.match_chip) { - case I2C_DRIVERID_SAA711X: - print_regs(fd, &get_reg, 0, 0xff, stride); + + /* 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; + default: + if (get_reg.match.type == V4L2_CHIP_MATCH_I2C_DRIVER) + name = get_reg.match.name; break; - case I2C_DRIVERID_SAA717X: + } + + 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); - break; - case I2C_DRIVERID_SAA7127: + } else if (name == "saa7127") { print_regs(fd, &get_reg, 0, 0x7f, stride); - break; - case I2C_DRIVERID_CX25840: + } 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); - break; - case I2C_DRIVERID_CS5345: + } else if (name == "cs5345") { print_regs(fd, &get_reg, 1, 0x10, stride); - break; - case 0: - /* host chip, handle later */ - break; - default: - /* unknown i2c chip, dump 0-0xff by default */ - print_regs(fd, &get_reg, 0, 0xff, stride); - break; - } - if (get_reg.match_chip != 0) { - /* found i2c chip, we're done */ - goto list_done; - } - /* try to figure out which host chip it is */ - if (doioctl(fd, VIDIOC_G_CHIP_IDENT, &chip_id, "VIDIOC_G_CHIP_IDENT") != 0) { - chip_id.ident = V4L2_IDENT_NONE; - } - - switch (chip_id.ident) { - case V4L2_IDENT_CX23415: - case V4L2_IDENT_CX23416: + } else if (name == "cx23416") { print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride); - break; - case V4L2_IDENT_CX23418: + } else if (name == "cx23418") { print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride); - break; - default: - /* By default print range 0-0xff */ + } else { + /* unknown chip, dump 0-0xff by default */ print_regs(fd, &get_reg, 0, 0xff, stride); - break; } } list_done: @@ -693,22 +772,16 @@ list_done: } } - if (options[OptListDriverIDs]) { - printf("Known I2C driver IDs:\n"); - for (int i = 0; driverids[i].name; i++) - printf("%s\n", driverids[i].name); - } - if (options[OptListSymbols]) { if (curr_bd == NULL) { printf("No symbols found for driver %s\n", vcap.driver); } else { - printf("Symbols for driver %s:\n", vcap.driver); + 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], curr_bd->regs[i].name); + 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], curr_bd->alt_regs[i].name); + printf("0x%08x: %s\n", curr_bd->alt_regs[i].reg, curr_bd->alt_regs[i].name); } } |