void common_process_controls(int fd) { find_controls(fd); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { if (ctrl_str2q.find(*iter) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", iter->c_str()); exit(1); } } for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { if (ctrl_str2q.find(iter->first) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", iter->first.c_str()); exit(1); } } }
void common_process_controls(int fd) { struct v4l2_query_ext_ctrl qc = { V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND }; int rc; rc = test_ioctl(fd, VIDIOC_QUERY_EXT_CTRL, &qc); have_query_ext_ctrl = rc == 0; find_controls(fd); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { if (ctrl_str2q.find(*iter) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", iter->c_str()); exit(1); } } for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { if (ctrl_str2q.find(iter->first) == ctrl_str2q.end()) { fprintf(stderr, "unknown control '%s'\n", iter->first.c_str()); exit(1); } } }
int main(int argc, char **argv) { char *value, *subs; int i; int fd = -1; /* command args */ int ch; const char *device = "/dev/video0"; /* -d device */ struct v4l2_capability vcap; /* list_cap */ char short_options[26 * 2 * 2 + 1]; int idx = 0; 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 OptGetCtrl: subs = optarg; while (*subs != '\0') { parse_next_subopt(&subs, &value); if (strchr(value, '=')) { usage(); exit(1); } else { get_ctrls.push_back(value); } } break; case OptSetCtrl: subs = optarg; while (*subs != '\0') { parse_next_subopt(&subs, &value); if (const char *equal = strchr(value, '=')) { set_ctrls[std::string(value, (equal - value))] = equal + 1; } else { fprintf(stderr, "control '%s' without '='\n", value); exit(1); } } 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 (optind < argc) { printf("unknown arguments: "); while (optind < argc) printf("%s ", argv[optind++]); printf("\n"); 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; find_controls(fd); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { if (ctrl_str2id.find(*iter) == ctrl_str2id.end()) { fprintf(stderr, "unknown control '%s'\n", (*iter).c_str()); exit(1); } } for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { if (ctrl_str2id.find(iter->first) == ctrl_str2id.end()) { fprintf(stderr, "unknown control '%s'\n", iter->first.c_str()); exit(1); } } /* Information Opts */ if (options[OptSetCtrl] && !set_ctrls.empty()) { struct v4l2_ext_controls ctrls = { 0 }; for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl = { 0 }; ctrl.id = ctrl_str2id[iter->first]; ctrl.value = strtol(iter->second.c_str(), NULL, 0); if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG) mpeg_ctrls.push_back(ctrl); else user_ctrls.push_back(ctrl); } for (unsigned i = 0; i < user_ctrls.size(); i++) { struct v4l2_control ctrl; ctrl.id = user_ctrls[i].id; ctrl.value = user_ctrls[i].value; if (doioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL")) { fprintf(stderr, "%s: %s\n", ctrl_id2str[ctrl.id].c_str(), strerror(errno)); } } if (mpeg_ctrls.size()) { ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; ctrls.count = mpeg_ctrls.size(); ctrls.controls = &mpeg_ctrls[0]; if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls, "VIDIOC_S_EXT_CTRLS")) { if (ctrls.error_idx >= ctrls.count) { fprintf(stderr, "Error setting MPEG controls: %s\n", strerror(errno)); } else { fprintf(stderr, "%s: %s\n", ctrl_id2str[mpeg_ctrls[ctrls.error_idx].id].c_str(), strerror(errno)); } } } } /* Get options */ if (options[OptGetCtrl] && !get_ctrls.empty()) { struct v4l2_ext_controls ctrls = { 0 }; mpeg_ctrls.clear(); user_ctrls.clear(); for (ctrl_get_list::iterator iter = get_ctrls.begin(); iter != get_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl = { 0 }; ctrl.id = ctrl_str2id[*iter]; if (V4L2_CTRL_ID2CLASS(ctrl.id) == V4L2_CTRL_CLASS_MPEG) mpeg_ctrls.push_back(ctrl); else user_ctrls.push_back(ctrl); } for (unsigned i = 0; i < user_ctrls.size(); i++) { struct v4l2_control ctrl; ctrl.id = user_ctrls[i].id; doioctl(fd, VIDIOC_G_CTRL, &ctrl, "VIDIOC_G_CTRL"); printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); } if (mpeg_ctrls.size()) { ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; ctrls.count = mpeg_ctrls.size(); ctrls.controls = &mpeg_ctrls[0]; doioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls, "VIDIOC_G_EXT_CTRLS"); for (unsigned i = 0; i < mpeg_ctrls.size(); i++) { struct v4l2_ext_control ctrl = mpeg_ctrls[i]; printf("%s: %d\n", ctrl_id2str[ctrl.id].c_str(), ctrl.value); } } } if (options[OptListCtrlsMenus]) { list_controls(fd, 1); } if (options[OptListCtrls]) { list_controls(fd, 0); } close(fd); exit(app_result); }
void common_set(int fd) { if (options[OptSetPriority]) { if (doioctl(fd, VIDIOC_S_PRIORITY, &prio) >= 0) { printf("Priority set: %d\n", prio); } } if (options[OptSetCtrl] && !set_ctrls.empty()) { struct v4l2_ext_controls ctrls; class2ctrls_map class2ctrls; bool use_ext_ctrls = false; memset(&ctrls, 0, sizeof(ctrls)); for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl; struct v4l2_query_ext_ctrl &qc = ctrl_str2q[iter->first]; memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = qc.id; if (qc.type == V4L2_CTRL_TYPE_INTEGER64) use_ext_ctrls = true; if (qc.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD) { struct v4l2_ext_controls ctrls = { 0, 1 }; unsigned divide[V4L2_CTRL_MAX_DIMS] = { 0 }; ctrl_subset subset; long long v; unsigned d, i; use_ext_ctrls = true; ctrl.size = qc.elems * qc.elem_size; ctrl.ptr = malloc(ctrl.size); ctrls.controls = &ctrl; ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls); if (fill_subset(qc, subset)) return; divide[qc.nr_of_dims - 1] = 1; for (d = 0; d < qc.nr_of_dims - 1; d++) { divide[d] = qc.dims[d + 1]; for (i = 0; i < d; i++) divide[i] *= divide[d]; } switch (qc.type) { case V4L2_CTRL_TYPE_U8: v = strtoul(iter->second.c_str(), NULL, 0); for (i = 0; i < qc.elems; i++) if (idx_in_subset(qc, subset, divide, i)) ctrl.p_u8[i] = v; break; case V4L2_CTRL_TYPE_U16: v = strtoul(iter->second.c_str(), NULL, 0); for (i = 0; i < qc.elems; i++) if (idx_in_subset(qc, subset, divide, i)) ctrl.p_u16[i] = v; break; case V4L2_CTRL_TYPE_U32: v = strtoul(iter->second.c_str(), NULL, 0); for (i = 0; i < qc.elems; i++) if (idx_in_subset(qc, subset, divide, i)) ctrl.p_u32[i] = v; break; case V4L2_CTRL_TYPE_STRING: strncpy(ctrl.string, iter->second.c_str(), qc.maximum); ctrl.string[qc.maximum] = 0; break; default: fprintf(stderr, "%s: unsupported payload type\n", qc.name); break; } } else { if (V4L2_CTRL_DRIVER_PRIV(ctrl.id)) use_ext_ctrls = true; ctrl.value = strtol(iter->second.c_str(), NULL, 0); } class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl); } for (class2ctrls_map::iterator iter = class2ctrls.begin(); iter != class2ctrls.end(); ++iter) { if (!use_ext_ctrls && (iter->first == V4L2_CTRL_CLASS_USER || iter->first == V4L2_CID_PRIVATE_BASE)) { for (unsigned i = 0; i < iter->second.size(); i++) { struct v4l2_control ctrl; ctrl.id = iter->second[i].id; ctrl.value = iter->second[i].value; if (doioctl(fd, VIDIOC_S_CTRL, &ctrl)) { fprintf(stderr, "%s: %s\n", ctrl_id2str[ctrl.id].c_str(), strerror(errno)); } } continue; } if (iter->second.size()) { ctrls.ctrl_class = iter->first; ctrls.count = iter->second.size(); ctrls.controls = &iter->second[0]; if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) { if (ctrls.error_idx >= ctrls.count) { fprintf(stderr, "Error setting controls: %s\n", strerror(errno)); } else { fprintf(stderr, "%s: %s\n", ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(), strerror(errno)); } } } } } }
void common_set(int fd) { if (options[OptSetPriority]) { if (doioctl(fd, VIDIOC_S_PRIORITY, &prio) >= 0) { printf("Priority set: %d\n", prio); } } if (options[OptSetCtrl] && !set_ctrls.empty()) { struct v4l2_ext_controls ctrls; class2ctrls_map class2ctrls; bool use_ext_ctrls = false; memset(&ctrls, 0, sizeof(ctrls)); for (ctrl_set_map::iterator iter = set_ctrls.begin(); iter != set_ctrls.end(); ++iter) { struct v4l2_ext_control ctrl; memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = ctrl_str2q[iter->first].id; if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_INTEGER64) use_ext_ctrls = true; if (ctrl_str2q[iter->first].type == V4L2_CTRL_TYPE_STRING) { unsigned len = iter->second.length(); unsigned maxlen = ctrl_str2q[iter->first].maximum; use_ext_ctrls = true; ctrl.size = maxlen + 1; ctrl.string = (char *)malloc(ctrl.size); if (len > maxlen) { memcpy(ctrl.string, iter->second.c_str(), maxlen); ctrl.string[maxlen] = 0; } else { strcpy(ctrl.string, iter->second.c_str()); } } else { if (V4L2_CTRL_DRIVER_PRIV(ctrl.id)) use_ext_ctrls = true; ctrl.value = strtol(iter->second.c_str(), NULL, 0); } class2ctrls[V4L2_CTRL_ID2CLASS(ctrl.id)].push_back(ctrl); } for (class2ctrls_map::iterator iter = class2ctrls.begin(); iter != class2ctrls.end(); ++iter) { if (!use_ext_ctrls && (iter->first == V4L2_CTRL_CLASS_USER || iter->first == V4L2_CID_PRIVATE_BASE)) { for (unsigned i = 0; i < iter->second.size(); i++) { struct v4l2_control ctrl; ctrl.id = iter->second[i].id; ctrl.value = iter->second[i].value; if (doioctl(fd, VIDIOC_S_CTRL, &ctrl)) { fprintf(stderr, "%s: %s\n", ctrl_id2str[ctrl.id].c_str(), strerror(errno)); } } continue; } if (iter->second.size()) { ctrls.ctrl_class = iter->first; ctrls.count = iter->second.size(); ctrls.controls = &iter->second[0]; if (doioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls)) { if (ctrls.error_idx >= ctrls.count) { fprintf(stderr, "Error setting MPEG controls: %s\n", strerror(errno)); } else { fprintf(stderr, "%s: %s\n", ctrl_id2str[iter->second[ctrls.error_idx].id].c_str(), strerror(errno)); } } } } } }