~ubuntu-branches/ubuntu/precise/v4l-utils/precise

« back to all changes in this revision

Viewing changes to utils/v4l2-dbg/v4l2-dbg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gregor Jasny
  • Date: 2010-02-28 19:44:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100228194415-067hdj8rvawj91zw
Tags: upstream-0.7.90
ImportĀ upstreamĀ versionĀ 0.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
 */
 
18
 
 
19
#include <unistd.h>
 
20
#include <features.h>           /* Uses _GNU_SOURCE to define getsubopt in stdlib.h */
 
21
#include <stdlib.h>
 
22
#include <stdio.h>
 
23
#include <string.h>
 
24
#include <inttypes.h>
 
25
#include <getopt.h>
 
26
#include <sys/types.h>
 
27
#include <sys/stat.h>
 
28
#include <fcntl.h>
 
29
#include <ctype.h>
 
30
#include <errno.h>
 
31
#include <sys/ioctl.h>
 
32
#include <sys/time.h>
 
33
#include <math.h>
 
34
#include <sys/klog.h>
 
35
 
 
36
#include <linux/videodev2.h>
 
37
#include <linux/i2c-id.h>
 
38
#include <media/v4l2-chip-ident.h>
 
39
 
 
40
#include <list>
 
41
#include <vector>
 
42
#include <map>
 
43
#include <string>
 
44
 
 
45
#include "v4l2-dbg-bttv.h"
 
46
#include "v4l2-dbg-saa7134.h"
 
47
#include "v4l2-dbg-em28xx.h"
 
48
#include "v4l2-dbg-ac97.h"
 
49
#include "v4l2-dbg-tvp5150.h"
 
50
#include "v4l2-dbg-micron.h"
 
51
 
 
52
#define ARRAY_SIZE(arr) ((int)(sizeof(arr) / sizeof((arr)[0])))
 
53
 
 
54
struct board_list {
 
55
        const char *name;
 
56
        int prefix;             /* Register prefix size */
 
57
        const struct board_regs *regs;
 
58
        int regs_size;
 
59
        const struct board_regs *alt_regs;
 
60
        int alt_regs_size;
 
61
};
 
62
 
 
63
static const struct board_list boards[] = {
 
64
#define AC97_BOARD 0
 
65
        {                               /* From v4l2-dbg-ac97.h */
 
66
                AC97_IDENT,
 
67
                sizeof(AC97_PREFIX) - 1,
 
68
                ac97_regs,
 
69
                ARRAY_SIZE(ac97_regs),
 
70
                NULL,
 
71
                0,
 
72
        },
 
73
        {                               /* From v4l2-dbg-bttv.h */
 
74
                BTTV_IDENT,
 
75
                sizeof(BTTV_PREFIX) - 1,
 
76
                bt8xx_regs,
 
77
                ARRAY_SIZE(bt8xx_regs),
 
78
                bt8xx_regs_other,
 
79
                ARRAY_SIZE(bt8xx_regs_other),
 
80
        },
 
81
        {                               /* From v4l2-dbg-saa7134.h */
 
82
                SAA7134_IDENT,
 
83
                sizeof(SAA7134_PREFIX) - 1,
 
84
                saa7134_regs,
 
85
                ARRAY_SIZE(saa7134_regs),
 
86
                NULL,
 
87
                0,
 
88
        },
 
89
        {                               /* From v4l2-dbg-em28xx.h */
 
90
                EM28XX_IDENT,
 
91
                sizeof(EM28XX_PREFIX) - 1,
 
92
                em28xx_regs,
 
93
                ARRAY_SIZE(em28xx_regs),
 
94
                em28xx_alt_regs,
 
95
                ARRAY_SIZE(em28xx_alt_regs),
 
96
        },
 
97
        {                               /* From v4l2-dbg-tvp5150.h */
 
98
                TVP5150_IDENT,
 
99
                sizeof(TVP5150_PREFIX) - 1,
 
100
                tvp5150_regs,
 
101
                ARRAY_SIZE(tvp5150_regs),
 
102
                NULL,
 
103
                0,
 
104
        },
 
105
        {                               /* From v4l2-dbg-micron.h */
 
106
                MT9V011_IDENT,
 
107
                sizeof(MT9V011_PREFIX) - 1,
 
108
                mt9v011_regs,
 
109
                ARRAY_SIZE(mt9v011_regs),
 
110
                NULL,
 
111
                0,
 
112
        },
 
113
};
 
114
 
 
115
struct chipid {
 
116
        const char *name;
 
117
        unsigned id;
 
118
};
 
119
 
 
120
extern struct chipid chipids[];
 
121
 
 
122
/* Short option list
 
123
 
 
124
   Please keep in alphabetical order.
 
125
   That makes it easier to see which short options are still free.
 
126
 
 
127
   In general the lower case is used to set something and the upper
 
128
   case is used to retrieve a setting. */
 
129
enum Option {
 
130
        OptListRegisters = 'l',
 
131
        OptGetRegister = 'g',
 
132
        OptSetRegister = 's',
 
133
        OptSetDevice = 'd',
 
134
        OptGetDriverInfo = 'D',
 
135
        OptChip = 'c',
 
136
        OptScanChipIdents = 'S',
 
137
        OptGetChipIdent = 'i',
 
138
        OptSetStride = 'w',
 
139
        OptHelp = 'h',
 
140
 
 
141
        OptLogStatus = 128,
 
142
        OptVerbose,
 
143
        OptListSymbols,
 
144
        OptLast = 256
 
145
};
 
146
 
 
147
static char options[OptLast];
 
148
 
 
149
static unsigned capabilities;
 
150
 
 
151
static struct option long_options[] = {
 
152
        {"device", required_argument, 0, OptSetDevice},
 
153
        {"help", no_argument, 0, OptHelp},
 
154
        {"list-registers", optional_argument, 0, OptListRegisters},
 
155
        {"get-register", required_argument, 0, OptGetRegister},
 
156
        {"set-register", required_argument, 0, OptSetRegister},
 
157
        {"chip", required_argument, 0, OptChip},
 
158
        {"scan-chip-idents", no_argument, 0, OptScanChipIdents},
 
159
        {"get-chip-ident", no_argument, 0, OptGetChipIdent},
 
160
        {"info", no_argument, 0, OptGetDriverInfo},
 
161
        {"verbose", no_argument, 0, OptVerbose},
 
162
        {"log-status", no_argument, 0, OptLogStatus},
 
163
        {"list-symbols", no_argument, 0, OptListSymbols},
 
164
        {"wide", required_argument, 0, OptSetStride},
 
165
        {0, 0, 0, 0}
 
166
};
 
167
 
 
168
static void usage(void)
 
169
{
 
170
        printf("Usage: v4l2-dbg [options] [values]\n"
 
171
               "  -D, --info         Show driver info [VIDIOC_QUERYCAP]\n"
 
172
               "  -d, --device=<dev> Use device <dev> instead of /dev/video0\n"
 
173
               "                     If <dev> is a single digit, then /dev/video<dev> is used\n"
 
174
               "  -h, --help         Display this help message\n"
 
175
               "  --verbose          Turn on verbose ioctl error reporting\n"
 
176
               "  -c, --chip=<chip>  The chip identifier to use with other commands\n"
 
177
               "                     It can be one of:\n"
 
178
               "                         I2C driver name\n"
 
179
               "                         I2C 7-bit address\n"
 
180
               "                         AC97: for ac97 anciliary mixer\n"
 
181
               "                         host<num>: host chip number <num>\n"
 
182
               "                         host (default): same as host0\n"
 
183
               "  -l, --list-registers[=min=<addr>[,max=<addr>]]\n"
 
184
               "                     Dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]\n"
 
185
               "  -g, --get-register=<addr>\n"
 
186
               "                     Get the specified register [VIDIOC_DBG_G_REGISTER]\n"
 
187
               "  -s, --set-register=<addr>\n"
 
188
               "                     Set the register with the commandline arguments\n"
 
189
               "                     The register will autoincrement [VIDIOC_DBG_S_REGISTER]\n"
 
190
               "  -S, --scan-chip-idents\n"
 
191
               "                     Scan the available host and i2c chips [VIDIOC_DBG_G_CHIP_IDENT]\n"
 
192
               "  -i, --get-chip-ident\n"
 
193
               "                     Get the chip identifier [VIDIOC_DBG_G_CHIP_IDENT]\n"
 
194
               "  -w, --wide=<reg length>\n"
 
195
               "                     Sets step between two registers\n"
 
196
               "  --list-symbols     List the symbolic register names you can use, if any\n"
 
197
               "  --log-status       Log the board status in the kernel log [VIDIOC_LOG_STATUS]\n");
 
198
        exit(0);
 
199
}
 
200
 
 
201
static std::string cap2s(unsigned cap)
 
202
{
 
203
        std::string s;
 
204
 
 
205
        if (cap & V4L2_CAP_VIDEO_CAPTURE)
 
206
                s += "\t\tVideo Capture\n";
 
207
        if (cap & V4L2_CAP_VIDEO_OUTPUT)
 
208
                s += "\t\tVideo Output\n";
 
209
        if (cap & V4L2_CAP_VIDEO_OVERLAY)
 
210
                s += "\t\tVideo Overlay\n";
 
211
        if (cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
 
212
                s += "\t\tVideo Output Overlay\n";
 
213
        if (cap & V4L2_CAP_VBI_CAPTURE)
 
214
                s += "\t\tVBI Capture\n";
 
215
        if (cap & V4L2_CAP_VBI_OUTPUT)
 
216
                s += "\t\tVBI Output\n";
 
217
        if (cap & V4L2_CAP_SLICED_VBI_CAPTURE)
 
218
                s += "\t\tSliced VBI Capture\n";
 
219
        if (cap & V4L2_CAP_SLICED_VBI_OUTPUT)
 
220
                s += "\t\tSliced VBI Output\n";
 
221
        if (cap & V4L2_CAP_RDS_CAPTURE)
 
222
                s += "\t\tRDS Capture\n";
 
223
        if (cap & V4L2_CAP_TUNER)
 
224
                s += "\t\tTuner\n";
 
225
        if (cap & V4L2_CAP_AUDIO)
 
226
                s += "\t\tAudio\n";
 
227
        if (cap & V4L2_CAP_RADIO)
 
228
                s += "\t\tRadio\n";
 
229
        if (cap & V4L2_CAP_READWRITE)
 
230
                s += "\t\tRead/Write\n";
 
231
        if (cap & V4L2_CAP_ASYNCIO)
 
232
                s += "\t\tAsync I/O\n";
 
233
        if (cap & V4L2_CAP_STREAMING)
 
234
                s += "\t\tStreaming\n";
 
235
        return s;
 
236
}
 
237
 
 
238
static void print_regs(int fd, struct v4l2_dbg_register *reg, unsigned long min, unsigned long max, int stride)
 
239
{
 
240
        unsigned long mask = stride > 1 ? 0x1f : 0x0f;
 
241
        unsigned long i;
 
242
        int line = 0;
 
243
 
 
244
        for (i = min & ~mask; i <= max; i += stride) {
 
245
                if ((i & mask) == 0 && line % 32 == 0) {
 
246
                        if (stride == 4)
 
247
                                printf("\n                00       04       08       0C       10       14       18       1C");
 
248
                        else
 
249
                                printf("\n          00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
 
250
                }
 
251
 
 
252
                if ((i & mask) == 0) {
 
253
                        printf("\n%08lx: ", i);
 
254
                        line++;
 
255
                }
 
256
                if (i < min) {
 
257
                        printf("%*s ", 2 * stride, "");
 
258
                        continue;
 
259
                }
 
260
                reg->reg = i;
 
261
                if (ioctl(fd, VIDIOC_DBG_G_REGISTER, reg) < 0) {
 
262
                        fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
 
263
                                        "failed for 0x%llx\n", reg->reg);
 
264
                } else {
 
265
                        printf("%0*llx ", 2 * stride, reg->val);
 
266
                }
 
267
                usleep(1);
 
268
        }
 
269
        printf("\n");
 
270
}
 
271
 
 
272
static void print_chip(struct v4l2_dbg_chip_ident *chip)
 
273
{
 
274
        const char *name = NULL;
 
275
 
 
276
        for (int i = 0; chipids[i].name; i++) {
 
277
                if (chipids[i].id == chip->ident) {
 
278
                        name = chipids[i].name;
 
279
                        break;
 
280
                }
 
281
        }
 
282
        if (name)
 
283
                printf("%-10s revision 0x%08x\n", name, chip->revision);
 
284
        else
 
285
                printf("%-10d revision 0x%08x\n", chip->ident, chip->revision);
 
286
}
 
287
 
 
288
static unsigned long long parse_reg(const struct board_list *curr_bd, const std::string &reg)
 
289
{
 
290
        if (curr_bd) {
 
291
                for (int i = 0; i < curr_bd->regs_size; i++) {
 
292
                        if (!strcasecmp(reg.c_str(), curr_bd->regs[i].name) ||
 
293
                            !strcasecmp(reg.c_str(), curr_bd->regs[i].name + curr_bd->prefix)) {
 
294
                                return curr_bd->regs[i].reg;
 
295
                        }
 
296
                }
 
297
                for (int i = 0; i < curr_bd->alt_regs_size; i++) {
 
298
                        if (!strcasecmp(reg.c_str(), curr_bd->alt_regs[i].name) ||
 
299
                            !strcasecmp(reg.c_str(), curr_bd->alt_regs[i].name + curr_bd->prefix)) {
 
300
                                return curr_bd->alt_regs[i].reg;
 
301
                        }
 
302
                }
 
303
        }
 
304
        return strtoull(reg.c_str(), NULL, 0);
 
305
}
 
306
 
 
307
static const char *reg_name(const struct board_list *curr_bd, unsigned long long reg)
 
308
{
 
309
        if (curr_bd) {
 
310
                for (int i = 0; i < curr_bd->regs_size; i++) {
 
311
                        if (reg == curr_bd->regs[i].reg)
 
312
                                return curr_bd->regs[i].name;
 
313
                }
 
314
                for (int i = 0; i < curr_bd->alt_regs_size; i++) {
 
315
                        if (reg == curr_bd->regs[i].reg)
 
316
                                return curr_bd->regs[i].name;
 
317
                }
 
318
        }
 
319
        return NULL;
 
320
}
 
321
 
 
322
static const char *binary(unsigned long long val)
 
323
{
 
324
        static char bin[80];
 
325
        char *p = bin;
 
326
        int i, j;
 
327
        int bits = 64;
 
328
 
 
329
        if ((val & 0xffffffff00000000LL) == 0) {
 
330
                if ((val & 0xffff0000) == 0) {
 
331
                        if ((val & 0xff00) == 0)
 
332
                                bits = 8;
 
333
                        else
 
334
                                bits= 16;
 
335
                }
 
336
                else
 
337
                        bits = 32;
 
338
        }
 
339
 
 
340
        for (i = bits - 1; i >= 0; i -= 8) {
 
341
                for (j = i; j >= i - 7; j--) {
 
342
                        if (val & (1LL << j))
 
343
                                *p++ = '1';
 
344
                        else
 
345
                                *p++ = '0';
 
346
                }
 
347
                *p++ = ' ';
 
348
        }
 
349
        p[-1] = 0;
 
350
        return bin;
 
351
}
 
352
 
 
353
static int doioctl(int fd, unsigned long int request, void *parm, const char *name)
 
354
{
 
355
        int retVal = ioctl(fd, request, parm);
 
356
 
 
357
        if (options[OptVerbose]) {
 
358
                if (retVal < 0)
 
359
                        printf("%s: failed: %s\n", name, strerror(errno));
 
360
                else
 
361
                        printf("%s: ok\n", name);
 
362
        }
 
363
 
 
364
        return retVal;
 
365
}
 
366
 
 
367
static int parse_subopt(char **subs, const char * const *subopts, char **value)
 
368
{
 
369
        int opt = getsubopt(subs, (char * const *)subopts, value);
 
370
 
 
371
        if (opt == -1) {
 
372
                fprintf(stderr, "Invalid suboptions specified\n");
 
373
                usage();
 
374
                exit(1);
 
375
        }
 
376
        if (value == NULL) {
 
377
                fprintf(stderr, "No value given to suboption <%s>\n",
 
378
                                subopts[opt]);
 
379
                usage();
 
380
                exit(1);
 
381
        }
 
382
        return opt;
 
383
}
 
384
 
 
385
int main(int argc, char **argv)
 
386
{
 
387
        char *value, *subs;
 
388
        int i, forcedstride = 0;
 
389
 
 
390
        int fd = -1;
 
391
 
 
392
        /* command args */
 
393
        int ch;
 
394
        const char *device = "/dev/video0";     /* -d device */
 
395
        struct v4l2_capability vcap;    /* list_cap */
 
396
        struct v4l2_dbg_register set_reg;
 
397
        struct v4l2_dbg_register get_reg;
 
398
        struct v4l2_dbg_chip_ident chip_id;
 
399
        const struct board_list *curr_bd = NULL;
 
400
        char short_options[26 * 2 * 2 + 1];
 
401
        int idx = 0;
 
402
        std::string reg_min_arg, reg_max_arg;
 
403
        std::string reg_set_arg;
 
404
        unsigned long long reg_min = 0, reg_max = 0;
 
405
        std::vector<std::string> get_regs;
 
406
        struct v4l2_dbg_match match;
 
407
 
 
408
        match.type = V4L2_CHIP_MATCH_HOST;
 
409
        match.addr = 0;
 
410
        memset(&set_reg, 0, sizeof(set_reg));
 
411
        memset(&get_reg, 0, sizeof(get_reg));
 
412
        memset(&chip_id, 0, sizeof(chip_id));
 
413
 
 
414
        if (argc == 1) {
 
415
                usage();
 
416
                return 0;
 
417
        }
 
418
        for (i = 0; long_options[i].name; i++) {
 
419
                if (!isalpha(long_options[i].val))
 
420
                        continue;
 
421
                short_options[idx++] = long_options[i].val;
 
422
                if (long_options[i].has_arg == required_argument)
 
423
                        short_options[idx++] = ':';
 
424
        }
 
425
        while (1) {
 
426
                int option_index = 0;
 
427
 
 
428
                short_options[idx] = 0;
 
429
                ch = getopt_long(argc, argv, short_options,
 
430
                                 long_options, &option_index);
 
431
                if (ch == -1)
 
432
                        break;
 
433
 
 
434
                options[(int)ch] = 1;
 
435
                switch (ch) {
 
436
                case OptHelp:
 
437
                        usage();
 
438
                        return 0;
 
439
 
 
440
                case OptSetDevice:
 
441
                        device = optarg;
 
442
                        if (device[0] >= '0' && device[0] <= '9' && device[1] == 0) {
 
443
                                static char newdev[20];
 
444
                                char dev = device[0];
 
445
 
 
446
                                sprintf(newdev, "/dev/video%c", dev);
 
447
                                device = newdev;
 
448
                        }
 
449
                        break;
 
450
 
 
451
                case OptChip:
 
452
                        if (isdigit(optarg[0])) {
 
453
                                match.type = V4L2_CHIP_MATCH_I2C_ADDR;
 
454
                                match.addr = strtoul(optarg, NULL, 0);
 
455
                                break;
 
456
                        }
 
457
                        if (!memcmp(optarg, "host", 4)) {
 
458
                                match.type = V4L2_CHIP_MATCH_HOST;
 
459
                                match.addr = strtoul(optarg + 4, NULL, 0);
 
460
                                break;
 
461
                        }
 
462
                        if (!strcasecmp(optarg, "ac97")) {
 
463
                                match.type = V4L2_CHIP_MATCH_AC97;
 
464
                                match.addr = 0;
 
465
                                break;
 
466
                        }
 
467
                        match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
 
468
                        strncpy(match.name, optarg, sizeof(match.name));
 
469
                        match.name[sizeof(match.name) - 1] = '\0';
 
470
                        break;
 
471
 
 
472
                case OptSetRegister:
 
473
                        reg_set_arg = optarg;
 
474
                        break;
 
475
 
 
476
                case OptGetRegister:
 
477
                        get_regs.push_back(optarg);
 
478
                        break;
 
479
 
 
480
                case OptSetStride:
 
481
                        forcedstride = strtoull(optarg, 0L, 0);
 
482
                        break;
 
483
 
 
484
                case OptListRegisters:
 
485
                        subs = optarg;
 
486
                        if (subs == NULL)
 
487
                                break;
 
488
 
 
489
                        while (*subs != '\0') {
 
490
                                static const char * const subopts[] = {
 
491
                                        "min",
 
492
                                        "max",
 
493
                                        NULL
 
494
                                };
 
495
 
 
496
                                switch (parse_subopt(&subs, subopts, &value)) {
 
497
                                case 0:
 
498
                                        reg_min_arg = value;
 
499
                                        //if (reg_max == 0)
 
500
                                        //      reg_max = reg_min + 0xff;
 
501
                                        break;
 
502
                                case 1:
 
503
                                        reg_max_arg = value;
 
504
                                        break;
 
505
                                }
 
506
                        }
 
507
                        break;
 
508
 
 
509
                case OptGetChipIdent:
 
510
                case OptListSymbols:
 
511
                        break;
 
512
 
 
513
                case ':':
 
514
                        fprintf(stderr, "Option `%s' requires a value\n",
 
515
                                argv[optind]);
 
516
                        usage();
 
517
                        return 1;
 
518
 
 
519
                case '?':
 
520
                        fprintf(stderr, "Unknown argument `%s'\n",
 
521
                                argv[optind]);
 
522
                        usage();
 
523
                        return 1;
 
524
                }
 
525
        }
 
526
 
 
527
        if ((fd = open(device, O_RDWR)) < 0) {
 
528
                fprintf(stderr, "Failed to open %s: %s\n", device,
 
529
                        strerror(errno));
 
530
                exit(1);
 
531
        }
 
532
 
 
533
        doioctl(fd, VIDIOC_QUERYCAP, &vcap, "VIDIOC_QUERYCAP");
 
534
        capabilities = vcap.capabilities;
 
535
 
 
536
        /* Information Opts */
 
537
 
 
538
        if (options[OptGetDriverInfo]) {
 
539
                printf("Driver info:\n");
 
540
                printf("\tDriver name   : %s\n", vcap.driver);
 
541
                printf("\tCard type     : %s\n", vcap.card);
 
542
                printf("\tBus info      : %s\n", vcap.bus_info);
 
543
                printf("\tDriver version: %d\n", vcap.version);
 
544
                printf("\tCapabilities  : 0x%08X\n", vcap.capabilities);
 
545
                printf("%s", cap2s(vcap.capabilities).c_str());
 
546
        }
 
547
 
 
548
        if (match.type == V4L2_CHIP_MATCH_AC97) {
 
549
                curr_bd = &boards[AC97_BOARD];
 
550
        } else if (match.type == V4L2_CHIP_MATCH_HOST) {
 
551
                for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
 
552
                        if (!strcasecmp((char *)vcap.driver, boards[board].name)) {
 
553
                                curr_bd = &boards[board];
 
554
                                break;
 
555
                        }
 
556
                }
 
557
        } else if (match.type == V4L2_CHIP_MATCH_I2C_DRIVER) {
 
558
                for (int board = ARRAY_SIZE(boards) - 1; board >= 0; board--) {
 
559
                        if (!strcasecmp(match.name, boards[board].name)) {
 
560
                                curr_bd = &boards[board];
 
561
                                break;
 
562
                        }
 
563
                }
 
564
        }
 
565
 
 
566
        /* Set options */
 
567
 
 
568
        if (options[OptSetRegister]) {
 
569
                set_reg.match = match;
 
570
                if (optind >= argc)
 
571
                        usage();
 
572
                set_reg.reg = parse_reg(curr_bd, reg_set_arg);
 
573
                while (optind < argc) {
 
574
                        set_reg.val = strtoull(argv[optind++], NULL, 0);
 
575
                        if (doioctl(fd, VIDIOC_DBG_S_REGISTER, &set_reg,
 
576
                                                "VIDIOC_DBG_S_REGISTER") >= 0) {
 
577
                                const char *name = reg_name(curr_bd, set_reg.reg);
 
578
 
 
579
                                printf("Register ");
 
580
 
 
581
                                if (name)
 
582
                                        printf("%s (0x%08llx)", name, set_reg.reg);
 
583
                                else
 
584
                                        printf("0x%08llx", set_reg.reg);
 
585
 
 
586
                                printf(" set to 0x%llx\n", set_reg.val);
 
587
                        } else {
 
588
                                printf("Failed to set register 0x%08llx value 0x%llx: %s\n",
 
589
                                        set_reg.reg, set_reg.val, strerror(errno));
 
590
                        }
 
591
                        set_reg.reg++;
 
592
                }
 
593
        }
 
594
 
 
595
        if (options[OptGetChipIdent]) {
 
596
                chip_id.match = match;
 
597
                if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0)
 
598
                        print_chip(&chip_id);
 
599
        }
 
600
 
 
601
        if (options[OptScanChipIdents]) {
 
602
                int i;
 
603
 
 
604
                chip_id.match.type = V4L2_CHIP_MATCH_HOST;
 
605
                chip_id.match.addr = 0;
 
606
 
 
607
                while (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) {
 
608
                        printf("host%d: ", chip_id.match.addr);
 
609
                        print_chip(&chip_id);
 
610
                        chip_id.match.addr++;
 
611
                }
 
612
 
 
613
                chip_id.match.type = V4L2_CHIP_MATCH_I2C_ADDR;
 
614
                for (i = 0; i < 128; i++) {
 
615
                        chip_id.match.addr = i;
 
616
                        if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") == 0 && chip_id.ident) {
 
617
                                printf("i2c 0x%02x: ", i);
 
618
                                print_chip(&chip_id);
 
619
                        }
 
620
                }
 
621
        }
 
622
 
 
623
        if (options[OptGetRegister]) {
 
624
                int stride = 1;
 
625
 
 
626
                get_reg.match = match;
 
627
                printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
 
628
 
 
629
                for (std::vector<std::string>::iterator iter = get_regs.begin();
 
630
                                iter != get_regs.end(); ++iter) {
 
631
                        get_reg.reg = parse_reg(curr_bd, *iter);
 
632
                        if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
 
633
                                fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
 
634
                                                "failed for 0x%llx\n", get_reg.reg);
 
635
                        else {
 
636
                                const char *name = reg_name(curr_bd, get_reg.reg);
 
637
 
 
638
                                printf("Register ");
 
639
 
 
640
                                if (name)
 
641
                                        printf("%s (0x%08llx)", name, get_reg.reg);
 
642
                                else
 
643
                                        printf("0x%08llx", get_reg.reg);
 
644
 
 
645
                                printf(" = %llxh (%lldd  %sb)\n",
 
646
                                        get_reg.val, get_reg.val, binary(get_reg.val));
 
647
                        }
 
648
                }
 
649
        }
 
650
 
 
651
        if (options[OptListRegisters]) {
 
652
                std::string name;
 
653
                int stride = 1;
 
654
 
 
655
                get_reg.match = match;
 
656
                if (forcedstride) {
 
657
                        stride = forcedstride;
 
658
                } else if (get_reg.match.type == V4L2_CHIP_MATCH_HOST) {
 
659
                        stride = 4;
 
660
                }
 
661
                printf("ioctl: VIDIOC_DBG_G_REGISTER\n");
 
662
 
 
663
                if (curr_bd) {
 
664
                        if (reg_min_arg.empty())
 
665
                                reg_min = 0;
 
666
                        else
 
667
                                reg_min = parse_reg(curr_bd, reg_min_arg);
 
668
 
 
669
 
 
670
                        if (reg_max_arg.empty())
 
671
                                reg_max = (1ll << 32) - 1;
 
672
                        else
 
673
                                reg_max = parse_reg(curr_bd, reg_max_arg);
 
674
 
 
675
                        for (int i = 0; i < curr_bd->regs_size; i++) {
 
676
                                if (reg_min_arg.empty() || ((curr_bd->regs[i].reg >= reg_min) && curr_bd->regs[i].reg <= reg_max)) {
 
677
                                        get_reg.reg = curr_bd->regs[i].reg;
 
678
 
 
679
                                        if (ioctl(fd, VIDIOC_DBG_G_REGISTER, &get_reg) < 0)
 
680
                                                fprintf(stderr, "ioctl: VIDIOC_DBG_G_REGISTER "
 
681
                                                                "failed for 0x%llx\n", get_reg.reg);
 
682
                                        else {
 
683
                                                const char *name = reg_name(curr_bd, get_reg.reg);
 
684
 
 
685
                                                printf("Register ");
 
686
 
 
687
                                                if (name)
 
688
                                                        printf("%s (0x%08llx)", name, get_reg.reg);
 
689
                                                else
 
690
                                                        printf("0x%08llx", get_reg.reg);
 
691
 
 
692
                                                printf(" = %llxh (%lldd  %sb)\n",
 
693
                                                        get_reg.val, get_reg.val, binary(get_reg.val));
 
694
                                        }
 
695
                                }
 
696
                        }
 
697
                        goto list_done;
 
698
                }
 
699
 
 
700
                if (!reg_min_arg.empty()) {
 
701
                        reg_min = parse_reg(curr_bd, reg_min_arg);
 
702
                        if (reg_max_arg.empty())
 
703
                                reg_max = reg_min + 0xff;
 
704
                        else
 
705
                                reg_max = parse_reg(curr_bd, reg_max_arg);
 
706
                        /* Explicit memory range: just do it */
 
707
                        print_regs(fd, &get_reg, reg_min, reg_max, stride);
 
708
                        goto list_done;
 
709
                }
 
710
 
 
711
                /* try to figure out which chip it is */
 
712
                chip_id.match = match;
 
713
                if (doioctl(fd, VIDIOC_DBG_G_CHIP_IDENT, &chip_id, "VIDIOC_DBG_G_CHIP_IDENT") != 0) {
 
714
                        chip_id.ident = V4L2_IDENT_NONE;
 
715
                }
 
716
                switch (chip_id.ident) {
 
717
                case V4L2_IDENT_CX23415:
 
718
                case V4L2_IDENT_CX23416:
 
719
                        name = "cx23416";
 
720
                        break;
 
721
                case V4L2_IDENT_CX23418:
 
722
                        name = "cx23418";
 
723
                        break;
 
724
                case V4L2_IDENT_CAFE:
 
725
                        name = "cafe";
 
726
                        break;
 
727
                default:
 
728
                        if (get_reg.match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
 
729
                                name = get_reg.match.name;
 
730
                        break;
 
731
                }
 
732
 
 
733
                if (name == "saa7115") {
 
734
                        print_regs(fd, &get_reg, 0, 0xff, stride);
 
735
                } else if (name == "saa717x") {
 
736
                        // FIXME: use correct reg regions
 
737
                        print_regs(fd, &get_reg, 0, 0xff, stride);
 
738
                } else if (name == "saa7127") {
 
739
                        print_regs(fd, &get_reg, 0, 0x7f, stride);
 
740
                } else if (name == "ov7670") {
 
741
                        print_regs(fd, &get_reg, 0, 0x89, stride);
 
742
                } else if (name == "cx25840") {
 
743
                        print_regs(fd, &get_reg, 0, 2, stride);
 
744
                        print_regs(fd, &get_reg, 0x100, 0x15f, stride);
 
745
                        print_regs(fd, &get_reg, 0x200, 0x23f, stride);
 
746
                        print_regs(fd, &get_reg, 0x400, 0x4bf, stride);
 
747
                        print_regs(fd, &get_reg, 0x800, 0x9af, stride);
 
748
                } else if (name == "cs5345") {
 
749
                        print_regs(fd, &get_reg, 1, 0x10, stride);
 
750
                } else if (name == "cx23416") {
 
751
                        print_regs(fd, &get_reg, 0x02000000, 0x020000ff, stride);
 
752
                } else if (name == "cx23418") {
 
753
                        print_regs(fd, &get_reg, 0x02c40000, 0x02c409c7, stride);
 
754
                } else if (name == "cafe") {
 
755
                        print_regs(fd, &get_reg, 0, 0x43, stride);
 
756
                        print_regs(fd, &get_reg, 0x88, 0x8f, stride);
 
757
                        print_regs(fd, &get_reg, 0xb4, 0xbb, stride);
 
758
                        print_regs(fd, &get_reg, 0x3000, 0x300c, stride);
 
759
                } else {
 
760
                        /* unknown chip, dump 0-0xff by default */
 
761
                        print_regs(fd, &get_reg, 0, 0xff, stride);
 
762
                }
 
763
        }
 
764
list_done:
 
765
 
 
766
        if (options[OptLogStatus]) {
 
767
                static char buf[40960];
 
768
                int len;
 
769
 
 
770
                if (doioctl(fd, VIDIOC_LOG_STATUS, NULL, "VIDIOC_LOG_STATUS") == 0) {
 
771
                        printf("\nStatus Log:\n\n");
 
772
                        len = klogctl(3, buf, sizeof(buf) - 1);
 
773
                        if (len >= 0) {
 
774
                                char *p = buf;
 
775
                                char *q;
 
776
 
 
777
                                buf[len] = 0;
 
778
                                while ((q = strstr(p, "START STATUS CARD #"))) {
 
779
                                        p = q + 1;
 
780
                                }
 
781
                                if (p) {
 
782
                                        while (p > buf && *p != '<') p--;
 
783
                                        q = p;
 
784
                                        while ((q = strstr(q, "<6>"))) {
 
785
                                                memcpy(q, "   ", 3);
 
786
                                        }
 
787
                                        printf("%s", p);
 
788
                                }
 
789
                        }
 
790
                }
 
791
        }
 
792
 
 
793
        if (options[OptListSymbols]) {
 
794
                if (curr_bd == NULL) {
 
795
                        printf("No symbols found for driver %s\n", vcap.driver);
 
796
                }
 
797
                else {
 
798
                        printf("Symbols for driver %s:\n", curr_bd->name);
 
799
                        for (int i = 0; i < curr_bd->regs_size; i++)
 
800
                                printf("0x%08x: %s\n", curr_bd->regs[i].reg, curr_bd->regs[i].name);
 
801
                        for (int i = 0; i < curr_bd->alt_regs_size; i++)
 
802
                                printf("0x%08x: %s\n", curr_bd->alt_regs[i].reg, curr_bd->alt_regs[i].name);
 
803
                }
 
804
        }
 
805
 
 
806
        close(fd);
 
807
        exit(0);
 
808
}