Index: uspace/drv/bus/usb/usbhid/multimedia/multimedia.c
===================================================================
--- uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision e3e0953afa373443a78ac42c3a5cd6ab3fd66c0d)
+++ uspace/drv/bus/usb/usbhid/multimedia/multimedia.c	(revision 05920d23f2a66887d82aa6ae6bdce695c0ab0225)
@@ -67,11 +67,9 @@
 	/** IPC session to the console device (for sending key events). */
 	async_sess_t *console_sess;
-	/** DDF function */
-	ddf_fun_t *fun;
 } usb_multimedia_t;
 
 
 /*----------------------------------------------------------------------------*/
-/** 
+/**
  * Default handler for IPC methods not handled by DDF.
  *
@@ -88,11 +86,10 @@
 {
 	usb_log_debug(NAME " default_connection_handler()\n");
-
-	usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
-
-	if (multim_dev == NULL) {
+	if (fun == NULL || fun->driver_data == NULL) {
 		async_answer_0(icallid, EINVAL);
 		return;
 	}
+
+	usb_multimedia_t *multim_dev = fun->driver_data;
 
 	async_sess_t *sess =
@@ -109,11 +106,8 @@
 		async_answer_0(icallid, EINVAL);
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 static ddf_dev_ops_t multimedia_ops = {
 	.default_handler = default_connection_handler
 };
-
 /*----------------------------------------------------------------------------*/
 /**
@@ -134,5 +128,5 @@
  * @param key Key code of the key according to HID Usage Tables.
  */
-static void usb_multimedia_push_ev(usb_hid_dev_t *hid_dev,
+static void usb_multimedia_push_ev(
     usb_multimedia_t *multim_dev, int type, unsigned int key)
 {
@@ -154,10 +148,12 @@
 
 	async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
-	async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
-	async_exchange_end(exch);
-}
-
-/*----------------------------------------------------------------------------*/
-
+	if (exch != NULL) {
+		async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
+		async_exchange_end(exch);
+	} else {
+		usb_log_warning("Failed to send multimedia key.\n");
+	}
+}
+/*----------------------------------------------------------------------------*/
 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
 {
@@ -186,5 +182,4 @@
 
 	multim_dev->console_sess = NULL;
-	multim_dev->fun = fun;
 
 	//todo Autorepeat?
@@ -211,48 +206,54 @@
 
 	/* Save the KBD device structure into the HID device structure. */
-	*data = multim_dev;
+	*data = fun;
 
 	usb_log_debug(NAME " HID/multimedia structure initialized.\n");
 	return EOK;
 }
-
-/*----------------------------------------------------------------------------*/
-
+/*----------------------------------------------------------------------------*/
 void usb_multimedia_deinit(struct usb_hid_dev *hid_dev, void *data)
 {
-	if (data != NULL) {
-		usb_multimedia_t *multim_dev = data;
+	ddf_fun_t *fun = data;
+	if (fun != NULL && fun->driver_data != NULL) {
+		usb_multimedia_t *multim_dev = fun->driver_data;
 		/* Hangup session to the console */
 		if (multim_dev->console_sess)
 			async_hangup(multim_dev->console_sess);
-		const int ret = ddf_fun_unbind(multim_dev->fun);
+		const int ret = ddf_fun_unbind(fun);
 		if (ret != EOK) {
 			usb_log_error("Failed to unbind %s function.\n",
-			    multim_dev->fun->name);
+			    fun->name);
 		} else {
-			usb_log_debug2("%s unbound.\n", multim_dev->fun->name);
+			usb_log_debug2("%s unbound.\n", fun->name);
 			/* This frees multim_dev too as it was stored in
 			 * fun->data */
-			ddf_fun_destroy(multim_dev->fun);
+			ddf_fun_destroy(fun);
 		}
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-
+	} else {
+		usb_log_error(
+		    "Failed to deinit multimedia subdriver, data missing.\n");
+	}
+}
+/*----------------------------------------------------------------------------*/
 bool usb_multimedia_polling_callback(struct usb_hid_dev *hid_dev, void *data)
 {
 	// TODO: checks
-	if (hid_dev == NULL || data == NULL) {
+	ddf_fun_t *fun = data;
+	if (hid_dev == NULL || fun == NULL || fun->driver_data == NULL) {
 		return false;
 	}
 
-	usb_multimedia_t *multim_dev = data;
+	usb_multimedia_t *multim_dev = fun->driver_data;
 
 	usb_hid_report_path_t *path = usb_hid_report_path();
+	if (path == NULL)
+		return true; /* This might be a temporary failure. */
+
 	int ret =
 	    usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
-	if (ret != EOK)
+	if (ret != EOK) {
+		usb_hid_report_path_free(path);
 		return true; /* This might be a temporary failure. */
+	}
 
 	usb_hid_report_path_set_report_id(path, hid_dev->report_id);
@@ -263,10 +264,9 @@
 	    USB_HID_REPORT_TYPE_INPUT);
 
-	/*! @todo Is this iterating OK if done multiple times? 
-	 *  @todo The parsing is not OK
-	 */
+	//FIXME Is this iterating OK if done multiple times?
+	//FIXME The parsing is not OK. (what's wrong?)
 	while (field != NULL) {
-		if(field->value != 0) {
-			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n", 
+		if (field->value != 0) {
+			usb_log_debug(NAME " KEY VALUE(%X) USAGE(%X)\n",
 			    field->value, field->usage);
 			const unsigned key =
@@ -275,6 +275,5 @@
 			    usbhid_multimedia_usage_to_str(field->usage);
 			usb_log_info("Pressed key: %s\n", key_str);
-			usb_multimedia_push_ev(hid_dev, multim_dev, KEY_PRESS,
-			                       key);
+			usb_multimedia_push_ev(multim_dev, KEY_PRESS, key);
 		}
 
@@ -289,5 +288,4 @@
 	return true;
 }
-
 /**
  * @}
