示例#1
0
文件: xtkbd.c 项目: jvesely/helenos
/** 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);
	xt_kbd_t *kbd = ddf_dev_data_get(ddf_fun_get_dev(fun));

	switch (method) {
	case KBDEV_SET_IND: {
		/*
		 * XT keyboards do not support setting mods,
		 * assume AT keyboard with Scan Code Set 1.
		 */
		const unsigned mods = IPC_GET_ARG1(*icall);
		const uint8_t status = 0 |
		    ((mods & KM_CAPS_LOCK) ? LI_CAPS : 0) |
		    ((mods & KM_NUM_LOCK) ? LI_NUM : 0) |
		    ((mods & KM_SCROLL_LOCK) ? LI_SCROLL : 0);
		uint8_t cmds[] = { KBD_CMD_SET_LEDS, status };
		
		async_exch_t *exch = async_exchange_begin(kbd->parent_sess);
		const ssize_t size = chardev_write(exch, cmds, sizeof(cmds));
		async_exchange_end(exch);
		
		async_answer_0(icallid, size < 0 ? size : EOK);
		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;
	}
}
示例#2
0
/** Read data from i8042 port.
 *
 * @param fun    DDF function.
 * @param buffer Data place.
 * @param size   Data place size.
 *
 * @return Bytes read.
 *
 */
static int i8042_read(ddf_fun_t *fun, char *data, size_t size)
{
    i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    buffer_t *buffer = (fun == controller->aux_fun) ?
                       &controller->aux_buffer : &controller->kbd_buffer;

    for (size_t i = 0; i < size; ++i)
        *data++ = buffer_read(buffer);

    return size;
}
示例#3
0
static int ne2k_set_address(ddf_fun_t *fun, const nic_address_t *address)
{
	nic_t *nic_data = DRIVER_DATA(ddf_fun_get_dev(fun));
	int rc = nic_report_address(nic_data, address);
	if (rc != EOK) {
		return EINVAL;
	}
	/* Note: some frame with previous physical address may slip to NIL here
	 * (for a moment the filtering is not exact), but ethernet should be OK with
	 * that. Some frames may also be lost, but this is not a problem.
	 */
	ne2k_set_physical_address((ne2k_t *) nic_get_specific(nic_data), address);
	return EOK;
}
示例#4
0
文件: atkbd.c 项目: jvesely/helenos
/** 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;
    }
}
示例#5
0
/** Write data to i8042 port.
 *
 * @param fun    DDF function.
 * @param buffer Data source.
 * @param size   Data size.
 *
 * @return Bytes written.
 *
 */
static int i8042_write(ddf_fun_t *fun, char *buffer, size_t size)
{
    i8042_t *controller = dev_i8042(ddf_fun_get_dev(fun));
    fibril_mutex_lock(&controller->write_guard);

    for (size_t i = 0; i < size; ++i) {
        if (controller->aux_fun == fun) {
            wait_ready(controller);
            pio_write_8(&controller->regs->status,
                        i8042_CMD_WRITE_AUX);
        }

        wait_ready(controller);
        pio_write_8(&controller->regs->data, buffer[i]);
    }

    fibril_mutex_unlock(&controller->write_guard);
    return size;
}
示例#6
0
/** Register root hub in devman.
 *
 * @param arg Host controller device (type <code>device_t *</code>).
 * @return Error code.
 */
int hub_register_in_devman_fibril(void *arg)
{
	ddf_fun_t *hc_dev = (ddf_fun_t *) arg;

	/*
	 * Wait until parent device is properly initialized.
	 */
	async_sess_t *sess;
	do {
		sess = devman_device_connect(EXCHANGE_SERIALIZE,
		    ddf_fun_get_handle(hc_dev), 0);
	} while (!sess);
	async_hangup(sess);

	int rc;

	usb_hc_connection_t hc_conn;
	usb_hc_connection_initialize(&hc_conn, ddf_fun_get_handle(hc_dev));

	rc = usb_hc_connection_open(&hc_conn);
	assert(rc == EOK);

	ddf_fun_t *hub_dev;
	rc = usb_hc_new_device_wrapper(ddf_fun_get_dev(hc_dev), &hc_conn, USB_SPEED_FULL,
	    pretend_port_rest, NULL, NULL, &rh_ops, hc_dev, &hub_dev);
	if (rc != EOK) {
		usb_log_fatal("Failed to create root hub: %s.\n",
		    str_error(rc));
	}

	usb_hc_connection_close(&hc_conn);

	usb_log_info("Created root hub function (handle %zu).\n",
	    (size_t) ddf_fun_get_handle(hub_dev));

	return 0;
}
示例#7
0
static hda_t *fun_to_hda(ddf_fun_t *fun)
{
	return (hda_t *)ddf_dev_data_get(ddf_fun_get_dev(fun));
}
示例#8
0
static sb_mixer_t *fun_to_mixer(ddf_fun_t *fun)
{
	sb16_t *sb = (sb16_t *)ddf_dev_data_get(ddf_fun_get_dev(fun));
	return &sb->mixer;
}