static void filter_redirector_setup(NetFilterState *nf, Error **errp) { MirrorState *s = FILTER_REDIRECTOR(nf); Chardev *chr; if (!s->indev && !s->outdev) { error_setg(errp, "filter redirector needs 'indev' or " "'outdev' at least one property set"); return; } else if (s->indev && s->outdev) { if (!strcmp(s->indev, s->outdev)) { error_setg(errp, "'indev' and 'outdev' could not be same " "for filter redirector"); return; } } net_socket_rs_init(&s->rs, redirector_rs_finalize); if (s->indev) { chr = qemu_chr_find(s->indev); if (chr == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "IN Device '%s' not found", s->indev); return; } if (!qemu_chr_fe_init(&s->chr_in, chr, errp)) { return; } qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read, redirector_chr_read, redirector_chr_event, nf, NULL, true); } if (s->outdev) { chr = qemu_chr_find(s->outdev); if (chr == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "OUT Device '%s' not found", s->outdev); return; } if (!qemu_chr_fe_init(&s->chr_out, chr, errp)) { return; } } }
static CharDriverState *net_vhost_parse_chardev(const NetdevVhostUserOptions *opts) { CharDriverState *chr = qemu_chr_find(opts->chardev); VhostUserChardevProps props; if (chr == NULL) { error_report("chardev \"%s\" not found", opts->chardev); return NULL; } /* inspect chardev opts */ memset(&props, 0, sizeof(props)); if (qemu_opt_foreach(chr->opts, net_vhost_chardev_opts, &props, true) != 0) { return NULL; } if (!props.is_socket || !props.is_unix) { error_report("chardev \"%s\" is not a unix socket", opts->chardev); return NULL; } qemu_chr_fe_claim_no_fail(chr); return chr; }
static void rng_egd_opened(RngBackend *b, Error **errp) { RngEgd *s = RNG_EGD(b); if (s->chr_name == NULL) { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "chardev", "a valid character device"); return; } s->chr = qemu_chr_find(s->chr_name); if (s->chr == NULL) { error_set(errp, QERR_DEVICE_NOT_FOUND, s->chr_name); return; } if (qemu_chr_fe_claim(s->chr) != 0) { error_set(errp, QERR_DEVICE_IN_USE, s->chr_name); return; } /* FIXME we should resubmit pending requests when the CDS reconnects. */ qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read, NULL, s); }
static int parse_chr(DeviceState *dev, const char *str, void **ptr) { CharDriverState *chr = qemu_chr_find(str); if (chr == NULL) { return -ENOENT; } if (qemu_chr_fe_claim(chr) != 0) { return -EEXIST; } *ptr = chr; return 0; }
static int parse_chr(DeviceState *dev, const char *str, void **ptr) { CharDriverState *chr = qemu_chr_find(str); if (chr == NULL) { return -ENOENT; } if (chr->avail_connections < 1) { return -EEXIST; } *ptr = chr; --chr->avail_connections; return 0; }
static void filter_mirror_setup(NetFilterState *nf, Error **errp) { MirrorState *s = FILTER_MIRROR(nf); Chardev *chr; chr = qemu_chr_find(s->outdev); if (chr == NULL) { error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found", s->outdev); return; } qemu_chr_fe_init(&s->chr_out, chr, errp); }
static int parse_chr(DeviceState *dev, Property *prop, const char *str) { CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); *ptr = qemu_chr_find(str); if (*ptr == NULL) { return -ENOENT; } if ((*ptr)->avail_connections < 1) { return -EEXIST; } --(*ptr)->avail_connections; return 0; }
static void parse_chr(DeviceState *dev, const char *str, void **ptr, const char *propname, Error **errp) { CharDriverState *chr = qemu_chr_find(str); if (chr == NULL) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(OBJECT(dev)), propname, str); return; } if (qemu_chr_fe_claim(chr) != 0) { error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use", object_get_typename(OBJECT(dev)), propname, str); return; } *ptr = chr; }
static int stm32_button_init(SysBusDevice *dev, const char* id) { stm32_button_state *s = FROM_SYSBUS(stm32_button_state, dev); //Initialisation de la pin de sortie //Initialisation of the output pin qdev_init_gpio_out(&dev->qdev, &s->gpio_out, 1); //Initialisation du Chardev s->chr = qdev_init_chardev(&dev->qdev); s->chr = qemu_chr_find(id); if (s->chr) { qemu_chr_add_handlers(s->chr, stm32_can_receive, stm32_receive, stm32_event, s); } stm32_button_reset(s); vmstate_register(&dev->qdev, -1, &vmstate_stm32_button, s); return 0; }
/* * Return 0 is success. * Return 1 is failed. */ static int find_and_check_chardev(Chardev **chr, char *chr_name, Error **errp) { *chr = qemu_chr_find(chr_name); if (*chr == NULL) { error_setg(errp, "Device '%s' not found", chr_name); return 1; } if (!qemu_chr_has_feature(*chr, QEMU_CHAR_FEATURE_RECONNECTABLE)) { error_setg(errp, "chardev \"%s\" is not reconnectable", chr_name); return 1; } return 0; }
static int stm32_led_init(SysBusDevice *dev, const char* id) { stm32_led_state *s = FROM_SYSBUS(stm32_led_state, dev); //Initialisation des pins d'entrées qdev_init_gpio_in(&dev->qdev, stm32_led_recvirq, 1); //Initialiser le chardev s->chr = qdev_init_chardev(&dev->qdev); s->chr = qemu_chr_find(id); if (s->chr) { qemu_chr_add_handlers(s->chr, stm32_can_receive, stm32_receive, stm32_event, s); } stm32_led_reset(s); vmstate_register(&dev->qdev, -1, &vmstate_stm32_led, s); return 0; }
static void qemu_chr_open_mux(Chardev *chr, ChardevBackend *backend, bool *be_opened, Error **errp) { ChardevMux *mux = backend->u.mux.data; Chardev *drv; MuxChardev *d = MUX_CHARDEV(chr); drv = qemu_chr_find(mux->chardev); if (drv == NULL) { error_setg(errp, "mux: base chardev %s not found", mux->chardev); return; } d->focus = -1; /* only default to opened state if we've realized the initial * set of muxes */ *be_opened = machine_init_done; qemu_chr_fe_init(&d->chr, drv, errp); }
static Chardev *net_vhost_claim_chardev( const NetdevVhostUserOptions *opts, Error **errp) { Chardev *chr = qemu_chr_find(opts->chardev); if (chr == NULL) { error_setg(errp, "chardev \"%s\" not found", opts->chardev); return NULL; } if (!qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE)) { error_setg(errp, "chardev \"%s\" is not reconnectable", opts->chardev); return NULL; } if (!qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_FD_PASS)) { error_setg(errp, "chardev \"%s\" does not support FD passing", opts->chardev); return NULL; } return chr; }
static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); Error *local_err = NULL; Property *prop = opaque; CharBackend *be = qdev_get_prop_ptr(dev, prop); CharDriverState *s; char *str; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); return; } visit_type_str(v, name, &str, &local_err); if (local_err) { error_propagate(errp, local_err); return; } if (!*str) { g_free(str); be->chr = NULL; return; } s = qemu_chr_find(str); if (s == NULL) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(obj), prop->name, str); } else if (!qemu_chr_fe_init(be, s, errp)) { error_prepend(errp, "Property '%s.%s' can't take value '%s': ", object_get_typename(obj), prop->name, str); } g_free(str); }
static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts) { const char *value; value = qemu_opt_get(opts, "chardev"); if (value) { Error *err = NULL; Chardev *dev = qemu_chr_find(value); if (!dev) { error_report("tpm-emulator: tpm chardev '%s' not found.", value); goto err; } if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) { error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':", value); error_report_err(err); goto err; } tpm_emu->options->chardev = g_strdup(value); } if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) { goto err; } /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used * by passthrough driver, which not yet using GIOChannel. */ if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd, &tpm_emu->tpm_version)) { error_report("'%s' is not emulating TPM device. Error: %s", tpm_emu->options->chardev, strerror(errno)); goto err; } switch (tpm_emu->tpm_version) { case TPM_VERSION_1_2: trace_tpm_emulator_handle_device_opts_tpm12(); break; case TPM_VERSION_2_0: trace_tpm_emulator_handle_device_opts_tpm2(); break; default: trace_tpm_emulator_handle_device_opts_unspec(); } if (tpm_emulator_probe_caps(tpm_emu) || tpm_emulator_check_caps(tpm_emu)) { goto err; } return tpm_emulator_block_migration(tpm_emu); err: trace_tpm_emulator_handle_device_opts_startup_error(); return -1; }
static void char_mux_test(void) { QemuOpts *opts; Chardev *chr, *base; char *data; FeHandler h1 = { 0, false, 0, false, }, h2 = { 0, false, 0, false, }; CharBackend chr_be1, chr_be2; opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label", 1, &error_abort); qemu_opt_set(opts, "backend", "ringbuf", &error_abort); qemu_opt_set(opts, "size", "128", &error_abort); qemu_opt_set(opts, "mux", "on", &error_abort); chr = qemu_chr_new_from_opts(opts, NULL, &error_abort); g_assert_nonnull(chr); qemu_opts_del(opts); qemu_chr_fe_init(&chr_be1, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be1, fe_can_read, fe_read, fe_event, NULL, &h1, NULL, true); qemu_chr_fe_init(&chr_be2, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, true); qemu_chr_fe_take_focus(&chr_be2); base = qemu_chr_find("mux-label-base"); g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; g_assert_cmpint(h1.last_event, !=, 42); /* should be MUX_OUT or OPENED */ g_assert_cmpint(h2.last_event, !=, 42); /* should be MUX_IN or OPENED */ /* sending event on the base broadcast to all fe, historical reasons? */ qemu_chr_be_event(base, 42); g_assert_cmpint(h1.last_event, ==, 42); g_assert_cmpint(h2.last_event, ==, 42); qemu_chr_be_event(chr, -1); g_assert_cmpint(h1.last_event, ==, 42); g_assert_cmpint(h2.last_event, ==, -1); /* switch focus */ qemu_chr_be_write(base, (void *)"\1b", 2); g_assert_cmpint(h1.last_event, ==, 42); g_assert_cmpint(h2.last_event, ==, CHR_EVENT_BREAK); qemu_chr_be_write(base, (void *)"\1c", 2); g_assert_cmpint(h1.last_event, ==, CHR_EVENT_MUX_IN); g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT); qemu_chr_be_event(chr, -1); g_assert_cmpint(h1.last_event, ==, -1); g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h2.read_count, ==, 0); g_assert_cmpint(h1.read_count, ==, 6); g_assert_cmpstr(h1.read_buf, ==, "hello"); h1.read_count = 0; qemu_chr_be_write(base, (void *)"\1b", 2); g_assert_cmpint(h1.last_event, ==, CHR_EVENT_BREAK); g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT); /* open/close state and corresponding events */ g_assert_true(qemu_chr_fe_backend_open(&chr_be1)); g_assert_true(qemu_chr_fe_backend_open(&chr_be2)); g_assert_true(h1.is_open); g_assert_false(h1.openclose_mismatch); g_assert_true(h2.is_open); g_assert_false(h2.openclose_mismatch); h1.openclose_count = h2.openclose_count = 0; qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, NULL, false); qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, NULL, NULL, NULL, NULL, false); g_assert_cmpint(h1.openclose_count, ==, 0); g_assert_cmpint(h2.openclose_count, ==, 0); h1.is_open = h2.is_open = false; qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, fe_event, NULL, &h1, NULL, false); qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, fe_event, NULL, &h2, NULL, false); g_assert_cmpint(h1.openclose_count, ==, 1); g_assert_false(h1.openclose_mismatch); g_assert_cmpint(h2.openclose_count, ==, 1); g_assert_false(h2.openclose_mismatch); qemu_chr_be_event(base, CHR_EVENT_CLOSED); qemu_chr_be_event(base, CHR_EVENT_OPENED); g_assert_cmpint(h1.openclose_count, ==, 3); g_assert_false(h1.openclose_mismatch); g_assert_cmpint(h2.openclose_count, ==, 3); g_assert_false(h2.openclose_mismatch); qemu_chr_fe_set_handlers(&chr_be2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, false); qemu_chr_fe_set_handlers(&chr_be1, fe_can_read, fe_read, fe_event, NULL, &h1, NULL, false); /* remove first handler */ qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, NULL, true); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 0); qemu_chr_be_write(base, (void *)"\1c", 2); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; /* print help */ qemu_chr_be_write(base, (void *)"\1?", 2); data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort); g_assert_cmpint(strlen(data), !=, 0); g_free(data); qemu_chr_fe_deinit(&chr_be1, false); qemu_chr_fe_deinit(&chr_be2, true); }
static void char_mux_test(void) { QemuOpts *opts; Chardev *chr, *base; char *data; FeHandler h1 = { 0, }, h2 = { 0, }; CharBackend chr_be1, chr_be2; opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label", 1, &error_abort); qemu_opt_set(opts, "backend", "ringbuf", &error_abort); qemu_opt_set(opts, "size", "128", &error_abort); qemu_opt_set(opts, "mux", "on", &error_abort); chr = qemu_chr_new_from_opts(opts, &error_abort); g_assert_nonnull(chr); qemu_opts_del(opts); qemu_chr_fe_init(&chr_be1, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be1, fe_can_read, fe_read, fe_event, NULL, &h1, NULL, true); qemu_chr_fe_init(&chr_be2, chr, &error_abort); qemu_chr_fe_set_handlers(&chr_be2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, true); qemu_chr_fe_take_focus(&chr_be2); base = qemu_chr_find("mux-label-base"); g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; /* switch focus */ qemu_chr_be_write(base, (void *)"\1c", 2); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h2.read_count, ==, 0); g_assert_cmpint(h1.read_count, ==, 6); g_assert_cmpstr(h1.read_buf, ==, "hello"); h1.read_count = 0; /* remove first handler */ qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, NULL, true); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 0); qemu_chr_be_write(base, (void *)"\1c", 2); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); g_assert_cmpint(h2.read_count, ==, 6); g_assert_cmpstr(h2.read_buf, ==, "hello"); h2.read_count = 0; /* print help */ qemu_chr_be_write(base, (void *)"\1?", 2); data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort); g_assert_cmpint(strlen(data), !=, 0); g_free(data); qemu_chr_fe_deinit(&chr_be1, false); qemu_chr_fe_deinit(&chr_be2, true); }
static void ss_realize(DeviceState *dev, Error **errp) { SlaveBootInt *s = SBI(dev); const char *prefix = object_get_canonical_path(OBJECT(dev)); unsigned int i; const char *port_name; Chardev *chr; for (i = 0; i < ARRAY_SIZE(slave_boot_regs_info); ++i) { DepRegisterInfo *r = &s->regs_info[ slave_boot_regs_info[i].decode.addr / 4]; *r = (DepRegisterInfo) { .data = (uint8_t *)&s->regs[ slave_boot_regs_info[i].decode.addr / 4], .data_size = sizeof(uint32_t), .access = &slave_boot_regs_info[i], .debug = SBI_ERR_DEBUG, .prefix = prefix, .opaque = s, }; } port_name = g_strdup("smap_busy_b"); qdev_init_gpio_out_named(dev, &s->smap_busy, port_name, 1); g_free((gpointer) port_name); port_name = g_strdup("smap_in_b"); qdev_init_gpio_in_named(dev, smap_update, port_name, 2); g_free((gpointer) port_name); chr = qemu_chr_find("sbi"); qdev_prop_set_chr(dev, "chardev", chr); if (!qemu_chr_fe_get_driver(&s->chr)) { DPRINT("SBI interface not connected\n"); } else { qemu_chr_fe_set_handlers(&s->chr, ss_sbi_can_receive, ss_sbi_receive, NULL, NULL, s, NULL, true); } fifo_create8(&s->fifo, 1024 * 4); } static void ss_reset(DeviceState *dev) { SlaveBootInt *s = SBI(dev); uint32_t i; for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) { dep_register_reset(&s->regs_info[i]); } fifo_reset(&s->fifo); s->busy_line = 1; qemu_set_irq(s->smap_busy, s->busy_line); ss_update_busy_line(s); sbi_update_irq(s); /* Note : cs always 0 when rp is not connected * i.e slave always respond to master data irrespective of * master state * * as rdwr is also 0, initial state of sbi is data load. Hack this bit * to become 1, when sbi changes to write mode. So, its assumed in * non remote-port model master should expect data when slave wishes * to send. */ }