diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c
index fabd092..8e6e20f 100644
--- a/extras/usb_id/usb_id.c
+++ b/extras/usb_id/usb_id.c
@@ -56,6 +56,7 @@ static char serial_str[UTIL_NAME_SIZE];
 static char packed_if_str[UTIL_NAME_SIZE];
 static char revision_str[64];
 static char type_str[64];
+static char bustype_str[64];
 static char instance_str[64];
 static const char *ifnum;
 static const char *driver;
@@ -147,6 +148,29 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len
 	return type_num;
 }
 
+static int set_usb_input_bustype(char *to, const char *from, size_t len)
+{
+	int bustype_num = 0;
+	char *eptr;
+	char *type = "unknown";
+
+	bustype_num = strtoul(from, &eptr, 0);
+	if (eptr != from) {
+		switch (bustype_num) {
+		case 3:
+			type = "usb";
+			break;
+		case 5:
+			type = "bluetooth";
+			break;
+		default:
+			break;
+		}
+	}
+	util_strscpy(to, len, type);
+	return bustype_num;
+}
+
 static void set_scsi_type(char *to, const char *from, size_t len)
 {
 	int type_num;
@@ -312,8 +336,8 @@ static int usb_id(struct udev_device *dev)
 		set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1);
 	}
 
-	info(udev, "%s: if_class %d protocol %d\n",
-	     udev_device_get_syspath(dev_interface), if_class_num, protocol);
+	info(udev, "%s: if_class %d protocol %d type_str: %s\n",
+	     udev_device_get_syspath(dev_interface), if_class_num, protocol, type_str);
 
 	/* usb device directory */
 	dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device");
@@ -326,6 +350,57 @@ static int usb_id(struct udev_device *dev)
 	/* all interfaces of the device in a single string */
 	dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str));
 
+	/* input device XXX this check is not right, we might use a dev_input
+	 * as below */
+	if ((protocol == 0) && !use_usb_info) {
+		struct udev_device *dev_input;
+		const char *input_vendor, *input_model, *input_rev, *input_bustype;
+
+		/* get input device */
+		dev_input = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL);
+		if (dev_input == NULL) {
+			info(udev, "unable to find parent 'input' device of '%s'\n",
+			     udev_device_get_syspath(dev));
+			goto fallback;
+		}
+
+		input_vendor = udev_device_get_sysattr_value(dev_input, "id/vendor");
+		if (!input_vendor) {
+			info(udev, "%s: cannot get input vendor attribute\n",
+			     udev_device_get_sysname(dev_input));
+			goto fallback;
+		}
+		udev_util_encode_string(input_vendor, vendor_str_enc, sizeof(vendor_str_enc));
+		udev_util_replace_whitespace(input_vendor, vendor_str, sizeof(vendor_str)-1);
+		udev_util_replace_chars(vendor_str, NULL);
+
+		vendor_id = input_vendor;
+		product_id = udev_device_get_sysattr_value(dev_input, "id/product");
+
+		input_model = udev_device_get_sysattr_value(dev_input, "name");
+		if (!input_model) {
+			info(udev, "%s: cannot get input model attribute\n",
+			     udev_device_get_sysname(dev_input));
+			goto fallback;
+		}
+		udev_util_encode_string(input_model, model_str_enc, sizeof(model_str_enc));
+		udev_util_replace_whitespace(input_model, model_str, sizeof(model_str)-1);
+		udev_util_replace_chars(model_str, NULL);
+
+		input_rev = udev_device_get_sysattr_value(dev_input, "id/version");
+		if (!input_rev) {
+			info(udev, "%s: cannot get input revision attribute\n",
+			     udev_device_get_sysname(dev_input));
+			goto fallback;
+		}
+		udev_util_replace_whitespace(input_rev, revision_str, sizeof(revision_str)-1);
+		udev_util_replace_chars(revision_str, NULL);
+
+		/* get Bus type, see BUS_* in linux/input.h */
+		input_bustype = udev_device_get_sysattr_value(dev_input, "id/bustype");
+		set_usb_input_bustype(bustype_str, input_bustype, sizeof(bustype_str) - 1 );
+	}
+
 	/* mass storage : SCSI or ATAPI */
 	if ((protocol == 6 || protocol == 2) && !use_usb_info) {
 		struct udev_device *dev_scsi;
@@ -390,8 +465,12 @@ static int usb_id(struct udev_device *dev)
 	}
 
 fallback:
-	vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
-	product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");
+	if (vendor_id[0] == '\0') {
+		vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
+	}
+	if (product_id[0] == '\0') {
+		product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");
+	}
 
 	/* fallback to USB vendor & device */
 	if (vendor_str[0] == '\0') {
@@ -559,7 +638,7 @@ int main(int argc, char **argv)
 				printf("ID_TYPE=%s\n", type_str);
 			if (instance_str[0] != '\0')
 				printf("ID_INSTANCE=%s\n", instance_str);
-			printf("ID_BUS=usb\n");
+			printf("ID_BUS=%s\n", (bustype_str[0] == '\0') ? "usb" : bustype_str);
 			if (packed_if_str[0] != '\0')
 				printf("ID_USB_INTERFACES=:%s\n", packed_if_str);
 			if (ifnum != NULL)
