Esempio n. 1
0
/** Callback when new device is passed to this driver.
 * This function is the body of the test: it shall register new child
 * (named `clone') that shall be driven by the same task. When the clone
 * is added, it registers another child (named `child') that is also driven
 * by this task. The conditions ensure that we do not recurse indefinitely.
 * When successful, the device tree shall contain following fragment:
 *
 * /virtual/test1
 * /virtual/test1/clone
 * /virtual/test1/clone/child
 *
 * and devman shall not deadlock.
 *
 *
 * @param dev New device.
 * @return Error code reporting success of the operation.
 */
static int test1_dev_add(ddf_dev_t *dev)
{
	ddf_fun_t *fun_a;
	test1_t *test1;
	int rc;

	ddf_msg(LVL_DEBUG, "dev_add(name=\"%s\", handle=%d)",
	    dev->name, (int) dev->handle);

	test1 = ddf_dev_data_alloc(dev, sizeof(test1_t));
	if (test1 == NULL) {
		ddf_msg(LVL_ERROR, "Failed allocating soft state.\n");
		return ENOMEM;
	}

	fun_a = ddf_fun_create(dev, fun_exposed, "a");
	if (fun_a == NULL) {
		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
		return ENOMEM;
	}

	test1->fun_a = fun_a;

	rc = ddf_fun_bind(fun_a);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
		ddf_fun_destroy(fun_a);
		return rc;
	}

	ddf_fun_add_to_category(fun_a, "virtual");

	if (str_cmp(dev->name, "null") == 0) {
		fun_a->ops = &char_device_ops;
		ddf_fun_add_to_category(fun_a, "virt-null");
	} else if (str_cmp(dev->name, "test1") == 0) {
		(void) register_fun_verbose(dev,
		    "cloning myself ;-)", "clone",
		    "virtual&test1", 10, EOK, &test1->clone);
		(void) register_fun_verbose(dev,
		    "cloning myself twice ;-)", "clone",
		    "virtual&test1", 10, EEXISTS, NULL);
	} else if (str_cmp(dev->name, "clone") == 0) {
		(void) register_fun_verbose(dev,
		    "run by the same task", "child",
		    "virtual&test1&child", 10, EOK, &test1->child);
	}

	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);

	return EOK;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/** 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;
}
Esempio n. 4
0
static int register_fun_and_add_to_category(ddf_dev_t *parent,
    const char *base_name, size_t index, const char *class_name,
    ddf_fun_t **pfun)
{
	ddf_fun_t *fun = NULL;
	int rc;
	char *fun_name = NULL;
	
	rc = asprintf(&fun_name, "%s%zu", base_name, index);
	if (rc < 0) {
		ddf_msg(LVL_ERROR, "Failed to format string: %s", str_error(rc));
		goto leave;
	}
	
	fun = ddf_fun_create(parent, fun_exposed, fun_name);
	if (fun == NULL) {
		ddf_msg(LVL_ERROR, "Failed creating function %s", fun_name);
		rc = ENOMEM;
		goto leave;
	}

	rc = ddf_fun_bind(fun);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", fun_name,
		    str_error(rc));
		goto leave;
	}
	
	ddf_fun_add_to_category(fun, class_name);

	ddf_msg(LVL_NOTE, "Registered exposed function `%s'.", fun_name);

leave:	
	free(fun_name);
	
	if ((rc != EOK) && (fun != NULL)) {
		ddf_fun_destroy(fun);
	}
	
	*pfun = fun;
	return rc;
}
Esempio n. 5
0
/** Simulate plugging and surprise unplugging.
 *
 * @param arg Parent device structure (ddf_dev_t *).
 * @return Always EOK.
 */
static int plug_unplug(void *arg)
{
	test2_t *test2 = (test2_t *) arg;
	ddf_fun_t *fun_a;
	int rc;

	async_usleep(1000);

	(void) register_fun_verbose(test2->dev, "child driven by the same task",
	    "child", "virtual&test2", 10, &test2->child);
	(void) register_fun_verbose(test2->dev, "child driven by test1",
	    "test1", "virtual&test1", 10, &test2->test1);

	fun_a = ddf_fun_create(test2->dev, fun_exposed, "a");
	if (fun_a == NULL) {
		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
		return ENOMEM;
	}

	rc = ddf_fun_bind(fun_a);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
		return rc;
	}

	ddf_fun_add_to_category(fun_a, "virtual");
	test2->fun_a = fun_a;

	async_usleep(10000000);

	ddf_msg(LVL_NOTE, "Unbinding function test1.");
	ddf_fun_unbind(test2->test1);
	async_usleep(1000000);
	ddf_msg(LVL_NOTE, "Unbinding function child.");
	ddf_fun_unbind(test2->child);

	return EOK;
}
Esempio n. 6
0
/** 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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
/**
 * 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);
	}
}
Esempio n. 9
0
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;
}