Index: uspace/lib/libdrv/generic/driver.c
===================================================================
--- uspace/lib/libdrv/generic/driver.c	(revision a1769ee69bfe08ce9226b2933a4d000a1218afd1)
+++ uspace/lib/libdrv/generic/driver.c	(revision 57937dd6bf7466b5c022cfaf61001daece9e0a5a)
@@ -35,5 +35,5 @@
 /** @file
  */
- 
+
 #include <assert.h>
 #include <ipc/services.h>
@@ -62,14 +62,14 @@
 	device_t *dev = (device_t *)malloc(sizeof(device_t));
 	if (NULL != dev) {
-		memset(dev, 0, sizeof(device_t));		
-	}	
-	return dev;	
-}
-
-static device_t * driver_get_device(link_t *devices, device_handle_t handle) 
-{	
+		memset(dev, 0, sizeof(device_t));
+	}
+	return dev;
+}
+
+static device_t * driver_get_device(link_t *devices, device_handle_t handle)
+{
 	device_t *dev = NULL;
 	link_t *link = devices->next;
-	
+
 	while (link != devices) {
 		dev = list_get_instance(link, device_t, link);
@@ -78,15 +78,15 @@
 		}
 	}
-	
+
 	return NULL;
 }
 
-static void driver_add_device(ipc_callid_t iid, ipc_call_t *icall) 
+static void driver_add_device(ipc_callid_t iid, ipc_call_t *icall)
 {
 	printf("%s: driver_add_device\n", driver->name);
-	
+
 	// result of the operation - device was added, device is not present etc.
-	ipcarg_t ret = 0;	
-	device_handle_t dev_handle =  IPC_GET_ARG1(*icall);	
+	ipcarg_t ret = 0;
+	device_handle_t dev_handle =  IPC_GET_ARG1(*icall);
 	device_t *dev = driver_create_device();
 	dev->handle = dev_handle;
@@ -96,5 +96,5 @@
 	}
 	printf("%s: new device with handle = %x was added.\n", driver->name, dev_handle);
-	
+
 	ipc_answer_1(iid, EOK, ret);
 }
@@ -103,13 +103,13 @@
 {
 	printf("%s: driver_connection_devman \n", driver->name);
-	
+
 	/* Accept connection */
 	ipc_answer_0(iid, EOK);
-	
+
 	bool cont = true;
 	while (cont) {
 		ipc_call_t call;
 		ipc_callid_t callid = async_get_call(&call);
-		
+
 		switch (IPC_GET_METHOD(call)) {
 		case IPC_M_PHONE_HUNGUP:
@@ -123,48 +123,74 @@
 				ipc_answer_0(callid, ENOENT);
 		}
-	}	
-}
-
-/** 
+	}
+}
+
+/**
  * Generic client connection handler both for applications and drivers.
- * 
- * @param driver true for driver client, false for other clients (applications, services etc.). 
- */
-static void driver_connection_gen(ipc_callid_t iid, ipc_call_t *icall, bool driver) {
-	/*
-	 * Answer the first IPC_M_CONNECT_ME_TO call and remember the handle of the device to which the client connected.
-	 */
-	device_handle_t handle = IPC_GET_ARG1(*icall); 
+ *
+ * @param driver true for driver client, false for other clients (applications, services etc.).
+ */
+static void driver_connection_gen(ipc_callid_t iid, ipc_call_t *icall, bool driver)
+{
+	// Answer the first IPC_M_CONNECT_ME_TO call and remember the handle of the device to which the client connected.
+	device_handle_t handle = IPC_GET_ARG1(*icall);
 	device_t *dev = driver_get_device(&devices, handle);
-	
+
 	if (dev == NULL) {
 		ipc_answer_0(iid, ENOENT);
 		return;
 	}
+
+	// TODO open the device (introduce some callbacks for opening and closing devices registered by the driver)
 	
-	// TODO introduce generic device interface for opening and closing devices
-	// and call its open callback here to find out wheter the device can be used by the connecting client
-		
-
 	ipc_answer_0(iid, EOK);
-	
+
 	while (1) {
 		ipc_callid_t callid;
 		ipc_call_t call;
-	
+
 		callid = async_get_call(&call);
 		ipcarg_t method = IPC_GET_METHOD(call);
 		switch  (method) {
 		case IPC_M_PHONE_HUNGUP:
-			// TODO close the device 
+		
+			// TODO close the device
+			
 			ipc_answer_0(callid, EOK);
 			return;
 		default:
-			if (DEV_IFACE_FIRST <= method && method < DEV_IFACE_MAX) {
-				// TODO - try to find interface, if supported
-				// otherwise return  ENOTSUP				
-			} else {
+
+			if (!is_valid_iface_id(method)) {
+				// this is not device's interface
 				ipc_answer_0(callid, ENOTSUP);
+				break;
 			}
+
+			// calling one of the device's interfaces
+			
+			// get the device interface structure
+			void *iface = device_get_iface(dev, method);
+			if (NULL == iface) {
+				ipc_answer_0(callid, ENOTSUP);
+				break;
+			}
+
+			// get the corresponding interface for remote request handling ("remote interface")
+			remote_iface_t* rem_iface = get_remote_iface(method);
+			assert(NULL != rem_iface);
+
+			// get the method of the remote interface
+			ipcarg_t iface_method_idx = IPC_GET_ARG1(call);
+			remote_iface_func_ptr_t iface_method_ptr = get_remote_method(rem_iface, iface_method_idx);
+			if (NULL == iface_method_ptr) {
+				// the interface has not such method
+				ipc_answer_0(callid, ENOTSUP);
+				break;
+			}
+			
+			// call the remote interface's method, which will receive parameters from the remote client
+			// and it will pass it to the corresponding local interface method associated with the device 
+			// by its driver
+			(*iface_method_ptr)(dev, iface, callid, &call);
 			break;
 		}
@@ -174,10 +200,10 @@
 static void driver_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
 {
-	driver_connection_gen(iid, icall, true); 
+	driver_connection_gen(iid, icall, true);
 }
 
 static void driver_connection_client(ipc_callid_t iid, ipc_call_t *icall)
 {
-	driver_connection_gen(iid, icall, false); 
+	driver_connection_gen(iid, icall, false);
 }
 
@@ -199,10 +225,10 @@
 		break;
 	case DRIVER_CLIENT:
-		// handle requests from client applications 
+		// handle requests from client applications
 		driver_connection_client(iid, icall);
 		break;
 
 	default:
-		/* No such interface */ 
+		/* No such interface */
 		ipc_answer_0(iid, ENOENT);
 	}
@@ -212,7 +238,7 @@
 {
 	printf("%s: child_device_register\n", driver->name);
-	
+
 	assert(NULL != child->name);
-	
+
 	if (EOK == devman_child_device_register(child->name, &child->match_ids, parent->handle, &child->handle)) {
 		return true;
@@ -221,16 +247,16 @@
 }
 
-int driver_main(driver_t *drv) 
+int driver_main(driver_t *drv)
 {
 	// remember the driver structure - driver_ops will be called by generic handler for incoming connections
 	driver = drv;
-	
+
 	// register driver by device manager with generic handler for incoming connections
-	devman_driver_register(driver->name, driver_connection);		
+	devman_driver_register(driver->name, driver_connection);
 
 	async_manager();
 
 	// Never reached
-	return 0;	
+	return 0;
 }
 
