예제 #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
/** Character device connection handler */
static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	ipc_callid_t callid;
	ipc_call_t call;
	sysarg_t method;
	service_id_t dsid;
	int dev_addr, i;

	/* Get the device handle. */
	dsid = IPC_GET_ARG1(*icall);

	/* Determine which disk device is the client connecting to. */
	dev_addr = -1;
	for (i = 0; i < ADB_MAX_ADDR; i++) {
		if (adb_dev[i].service_id == dsid)
			dev_addr = i;
	}

	if (dev_addr < 0) {
		async_answer_0(iid, EINVAL);
		return;
	}

	/* Answer the IPC_M_CONNECT_ME_TO call. */
	async_answer_0(iid, EOK);

	while (true) {
		callid = async_get_call(&call);
		method = IPC_GET_IMETHOD(call);
		
		if (!method) {
			/* The other side has hung up. */
			async_answer_0(callid, EOK);
			return;
		}
		
		async_sess_t *sess =
		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
		if (sess != NULL) {
			if (adb_dev[dev_addr].client_sess == NULL) {
				adb_dev[dev_addr].client_sess = sess;
				
				/*
				 * A hack so that we send the data to the session
				 * regardless of which address the device is on.
				 */
				for (i = 0; i < ADB_MAX_ADDR; ++i) {
					if (adb_dev[i].service_id == dsid)
						adb_dev[i].client_sess = sess;
				}
				
				async_answer_0(callid, EOK);
			} else
				async_answer_0(callid, ELIMIT);
		} else
			async_answer_0(callid, EINVAL);
	}
}
예제 #3
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;
    }
}
예제 #4
0
static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	async_answer_0(iid, EOK);
	
	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call)) {
			if (client_sess != NULL) {
				async_hangup(client_sess);
				client_sess = NULL;
			}
			
			async_answer_0(callid, EOK);
			return;
		}
		
		async_sess_t *sess =
		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
		if (sess != NULL) {
			if (client_sess == NULL) {
				client_sess = sess;
				async_answer_0(callid, EOK);
			} else
				async_answer_0(callid, ELIMIT);
		} else {
			switch (IPC_GET_IMETHOD(call)) {
			case INPUT_YIELD:
				kbd_devs_yield();
				async_answer_0(callid, EOK);
				break;
			case INPUT_RECLAIM:
				kbd_devs_reclaim();
				async_answer_0(callid, EOK);
				break;
			default:
				async_answer_0(callid, EINVAL);
			}
		}
	}
}
예제 #5
0
/**
 * Default handler for IPC methods not handled by DDF.
 *
 * Currently recognizes only one method (IPC_M_CONNECT_TO_ME), in which case it
 * assumes the caller is the console and thus it stores IPC session to it for
 * later use by the driver to notify about key events.
 *
 * @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)
{
	usb_log_debug(NAME " default_connection_handler()\n");

	usb_multimedia_t *multim_dev = ddf_fun_data_get(fun);

	async_sess_t *sess =
	    async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
	if (sess != NULL) {
		if (multim_dev->console_sess == NULL) {
			multim_dev->console_sess = sess;
			usb_log_debug(NAME " Saved session to console: %p\n",
			    sess);
			async_answer_0(icallid, EOK);
		} else
			async_answer_0(icallid, ELIMIT);
	} else
		async_answer_0(icallid, EINVAL);
}