예제 #1
0
static void kbdev_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	kbdev_t *kbdev;
	int retval;
	int type, key;

	/* Kbdev device structure */
	kbdev = arg;

	while (true) {
		ipc_call_t call;
		ipc_callid_t callid;

		callid = async_get_call(&call);
		if (!IPC_GET_IMETHOD(call)) {
			kbdev_destroy(kbdev);
			return;
		}

		switch (IPC_GET_IMETHOD(call)) {
		case KBDEV_EVENT:
			/* Got event from keyboard device */
			retval = 0;
			type = IPC_GET_ARG1(call);
			key = IPC_GET_ARG2(call);
			kbd_push_event(kbdev->kbd_dev, type, key);
			break;
		default:
			retval = ENOTSUP;
			break;
		}

		async_answer_0(callid, retval);
	}
}
예제 #2
0
파일: apic.c 프로젝트: jvesely/helenos
/** Handle one connection to APIC.
 *
 * @param iid   Hash of the request that opened the connection.
 * @param icall Call data of the request that opened the connection.
 * @param arg	Local argument.
 */
static void apic_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	ipc_callid_t callid;
	ipc_call_t call;
	
	/*
	 * Answer the first IPC_M_CONNECT_ME_TO call.
	 */
	async_answer_0(iid, EOK);
	
	while (true) {
		callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call)) {
			/* The other side has hung up. */
			async_answer_0(callid, EOK);
			return;
		}
		
		switch (IPC_GET_IMETHOD(call)) {
		case IRC_ENABLE_INTERRUPT:
			async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
			break;
		case IRC_CLEAR_INTERRUPT:
			/* Noop */
			async_answer_0(callid, EOK);
			break;
		default:
			async_answer_0(callid, EINVAL);
			break;
		}
	}
}
예제 #3
0
파일: adb.c 프로젝트: jvesely/helenos
static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	/* Ignore parameters, the connection is already opened */
	while (true) {

		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);

		int retval = EOK;
		
		if (!IPC_GET_IMETHOD(call)) {
			/* TODO: Handle hangup */
			return;
		}
		
		switch (IPC_GET_IMETHOD(call)) {
		case ADB_REG_NOTIF:
			adb_kbd_reg0_data(IPC_GET_ARG1(call));
			break;
		default:
			retval = ENOENT;
		}
		async_answer_0(callid, retval);
	}
}
예제 #4
0
static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call)) {
			/* TODO: Handle hangup */
			return;
		}
		
		switch (IPC_GET_IMETHOD(call)) {
		case LOC_EVENT_CAT_CHANGE:
			fibril_mutex_lock(&loc_callback_mutex);
			loc_cat_change_cb_t cb_fun = cat_change_cb;
			fibril_mutex_unlock(&loc_callback_mutex);
			
			async_answer_0(callid, EOK);
			
			if (cb_fun != NULL)
				(*cb_fun)();
			
			break;
		default:
			async_answer_0(callid, ENOTSUP);
		}
	}
}
예제 #5
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);
	}
}
예제 #6
0
/** Handle loader connection.
 *
 * Receive and carry out commands (of which the last one should be
 * to execute the loaded program).
 */
static void ldr_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	/* Already have a connection? */
	if (connected) {
		async_answer_0(iid, ELIMIT);
		return;
	}
	
	connected = true;
	
	/* Accept the connection */
	async_answer_0(iid, EOK);
	
	/* Ignore parameters, the connection is already open */
	(void) icall;
	
	while (true) {
		int retval;
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call))
			exit(0);
		
		switch (IPC_GET_IMETHOD(call)) {
		case LOADER_GET_TASKID:
			ldr_get_taskid(callid, &call);
			continue;
		case LOADER_SET_CWD:
			ldr_set_cwd(callid, &call);
			continue;
		case LOADER_SET_PATHNAME:
			ldr_set_pathname(callid, &call);
			continue;
		case LOADER_SET_ARGS:
			ldr_set_args(callid, &call);
			continue;
		case LOADER_SET_FILES:
			ldr_set_files(callid, &call);
			continue;
		case LOADER_LOAD:
			ldr_load(callid, &call);
			continue;
		case LOADER_RUN:
			ldr_run(callid, &call);
			/* Not reached */
		default:
			retval = EINVAL;
			break;
		}
		
		async_answer_0(callid, retval);
	}
}
예제 #7
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);
			}
		}
	}
}
예제 #8
0
static void inet_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);

		if (!IPC_GET_IMETHOD(call)) {
			/* TODO: Handle hangup */
			return;
		}

		switch (IPC_GET_IMETHOD(call)) {
		case INET_EV_RECV:
			inet_ev_recv(callid, &call);
			break;
		default:
			async_answer_0(callid, ENOTSUP);
		}
	}
}
예제 #9
0
파일: device.c 프로젝트: jvesely/helenos
/** Main IPC call handling from virtual host controller.
 *
 * @param iid   Caller identification
 * @param icall Initial incoming call
 * @param arg   Local argument
 */
static void callback_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	assert(DEV != NULL);

	async_answer_0(iid, EOK);

	while (true) {
		ipc_callid_t callid;
		ipc_call_t call;

		callid = async_get_call(&call);
		bool processed = usbvirt_ipc_handle_call(DEV, callid, &call);
		if (!processed) {
			if (!IPC_GET_IMETHOD(call)) {
				async_answer_0(callid, EOK);
				return;
			} else
				async_answer_0(callid, EINVAL);
		}
	}
}
예제 #10
0
static void bd_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	bd_t *bd = (bd_t *)arg;

	(void)bd;

	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);

		if (!IPC_GET_IMETHOD(call)) {
			/* TODO: Handle hangup */
			return;
		}

		switch (IPC_GET_IMETHOD(call)) {
		default:
			async_answer_0(callid, ENOTSUP);
		}
	}
}
예제 #11
0
static void mouse_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	async_answer_0(iid, EOK);
	
	async_sess_t *sess =
	    async_callback_receive(EXCHANGE_SERIALIZE);
	fibril_mutex_lock(&client_mutex);
		if (client_sess == NULL) {
			client_sess = sess;
		}
	fibril_mutex_unlock(&client_mutex);

	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call))
			break;
		
		async_answer_0(callid, ENOTSUP);
	}
}
예제 #12
0
파일: drec.c 프로젝트: jvesely/helenos
/**
 * Recording callback. Writes recorded data.
 * @param iid IPC call id.
 * @param icall Poitner to IPC call structure.
 * @param arg Argument. Poitner to recording helper structure.
 */
static void device_event_callback(ipc_callid_t iid, ipc_call_t *icall, void* arg)
{
	async_answer_0(iid, EOK);
	record_t *rec = arg;
	const size_t buffer_part = rec->buffer.size / BUFFER_PARTS;
	bool record = true;
	while (record) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		switch(IPC_GET_IMETHOD(call)) {
		case PCM_EVENT_CAPTURE_TERMINATED:
			printf("Recording terminated\n");
			record = false;
			break;
		case PCM_EVENT_FRAMES_CAPTURED:
			printf("%" PRIun " frames\n", IPC_GET_ARG1(call));
			break;
		default:
			printf("Unknown event %" PRIun ".\n", IPC_GET_IMETHOD(call));
			async_answer_0(callid, ENOTSUP);
			continue;
		}

		if (!record) {
			async_answer_0(callid, EOK);
			break;
		}

		/* Write directly from device buffer to file */
		const size_t bytes = fwrite(rec->buffer.position,
		   sizeof(uint8_t), buffer_part, rec->file);
		printf("%zu ", bytes);
		rec->buffer.position += buffer_part;

		if (rec->buffer.position >= (rec->buffer.base + rec->buffer.size))
			rec->buffer.position = rec->buffer.base;
		async_answer_0(callid, EOK);
	}
}
예제 #13
0
int iplink_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	iplink_srv_t *srv = (iplink_srv_t *)arg;
	int rc;

	fibril_mutex_lock(&srv->lock);
	if (srv->connected) {
		fibril_mutex_unlock(&srv->lock);
		async_answer_0(iid, EBUSY);
		return EBUSY;
	}

	srv->connected = true;
	fibril_mutex_unlock(&srv->lock);

	/* Accept the connection */
	async_answer_0(iid, EOK);

	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
	if (sess == NULL)
		return ENOMEM;

	srv->client_sess = sess;

	rc = srv->ops->open(srv);
	if (rc != EOK)
		return rc;

	while (true) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		sysarg_t method = IPC_GET_IMETHOD(call);

		if (!method) {
			/* The other side has hung up */
		    	fibril_mutex_lock(&srv->lock);
			srv->connected = false;
		    	fibril_mutex_unlock(&srv->lock);
			async_answer_0(callid, EOK);
			break;
		}

		switch (method) {
		case IPLINK_GET_MTU:
			iplink_get_mtu_srv(srv, callid, &call);
			break;
		case IPLINK_SEND:
			iplink_send_srv(srv, callid, &call);
			break;
		case IPLINK_ADDR_ADD:
			iplink_addr_add_srv(srv, callid, &call);
			break;
		case IPLINK_ADDR_REMOVE:
			iplink_addr_remove_srv(srv, callid, &call);
			break;
		default:
			async_answer_0(callid, EINVAL);
		}
	}

	return srv->ops->close(srv);
}
예제 #14
0
파일: protocol.c 프로젝트: jvesely/helenos
/**
 * Server side implementation of the hound protocol. IPC connection handler.
 * @param iid initial call id
 * @param icall pointer to initial call structure.
 * @param arg (unused)
 */
void hound_connection_handler(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	/* Accept connection if there is a valid iface*/
	if (server_iface) {
		async_answer_0(iid, EOK);
	} else {
		async_answer_0(iid, ENOTSUP);
		return;
	}

	while (1) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		switch (IPC_GET_IMETHOD(call)) {
		case IPC_M_HOUND_CONTEXT_REGISTER: {
			/* check interface functions */
			if (!server_iface || !server_iface->add_context) {
				async_answer_0(callid, ENOTSUP);
				break;
			}
			bool record = IPC_GET_ARG1(call);
			void *name;

			/* Get context name */
			int ret =
			    async_data_write_accept(&name, true, 0, 0, 0, 0);
			if (ret != EOK) {
				async_answer_0(callid, ret);
				break;
			}
			hound_context_id_t id = 0;
			ret = server_iface->add_context(server_iface->server,
			    &id, name, record);
			/** new context should create a copy */
			free(name);
			if (ret != EOK) {
				async_answer_0(callid, ret);
			} else {
				async_answer_1(callid, EOK, id);
			}
			break;
		}
		case IPC_M_HOUND_CONTEXT_UNREGISTER: {
			/* check interface functions */
			if (!server_iface || !server_iface->rem_context) {
				async_answer_0(callid, ENOTSUP);
				break;
			}

			/* get id, 1st param */
			hound_context_id_t id = IPC_GET_ARG1(call);
			const int ret =
			    server_iface->rem_context(server_iface->server, id);
			async_answer_0(callid, ret);
			break;
		}
		case IPC_M_HOUND_GET_LIST: {
			/* check interface functions */
			if (!server_iface || !server_iface->get_list) {
				async_answer_0(callid, ENOTSUP);
				break;
			}

			const char **list = NULL;
			const int flags = IPC_GET_ARG1(call);
			size_t count = IPC_GET_ARG2(call);
			const bool conn = IPC_GET_ARG3(call);
			char *conn_name = NULL;
			int ret = EOK;

			/* get connected actor name if provided */
			if (conn)
				ret = async_data_write_accept(
				    (void**)&conn_name, true, 0, 0, 0, 0);

			if (ret == EOK)
				ret = server_iface->get_list(
				    server_iface->server, &list, &count,
				    conn_name, flags);
			free(conn_name);

			/* Alloc string sizes array */
			size_t *sizes = NULL;
			if (count)
				sizes = calloc(count, sizeof(size_t));
			if (count && !sizes)
				ret = ENOMEM;
			async_answer_1(callid, ret, count);

			/* We are done */
			if (count == 0 || ret != EOK)
				break;

			/* Prepare sizes table */
			for (unsigned i = 0; i < count; ++i)
				sizes[i] = str_size(list[i]);

			/* Send sizes table */
			ipc_callid_t id;
			if (async_data_read_receive(&id, NULL)) {
				ret = async_data_read_finalize(id, sizes,
				    count * sizeof(size_t));
			}
			free(sizes);

			/* Proceed to send names */
			for (unsigned i = 0; i < count; ++i) {
				size_t size = str_size(list[i]);
				ipc_callid_t id;
				if (ret == EOK &&
				    async_data_read_receive(&id, NULL)) {
					ret = async_data_read_finalize(id,
					    list[i], size);
				}
				free(list[i]);
			}
			free(list);
			break;
		}
		case IPC_M_HOUND_CONNECT: {
			/* check interface functions */
			if (!server_iface || !server_iface->connect) {
				async_answer_0(callid, ENOTSUP);
				break;
			}

			void *source = NULL;
			void *sink = NULL;

			/* read source name */
			int ret =
			    async_data_write_accept(&source, true, 0, 0, 0, 0);
			/* read sink name */
			if (ret == EOK)
				ret = async_data_write_accept(&sink,
				    true, 0, 0, 0, 0);

			if (ret == EOK)
				ret = server_iface->connect(
				    server_iface->server, source, sink);
			free(source);
			free(sink);
			async_answer_0(callid, ret);
			break;
		}
		case IPC_M_HOUND_DISCONNECT: {
			/* check interface functions */
			if (!server_iface || !server_iface->disconnect) {
				async_answer_0(callid, ENOTSUP);
				break;
			}

			void *source = NULL;
			void *sink = NULL;

			/* read source name */
			int ret =
			    async_data_write_accept(&source, true, 0, 0, 0, 0);
			/*read sink name */
			if (ret == EOK)
				ret = async_data_write_accept(&sink,
				    true, 0, 0, 0, 0);
			if (ret == EOK)
				ret = server_iface->connect(
				    server_iface->server, source, sink);
			free(source);
			free(sink);
			async_answer_0(callid, ret);
			break;
		}
		case IPC_M_HOUND_STREAM_ENTER: {
			/* check interface functions */
			if (!server_iface || !server_iface->is_record_context
			    || !server_iface->add_stream
			    || !server_iface->rem_stream) {
				async_answer_0(callid, ENOTSUP);
				break;
			}

			/* get parameters */
			hound_context_id_t id = IPC_GET_ARG1(call);
			const int flags = IPC_GET_ARG2(call);
			const format_convert_t c = {.arg = IPC_GET_ARG3(call)};
			const pcm_format_t f = {
			    .sampling_rate = c.f.rate * 100,
			    .channels = c.f.channels,
			    .sample_format = c.f.format,
			};
			size_t bsize = IPC_GET_ARG4(call);

			void *stream;
			int ret = server_iface->add_stream(server_iface->server,
			    id, flags, f, bsize, &stream);
			if (ret != EOK) {
				async_answer_0(callid, ret);
				break;
			}
			const bool rec = server_iface->is_record_context(
			    server_iface->server, id);
			if (rec) {
				if(server_iface->stream_data_read) {
					async_answer_0(callid, EOK);
					/* start answering read calls */
					hound_server_write_data(stream);
					server_iface->rem_stream(
					    server_iface->server, stream);
				} else {
					async_answer_0(callid, ENOTSUP);
				}
			} else {
				if (server_iface->stream_data_write) {
					async_answer_0(callid, EOK);
					/* accept write calls */
					hound_server_read_data(stream);
					server_iface->rem_stream(
					    server_iface->server, stream);
				} else {
					async_answer_0(callid, ENOTSUP);
				}
			}
			break;
		}
		case IPC_M_HOUND_STREAM_EXIT:
		case IPC_M_HOUND_STREAM_DRAIN:
			/* Stream exit/drain is only allowed in stream context*/
			async_answer_0(callid, EINVAL);
			break;
		default:
			async_answer_0(callid, ENOTSUP);
			return;
		}
	}
}

/**
 * Read data and push it to the stream.
 * @param stream target stream, will push data there.
 */
static void hound_server_read_data(void *stream)
{
	ipc_callid_t callid;
	ipc_call_t call;
	size_t size = 0;
	int ret_answer = EOK;
	/* accept data write or drain */
	while (async_data_write_receive_call(&callid, &call, &size)
	    || (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN)) {
		/* check drain first */
		if (IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_DRAIN) {
			int ret = ENOTSUP;
			if (server_iface->drain_stream)
				ret = server_iface->drain_stream(stream);
			async_answer_0(callid, ret);
			continue;
		}

		/* there was an error last time */
		if (ret_answer != EOK) {
			async_answer_0(callid, ret_answer);
			continue;
		}

		char *buffer = malloc(size);
		if (!buffer) {
			async_answer_0(callid, ENOMEM);
			continue;
		}
		const int ret = async_data_write_finalize(callid, buffer, size);
		if (ret == EOK) {
			/* push data to stream */
			ret_answer = server_iface->stream_data_write(
			    stream, buffer, size);
		}
	}
	const int ret = IPC_GET_IMETHOD(call) == IPC_M_HOUND_STREAM_EXIT
	    ? EOK : EINVAL;

	async_answer_0(callid, ret);
}
예제 #15
0
static void vfs_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	bool cont = true;
	
	/*
	 * The connection was opened via the IPC_CONNECT_ME_TO call.
	 * This call needs to be answered.
	 */
	async_answer_0(iid, EOK);
	
	while (cont) {
		ipc_call_t call;
		ipc_callid_t callid = async_get_call(&call);
		
		if (!IPC_GET_IMETHOD(call))
			break;
		
		switch (IPC_GET_IMETHOD(call)) {
		case VFS_IN_REGISTER:
			vfs_register(callid, &call);
			cont = false;
			break;
		case VFS_IN_MOUNT:
			vfs_mount(callid, &call);
			break;
		case VFS_IN_UNMOUNT:
			vfs_unmount(callid, &call);
			break;
		case VFS_IN_OPEN:
			vfs_open(callid, &call);
			break;
		case VFS_IN_CLOSE:
			vfs_close(callid, &call);
			break;
		case VFS_IN_READ:
			vfs_read(callid, &call);
			break;
		case VFS_IN_WRITE:
			vfs_write(callid, &call);
			break;
		case VFS_IN_SEEK:
			vfs_seek(callid, &call);
			break;
		case VFS_IN_TRUNCATE:
			vfs_truncate(callid, &call);
			break;
		case VFS_IN_FSTAT:
			vfs_fstat(callid, &call);
			break;
		case VFS_IN_STAT:
			vfs_stat(callid, &call);
			break;
		case VFS_IN_MKDIR:
			vfs_mkdir(callid, &call);
			break;
		case VFS_IN_UNLINK:
			vfs_unlink(callid, &call);
			break;
		case VFS_IN_RENAME:
			vfs_rename(callid, &call);
			break;
		case VFS_IN_SYNC:
			vfs_sync(callid, &call);
			break;
		case VFS_IN_DUP:
			vfs_dup(callid, &call);
			break;
		case VFS_IN_WAIT_HANDLE:
			vfs_wait_handle(callid, &call);
			break;
		case VFS_IN_MTAB_GET:
			vfs_get_mtab(callid, &call);
			break;
		default:
			async_answer_0(callid, ENOTSUP);
			break;
		}
	}
	
	/*
	 * Open files for this client will be cleaned up when its last
	 * connection fibril terminates.
	 */
}
예제 #16
0
static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	void *fs_va = NULL;
	ipc_callid_t callid;
	ipc_call_t call;
	sysarg_t method;
	size_t comm_size;
	unsigned int flags;
	int retval;
	uint64_t ba;
	size_t cnt;

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

	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
		async_answer_0(callid, EHANGUP);
		return;
	}

	(void) async_share_out_finalize(callid, &fs_va);
	if (fs_va == AS_MAP_FAILED) {
		async_answer_0(callid, EHANGUP);
		return;
	}

	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;
		}
		
		switch (method) {
		case BD_READ_BLOCKS:
			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
			    IPC_GET_ARG2(call));
			cnt = IPC_GET_ARG3(call);
			if (cnt * block_size > comm_size) {
				retval = ELIMIT;
				break;
			}
			retval = file_bd_read_blocks(ba, cnt, fs_va);
			break;
		case BD_WRITE_BLOCKS:
			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
			    IPC_GET_ARG2(call));
			cnt = IPC_GET_ARG3(call);
			if (cnt * block_size > comm_size) {
				retval = ELIMIT;
				break;
			}
			retval = file_bd_write_blocks(ba, cnt, fs_va);
			break;
		case BD_GET_BLOCK_SIZE:
			async_answer_1(callid, EOK, block_size);
			continue;
		case BD_GET_NUM_BLOCKS:
			async_answer_2(callid, EOK, LOWER32(num_blocks),
			    UPPER32(num_blocks));
			continue;
		default:
			retval = EINVAL;
			break;
		}
		async_answer_0(callid, retval);
	}
}
예제 #17
0
static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
{
	ipc_callid_t callid;
	ipc_call_t call;
	tcp_client_t client;

	/* Accept the connection */
	async_answer_0(iid, EOK);

	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
	socket_cores_initialize(&client.sockets);

	while (true) {
		callid = async_get_call(&call);
		if (!IPC_GET_IMETHOD(call))
			break;

		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
		    (int)IPC_GET_IMETHOD(call));

		switch (IPC_GET_IMETHOD(call)) {
		case NET_SOCKET:
			tcp_sock_socket(&client, callid, call);
			break;
		case NET_SOCKET_BIND:
			tcp_sock_bind(&client, callid, call);
			break;
		case NET_SOCKET_LISTEN:
			tcp_sock_listen(&client, callid, call);
			break;
		case NET_SOCKET_CONNECT:
			tcp_sock_connect(&client, callid, call);
			break;
		case NET_SOCKET_ACCEPT:
			tcp_sock_accept(&client, callid, call);
			break;
		case NET_SOCKET_SEND:
			tcp_sock_send(&client, callid, call);
			break;
		case NET_SOCKET_SENDTO:
			tcp_sock_sendto(&client, callid, call);
			break;
		case NET_SOCKET_RECV:
		case NET_SOCKET_RECVFROM:
			tcp_sock_recvfrom(&client, callid, call);
			break;
		case NET_SOCKET_CLOSE:
			tcp_sock_close(&client, callid, call);
			break;
		case NET_SOCKET_GETSOCKOPT:
			tcp_sock_getsockopt(&client, callid, call);
			break;
		case NET_SOCKET_SETSOCKOPT:
			tcp_sock_setsockopt(&client, callid, call);
			break;
		default:
			async_answer_0(callid, ENOTSUP);
			break;
		}
	}

	/* Clean up */
	log_msg(LVL_DEBUG, "tcp_sock_connection: Clean up");
	async_hangup(client.sess);
	socket_cores_release(NULL, &client.sockets, &gsock, tcp_free_sock_data);
}