Example #1
0
static int test2_dev_remove(ddf_dev_t *dev)
{
	test2_t *test2 = (test2_t *)dev->driver_data;
	int rc;

	ddf_msg(LVL_DEBUG, "test2_dev_remove(%p)", dev);

	if (test2->fun_a != NULL) {
		rc = fun_remove(test2->fun_a, "a");
		if (rc != EOK)
			return rc;
	}

	if (test2->fun_err != NULL) {
		rc = fun_remove(test2->fun_err, "ERROR");
		if (rc != EOK)
			return rc;
	}

	if (test2->child != NULL) {
		rc = fun_remove(test2->child, "child");
		if (rc != EOK)
			return rc;
	}

	if (test2->test1 != NULL) {
		rc = fun_remove(test2->test1, "test1");
		if (rc != EOK)
			return rc;
	}

	return EOK;
}
Example #2
0
static int test1_dev_gone(ddf_dev_t *dev)
{
	test1_t *test1 = (test1_t *)dev->driver_data;
	int rc;

	ddf_msg(LVL_DEBUG, "test1_dev_remove(%p)", dev);

	if (test1->fun_a != NULL) {
		rc = fun_unbind(test1->fun_a, "a");
		if (rc != EOK)
			return rc;
	}

	if (test1->clone != NULL) {
		rc = fun_unbind(test1->clone, "clone");
		if (rc != EOK)
			return rc;
	}

	if (test1->child != NULL) {
		rc = fun_unbind(test1->child, "child");
		if (rc != EOK)
			return rc;
	}

	return EOK;
}
Example #3
0
/** Default handler for IPC methods not handled by DDF.
 *
 * @param fun     Device function handling the call.
 * @param icallid Call id.
 * @param icall   Call data.
 *
 */
static void default_connection_handler(ddf_fun_t *fun,
                                       ipc_callid_t icallid, ipc_call_t *icall)
{
    const sysarg_t method = IPC_GET_IMETHOD(*icall);
    at_kbd_t *kbd = ddf_dev_data_get(ddf_fun_get_dev(fun));

    switch (method) {
    case KBDEV_SET_IND: {
        async_answer_0(icallid, ENOTSUP);
        break;
    }
    /*
     * This might be ugly but async_callback_receive_start makes no
     * difference for incorrect call and malloc failure.
     */
    case IPC_M_CONNECT_TO_ME: {
        async_sess_t *sess =
            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);

        /* Probably ENOMEM error, try again. */
        if (sess == NULL) {
            ddf_msg(LVL_WARN,
                    "Failed creating callback session");
            async_answer_0(icallid, EAGAIN);
            break;
        }

        if (kbd->client_sess == NULL) {
            kbd->client_sess = sess;
            ddf_msg(LVL_DEBUG, "Set client session");
            async_answer_0(icallid, EOK);
        } else {
            ddf_msg(LVL_ERROR, "Client session already set");
            async_answer_0(icallid, ELIMIT);
        }

        break;
    }
    default:
        ddf_msg(LVL_ERROR, "Unknown method: %d.", (int)method);
        async_answer_0(icallid, EINVAL);
        break;
    }
}
Example #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;
}
Example #5
0
static int hda_set_event_session(ddf_fun_t *fun, async_sess_t *sess)
{
	hda_t *hda = fun_to_hda(fun);

	ddf_msg(LVL_NOTE, "hda_set_event_session()");
	hda_lock(hda);
	hda->ev_sess = sess;
	hda_unlock(hda);

	return EOK;
}
Example #6
0
static int fun_remove(ddf_fun_t *fun, const char *name)
{
	int rc;

	ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')", fun, name);
	rc = ddf_fun_offline(fun);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
		return rc;
	}

	rc = ddf_fun_unbind(fun);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
		return rc;
	}

	ddf_fun_destroy(fun);
	return EOK;
}
Example #7
0
static int hda_start_capture(ddf_fun_t *fun, unsigned frames, unsigned channels,
    unsigned rate, pcm_sample_format_t format)
{
	hda_t *hda = fun_to_hda(fun);
	int rc;

	ddf_msg(LVL_NOTE, "hda_start_capture()");
	hda_lock(hda);

	if (hda->pcm_stream != NULL) {
		hda_unlock(hda);
		return EBUSY;
	}

	/* XXX Choose appropriate parameters */
	uint32_t fmt;
	/* 48 kHz, 16-bits, 1 channel */
	fmt = (fmt_base_44khz << fmt_base) | (fmt_bits_16 << fmt_bits_l) | 1;

	ddf_msg(LVL_NOTE, "hda_start_capture() - create input stream");
	hda->pcm_stream = hda_stream_create(hda, sdir_input, hda->pcm_buffers,
	    fmt);
	if (hda->pcm_stream == NULL) {
		hda_unlock(hda);
		return EIO;
	}

	rc = hda_in_converter_setup(hda->ctl->codec, hda->pcm_stream);
	if (rc != EOK) {
		hda_stream_destroy(hda->pcm_stream);
		hda->pcm_stream = NULL;
		hda_unlock(hda);
		return rc;
	}

	hda->capturing = true;
	hda_stream_start(hda->pcm_stream);
	hda_unlock(hda);
	return EOK;
}
Example #8
0
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;
}
Example #9
0
static async_sess_t *hda_get_event_session(ddf_fun_t *fun)
{
	hda_t *hda = fun_to_hda(fun);
	async_sess_t *sess;

	ddf_msg(LVL_NOTE, "hda_get_event_session()");

	hda_lock(hda);
	sess = hda->ev_sess;
	hda_unlock(hda);

	return sess;
}
Example #10
0
/** Get the root device.
 *
 * @param dev Device which is root of the whole device tree
 *            (both of HW and pseudo devices).
 *
 * @return Zero on success, negative error number otherwise.
 *
 */
static int mac_dev_add(ddf_dev_t *dev)
{
#if 0
	/* Register functions */
	if (!mac_add_fun(dev, "pci0", "intel_pci", &pci_data))
		ddf_msg(LVL_ERROR, "Failed to add functions for Mac platform.");
#else
	(void)pci_data;
	(void)mac_add_fun;
#endif
	
	return EOK;
}
Example #11
0
/** Add the root device.
 *
 * @param dev Device which is root of the whole device tree
 *            (both of HW and pseudo devices).
 *
 * @return Zero on success, negative error number otherwise.
 *
 */
static int rootamdm37x_dev_add(ddf_dev_t *dev)
{
	assert(dev);
	amdm37x_t *device = ddf_dev_data_alloc(dev, sizeof(amdm37x_t));
	if (!device)
		return ENOMEM;
	int ret = amdm37x_init(device, DEBUG_CM);
	if (ret != EOK) {
		ddf_msg(LVL_FATAL, "Failed to setup hw access!.\n");
		return ret;
	}

	/* Set dplls to ON and automatic */
	amdm37x_setup_dpll_on_autoidle(device);

	/* Enable function and interface clocks */
	amdm37x_usb_clocks_set(device, true);

	/* Init TLL */
	ret = amdm37x_usb_tll_init(device);
	if (ret != EOK) {
		ddf_msg(LVL_FATAL, "Failed to init USB TLL!.\n");
		amdm37x_usb_clocks_set(device, false);
		return ret;
	}

	/* Register functions */
	if (rootamdm37x_add_fun(dev, "ohci", "usb/host=ohci", &ohci) != EOK)
		ddf_msg(LVL_ERROR, "Failed to add OHCI function for "
		    "BeagleBoard-xM platform.");
	if (rootamdm37x_add_fun(dev, "ehci", "usb/host=ehci", &ehci) != EOK)
		ddf_msg(LVL_ERROR, "Failed to add EHCI function for "
		    "BeagleBoard-xM platform.");
	if (rootamdm37x_add_fun(dev, "dispc", "amdm37x&dispc", &ehci) != EOK)
		ddf_msg(LVL_ERROR, "Failed to add dispc function for "
		    "BeagleBoard-xM platform.");

	return EOK;
}
Example #12
0
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;
}
Example #13
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;
}
Example #14
0
/** Initialize a new ddf driver instance of the driver
 *
 * @param[in] device DDF instance of the device to initialize.
 *
 * @return Error code.
 *
 */
static int at_kbd_add(ddf_dev_t *device)
{
	int rc;

	if (!device)
		return EINVAL;

	at_kbd_t *kbd = ddf_dev_data_alloc(device, sizeof(at_kbd_t));
	if (kbd == NULL) {
		ddf_msg(LVL_ERROR, "Failed to allocate AT_KBD driver instance.");
		return ENOMEM;
	}

	rc = at_kbd_init(kbd, device);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed to initialize AT_KBD driver: %s.",
		    str_error(rc));
    		return rc;
	}

	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
	return EOK;
}
Example #15
0
static int hda_stop_capture(ddf_fun_t *fun, bool immediate)
{
	hda_t *hda = fun_to_hda(fun);

	ddf_msg(LVL_NOTE, "hda_stop_capture()");
	hda_lock(hda);
	hda_stream_stop(hda->pcm_stream);
	hda_stream_reset(hda->pcm_stream);
	hda->capturing = false;
	hda_stream_destroy(hda->pcm_stream);
	hda->pcm_stream = NULL;
	hda_unlock(hda);

	hda_pcm_event(hda, PCM_EVENT_CAPTURE_TERMINATED);
	return EOK;
}
Example #16
0
static int hda_release_buffer(ddf_fun_t *fun)
{
	hda_t *hda = fun_to_hda(fun);

	hda_lock(hda);

	ddf_msg(LVL_NOTE, "hda_release_buffer()");
	if (hda->pcm_buffers == NULL) {
		hda_unlock(hda);
		return EINVAL;
	}

	hda_stream_buffers_free(hda->pcm_buffers);
	hda->pcm_buffers = NULL;

	hda_unlock(hda);
	return EOK;
}
Example #17
0
/** Initialize a new ddf driver instance
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
static int mouse_add(ddf_dev_t *device)
{
	if (!device)
		return EINVAL;

#define CHECK_RET_RETURN(ret, message...) \
if (ret != EOK) { \
	ddf_msg(LVL_ERROR, message); \
	return ret; \
} else (void)0

	ps2_mouse_t *mouse = ddf_dev_data_alloc(device, sizeof(ps2_mouse_t));
	int ret = (mouse == NULL) ? ENOMEM : EOK;
	CHECK_RET_RETURN(ret, "Failed to allocate mouse driver instance.");

	ret = ps2_mouse_init(mouse, device);
	CHECK_RET_RETURN(ret,
	    "Failed to initialize mouse driver: %s.", str_error(ret));

	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    device->name, device->handle);
	return EOK;
}
Example #18
0
static int test3_dev_remove(ddf_dev_t *dev)
{
	test3_t *test3 = (test3_t *)dev->driver_data;
	char *fun_name;
	int rc;
	size_t i;

	for (i = 0; i < NUM_FUNCS; i++) {
		rc = asprintf(&fun_name, "test3_%zu", i);
		if (rc < 0) {
			ddf_msg(LVL_ERROR, "Failed to format string: %s", str_error(rc));
			return ENOMEM;
		}

		rc = fun_remove(test3->fun[i], fun_name);
		if (rc != EOK)
			return rc;

		free(fun_name);
	}

	return EOK;
}
Example #19
0
/** Initialize a new ddf driver instance of the driver
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
static int xt_kbd_add(ddf_dev_t *device)
{
	if (!device)
		return EINVAL;

#define CHECK_RET_RETURN(ret, message...) \
if (ret != EOK) { \
	ddf_msg(LVL_ERROR, message); \
	return ret; \
} else (void)0

	xt_kbd_t *kbd = ddf_dev_data_alloc(device, sizeof(xt_kbd_t));
	int ret = (kbd == NULL) ? ENOMEM : EOK;
	CHECK_RET_RETURN(ret, "Failed to allocate XT/KBD driver instance.");

	ret = xt_kbd_init(kbd, device);
	CHECK_RET_RETURN(ret,
	    "Failed to initialize XT_KBD driver: %s.", str_error(ret));

	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
	return EOK;
}
Example #20
0
/** 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;
}
Example #21
0
/** Get data and parse scancodes.
 *
 * @param arg Pointer to at_kbd_t structure.
 *
 * @return EIO on error.
 *
 */
static int polling(void *arg)
{
    const at_kbd_t *kbd = arg;

    assert(kbd);
    assert(kbd->parent_sess);

    async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess);

    while (true) {
        if (!parent_exch)
            parent_exch = async_exchange_begin(kbd->parent_sess);

        uint8_t code = 0;
        ssize_t size = chardev_read(parent_exch, &code, 1);
        if (size != 1)
            return EIO;

        const unsigned int *map;
        size_t map_size;

        if (code == KBD_SCANCODE_SET_EXTENDED) {
            map = scanmap_e0;
            map_size = sizeof(scanmap_e0) / sizeof(unsigned int);

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
        } else if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) {
            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0x14)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0x77)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0xe1)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0xf0)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0x14)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code != 0xf0)
                continue;

            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
            if (code == 0x77)
                push_event(kbd->client_sess, KEY_PRESS, KC_BREAK);

            continue;
        } else {
            map = scanmap_simple;
            map_size = sizeof(scanmap_simple) / sizeof(unsigned int);
        }

        kbd_event_type_t type;
        if (code == KBD_SCANCODE_KEY_RELEASE) {
            type = KEY_RELEASE;
            size = chardev_read(parent_exch, &code, 1);
            if (size != 1)
                return EIO;
        } else {
            type = KEY_PRESS;
        }

        const unsigned int key = (code < map_size) ? map[code] : 0;

        if (key != 0)
            push_event(kbd->client_sess, type, key);
        else
            ddf_msg(LVL_WARN, "Unknown scancode: %hhx", code);
    }
}
Example #22
0
/** Get data and parse scancodes.
 *
 * @param arg Pointer to xt_kbd_t structure.
 *
 * @return EIO on error.
 *
 */
static int polling(void *arg)
{
	const xt_kbd_t *kbd = arg;
	
	assert(kbd);
	assert(kbd->parent_sess);
	
	async_exch_t *parent_exch = async_exchange_begin(kbd->parent_sess);
	
	while (true) {
		if (!parent_exch)
			parent_exch = async_exchange_begin(kbd->parent_sess);
		
		const unsigned int *map = scanmap_simple;
		size_t map_size = sizeof(scanmap_simple) / sizeof(unsigned int);
		
		uint8_t code = 0;
		ssize_t size = chardev_read(parent_exch, &code, 1);
		if (size != 1)
			return EIO;
		
		/* Ignore AT command reply */
		if ((code == KBD_ACK) || (code == KBD_RESEND))
			continue;
		
		/* Extended set */
		if (code == KBD_SCANCODE_SET_EXTENDED) {
			map = scanmap_e0;
			map_size = sizeof(scanmap_e0) / sizeof(unsigned int);
			
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			/* Handle really special keys */
			
			if (code == 0x2a) {  /* Print Screen */
				size = chardev_read(parent_exch, &code, 1);
				if (size != 1)
					return EIO;
				
				if (code != 0xe0)
					continue;
				
				size = chardev_read(parent_exch, &code, 1);
				if (size != 1)
					return EIO;
				
				if (code == 0x37)
					push_event(kbd->client_sess, KEY_PRESS, KC_PRTSCR);
				
				continue;
			}
			
			if (code == 0x46) {  /* Break */
				size = chardev_read(parent_exch, &code, 1);
				if (size != 1)
					return EIO;
				
				if (code != 0xe0)
					continue;
				
				size = chardev_read(parent_exch, &code, 1);
				if (size != 1)
					return EIO;
				
				if (code == 0xc6)
					push_event(kbd->client_sess, KEY_PRESS, KC_BREAK);
				
				continue;
			}
		}
		
		/* Extended special set */
		if (code == KBD_SCANCODE_SET_EXTENDED_SPECIAL) {
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			if (code != 0x1d)
				continue;
			
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			if (code != 0x45)
				continue;
			
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			if (code != 0xe1)
				continue;
			
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			if (code != 0x9d)
				continue;
			
			size = chardev_read(parent_exch, &code, 1);
			if (size != 1)
				return EIO;
			
			if (code == 0xc5)
				push_event(kbd->client_sess, KEY_PRESS, KC_PAUSE);
			
			continue;
		}
		
		/* Bit 7 indicates press/release */
		const kbd_event_type_t type =
		    (code & 0x80) ? KEY_RELEASE : KEY_PRESS;
		code &= ~0x80;
		
		const unsigned int key = (code < map_size) ? map[code] : 0;
		
		if (key != 0)
			push_event(kbd->client_sess, type, key);
		else
			ddf_msg(LVL_WARN, "Unknown scancode: %hhx", code);
	}
}
Example #23
0
static int hda_get_buffer_position(ddf_fun_t *fun, size_t *pos)
{
	ddf_msg(LVL_NOTE, "hda_get_buffer_position()");
	return ENOTSUP;
}
Example #24
0
static int test2_fun_offline(ddf_fun_t *fun)
{
	ddf_msg(LVL_DEBUG, "test2_fun_offline()");
	return ddf_fun_offline(fun);
}