int testChipIdent(struct node *node) { struct v4l2_dbg_chip_ident chip; int ret; memset(&chip, 0, sizeof(chip)); chip.match.type = V4L2_CHIP_MATCH_HOST; chip.match.addr = 0; ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip); // Must return either 0 (OK) or EINVAL (not supported) if (ret == 0) { struct v4l2_dbg_chip_ident orig; memset(&orig, 0, sizeof(orig)); // set invalid match_type chip.match.type = V4L2_CHIP_MATCH_I2C_ADDR + 1; chip.match.addr = 0xdeadbeef; chip.ident = 0xdeadbeef; chip.revision = 0xdeadbeef; orig = chip; ret = doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip); if (ret != EINVAL) return fail("Invalid match_type accepted\n"); fail_on_test(memcmp(&orig, &chip, sizeof(chip))); return 0; } return ret; }
int testRegister(struct node *node) { struct v4l2_dbg_register reg; struct v4l2_dbg_chip_ident chip; int ret; int uid = getuid(); reg.match.type = V4L2_CHIP_MATCH_HOST; reg.match.addr = 0; reg.reg = 0; ret = doioctl(node, VIDIOC_DBG_G_REGISTER, ®); if (ret == ENOTTY) return ret; // Not allowed to call VIDIOC_DBG_G_REGISTER unless root fail_on_test(uid && ret != EPERM); fail_on_test(uid == 0 && ret); chip.match.type = V4L2_CHIP_MATCH_HOST; chip.match.addr = 0; fail_on_test(doioctl(node, VIDIOC_DBG_G_CHIP_IDENT, &chip)); if (uid) { // Don't test S_REGISTER as root, don't want to risk // messing with registers in the compliance test. reg.reg = reg.val = 0; ret = doioctl(node, VIDIOC_DBG_S_REGISTER, ®); fail_on_test(ret != ENOTTY && ret != EINVAL && ret != EPERM); } return 0; }
int testOutputAudio(struct node *node) { struct v4l2_output voutput; unsigned o = 0; int ret; if (node->audio_outputs && node->outputs == 0) return fail("audio outputs found but no video outputs?!\n"); for (o = 0; o < node->outputs; o++) { ret = doioctl(node, VIDIOC_S_OUTPUT, &o); if (ret) return fail("could not select output %d\n", o); voutput.index = o; ret = doioctl(node, VIDIOC_ENUMOUTPUT, &voutput); if (ret) return fail("could not enumerate output %d\n", o); if (checkOutputAudioSet(node, voutput.audioset)) return fail("invalid audioset for output %d\n", o); } if (node->audio_outputs == 0 && node->audio_inputs && (caps & V4L2_CAP_AUDIO)) return fail("no audio inputs or outputs reported, but CAP_AUDIO set\n"); return node->audio_outputs ? 0 : -ENOSYS; }
static int testParmType(struct node *node, unsigned type) { struct v4l2_streamparm parm; int ret; memset(&parm, 0, sizeof(parm)); parm.type = type; ret = doioctl(node, VIDIOC_G_PARM, &parm); if (ret == ENOTTY) return ret; if (ret == EINVAL) return ENOTTY; if (ret) return fail("expected EINVAL, but got %d when getting parms for buftype %d\n", ret, type); fail_on_test(parm.type != type); ret = testParmStruct(node, parm); if (ret) return ret; memset(&parm, 0, sizeof(parm)); parm.type = type; ret = doioctl(node, VIDIOC_S_PARM, &parm); if (ret == ENOTTY) return 0; if (ret) return fail("got error %d when setting parms for buftype %d\n", ret, type); fail_on_test(parm.type != type); return testParmStruct(node, parm); }
static int checkOutputAudioSet(struct node *node, __u32 audioset) { struct v4l2_audioout output; unsigned i; int ret; ret = doioctl(node, VIDIOC_G_AUDOUT, &output); if (audioset == 0 && ret != EINVAL) return fail("No audio outputs, but G_AUDOUT did not return EINVAL\n"); if (audioset) { if (ret) return fail("Audio outputs, but G_AUDOUT returned an error\n"); if (output.index >= node->audio_outputs) return fail("invalid current audio output %d\n", output.index); if (checkOutputAudio(output, output.index)) return fail("invalid attributes for audio output %d\n", output.index); } for (i = 0; i <= node->audio_outputs; i++) { int valid = audioset & (1 << i); memset(&output, 0xff, sizeof(output)); memset(output.reserved, 0, sizeof(output.reserved)); output.index = i; output.mode = 0; ret = doioctl(node, VIDIOC_S_AUDOUT, &output); if (!valid && ret != EINVAL) return fail("can set invalid audio output %d\n", i); if (valid && ret) return fail("can't set valid audio output %d\n", i); } return 0; }
int dobulk(int EndPt, void *pvBuf, size_t cbBuf, const char *pszWho) { #if 0 struct usbdevfs_urb KUrb = {0}; KUrb.type = USBDEVFS_URB_TYPE_BULK; KUrb.endpoint = EndPt; KUrb.buffer = pvBuf; KUrb.buffer_length = cbBuf; KUrb.actual_length = 0; //cbBuf KUrb.flags = 0; /* ISO_ASAP/SHORT_NOT_OK */ if (!doioctl(USBDEVFS_SUBMITURB, &KUrb, pszWho)) { struct usbdevfs_urb *pKUrb = NULL; if (!doioctl(USBDEVFS_REAPURB, &pKUrb, pszWho) && pKUrb == &KUrb) return KUrb.actual_length; } return -1; #else struct usbdevfs_bulktransfer BulkMsg = {0}; BulkMsg.ep = EndPt; BulkMsg.timeout = 1000; BulkMsg.len = cbBuf; BulkMsg.data = pvBuf; int rc = doioctl(USBDEVFS_BULK, &BulkMsg, pszWho); // printf("rc=%d BulkMsg.len=%d cbBuf=%d\n", rc, BulkMsg.len, cbBuf); if (rc >= 0) return rc; return -1; #endif }
static int checkTimings(struct node *node, bool has_timings) { struct v4l2_enum_dv_timings enumtimings; struct v4l2_dv_timings timings; int ret; unsigned i; memset(&timings, 0xff, sizeof(timings)); ret = doioctl(node, VIDIOC_G_DV_TIMINGS, &timings); if (ret && has_timings) return fail("TIMINGS cap set, but could not get current timings\n"); if (!ret && !has_timings) return fail("TIMINGS cap not set, but could still get timings\n"); for (i = 0; ; i++) { memset(&enumtimings, 0xff, sizeof(enumtimings)); enumtimings.index = i; ret = doioctl(node, VIDIOC_ENUM_DV_TIMINGS, &enumtimings); if (ret) break; if (check_0(enumtimings.reserved, sizeof(enumtimings.reserved))) return fail("reserved not zeroed\n"); if (enumtimings.index != i) return fail("index changed!\n"); } if (i == 0 && has_timings) return fail("TIMINGS cap set, but no timings can be enumerated\n"); if (i && !has_timings) return fail("TIMINGS cap was not set, but timings can be enumerated\n"); ret = doioctl(node, VIDIOC_QUERY_DV_TIMINGS, &timings); if (!ret && !has_timings) return fail("TIMINGS cap was not set, but could still query timings\n"); return 0; }
void stds_set(int fd) { if (options[OptSetStandard]) { if (standard & (1ULL << 63)) { struct v4l2_standard vs; vs.index = standard & 0xffff; if (test_ioctl(fd, VIDIOC_ENUMSTD, &vs) >= 0) { standard = vs.id; } } if (doioctl(fd, VIDIOC_S_STD, &standard) == 0) printf("Standard set to %08llx\n", (unsigned long long)standard); } if (options[OptSetDvBtTimings]) { struct v4l2_enum_dv_timings et; if (query_and_set_dv_timings) doioctl(fd, VIDIOC_QUERY_DV_TIMINGS, &dv_timings); if (enum_and_set_dv_timings >= 0) { memset(&et, 0, sizeof(et)); et.index = enum_and_set_dv_timings; doioctl(fd, VIDIOC_ENUM_DV_TIMINGS, &et); dv_timings = et.timings; } if (doioctl(fd, VIDIOC_S_DV_TIMINGS, &dv_timings) >= 0) { printf("BT timings set\n"); } } }
static int testPrio(struct node *node, struct node *node2) { enum v4l2_priority prio; int err; if (node->is_m2m) { fail_on_test(doioctl(node, VIDIOC_G_PRIORITY, &prio) != ENOTTY); return 0; } err = check_prio(node, node2, V4L2_PRIORITY_DEFAULT); if (err) return err; prio = V4L2_PRIORITY_RECORD; // Must be able to change priority fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio)); // Must match the new prio fail_on_test(check_prio(node, node2, V4L2_PRIORITY_RECORD)); prio = V4L2_PRIORITY_INTERACTIVE; // Going back to interactive on the other node must fail fail_on_test(!doioctl(node2, VIDIOC_S_PRIORITY, &prio)); prio = V4L2_PRIORITY_INTERACTIVE; // Changing it on the first node must work. fail_on_test(doioctl(node, VIDIOC_S_PRIORITY, &prio)); fail_on_test(check_prio(node, node2, V4L2_PRIORITY_INTERACTIVE)); return 0; }
void io_set(int fd) { if (options[OptSetInput]) { if (doioctl(fd, VIDIOC_S_INPUT, &input) == 0) { struct v4l2_input vin; printf("Video input set to %d", input); vin.index = input; if (test_ioctl(fd, VIDIOC_ENUMINPUT, &vin) >= 0) printf(" (%s: %s)", vin.name, status2s(vin.status).c_str()); printf("\n"); } } if (options[OptSetOutput]) { if (doioctl(fd, VIDIOC_S_OUTPUT, &output) == 0) printf("Output set to %d\n", output); } if (options[OptSetAudioInput]) { if (doioctl(fd, VIDIOC_S_AUDIO, &vaudio) == 0) printf("Audio input set to %d\n", vaudio.index); } if (options[OptSetAudioOutput]) { if (doioctl(fd, VIDIOC_S_AUDOUT, &vaudout) == 0) printf("Audio output set to %d\n", vaudout.index); } }
void vbi_get(int fd) { if (options[OptGetSlicedVbiFormat]) { vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt) == 0) printfmt(vbi_fmt); } if (options[OptGetSlicedVbiOutFormat]) { vbi_fmt_out.type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT; if (doioctl(fd, VIDIOC_G_FMT, &vbi_fmt_out) == 0) printfmt(vbi_fmt_out); } if (options[OptGetVbiFormat]) { raw_fmt.type = V4L2_BUF_TYPE_VBI_CAPTURE; if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt) == 0) printfmt(raw_fmt); } if (options[OptGetVbiOutFormat]) { raw_fmt_out.type = V4L2_BUF_TYPE_VBI_OUTPUT; if (doioctl(fd, VIDIOC_G_FMT, &raw_fmt_out) == 0) printfmt(raw_fmt_out); } }
void stds_get(int fd) { if (options[OptGetStandard]) { if (doioctl(fd, VIDIOC_G_STD, &standard) == 0) { printf("Video Standard = 0x%08llx\n", (unsigned long long)standard); print_v4lstd((unsigned long long)standard); } } if (options[OptGetDvTimings]) { if (doioctl(fd, VIDIOC_G_DV_TIMINGS, &dv_timings) >= 0) { printf("DV timings:\n"); print_dv_timings(&dv_timings); } } if (options[OptGetDvTimingsCap]) { struct v4l2_dv_timings_cap dv_timings_cap; if (doioctl(fd, VIDIOC_DV_TIMINGS_CAP, &dv_timings_cap) >= 0) { static const flag_def dv_caps_def[] = { { V4L2_DV_BT_CAP_INTERLACED, "Interlaced" }, { V4L2_DV_BT_CAP_PROGRESSIVE, "Progressive" }, { V4L2_DV_BT_CAP_REDUCED_BLANKING, "Reduced Blanking" }, { V4L2_DV_BT_CAP_CUSTOM, "Custom Formats" }, { 0, NULL } }; struct v4l2_bt_timings_cap *bt = &dv_timings_cap.bt; printf("DV timings capabilities:\n"); if (dv_timings_cap.type != V4L2_DV_BT_656_1120) printf("\tUnknown type\n"); else { printf("\tMinimum Width: %u\n", bt->min_width); printf("\tMaximum Width: %u\n", bt->max_width); printf("\tMinimum Height: %u\n", bt->min_height); printf("\tMaximum Height: %u\n", bt->max_height); printf("\tMinimum PClock: %llu\n", bt->min_pixelclock); printf("\tMaximum PClock: %llu\n", bt->max_pixelclock); printf("\tStandards: %s\n", flags2s(bt->standards, dv_standards_def).c_str()); printf("\tCapabilities: %s\n", flags2s(bt->capabilities, dv_caps_def).c_str()); } } } if (options[OptQueryStandard]) { if (doioctl(fd, VIDIOC_QUERYSTD, &standard) == 0) { printf("Video Standard = 0x%08llx\n", (unsigned long long)standard); print_v4lstd((unsigned long long)standard); } } if (options[OptQueryDvTimings]) { doioctl(fd, VIDIOC_QUERY_DV_TIMINGS, &dv_timings); print_dv_timings(&dv_timings); } }
static int checkPresets(struct node *node, bool has_presets) { struct v4l2_dv_enum_preset enumpreset; struct v4l2_dv_preset preset; unsigned i; int ret; memset(&preset, 0xff, sizeof(preset)); ret = doioctl(node, VIDIOC_G_DV_PRESET, &preset); if (!ret && check_0(preset.reserved, sizeof(preset.reserved))) return fail("reserved not zeroed\n"); if (ret && has_presets) return fail("PRESET cap set, but could not get current preset\n"); if (!ret && !has_presets) return fail("PRESET cap not set, but could still get a preset\n"); if (preset.preset != V4L2_DV_INVALID) { ret = doioctl(node, VIDIOC_S_DV_PRESET, &preset); if (ret && has_presets) return fail("PRESET cap set, but could not set preset\n"); if (!ret && !has_presets) return fail("PRESET cap not set, but could still set a preset\n"); } preset.preset = V4L2_DV_INVALID; ret = doioctl(node, VIDIOC_S_DV_PRESET, &preset); if (ret != EINVAL && ret != ENOTTY) return fail("could set preset V4L2_DV_INVALID\n"); for (i = 0; ; i++) { memset(&enumpreset, 0xff, sizeof(enumpreset)); enumpreset.index = i; ret = doioctl(node, VIDIOC_ENUM_DV_PRESETS, &enumpreset); if (ret) break; if (check_ustring(enumpreset.name, sizeof(enumpreset.name))) return fail("invalid preset name\n"); if (check_0(enumpreset.reserved, sizeof(enumpreset.reserved))) return fail("reserved not zeroed\n"); if (enumpreset.index != i) return fail("index changed!\n"); if (enumpreset.preset == V4L2_DV_INVALID) return fail("invalid preset!\n"); if (enumpreset.width == 0 || enumpreset.height == 0) return fail("width or height not set\n"); } if (i == 0 && has_presets) return fail("PRESET cap set, but no presets can be enumerated\n"); if (i && !has_presets) return fail("PRESET cap was not set, but presets can be enumerated\n"); ret = doioctl(node, VIDIOC_QUERY_DV_PRESET, &preset); if (!ret && !has_presets) return fail("PRESET cap was not set, but could still query preset\n"); return 0; }
static int check_prio(struct node *node, struct node *node2, enum v4l2_priority match) { enum v4l2_priority prio; // Must be able to get priority fail_on_test(doioctl(node, VIDIOC_G_PRIORITY, &prio)); // Must match the expected prio fail_on_test(prio != match); fail_on_test(doioctl(node2, VIDIOC_G_PRIORITY, &prio)); fail_on_test(prio != match); return 0; }
void misc_get(int fd) { if (options[OptGetJpegComp]) { struct v4l2_jpegcompression jc; if (doioctl(fd, VIDIOC_G_JPEGCOMP, &jc) == 0) printjpegcomp(jc); } if (options[OptGetParm]) { memset(&parm, 0, sizeof(parm)); parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (doioctl(fd, VIDIOC_G_PARM, &parm) == 0) { const struct v4l2_fract &tf = parm.parm.capture.timeperframe; printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str()); if (parm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) printf("\tCapabilities : timeperframe\n"); if (parm.parm.capture.capturemode & V4L2_MODE_HIGHQUALITY) printf("\tCapture mode : high quality\n"); if (!tf.denominator || !tf.numerator) printf("\tFrames per second: invalid (%d/%d)\n", tf.denominator, tf.numerator); else printf("\tFrames per second: %.3f (%d/%d)\n", (1.0 * tf.denominator) / tf.numerator, tf.denominator, tf.numerator); printf("\tRead buffers : %d\n", parm.parm.capture.readbuffers); } } if (options[OptGetOutputParm]) { memset(&parm, 0, sizeof(parm)); parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (doioctl(fd, VIDIOC_G_PARM, &parm) == 0) { const struct v4l2_fract &tf = parm.parm.output.timeperframe; printf("Streaming Parameters %s:\n", buftype2s(parm.type).c_str()); if (parm.parm.output.capability & V4L2_CAP_TIMEPERFRAME) printf("\tCapabilities : timeperframe\n"); if (parm.parm.output.outputmode & V4L2_MODE_HIGHQUALITY) printf("\tOutput mode : high quality\n"); if (!tf.denominator || !tf.numerator) printf("\tFrames per second: invalid (%d/%d)\n", tf.denominator, tf.numerator); else printf("\tFrames per second: %.3f (%d/%d)\n", (1.0 * tf.denominator) / tf.numerator, tf.denominator, tf.numerator); printf("\tWrite buffers : %d\n", parm.parm.output.writebuffers); } } }
void vidout_get(int fd) { if (options[OptGetVideoOutFormat]) { vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out) == 0) printfmt(vfmt_out); } if (options[OptGetVideoOutMplaneFormat]) { vfmt_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; if (doioctl(fd, VIDIOC_G_FMT, &vfmt_out) == 0) printfmt(vfmt_out); } }
int testGetFormats(struct node *node) { struct v4l2_format fmt; bool supported = false; int type; int ret; for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) { memset(&fmt, 0xff, sizeof(fmt)); fmt.type = type; ret = doioctl(node, VIDIOC_G_FMT, &fmt); ret = testFormatsType(node, ret, type, fmt); if (ret && ret != ENOTTY) return ret; if (!ret) { supported = true; node->valid_buftypes |= 1 << type; } if (ret && (node->caps & buftype2cap[type])) return fail("%s cap set, but no %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); if (!ret && !(node->caps & buftype2cap[type])) { switch (type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: return fail("%s cap not set, but %s formats defined\n", buftype2s(type).c_str(), buftype2s(type).c_str()); default: /* ENUMFMT doesn't support other buftypes */ break; } } } memset(&fmt, 0xff, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_PRIVATE; ret = doioctl(node, VIDIOC_G_FMT, &fmt); ret = testFormatsType(node, ret, V4L2_BUF_TYPE_PRIVATE, fmt); if (ret && ret != ENOTTY) return ret; if (!ret) { supported = true; warn("Buffer type PRIVATE allowed!\n"); } return supported ? 0 : ENOTTY; }
static int standby_resume_standby_toggle(struct node *node, unsigned me, unsigned la, bool interactive) { if (!node->remote[la].in_standby) return NOTAPPLICABLE; struct cec_msg msg = {}; unsigned unresponsive_time = 0; __u8 new_status; node->remote[la].in_standby = false; /* Send Standby again to test that it is not acting like a toggle */ announce("Sending Standby message."); cec_msg_init(&msg, me, la); cec_msg_standby(&msg); int res = doioctl(node, CEC_TRANSMIT, &msg); fail_on_test(res && res != ENONET); fail_on_test(cec_msg_status_is_abort(&msg)); fail_on_test(wait_changing_power_status(node, me, la, new_status, unresponsive_time)); fail_on_test(new_status != CEC_OP_POWER_STATUS_STANDBY); fail_on_test(interactive && !question("Is the device still in standby?")); node->remote[la].in_standby = true; if (unresponsive_time > 0) warn("The device went correctly into standby, but became unresponsive for %d s during the transition.\n", unresponsive_time); return 0; }
static int checkEnumFreqBands(struct node *node, __u32 tuner, __u32 type, __u32 caps) { unsigned i; __u32 caps_union = 0; for (i = 0; ; i++) { struct v4l2_frequency_band band; int ret; memset(band.reserved, 0, sizeof(band.reserved)); band.tuner = tuner; band.type = type; band.index = i; ret = doioctl(node, VIDIOC_ENUM_FREQ_BANDS, &band); if (ret == EINVAL && i) return 0; if (ret) return fail("couldn't get freq band\n"); caps_union |= band.capability; if ((caps & V4L2_TUNER_CAP_LOW) != (band.capability & V4L2_TUNER_CAP_LOW)) return fail("Inconsistent CAP_LOW usage\n"); fail_on_test(band.rangehigh < band.rangelow); fail_on_test(band.index != i); fail_on_test(band.type != type); fail_on_test(band.tuner != tuner); fail_on_test((band.capability & V4L2_TUNER_CAP_FREQ_BANDS) == 0); check_0(band.reserved, sizeof(band.reserved)); } fail_on_test(caps_union != caps); return 0; }
static int set_interface(int iIf, int iAlt) { struct usbdevfs_setinterface SetIf = {0}; SetIf.interface = iIf; SetIf.altsetting = iAlt; return doioctl(USBDEVFS_SETINTERFACE, &SetIf, "set_interface"); }
static int testSlicedVBICapType(struct node *node, enum v4l2_buf_type type) { struct v4l2_sliced_vbi_cap cap; bool sliced_type = (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE || type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT); __u32 service_set = 0; int ret; memset(&cap, 0xff, sizeof(cap)); memset(&cap.reserved, 0, sizeof(cap.reserved)); cap.type = type; ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap); fail_on_test(check_0(cap.reserved, sizeof(cap.reserved))); fail_on_test(cap.type != type); fail_on_test(ret && ret != EINVAL && sliced_type); if (ret == EINVAL) { fail_on_test(sliced_type && (node->caps & buftype2cap[type])); if (node->caps & (V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT)) return 0; return -ENOSYS; } if (ret) return fail("expected EINVAL, but got %d when getting sliced VBI caps buftype %d\n", ret, type); fail_on_test(!(node->caps & buftype2cap[type])); for (int f = 0; f < 2; f++) for (int i = 0; i < 24; i++) service_set |= cap.service_lines[f][i]; fail_on_test(cap.service_set != service_set); fail_on_test(cap.service_lines[0][0] || cap.service_lines[1][0]); return 0; }
int testEnumInputAudio(struct node *node) { struct v4l2_audio input; unsigned i = 0; int ret; for (;;) { memset(&input, 0xff, sizeof(input)); input.index = i; ret = doioctl(node, VIDIOC_ENUMAUDIO, &input); if (i == 0 && ret == EINVAL) return -ENOSYS; if (ret == EINVAL) break; if (ret) return fail("could not enumerate audio input %d\n", i); if (checkInputAudio(input, i)) return fail("invalid attributes for audio input %d\n", i); node->audio_inputs++; i++; } if (node->audio_inputs && !(node->caps & V4L2_CAP_AUDIO)) return fail("audio inputs reported, but no CAP_AUDIO set\n"); return 0; }
int testEnumOutputAudio(struct node *node) { struct v4l2_audioout output; unsigned o = 0; int ret; for (;;) { memset(&output, 0xff, sizeof(output)); output.index = o; ret = doioctl(node, VIDIOC_ENUMAUDOUT, &output); if (o == 0 && ret == EINVAL) return -ENOSYS; if (ret == EINVAL) break; if (ret) return fail("could not enumerate audio output %d\n", o); if (checkOutputAudio(output, o)) return fail("invalid attributes for audio output %d\n", o); node->audio_outputs++; o++; } if (node->audio_outputs && !(node->caps & V4L2_CAP_AUDIO)) return fail("audio outputs reported, but no CAP_AUDIO set\n"); return 0; }
static int standby_resume_active_source_nowake(struct node *node, unsigned me, unsigned la, bool interactive) { if (!node->remote[la].in_standby) return NOTAPPLICABLE; struct cec_msg msg = {}; unsigned unresponsive_time = 0; __u8 new_status; node->remote[la].in_standby = false; /* In CEC 2.0 it is specified that a device shall not go out of standby if an Active Source message is received. */ announce("Sending Active Source message."); cec_msg_init(&msg, me, la); cec_msg_active_source(&msg, node->phys_addr); int res = doioctl(node, CEC_TRANSMIT, &msg); fail_on_test(res && res != ENONET); fail_on_test(wait_changing_power_status(node, me, la, new_status, unresponsive_time)); fail_on_test_v2_warn(node->remote[la].cec_version, new_status != CEC_OP_POWER_STATUS_STANDBY); node->remote[la].in_standby = true; if (unresponsive_time > 0) warn("The device stayed correctly in standby, but became unresponsive for %d s.\n", unresponsive_time); return 0; }
static int testSlicedVBICapType(struct node *node, unsigned type) { struct v4l2_sliced_vbi_cap cap; bool sliced_type = (type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE || type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT); __u32 service_set = 0; int ret; memset(&cap, 0xff, sizeof(cap)); memset(&cap.reserved, 0, sizeof(cap.reserved)); cap.type = type; ret = doioctl(node, VIDIOC_G_SLICED_VBI_CAP, &cap); if (ret == ENOTTY) { fail_on_test(sliced_type && (node->caps & buftype2cap[type])); return ret; } fail_on_test(check_0(cap.reserved, sizeof(cap.reserved))); fail_on_test(cap.type != type); fail_on_test(ret && ret != EINVAL); fail_on_test(ret && sliced_type && (node->caps & buftype2cap[type])); fail_on_test(!ret && (!sliced_type || !(node->caps & buftype2cap[type]))); if (ret) return 0; for (int f = 0; f < 2; f++) for (int i = 0; i < 24; i++) service_set |= cap.service_lines[f][i]; fail_on_test(cap.service_set != service_set); fail_on_test(cap.service_lines[0][0] || cap.service_lines[1][0]); return 0; }
static void print_devices(dev_vec files) { dev_map cards; int fd = -1; std::string bus_info; struct v4l2_capability vcap; for (dev_vec::iterator iter = files.begin(); iter != files.end(); ++iter) { fd = open(iter->c_str(), O_RDWR); memset(&vcap, 0, sizeof(vcap)); if (fd < 0) continue; doioctl(fd, VIDIOC_QUERYCAP, &vcap); close(fd); bus_info = (const char *)vcap.bus_info; if (cards[bus_info].empty()) cards[bus_info] += std::string((char *)vcap.card) + " (" + bus_info + "):\n"; cards[bus_info] += "\t" + (*iter); cards[bus_info] += "\n"; } for (dev_map::iterator iter = cards.begin(); iter != cards.end(); ++iter) { printf("%s\n", iter->second.c_str()); } }
int testTryFormats(struct node *node) { struct v4l2_format fmt, fmt_try; int type; int ret; for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; memset(&fmt, 0xff, sizeof(fmt)); fmt.type = type; doioctl(node, VIDIOC_G_FMT, &fmt); fmt_try = fmt; ret = doioctl(node, VIDIOC_TRY_FMT, &fmt_try); if (ret) return fail("%s is valid, but no TRY_FMT was implemented\n", buftype2s(type).c_str()); ret = testFormatsType(node, ret, type, fmt_try); if (ret) return ret; if (memcmp(&fmt, &fmt_try, sizeof(fmt))) return fail("TRY_FMT(G_FMT) != G_FMT\n"); } for (type = 0; type <= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; type++) { if (!(node->valid_buftypes & (1 << type))) continue; memset(&fmt, 0xff, sizeof(fmt)); fmt.type = type; fmt.fmt.pix.field = V4L2_FIELD_ANY; ret = doioctl(node, VIDIOC_TRY_FMT, &fmt); ret = testFormatsType(node, ret, type, fmt); if (ret) return fail("%s is valid, but TRY_FMT failed to return a format\n", buftype2s(type).c_str()); } memset(&fmt, 0xff, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_PRIVATE; ret = doioctl(node, VIDIOC_TRY_FMT, &fmt); if (!ret) warn("Buffer type PRIVATE allowed!\n"); return node->valid_buftypes ? 0 : ENOTTY; }
static int usb_set_connected(int ifnum, int conn) { struct usbdevfs_ioctl io; io.ifno = ifnum; io.ioctl_code = (conn) ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT; io.data = NULL; return doioctl(USBDEVFS_IOCTL, &io, "set_connected"); }
/*===========================================================================* * driver_task * *===========================================================================*/ PUBLIC void driver_task(void) { /* Main program of any device driver task. */ int r; message mess; /* Here is the main loop of the disk task. It waits for a message, carries * it out, and sends a reply. */ while (TRUE) { printf("CD: waiting for messages\n"); /* Wait for a request to read or write a disk block. */ if(receive(ANY, &mess) != OK) continue; device_caller = mess.m_source; proc_nr = mess.PROC_NR; printf("CD: message from %u, type %u\n",device_caller,proc_nr,mess.m_type); /* Now carry out the work. */ switch(mess.m_type) { case DEV_OPEN: case DEV_CLOSE: case CANCEL: case DEV_SELECT: /* forwards message to diskdriver and forwards response to caller*/ mess.m_source = thispid; /*make this the source*/ if(OK != sendrec(DRVR_PROC_NR, &mess)) panic("CryptcDrive","2 Message not sent back",s); printf("CD: waiting for diskdriver\n"); mess.m_source = thispid; /*make this the source*/ if(OK != send(device_caller, &mess)) panic("CryptDrive","3 Message not sent back",s); printf("CD: message to %u\n",device_caller); break; case DEV_IOCTL: doioctl(&mess); case DEV_READ: case DEV_WRITE: do_rdwt(&mess); break; case DEV_GATHER: case DEV_SCATTER: do_vrdwt(&mess); break; case HARD_INT: case SYS_SIG: case SYN_ALARM: break; /* don't reply */ } } }
int testControlEvents(struct node *node) { qctrl_list::iterator iter; for (iter = node->controls.begin(); iter != node->controls.end(); ++iter) { struct v4l2_event_subscription sub = { 0 }; struct v4l2_event ev; struct timeval timeout = { 0, 100 }; fd_set set; int ret; info("checking control event '%s' (0x%08x)\n", iter->name, iter->id); sub.type = V4L2_EVENT_CTRL; sub.id = iter->id; sub.flags = V4L2_EVENT_SUB_FL_SEND_INITIAL; ret = doioctl(node, VIDIOC_SUBSCRIBE_EVENT, &sub); if (ret) return fail("subscribe event for control '%s' failed\n", iter->name); //if (iter->type == V4L2_CTRL_TYPE_CTRL_CLASS) FD_ZERO(&set); FD_SET(node->fd, &set); ret = select(node->fd + 1, NULL, NULL, &set, &timeout); if (ret == 0) { if (iter->type != V4L2_CTRL_TYPE_CTRL_CLASS) return fail("failed to find event for control '%s'\n", iter->name); } else if (iter->type == V4L2_CTRL_TYPE_CTRL_CLASS) { return fail("found event for control class '%s'\n", iter->name); } if (ret) { ret = doioctl(node, VIDIOC_DQEVENT, &ev); if (ret) return fail("couldn't get event for control '%s'\n", iter->name); if (ev.type != V4L2_EVENT_CTRL || ev.id != iter->id) return fail("dequeued wrong event\n"); } ret = doioctl(node, VIDIOC_UNSUBSCRIBE_EVENT, &sub); if (ret) return fail("unsubscribe event for control '%s' failed\n", iter->name); } if (node->controls.empty()) return ENOTTY; return 0; }