static int amdm37x_dispc_dev_add(ddf_dev_t *dev) { assert(dev); /* Visualizer part */ ddf_fun_t *fun = ddf_fun_create(dev, fun_exposed, "viz"); if (!fun) { ddf_log_error("Failed to create visualizer function\n"); return ENOMEM; } visualizer_t *vis = ddf_fun_data_alloc(fun, sizeof(visualizer_t)); if (!vis) { ddf_log_error("Failed to allocate visualizer structure\n"); ddf_fun_destroy(fun); return ENOMEM; } graph_init_visualizer(vis); vis->reg_svc_handle = ddf_fun_get_handle(fun); ddf_fun_set_ops(fun, &graph_fun_ops); /* Hw part */ amdm37x_dispc_t *dispc = ddf_dev_data_alloc(dev, sizeof(amdm37x_dispc_t)); if (!dispc) { ddf_log_error("Failed to allocate dispc structure\n"); ddf_fun_destroy(fun); return ENOMEM; } int ret = amdm37x_dispc_init(dispc, vis); if (ret != EOK) { ddf_log_error("Failed to init dispc: %s\n", str_error(ret)); ddf_fun_destroy(fun); return ret; } /* Report to devman */ ret = ddf_fun_bind(fun); if (ret != EOK) { ddf_log_error("Failed to bind function: %s\n", str_error(ret)); amdm37x_dispc_fini(dispc); ddf_fun_destroy(fun); return ret; } ddf_fun_add_to_category(fun, "visualizer"); ddf_log_note("Added device `%s'\n", ddf_dev_get_name(dev)); return EOK; }
/** Initialize keyboard driver structure. * * @param kbd Keyboard driver structure to initialize. * @param dev DDF device structure. * * Connects to parent, creates keyboard function, starts polling fibril. * */ int at_kbd_init(at_kbd_t *kbd, ddf_dev_t *dev) { assert(kbd); assert(dev); kbd->client_sess = NULL; kbd->parent_sess = ddf_dev_parent_sess_create(dev); if (!kbd->parent_sess) { ddf_msg(LVL_ERROR, "Failed creating parent session."); return EIO; } kbd->kbd_fun = ddf_fun_create(dev, fun_exposed, "kbd"); if (!kbd->kbd_fun) { ddf_msg(LVL_ERROR, "Failed creating function 'kbd'."); return ENOMEM; } ddf_fun_set_ops(kbd->kbd_fun, &kbd_ops); int ret = ddf_fun_bind(kbd->kbd_fun); if (ret != EOK) { ddf_msg(LVL_ERROR, "Failed binding function 'kbd'."); ddf_fun_destroy(kbd->kbd_fun); return EEXIST; } ret = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard"); if (ret != EOK) { ddf_msg(LVL_ERROR, "Failed adding function 'kbd' to category " "'keyboard'."); ddf_fun_unbind(kbd->kbd_fun); ddf_fun_destroy(kbd->kbd_fun); return ENOMEM; } kbd->polling_fibril = fibril_create(polling, kbd); if (!kbd->polling_fibril) { ddf_msg(LVL_ERROR, "Failed creating polling fibril."); ddf_fun_unbind(kbd->kbd_fun); ddf_fun_destroy(kbd->kbd_fun); return ENOMEM; } fibril_add_ready(kbd->polling_fibril); return EOK; }
static bool mac_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id, mac_fun_t *fun_proto) { ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name); ddf_fun_t *fnode = NULL; int rc; /* Create new device. */ fnode = ddf_fun_create(dev, fun_inner, name); if (fnode == NULL) goto failure; mac_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(mac_fun_t)); *fun = *fun_proto; /* Add match ID */ rc = ddf_fun_add_match_id(fnode, str_match_id, 100); if (rc != EOK) goto failure; /* Set provided operations to the device. */ ddf_fun_set_ops(fnode, &mac_fun_ops); /* Register function. */ if (ddf_fun_bind(fnode) != EOK) { ddf_msg(LVL_ERROR, "Failed binding function %s.", name); goto failure; } return true; failure: if (fnode != NULL) ddf_fun_destroy(fnode); ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name); return false; }
static int rootamdm37x_add_fun(ddf_dev_t *dev, const char *name, const char *str_match_id, const rootamdm37x_fun_t *fun) { ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name); /* Create new device function. */ ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name); if (fnode == NULL) return ENOMEM; /* Add match id */ int ret = ddf_fun_add_match_id(fnode, str_match_id, 100); if (ret != EOK) { ddf_fun_destroy(fnode); return ret; } /* Alloc needed data */ rootamdm37x_fun_t *rf = ddf_fun_data_alloc(fnode, sizeof(rootamdm37x_fun_t)); if (!rf) { ddf_fun_destroy(fnode); return ENOMEM; } *rf = *fun; /* Set provided operations to the device. */ ddf_fun_set_ops(fnode, &rootamdm37x_fun_ops); /* Register function. */ ret = ddf_fun_bind(fnode); if (ret != EOK) { ddf_msg(LVL_ERROR, "Failed binding function %s.", name); ddf_fun_destroy(fnode); return ret; } return EOK; }
/** Initialize keyboard driver structure. * @param kbd Keyboard driver structure to initialize. * @param dev DDF device structure. * * Connects to parent, creates mouse function, starts polling fibril. */ int xt_kbd_init(xt_kbd_t *kbd, ddf_dev_t *dev) { assert(kbd); assert(dev); kbd->client_sess = NULL; kbd->parent_sess = ddf_dev_parent_sess_create(dev, EXCHANGE_SERIALIZE); if (!kbd->parent_sess) return ENOMEM; kbd->kbd_fun = ddf_fun_create(dev, fun_exposed, "kbd"); if (!kbd->kbd_fun) { return ENOMEM; } ddf_fun_set_ops(kbd->kbd_fun, &kbd_ops); int ret = ddf_fun_bind(kbd->kbd_fun); if (ret != EOK) { ddf_fun_destroy(kbd->kbd_fun); return ENOMEM; } ret = ddf_fun_add_to_category(kbd->kbd_fun, "keyboard"); if (ret != EOK) { ddf_fun_unbind(kbd->kbd_fun); ddf_fun_destroy(kbd->kbd_fun); return ENOMEM; } kbd->polling_fibril = fibril_create(polling, kbd); if (!kbd->polling_fibril) { ddf_fun_unbind(kbd->kbd_fun); ddf_fun_destroy(kbd->kbd_fun); return ENOMEM; } fibril_add_ready(kbd->polling_fibril); return EOK; }
static int ne2k_dev_add(ddf_dev_t *dev) { ddf_fun_t *fun; /* Allocate driver data for the device. */ nic_t *nic_data = nic_create_and_bind(dev); if (nic_data == NULL) return ENOMEM; nic_set_send_frame_handler(nic_data, ne2k_send); nic_set_state_change_handlers(nic_data, ne2k_on_activating, NULL, ne2k_on_stopping); nic_set_filtering_change_handlers(nic_data, ne2k_on_unicast_mode_change, ne2k_on_multicast_mode_change, ne2k_on_broadcast_mode_change, NULL, NULL); ne2k_t *ne2k = malloc(sizeof(ne2k_t)); if (NULL != ne2k) { memset(ne2k, 0, sizeof(ne2k_t)); nic_set_specific(nic_data, ne2k); } else { nic_unbind_and_destroy(dev); return ENOMEM; } int rc = ne2k_dev_init(nic_data); if (rc != EOK) { ne2k_dev_cleanup(dev); return rc; } rc = nic_report_address(nic_data, &ne2k->mac); if (rc != EOK) { ne2k_dev_cleanup(dev); return rc; } rc = nic_connect_to_services(nic_data); if (rc != EOK) { ne2k_dev_cleanup(dev); return rc; } fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0"); if (fun == NULL) { ne2k_dev_cleanup(dev); return ENOMEM; } nic_set_ddf_fun(nic_data, fun); ddf_fun_set_ops(fun, &ne2k_dev_ops); ddf_fun_data_implant(fun, nic_data); rc = ddf_fun_bind(fun); if (rc != EOK) { ddf_fun_destroy(fun); ne2k_dev_cleanup(dev); return rc; } rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); if (rc != EOK) { ddf_fun_unbind(fun); ddf_fun_destroy(fun); return rc; } return EOK; }
/** * Processes key events. * * @note This function was copied from AT keyboard driver and modified to suit * USB keyboard. * * @note Lock keys are not sent to the console, as they are completely handled * in the driver. It may, however, be required later that the driver * sends also these keys to application (otherwise it cannot use those * keys at all). * * @param hid_dev * @param multim_dev * @param type Type of the event (press / release). Recognized values: * KEY_PRESS, KEY_RELEASE * @param key Key code of the key according to HID Usage Tables. */ static void usb_multimedia_push_ev( usb_multimedia_t *multim_dev, int type, unsigned int key) { assert(multim_dev != NULL); const kbd_event_t ev = { .type = type, .key = key, .mods = 0, .c = 0, }; usb_log_debug2(NAME " Sending key %d to the console\n", ev.key); if (multim_dev->console_sess == NULL) { usb_log_warning( "Connection to console not ready, key discarded.\n"); return; } async_exch_t *exch = async_exchange_begin(multim_dev->console_sess); if (exch != NULL) { async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c); async_exchange_end(exch); } else { usb_log_warning("Failed to send multimedia key.\n"); } } int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data) { if (hid_dev == NULL || hid_dev->usb_dev == NULL) { return EINVAL; } usb_log_debug(NAME " Initializing HID/multimedia structure...\n"); /* Create the exposed function. */ ddf_fun_t *fun = ddf_fun_create( hid_dev->usb_dev->ddf_dev, fun_exposed, NAME); if (fun == NULL) { usb_log_error("Could not create DDF function node.\n"); return ENOMEM; } ddf_fun_set_ops(fun, &multimedia_ops); usb_multimedia_t *multim_dev = ddf_fun_data_alloc(fun, sizeof(usb_multimedia_t)); if (multim_dev == NULL) { ddf_fun_destroy(fun); return ENOMEM; } multim_dev->console_sess = NULL; //todo Autorepeat? int rc = ddf_fun_bind(fun); if (rc != EOK) { usb_log_error("Could not bind DDF function: %s.\n", str_error(rc)); ddf_fun_destroy(fun); return rc; } usb_log_debug(NAME " function created (handle: %" PRIun ").\n", ddf_fun_get_handle(fun)); rc = ddf_fun_add_to_category(fun, "keyboard"); if (rc != EOK) { usb_log_error( "Could not add DDF function to category 'keyboard': %s.\n", str_error(rc)); if (ddf_fun_unbind(fun) != EOK) { usb_log_error("Failed to unbind %s, won't destroy.\n", ddf_fun_get_name(fun)); } else { ddf_fun_destroy(fun); } return rc; } /* Save the KBD device structure into the HID device structure. */ *data = fun; usb_log_debug(NAME " HID/multimedia structure initialized.\n"); return EOK; } void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data) { ddf_fun_t *fun = data; usb_multimedia_t *multim_dev = ddf_fun_data_get(fun); /* Hangup session to the console */ if (multim_dev->console_sess) async_hangup(multim_dev->console_sess); if (ddf_fun_unbind(fun) != EOK) { usb_log_error("Failed to unbind %s, won't destroy.\n", ddf_fun_get_name(fun)); } else { usb_log_debug2("%s unbound.\n", ddf_fun_get_name(fun)); /* This frees multim_dev too as it was stored in * fun->data */ ddf_fun_destroy(fun); } }
/** Initialize i8042 driver structure. * * @param dev Driver structure to initialize. * @param regs I/O address of registers. * @param reg_size size of the reserved I/O address space. * @param irq_kbd IRQ for primary port. * @param irq_mouse IRQ for aux port. * @param ddf_dev DDF device structure of the device. * * @return Error code. * */ int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd, int irq_mouse, ddf_dev_t *ddf_dev) { const size_t range_count = sizeof(i8042_ranges) / sizeof(irq_pio_range_t); irq_pio_range_t ranges[range_count]; const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t); irq_cmd_t cmds[cmd_count]; int rc; bool kbd_bound = false; bool aux_bound = false; dev->kbd_fun = NULL; dev->aux_fun = NULL; if (reg_size < sizeof(i8042_regs_t)) { rc = EINVAL; goto error; } if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) { rc = EIO; goto error; } dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a"); if (dev->kbd_fun == NULL) { rc = ENOMEM; goto error; }; rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90); if (rc != EOK) goto error; dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b"); if (dev->aux_fun == NULL) { rc = ENOMEM; goto error; } rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90); if (rc != EOK) goto error; ddf_fun_set_ops(dev->kbd_fun, &ops); ddf_fun_set_ops(dev->aux_fun, &ops); buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE); buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE); fibril_mutex_initialize(&dev->write_guard); rc = ddf_fun_bind(dev->kbd_fun); if (rc != EOK) { ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.", ddf_fun_get_name(dev->kbd_fun)); goto error; } kbd_bound = true; rc = ddf_fun_bind(dev->aux_fun); if (rc != EOK) { ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.", ddf_fun_get_name(dev->aux_fun)); goto error; } aux_bound = true; /* Disable kbd and aux */ wait_ready(dev); pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB); wait_ready(dev); pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE); /* Flush all current IO */ while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL) (void) pio_read_8(&dev->regs->data); memcpy(ranges, i8042_ranges, sizeof(i8042_ranges)); ranges[0].base = (uintptr_t) regs; memcpy(cmds, i8042_cmds, sizeof(i8042_cmds)); cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status); cmds[3].addr = (void *) &(((i8042_regs_t *) regs)->data); irq_code_t irq_code = { .rangecount = range_count, .ranges = ranges, .cmdcount = cmd_count, .cmds = cmds }; rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler, &irq_code); if (rc != EOK) { ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.", ddf_dev_get_name(ddf_dev)); goto error; } rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler, &irq_code); if (rc != EOK) { ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.", ddf_dev_get_name(ddf_dev)); goto error; } /* Enable interrupts */ async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev); assert(parent_sess != NULL); const bool enabled = hw_res_enable_interrupt(parent_sess); if (!enabled) { log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.", ddf_dev_get_name(ddf_dev)); rc = EIO; goto error; } /* Enable port interrupts. */ wait_ready(dev); pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB); wait_ready(dev); pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE | i8042_AUX_IE); return EOK; error: if (kbd_bound) ddf_fun_unbind(dev->kbd_fun); if (aux_bound) ddf_fun_unbind(dev->aux_fun); if (dev->kbd_fun != NULL) ddf_fun_destroy(dev->kbd_fun); if (dev->aux_fun != NULL) ddf_fun_destroy(dev->aux_fun); return rc; }
static int vhc_dev_add(ddf_dev_t *dev) { static int vhc_count = 0; int rc; if (vhc_count > 0) { return ELIMIT; } vhc_data_t *data = ddf_dev_data_alloc(dev, sizeof(vhc_data_t)); if (data == NULL) { usb_log_fatal("Failed to allocate memory.\n"); return ENOMEM; } data->magic = 0xDEADBEEF; rc = usb_endpoint_manager_init(&data->ep_manager, (size_t) -1, bandwidth_count_usb11); if (rc != EOK) { usb_log_fatal("Failed to initialize endpoint manager.\n"); free(data); return rc; } usb_device_manager_init(&data->dev_manager, USB_SPEED_MAX); ddf_fun_t *hc = ddf_fun_create(dev, fun_exposed, "hc"); if (hc == NULL) { usb_log_fatal("Failed to create device function.\n"); free(data); return ENOMEM; } ddf_fun_set_ops(hc, &vhc_ops); list_initialize(&data->devices); fibril_mutex_initialize(&data->guard); data->hub = &virtual_hub_device; data->hc_fun = hc; rc = ddf_fun_bind(hc); if (rc != EOK) { usb_log_fatal("Failed to bind HC function: %s.\n", str_error(rc)); free(data); return rc; } rc = ddf_fun_add_to_category(hc, USB_HC_CATEGORY); if (rc != EOK) { usb_log_fatal("Failed to add function to HC class: %s.\n", str_error(rc)); free(data); return rc; } virtual_hub_device_init(hc); usb_log_info("Virtual USB host controller ready (dev %zu, hc %zu).\n", (size_t) ddf_dev_get_handle(dev), (size_t) ddf_fun_get_handle(hc)); rc = vhc_virtdev_plug_hub(data, data->hub, NULL); if (rc != EOK) { usb_log_fatal("Failed to plug root hub: %s.\n", str_error(rc)); free(data); return rc; } return EOK; }