public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core)
@ 2006-08-16  2:09 liyu
  2006-08-16  3:00 ` Alexey Dobriyan
  0 siblings, 1 reply; 5+ messages in thread
From: liyu @ 2006-08-16  2:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: Vojtech Pavlik, Greg, linux-usb-devel


Chanelogs: (upto 20060814)
	
	1. add force-feedback driver support.
	2. add simple driver module refcnt support.
	3. add two CONFIG_HID_SIMPLE and CONFIG_HID_SIMPLE_FF Kconfig entries.
	4. refactoring.
	5. replace two semaphones with mutex.
	6. some bugfixes.

It also can apply on 2.6.17.6 and 2.6.17.8 at least.

PS: I have not Subscribe linux-usb-devel maillist, please CC me your reply, thanks. 
	
Signed-off-by: Liyu <raise.sail@gmail.com>

diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid-core.c linux-2.6.17.7/drivers/usb/input/hid-core.c
--- linux-2.6.17.7/drivers/usb/input.orig/hid-core.c	2006-07-25 11:36:01.000000000 +0800
+++ linux-2.6.17.7/drivers/usb/input/hid-core.c	2006-08-16 09:17:58.000000000 +0800
@@ -26,6 +26,7 @@
 #include <asm/byteorder.h>
 #include <linux/input.h>
 #include <linux/wait.h>
+#include <linux/mutex.h>
 
 #undef DEBUG
 #undef DEBUG_DATA
@@ -33,6 +34,9 @@
 #include <linux/usb.h>
 
 #include "hid.h"
+#ifdef CONFIG_HID_SIMPLE
+#include "hid-simple.h"
+#endif
 #include <linux/hiddev.h>
 
 /*
@@ -46,6 +50,17 @@
 
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
 				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+
+#ifdef CONFIG_HID_SIMPLE
+/*
+ * The global data structure for simple device driver interface.
+ */
+static DEFINE_MUTEX(matched_lock);
+static DEFINE_MUTEX(simple_lock);
+static struct list_head matched_devices_list;
+static struct list_head simple_drivers_list;
+#endif
+
 /*
  * Module parameters.
  */
@@ -785,8 +800,22 @@ static __inline__ int search(__s32 *arra
 static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs)
 {
 	hid_dump_input(usage, value);
-	if (hid->claimed & HID_CLAIMED_INPUT)
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+#ifdef CONFIG_HID_SIMPLE
+		/* event filter here */
+		if (hid->simple) {
+			if (hid->simple->pre_event &&
+				!hid->simple->pre_event(hid, field, usage, 
+								value, regs))
+			return;
+		}
+#endif
 		hidinput_hid_event(hid, field, usage, value, regs);
+#ifdef CONFIG_HID_SIMPLE
+		if (hid->simple && hid->simple->post_event)
+			hid->simple->post_event(hid, field, usage, value, regs);
+#endif
+	}
 	if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
 		hiddev_hid_event(hid, field, usage, value, regs);
 }
@@ -832,7 +861,6 @@ static void hid_input_field(struct hid_d
 			&& field->usage[field->value[n] - min].hid
 			&& search(value, field->value[n], count))
 				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs);
-
 		if (value[n] >= min && value[n] <= max
 			&& field->usage[value[n] - min].hid
 			&& search(field->value, value[n], count))
@@ -1977,7 +2005,11 @@ fail:
 static void hid_disconnect(struct usb_interface *intf)
 {
 	struct hid_device *hid = usb_get_intfdata (intf);
-
+#ifdef CONFIG_HID_SIMPLE
+	struct list_head *node;
+	struct matched_device *matched;
+#endif
+	
 	if (!hid)
 		return;
 
@@ -1991,8 +2023,32 @@ static void hid_disconnect(struct usb_in
 	del_timer_sync(&hid->io_retry);
 	flush_scheduled_work();
 
-	if (hid->claimed & HID_CLAIMED_INPUT)
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+#ifdef CONFIG_HID_SIMPLE
+		matched = NULL;
+		mutex_lock(&matched_lock);
+		list_for_each(node, &matched_devices_list) {
+			matched = list_entry(node, struct matched_device, node);
+			if (matched->intf == intf) {
+				list_del(&matched->node);
+				break;
+			}
+			matched = NULL;
+		}
+		mutex_unlock(&matched_lock);
+		/* disconnect simple device driver if need */
+		if (matched && hid->simple) {
+			hidinput_simple_driver_disconnect(hid);
+			module_put(hid->simple->owner);
+			hidinput_simple_driver_pop(hid, matched);
+		}
+		if (matched) {
+			matched->intf = NULL;
+			kfree(matched);
+		}
+#endif
 		hidinput_disconnect(hid);
+	}
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		hiddev_disconnect(hid);
 
@@ -2005,12 +2061,150 @@ static void hid_disconnect(struct usb_in
 	hid_free_device(hid);
 }
 
+#ifdef CONFIG_HID_SIMPLE
+static int hidinput_simple_driver_bind_one(struct hidinput_simple_driver *simple,
+							struct hid_device *hid,
+						struct matched_device *matched)
+{
+	int ret;
+
+	if (!try_module_get(simple->owner))
+		return -ENODEV;
+	ret = hidinput_simple_driver_connect(simple, hid);
+	if (ret)
+		goto exit_err;
+	ret = hidinput_simple_driver_push(hid, simple, matched);
+	if (ret)
+		goto exit_err;
+	hidinput_simple_driver_setup_usage(hid);
+	printk(KERN_INFO"The simple HID driver \'%s\' attach on\'%s\'\n",
+						simple->name, hid->name);
+	goto exit;
+exit_err:
+	module_put(simple->owner);
+exit:
+	return ret;
+}
+
+static void hidinput_simple_driver_bind_foreach(void)
+{
+	struct hidinput_simple_driver *simple;
+	struct matched_device *matched=NULL;
+	struct list_head *matched_node = NULL;
+	struct list_head *simple_node = NULL;
+	struct hid_device *hid=NULL;
+
+	mutex_lock(&matched_lock);
+	list_for_each(matched_node, &matched_devices_list) {
+		matched = list_entry(matched_node, struct matched_device, node);
+		hid = usb_get_intfdata(matched->intf);
+		if (hid->simple)
+			continue;
+		mutex_lock(&simple_lock);
+		list_for_each(simple_node, &simple_drivers_list) {
+			simple = list_entry(simple_node, struct hidinput_simple_driver, node);
+
+			if (test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
+				continue;
+			if (!usb_match_id(matched->intf, simple->id_table))
+				continue;
+			hidinput_simple_driver_bind_one(simple, hid, matched);
+		}
+		mutex_unlock(&simple_lock);
+	}
+	mutex_unlock(&matched_lock);
+}
+
+static void hidinput_simple_driver_bind_foreach_simple(
+						struct matched_device *matched)
+{
+	struct hidinput_simple_driver *simple;
+	struct list_head *node;
+	struct hid_device *hid;
+	
+	if (!matched->intf)
+		return;
+	hid = usb_get_intfdata (matched->intf);
+	if (!hid || hid->simple)
+		return;
+
+	mutex_lock(&simple_lock);
+	list_for_each(node, &simple_drivers_list) {
+		simple = list_entry(node, struct hidinput_simple_driver, node);
+		if (test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
+			continue;
+		if (usb_match_id(matched->intf, simple->id_table)) {
+			hidinput_simple_driver_bind_one(simple, hid, matched);
+			break;
+		}
+	}
+	mutex_unlock(&simple_lock);
+}
+
+static void hidinput_simple_driver_bind_foreach_matched(
+					struct hidinput_simple_driver *simple)
+{
+	struct list_head *node=NULL;
+	struct matched_device *matched;
+	struct hid_device *hid=NULL;
+
+	if (!simple || test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
+		return;
+
+	mutex_lock(&matched_lock);
+	list_for_each(node, &matched_devices_list) {
+		matched = list_entry(node, struct matched_device, node);
+		hid = usb_get_intfdata (matched->intf);
+		if (hid->simple)
+			continue;
+		if (!usb_match_id(matched->intf, simple->id_table))
+			continue;
+		hidinput_simple_driver_bind_one(simple, hid, matched);
+	}
+	mutex_unlock(&matched_lock);
+}
+
+int hidinput_register_simple_driver(struct hidinput_simple_driver *simple)
+{
+	if (!simple || !simple->name)
+		return -EINVAL;
+
+	printk(KERN_INFO"The simple HID driver \'%s\' register.\n", 
+								simple->name);
+	hidinput_simple_driver_init(simple);
+	hidinput_simple_driver_bind_foreach_matched(simple);
+
+	mutex_lock(&simple_lock);
+	list_add(&simple->node, &simple_drivers_list);
+	mutex_unlock(&simple_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hidinput_register_simple_driver);
+
+void hidinput_unregister_simple_driver(struct hidinput_simple_driver *simple)
+{
+	printk(KERN_INFO"The simple HID driver \'%s\' unregister.\n", 
+							simple->name);
+	hidinput_simple_driver_clear(simple);
+	mutex_lock(&simple_lock);
+	list_del(&simple->node);
+	mutex_unlock(&simple_lock);
+	/* to active simple device driver that it is waiting */
+	hidinput_simple_driver_bind_foreach();
+}
+EXPORT_SYMBOL_GPL(hidinput_unregister_simple_driver);
+#endif
+
 static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct hid_device *hid;
 	char path[64];
 	int i;
 	char *c;
+#ifdef CONFIG_HID_SIMPLE
+	struct matched_device *matched;
+#endif
 
 	dbg("HID probe called for ifnum %d",
 			intf->altsetting->desc.bInterfaceNumber);
@@ -2021,13 +2215,24 @@ static int hid_probe(struct usb_interfac
 	hid_init_reports(hid);
 	hid_dump_device(hid);
 
-	if (!hidinput_connect(hid))
+	usb_set_intfdata(intf, hid);
+
+	if (!hidinput_connect(hid)) {
+#ifdef CONFIG_HID_SIMPLE
+		matched = kmalloc(sizeof(struct matched_device), GFP_KERNEL);
+		if (matched) {
+			matched->intf = intf;
+			mutex_lock(&matched_lock);
+			list_add(&matched->node, &matched_devices_list);
+			mutex_unlock(&matched_lock);
+			hidinput_simple_driver_bind_foreach_simple(matched);
+		}
+#endif
 		hid->claimed |= HID_CLAIMED_INPUT;
+	}
 	if (!hiddev_connect(hid))
 		hid->claimed |= HID_CLAIMED_HIDDEV;
 
-	usb_set_intfdata(intf, hid);
-
 	if (!hid->claimed) {
 		printk ("HID device not claimed by input or hiddev\n");
 		hid_disconnect(intf);
@@ -2108,6 +2313,10 @@ static int __init hid_init(void)
 	retval = hiddev_init();
 	if (retval)
 		goto hiddev_init_fail;
+#ifdef CONFIG_HID_SIMPLE
+	INIT_LIST_HEAD(&matched_devices_list);
+	INIT_LIST_HEAD(&simple_drivers_list);
+#endif
 	retval = usb_register(&hid_driver);
 	if (retval)
 		goto usb_register_fail;
@@ -2122,7 +2331,18 @@ hiddev_init_fail:
 
 static void __exit hid_exit(void)
 {
+#ifdef CONFIG_HID_SIMPLE
+	struct list_head *node, *tmp;
+	struct matched_device *matched;
+#endif
 	usb_deregister(&hid_driver);
+#ifdef CONFIG_HID_SIMPLE
+	list_for_each_safe(node, tmp, &matched_devices_list) {
+		matched = list_entry(node, struct matched_device, node);
+		list_del(&matched->node);
+		kfree(matched);
+	}
+#endif
 	hiddev_exit();
 }
 
diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid.h linux-2.6.17.7/drivers/usb/input/hid.h
--- linux-2.6.17.7/drivers/usb/input.orig/hid.h	2006-07-25 11:36:01.000000000 +0800
+++ linux-2.6.17.7/drivers/usb/input/hid.h	2006-08-15 15:41:50.000000000 +0800
@@ -380,8 +380,13 @@ struct hid_input {
 	struct list_head list;
 	struct hid_report *report;
 	struct input_dev *input;
+	void *private;
 };
 
+#ifdef CONFIG_HID_SIMPLE
+struct hidinput_simple_driver;
+#endif
+
 struct hid_device {							/* device report descriptor */
 	 __u8 *rdesc;
 	unsigned rsize;
@@ -445,6 +450,10 @@ struct hid_device {							/* device repo
 	int (*ff_event)(struct hid_device *hid, struct input_dev *input,
 			unsigned int type, unsigned int code, int value);
 
+#ifdef CONFIG_HID_SIMPLE
+	struct hidinput_simple_driver *simple;
+#endif
+
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
 	unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
 	unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid-input.c linux-2.6.17.7/drivers/usb/input/hid-input.c
--- linux-2.6.17.7/drivers/usb/input.orig/hid-input.c	2006-07-25 11:36:01.000000000 +0800
+++ linux-2.6.17.7/drivers/usb/input/hid-input.c	2006-08-16 09:23:37.000000000 +0800
@@ -36,7 +36,9 @@
 #undef DEBUG
 
 #include "hid.h"
-
+#ifdef CONFIG_HID_SIMPLE
+#include "hid-simple.h"
+#endif
 #define unk	KEY_UNKNOWN
 
 static const unsigned char hid_keyboard[256] = {
@@ -63,6 +65,8 @@ static const struct {
 	__s32 y;
 }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
 
+typedef void (*do_usage_t)(struct hid_field *, struct hid_usage *);
+
 #define map_abs(c)	do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
 #define map_rel(c)	do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
 #define map_key(c)	do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
@@ -736,8 +740,16 @@ static int hidinput_input_event(struct i
 	struct hid_field *field;
 	int offset;
 
-	if (type == EV_FF)
+	if (type == EV_FF) {
+#ifdef CONFIG_HID_SIMPLE_FF
+		if (hid->simple && hid->simple->ff_event) {
+			if (!hid->simple->ff_event(dev, type, code, value));
+				return 0;
+		}
+#else
 		return hid_ff_event(hid, dev, type, code, value);
+#endif
+	}
 
 	if (type != EV_LED)
 		return -1;
@@ -756,15 +768,63 @@ static int hidinput_input_event(struct i
 static int hidinput_open(struct input_dev *dev)
 {
 	struct hid_device *hid = dev->private;
+#ifdef CONFIG_HID_SIMPLE_FF
+	int ret = 0;
+
+	if (hid->simple && hid->simple->open)
+		ret = hid->simple->open(dev);
+	if (!ret)
+		return hid_open(hid);
+	else
+		return ret;
+#else
 	return hid_open(hid);
+#endif
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
 	struct hid_device *hid = dev->private;
+
+#ifdef CONFIG_HID_SIMPLE_FF
+	if (hid->simple && hid->simple->close)
+		hid->simple->close(dev);
+#endif
 	hid_close(hid);
 }
 
+#ifdef CONFIG_HID_SIMPLE_FF
+static int hidinput_upload_effect(struct input_dev *dev, struct ff_effect *effect)
+{
+	struct hid_device *hid;
+
+	hid = dev->private;
+	if (hid->simple && hid->simple->upload_effect)
+		return hid->simple->upload_effect(dev, effect);
+	return 0;
+}
+
+static int hidinput_erase_effect(struct input_dev *dev, int effect_id)
+{
+	struct hid_device *hid;
+
+	hid = dev->private;
+	if (hid->simple && hid->simple->erase_effect)
+		return hid->simple->erase_effect(dev, effect_id);
+	return 0;
+}
+
+static int hidinput_flush(struct input_dev *dev, struct file *filep)
+{
+	struct hid_device *hid;
+
+	hid = dev->private;
+	if (hid->simple && hid->simple->flush)
+		return hid->simple->flush(dev, filep);
+	return 0;
+}
+#endif
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -810,7 +870,11 @@ int hidinput_connect(struct hid_device *
 				input_dev->event = hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
-
+#ifdef CONFIG_HID_SIMPLE_FF			
+				input_dev->upload_effect = hidinput_upload_effect;
+				input_dev->erase_effect = hidinput_erase_effect;
+				input_dev->flush = hidinput_flush;
+#endif
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
 				input_dev->uniq = hid->uniq;
@@ -849,6 +913,293 @@ int hidinput_connect(struct hid_device *
 	return 0;
 }
 
+#ifdef CONFIG_HID_SIMPLE
+int hidinput_simple_driver_init(struct hidinput_simple_driver *drv)
+{
+	if (unlikely(!drv))
+		return -EINVAL;
+	INIT_LIST_HEAD(&drv->node);
+	INIT_LIST_HEAD(&drv->raw_devices);
+	drv->flags = 0;
+	return 0;
+}
+
+#define SET_BIT (1)
+#define CLR_BIT (0)
+static void inline hidinput_simple_configure_one_usage(int op, 
+						struct input_dev *input,
+						struct hid_usage *usage,
+						struct usage_block *usage_block)
+{
+	unsigned long *bits;
+	int flag;
+	struct hid_device *hid;
+	
+	hid = input->private;
+	switch (usage_block->event) {
+		case EV_KEY:
+			flag = HIDINPUT_SIMPLE_KEYBIT;
+			bits = input->keybit;
+			break;
+		case EV_REL:
+			flag = HIDINPUT_SIMPLE_RELBIT;
+			bits = input->relbit;
+			break;
+		case EV_ABS:
+			flag = HIDINPUT_SIMPLE_ABSBIT;
+			bits = input->relbit;
+			break;
+		case EV_MSC:
+			flag = HIDINPUT_SIMPLE_MSCBIT;
+			bits = input->absbit;
+			break;
+		case EV_SW:
+			flag = HIDINPUT_SIMPLE_SWBIT;
+			bits = input->swbit;
+			break;
+		case EV_LED:
+			flag = HIDINPUT_SIMPLE_LEDBIT;
+			bits = input->ledbit;
+			break;
+		case EV_SND:
+			flag = HIDINPUT_SIMPLE_SNDBIT;
+			bits = input->sndbit;
+			break;
+#ifdef CONFIG_HID_SIMPLE_FF
+		case EV_FF:
+			flag = HIDINPUT_SIMPLE_FFBIT;
+			bits = input->ffbit;
+			break;
+		case EV_FF_STATUS:
+			flag = HIDINPUT_SIMPLE_FFSTSBIT;
+			bits = NULL;
+			break;
+#endif
+		default:
+			return;
+	}
+
+	if (SET_BIT == op) {
+		usage->code = usage_block->code;
+		usage->type = usage_block->event;
+		if (bits)
+			set_bit(usage_block->code, bits);
+		if (!test_and_set_bit(usage_block->event, input->evbit))
+			set_bit(flag, &hid->simple->flags);
+	}
+	else if (CLR_BIT == op) {
+		usage->code = 0;
+		usage->type = 0;
+		if (bits)
+			clear_bit(usage_block->code, bits);
+		if (test_and_clear_bit(flag, &hid->simple->flags))
+			clear_bit(usage_block->event, input->evbit);
+	}
+}
+
+static do_usage_t hidinput_simple_driver_configure_usage_prep(
+							struct hid_device *hid,
+							int *op)
+{
+	do_usage_t do_usage;
+	
+	if (!hid->simple)
+		return NULL;
+
+	if (test_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags)) {
+		do_usage = hid->simple->setup_usage;
+		*op = SET_BIT;
+	}
+	else {
+		do_usage = hid->simple->clear_usage;
+		*op = CLR_BIT;
+	}
+	return do_usage;
+}
+
+static void __hidinput_simple_driver_configure_usage(int op,
+						struct hid_field *field,
+						struct hid_usage *hid_usage)
+{
+	struct input_dev *input = field->hidinput->input;
+	struct hid_device *hid = input->private;
+	struct usage_block *usage_block;
+	struct usage_page_block *page_block;
+	int page;
+	int usage;
+	
+	page = (hid_usage->hid & HID_USAGE_PAGE);
+	usage = (hid_usage->hid & HID_USAGE);
+	page_block = hid->simple->usage_page_table;
+	for (;page_block && page_block->usage_blockes;page_block++) {
+		if (page_block->page != page)
+			continue;
+		usage_block = page_block->usage_blockes;
+		for (; usage_block && usage_block->usage; usage_block++) {
+			if (usage_block->usage != usage)
+				continue;
+			hidinput_simple_configure_one_usage(op, input, 
+						hid_usage, usage_block);
+		}
+	}
+}
+
+/*
+ *  To give one simple device a configure usage chance.
+ *  The framework of this function come from hidinput_connect()
+ */
+void hidinput_simple_driver_configure_usage(struct hid_device *hid)
+{
+	struct hid_report *report;
+	int i, j, k;
+	do_usage_t do_usage;
+	int op;
+
+	if (!hid->simple)
+		return;
+
+	do_usage = hidinput_simple_driver_configure_usage_prep(hid, &op);
+
+	for (i = 0; i < hid->maxcollection; i++)
+		if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
+			hid->collection[i].type==HID_COLLECTION_PHYSICAL)
+			if (IS_INPUT_APPLICATION(hid->collection[i].usage))
+				break;
+
+	if (i == hid->maxcollection)
+		return;
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
+		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
+			if (!report->maxfield)
+				continue;
+
+			for (i = 0; i < report->maxfield; i++)
+				for (j = 0; j < report->field[i]->maxusage; j++) {
+					__hidinput_simple_driver_configure_usage(op, report->field[i], report->field[i]->usage + j);
+					if (do_usage)
+						do_usage(report->field[i],
+						report->field[i]->usage + j);
+				}
+		}
+
+	return;
+}
+#undef SET_BIT
+#undef CLR_BIT
+
+int hidinput_simple_driver_push(struct hid_device *hid, 
+					struct hidinput_simple_driver *simple,
+					struct matched_device *matched)
+{
+	struct raw_simple_device *raw_simple;
+	
+	raw_simple = kmalloc(sizeof(struct raw_simple_device), GFP_KERNEL);
+	if (!raw_simple)
+		return -ENOMEM;
+	raw_simple->intf = matched->intf;
+	hid = usb_get_intfdata(matched->intf);
+	hid->simple = simple;
+	list_add(&raw_simple->node, &simple->raw_devices);
+	return 0;
+}
+
+void hidinput_simple_driver_pop(struct hid_device *hid,
+					struct matched_device *matched)
+{
+	struct list_head *node;
+	struct raw_simple_device *raw_simple=NULL;
+
+	list_for_each (node, &hid->simple->raw_devices) {
+		raw_simple = list_entry(node, struct raw_simple_device, node);
+		if (raw_simple && raw_simple->intf == matched->intf) {
+			hid->simple = NULL;
+			list_del(&raw_simple->node);
+			kfree(raw_simple);
+			return;
+		}
+	}
+}
+
+void hidinput_simple_driver_clear(struct hidinput_simple_driver *simple)
+{
+	struct raw_simple_device *raw_simple;
+	struct hid_device *hid;
+
+	while (!list_empty_careful(&simple->raw_devices)) {
+		raw_simple = list_entry(simple->raw_devices.next, 
+					struct raw_simple_device, node);
+		hid = usb_get_intfdata (raw_simple->intf);
+		if (hid) {
+			if (hid->simple) {
+				BUG_ON(hid->simple != simple);
+				hid->simple = NULL;
+			}
+			hidinput_simple_driver_clear_usage(hid);
+			hidinput_simple_driver_disconnect(hid);
+		}
+		list_del_init(simple->raw_devices.next);
+	}
+}
+
+int hidinput_simple_driver_connect(struct hidinput_simple_driver *simple, 
+						struct hid_device *hid)
+{
+	struct hid_input *hidinput, *next;
+	int ret = -ENODEV;
+
+	if (!simple)
+		goto exit;
+	if (!simple->connect) {
+		ret = 0;
+		goto exit;
+	}
+
+	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
+		if (!simple->connect(hid, hidinput)) {
+			hid->simple = simple;
+			ret = 0;
+		}
+	}
+exit:
+	set_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags);
+	return ret;
+}
+
+
+void hidinput_simple_driver_disconnect(struct hid_device *hid)
+{
+	struct hid_input *hidinput, *next;
+
+	if (!hid || !hid->simple)
+		return;
+
+	if (!hid->simple->disconnect)
+		goto exit;
+	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
+		hid->simple->disconnect(hid, hidinput);
+	}
+exit:
+	clear_bit(HIDINPUT_SIMPLE_CONNECTED, &hid->simple->flags);
+	return;
+}
+
+struct hid_input* hidinput_simple_inputdev_to_hidinput(struct input_dev *dev)
+{
+	struct hid_device *hid = dev->private;
+	struct list_head *iter;
+	struct hid_input *hidinput;
+	
+	list_for_each(iter, &hid->inputs) {
+		hidinput = list_entry(iter, struct hid_input, list);
+		if (hidinput->input == dev)
+			return hidinput;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(hidinput_simple_inputdev_to_hidinput);
+#endif
+
 void hidinput_disconnect(struct hid_device *hid)
 {
 	struct hid_input *hidinput, *next;
diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid-simple.h linux-2.6.17.7/drivers/usb/input/hid-simple.h
--- linux-2.6.17.7/drivers/usb/input.orig/hid-simple.h	1970-01-01 08:00:00.000000000 +0800
+++ linux-2.6.17.7/drivers/usb/input/hid-simple.h	2006-08-15 09:43:09.000000000 +0800
@@ -0,0 +1,162 @@
+#ifdef CONFIG_HID_SIMPLE
+/*
+ *  NOTE:
+ *	For use me , you must include hid.h in your source first. 
+ */
+#ifndef __HID_SIMPLE_H
+#define __HID_SIMPLE_H
+
+#ifdef __KERNEL__
+
+#include <linux/usb.h>
+
+/***** The public interface for simple device driver *****/
+struct usage_block {
+	int usage; /* usage code */
+	int value; /* not used, for F_EVENT_BY_VALUE in future  */
+	int event; /* input event type, e.g. EV_KEY. */
+	int code;  /* input subsystem code, e.g. KEY_F1. */
+	int flags; /* not used */
+};
+
+struct usage_page_block {
+	int page; /* usage page code */
+	int flags; /* not used */
+	struct usage_block *usage_blockes;
+};
+
+/* usage_block flags list */
+#define F_EVENT_BY_VALUE (0x1) /* submit input event by usage_block.value, 
+				  not implement yet */
+
+#define USAGE_BLOCK(i_usage, i_value, i_event, i_code, i_flags) \
+	{\
+		.usage = (i_usage),\
+		.value = (i_value),\
+		.event = (i_event),\
+		.code = (i_code),\
+		.flags = (i_flags),\
+	}
+
+#define USAGE_BLOCK_NULL {}
+
+#define USAGE_PAGE_BLOCK(i_page, i_usage_blockes) \
+	{\
+		.page = (i_page),\
+		.usage_blockes = (i_usage_blockes),\
+	}
+
+#define USAGE_PAGE_BLOCK_NULL {}
+
+#define __SIMPLE_DRIVER_INIT \
+	.owner = THIS_MODULE,
+
+struct hidinput_simple_driver {
+/* private */
+	struct module *owner;
+	struct list_head node; /* link with simple_drivers_list */
+	struct list_head raw_devices;
+	unsigned long flags;
+/* public */
+	char *name;
+	int (*connect)(struct hid_device *, struct hid_input *);	
+	void (*disconnect)(struct hid_device *, struct hid_input *);
+	void (*setup_usage)(struct hid_field *,   struct hid_usage *);
+	void (*clear_usage)(struct hid_field *,   struct hid_usage *);
+	int (*pre_event)(const struct hid_device *, const struct hid_field *,
+					const struct hid_usage *, const __s32,
+					const struct pt_regs *regs);
+	int (*post_event)(const struct hid_device *, const struct hid_field *,
+					const struct hid_usage *, const __s32,
+					const struct pt_regs *regs);
+#ifdef CONFIG_HID_SIMPLE_FF
+	int (*open)(struct input_dev *dev);
+	void (*close)(struct input_dev *dev);
+        int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
+        int (*erase_effect)(struct input_dev *dev, int effect_id);
+	int (*flush)(struct input_dev *dev, struct file *file);
+	int (*ff_event)(struct input_dev *dev, int type, int code, int value);
+#endif
+	struct usb_device_id *id_table;
+	struct usage_page_block *usage_page_table;
+	void *private;
+};
+
+
+int hidinput_register_simple_driver(struct hidinput_simple_driver *device);
+void hidinput_unregister_simple_driver(struct hidinput_simple_driver *device);
+struct hid_input* hidinput_simple_inputdev_to_hidinput(struct input_dev *dev);
+
+/********************* The public section end ***********/
+
+/***** The private section for simple device driver implement only *****/
+
+/* 
+ *  matched_device record one device which hid-subsystem handle, it may 
+ *  be one simple device can not handle.
+ *
+ *  The element of matched_device list is inserted at hidinput_connect(), 
+ *  and is removed  at hidinput_disconnect().
+ */ 
+struct matched_device {
+	struct usb_interface *intf;
+	struct list_head node;
+};
+
+/* 
+ *  raw_simple_driver record one device which hid simple device handle.
+ *  It used as one member of hid_simple_driver.
+ */ 
+
+struct raw_simple_device {
+	struct usb_interface *intf;
+	struct list_head node;
+};
+
+void hidinput_simple_driver_configure_usage(struct hid_device *hid);
+int hidinput_simple_driver_init(struct hidinput_simple_driver *simple);
+int hidinput_simple_driver_push(struct hid_device *hid,
+				struct hidinput_simple_driver *simple,
+				struct matched_device *dev);
+void hidinput_simple_driver_pop(struct hid_device *hid,
+				struct matched_device *dev);
+void hidinput_simple_driver_clear(struct hidinput_simple_driver *simple);
+int hidinput_simple_driver_connect(struct hidinput_simple_driver *simple, 
+							struct hid_device *hid);
+void hidinput_simple_driver_disconnect(struct hid_device *hid);
+
+/* simple driver internal flags */
+#define HIDINPUT_SIMPLE_SETUP_USAGE	(0x0)
+#define HIDINPUT_SIMPLE_KEYBIT	(0x1)
+#define HIDINPUT_SIMPLE_RELBIT	(0x2)
+#define HIDINPUT_SIMPLE_ABSBIT	(0x3)
+#define HIDINPUT_SIMPLE_MSCBIT	(0x4)
+#define HIDINPUT_SIMPLE_SWBIT	(0x5)
+#define HIDINPUT_SIMPLE_LEDBIT	(0x6)
+#define HIDINPUT_SIMPLE_SNDBIT	(0x7)
+#ifdef CONFIG_HID_SIMPLE_FF
+#define HIDINPUT_SIMPLE_FFBIT	(0x8)
+#define HIDINPUT_SIMPLE_FFSTSBIT	(0x9)
+#endif
+#define HIDINPUT_SIMPLE_CONNECTED	(0x1f)
+
+static void inline hidinput_simple_driver_setup_usage(struct hid_device *hid)
+{
+	if (hid && hid->simple) {
+		set_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags);
+		hidinput_simple_driver_configure_usage(hid);
+	}
+}
+
+static void inline hidinput_simple_driver_clear_usage(struct hid_device *hid)
+{
+	if (hid && hid->simple) {
+		clear_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags);
+		hidinput_simple_driver_configure_usage(hid);
+	}
+}
+
+/***** The private section end.  *****/
+#endif /* __KERNEL__ */
+#endif /* __HID_SIMPLE_H */
+#endif /* CONFIG_HID_SIMPLE */




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core)
  2006-08-16  2:09 [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core) liyu
@ 2006-08-16  3:00 ` Alexey Dobriyan
       [not found]   ` <44E2B9D0.7030109@ccoss.com.cn>
  0 siblings, 1 reply; 5+ messages in thread
From: Alexey Dobriyan @ 2006-08-16  3:00 UTC (permalink / raw)
  To: liyu; +Cc: linux-kernel, Vojtech Pavlik, Greg, linux-usb-devel

On Wed, Aug 16, 2006 at 10:09:07AM +0800, liyu wrote:
> --- linux-2.6.17.7/drivers/usb/input.orig/hid-core.c
> +++ linux-2.6.17.7/drivers/usb/input/hid-core.c
> @@ -33,6 +34,9 @@
>  #include <linux/usb.h>
>
>  #include "hid.h"
> +#ifdef CONFIG_HID_SIMPLE
> +#include "hid-simple.h"
> +#endif

Headers on that level are supposed without ifdefs.

> @@ -46,6 +50,17 @@
>
>  static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
>  				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
> +
> +#ifdef CONFIG_HID_SIMPLE
> +/*
> + * The global data structure for simple device driver interface.
> + */
> +static DEFINE_MUTEX(matched_lock);
> +static DEFINE_MUTEX(simple_lock);

Way too generic name[s].

> +static struct list_head matched_devices_list;
> +static struct list_head simple_drivers_list;
> +#endif
> +
>  /*
>   * Module parameters.
>   */
> @@ -785,8 +800,22 @@ static __inline__ int search(__s32 *arra
>  static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt, struct pt_regs *regs)
>  {
>  	hid_dump_input(usage, value);
> -	if (hid->claimed & HID_CLAIMED_INPUT)
> +	if (hid->claimed & HID_CLAIMED_INPUT) {
> +#ifdef CONFIG_HID_SIMPLE
> +		/* event filter here */
> +		if (hid->simple) {
> +			if (hid->simple->pre_event &&
> +				!hid->simple->pre_event(hid, field, usage, 
> +								value, regs))
> +			return;
> +		}
> +#endif
>  		hidinput_hid_event(hid, field, usage, value, regs);
> +#ifdef CONFIG_HID_SIMPLE
> +		if (hid->simple && hid->simple->post_event)
> +			hid->simple->post_event(hid, field, usage, value, regs);
> +#endif
> +	}
>  	if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
>  		hiddev_hid_event(hid, field, usage, value, regs);
>  }
> @@ -832,7 +861,6 @@ static void hid_input_field(struct hid_d
>  			&& field->usage[field->value[n] - min].hid
>  			&& search(value, field->value[n], count))
>  				hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt, regs);
> -
>  		if (value[n] >= min && value[n] <= max
>  			&& field->usage[value[n] - min].hid
>  			&& search(field->value, value[n], count))
> @@ -1977,7 +2005,11 @@ fail:
>  static void hid_disconnect(struct usb_interface *intf)
>  {
>  	struct hid_device *hid = usb_get_intfdata (intf);
> -
> +#ifdef CONFIG_HID_SIMPLE
> +	struct list_head *node;
> +	struct matched_device *matched;
> +#endif
> +	
>  	if (!hid)
>  		return;
>  
> @@ -1991,8 +2023,32 @@ static void hid_disconnect(struct usb_in
>  	del_timer_sync(&hid->io_retry);
>  	flush_scheduled_work();
>  
> -	if (hid->claimed & HID_CLAIMED_INPUT)
> +	if (hid->claimed & HID_CLAIMED_INPUT) {
> +#ifdef CONFIG_HID_SIMPLE
> +		matched = NULL;
> +		mutex_lock(&matched_lock);
> +		list_for_each(node, &matched_devices_list) {
> +			matched = list_entry(node, struct matched_device, node);
> +			if (matched->intf == intf) {
> +				list_del(&matched->node);
> +				break;
> +			}
> +			matched = NULL;
> +		}
> +		mutex_unlock(&matched_lock);
> +		/* disconnect simple device driver if need */
> +		if (matched && hid->simple) {
> +			hidinput_simple_driver_disconnect(hid);
> +			module_put(hid->simple->owner);
> +			hidinput_simple_driver_pop(hid, matched);
> +		}
> +		if (matched) {
> +			matched->intf = NULL;
> +			kfree(matched);
> +		}
> +#endif
>  		hidinput_disconnect(hid);
> +	}
>  	if (hid->claimed & HID_CLAIMED_HIDDEV)
>  		hiddev_disconnect(hid);
>  
> @@ -2005,12 +2061,150 @@ static void hid_disconnect(struct usb_in
>  	hid_free_device(hid);
>  }
>  
> +#ifdef CONFIG_HID_SIMPLE
> +static int hidinput_simple_driver_bind_one(struct hidinput_simple_driver *simple,
> +							struct hid_device *hid,
> +						struct matched_device *matched)
> +{
> +	int ret;
> +
> +	if (!try_module_get(simple->owner))
> +		return -ENODEV;
> +	ret = hidinput_simple_driver_connect(simple, hid);
> +	if (ret)
> +		goto exit_err;
> +	ret = hidinput_simple_driver_push(hid, simple, matched);
> +	if (ret)
> +		goto exit_err;
> +	hidinput_simple_driver_setup_usage(hid);
> +	printk(KERN_INFO"The simple HID driver \'%s\' attach on\'%s\'\n",
> +						simple->name, hid->name);
> +	goto exit;
> +exit_err:
> +	module_put(simple->owner);
> +exit:
> +	return ret;
> +}
> +
> +static void hidinput_simple_driver_bind_foreach(void)
> +{
> +	struct hidinput_simple_driver *simple;
> +	struct matched_device *matched=NULL;
> +	struct list_head *matched_node = NULL;
> +	struct list_head *simple_node = NULL;
> +	struct hid_device *hid=NULL;
> +
> +	mutex_lock(&matched_lock);
> +	list_for_each(matched_node, &matched_devices_list) {
> +		matched = list_entry(matched_node, struct matched_device, node);
> +		hid = usb_get_intfdata(matched->intf);
> +		if (hid->simple)
> +			continue;
> +		mutex_lock(&simple_lock);
> +		list_for_each(simple_node, &simple_drivers_list) {
> +			simple = list_entry(simple_node, struct hidinput_simple_driver, node);
> +
> +			if (test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
> +				continue;
> +			if (!usb_match_id(matched->intf, simple->id_table))
> +				continue;
> +			hidinput_simple_driver_bind_one(simple, hid, matched);
> +		}
> +		mutex_unlock(&simple_lock);
> +	}
> +	mutex_unlock(&matched_lock);
> +}
> +
> +static void hidinput_simple_driver_bind_foreach_simple(
> +						struct matched_device *matched)
> +{
> +	struct hidinput_simple_driver *simple;
> +	struct list_head *node;
> +	struct hid_device *hid;
> +	
> +	if (!matched->intf)
> +		return;
> +	hid = usb_get_intfdata (matched->intf);
> +	if (!hid || hid->simple)
> +		return;
> +
> +	mutex_lock(&simple_lock);
> +	list_for_each(node, &simple_drivers_list) {
> +		simple = list_entry(node, struct hidinput_simple_driver, node);
> +		if (test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
> +			continue;
> +		if (usb_match_id(matched->intf, simple->id_table)) {
> +			hidinput_simple_driver_bind_one(simple, hid, matched);
> +			break;
> +		}
> +	}
> +	mutex_unlock(&simple_lock);
> +}
> +
> +static void hidinput_simple_driver_bind_foreach_matched(
> +					struct hidinput_simple_driver *simple)
> +{
> +	struct list_head *node=NULL;
> +	struct matched_device *matched;
> +	struct hid_device *hid=NULL;
> +
> +	if (!simple || test_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags))
> +		return;
> +
> +	mutex_lock(&matched_lock);
> +	list_for_each(node, &matched_devices_list) {
> +		matched = list_entry(node, struct matched_device, node);
> +		hid = usb_get_intfdata (matched->intf);
> +		if (hid->simple)
> +			continue;
> +		if (!usb_match_id(matched->intf, simple->id_table))
> +			continue;
> +		hidinput_simple_driver_bind_one(simple, hid, matched);
> +	}
> +	mutex_unlock(&matched_lock);
> +}
> +
> +int hidinput_register_simple_driver(struct hidinput_simple_driver *simple)
> +{
> +	if (!simple || !simple->name)
> +		return -EINVAL;

If someone registers nil drivers, he deserves oops.

> +
> +	printk(KERN_INFO"The simple HID driver \'%s\' register.\n", 
> +								simple->name);
> +	hidinput_simple_driver_init(simple);
> +	hidinput_simple_driver_bind_foreach_matched(simple);
> +
> +	mutex_lock(&simple_lock);
> +	list_add(&simple->node, &simple_drivers_list);
> +	mutex_unlock(&simple_lock);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(hidinput_register_simple_driver);
> +
> +void hidinput_unregister_simple_driver(struct hidinput_simple_driver *simple)
> +{
> +	printk(KERN_INFO"The simple HID driver \'%s\' unregister.\n", 
> +							simple->name);
> +	hidinput_simple_driver_clear(simple);
> +	mutex_lock(&simple_lock);
> +	list_del(&simple->node);
> +	mutex_unlock(&simple_lock);
> +	/* to active simple device driver that it is waiting */
> +	hidinput_simple_driver_bind_foreach();
> +}
> +EXPORT_SYMBOL_GPL(hidinput_unregister_simple_driver);
> +#endif
> +
>  static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  {
>  	struct hid_device *hid;
>  	char path[64];
>  	int i;
>  	char *c;
> +#ifdef CONFIG_HID_SIMPLE
> +	struct matched_device *matched;
> +#endif

Save #ifdef by moving var -+
                           |
>  	dbg("HID probe call|d for ifnum %d",
>  			int|->altsetting->desc.bInterfaceNumber);
> @@ -2021,13 +2215,24 @@ s|atic int hid_probe(struct usb_interfac
>  	hid_init_reports(hi|);
>  	hid_dump_device(hid|;
>                          |
> -	if (!hidinput_conne|t(hid))
> +	usb_set_intfdata(in|f, hid);
> +                        |
> +	if (!hidinput_conne|t(hid)) {
> +#ifdef CONFIG_HID_SIMPLE|
                   here <--+
> +		matched = kmalloc(sizeof(struct matched_device), GFP_KERNEL);
> +		if (matched) {
> +			matched->intf = intf;
> +			mutex_lock(&matched_lock);
> +			list_add(&matched->node, &matched_devices_list);
> +			mutex_unlock(&matched_lock);
> +			hidinput_simple_driver_bind_foreach_simple(matched);
> +		}
> +#endif
>  		hid->claimed |= HID_CLAIMED_INPUT;
> +	}
>  	if (!hiddev_connect(hid))
>  		hid->claimed |= HID_CLAIMED_HIDDEV;
>  
> -	usb_set_intfdata(intf, hid);
> -
>  	if (!hid->claimed) {
>  		printk ("HID device not claimed by input or hiddev\n");
>  		hid_disconnect(intf);
> @@ -2108,6 +2313,10 @@ static int __init hid_init(void)
>  	retval = hiddev_init();
>  	if (retval)
>  		goto hiddev_init_fail;
> +#ifdef CONFIG_HID_SIMPLE
> +	INIT_LIST_HEAD(&matched_devices_list);
> +	INIT_LIST_HEAD(&simple_drivers_list);
> +#endif
>  	retval = usb_register(&hid_driver);
>  	if (retval)
>  		goto usb_register_fail;
> @@ -2122,7 +2331,18 @@ hiddev_init_fail:
>  
>  static void __exit hid_exit(void)
>  {
> +#ifdef CONFIG_HID_SIMPLE
> +	struct list_head *node, *tmp;
> +	struct matched_device *matched;
> +#endif
>  	usb_deregister(&hid_driver);
> +#ifdef CONFIG_HID_SIMPLE
> +	list_for_each_safe(node, tmp, &matched_devices_list) {
> +		matched = list_entry(node, struct matched_device, node);
> +		list_del(&matched->node);
> +		kfree(matched);
> +	}
> +#endif
>  	hiddev_exit();
>  }
>  
> diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid.h linux-2.6.17.7/drivers/usb/input/hid.h
> --- linux-2.6.17.7/drivers/usb/input.orig/hid.h	2006-07-25 11:36:01.000000000 +0800
> +++ linux-2.6.17.7/drivers/usb/input/hid.h	2006-08-15 15:41:50.000000000 +0800
> @@ -380,8 +380,13 @@ struct hid_input {
>  	struct list_head list;
>  	struct hid_report *report;
>  	struct input_dev *input;
> +	void *private;
>  };
>  
> +#ifdef CONFIG_HID_SIMPLE
> +struct hidinput_simple_driver;
> +#endif

Totally unneeded ifdef.

>  struct hid_device {							/* device report descriptor */
>  	 __u8 *rdesc;
>  	unsigned rsize;
> @@ -445,6 +450,10 @@ struct hid_device {							/* device repo
>  	int (*ff_event)(struct hid_device *hid, struct input_dev *input,
>  			unsigned int type, unsigned int code, int value);
>  
> +#ifdef CONFIG_HID_SIMPLE
> +	struct hidinput_simple_driver *simple;
> +#endif
> +
>  #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
>  	unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
>  	unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
> diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid-input.c linux-2.6.17.7/drivers/usb/input/hid-input.c
> --- linux-2.6.17.7/drivers/usb/input.orig/hid-input.c	2006-07-25 11:36:01.000000000 +0800
> +++ linux-2.6.17.7/drivers/usb/input/hid-input.c	2006-08-16 09:23:37.000000000 +0800
> @@ -36,7 +36,9 @@
>  #undef DEBUG
>  
>  #include "hid.h"
> -
> +#ifdef CONFIG_HID_SIMPLE
> +#include "hid-simple.h"
> +#endif
>  #define unk	KEY_UNKNOWN
>  
>  static const unsigned char hid_keyboard[256] = {
> @@ -63,6 +65,8 @@ static const struct {
>  	__s32 y;
>  }  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
>  
> +typedef void (*do_usage_t)(struct hid_field *, struct hid_usage *);
> +
>  #define map_abs(c)	do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
>  #define map_rel(c)	do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
>  #define map_key(c)	do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
> @@ -736,8 +740,16 @@ static int hidinput_input_event(struct i
>  	struct hid_field *field;
>  	int offset;
>  
> -	if (type == EV_FF)
> +	if (type == EV_FF) {
> +#ifdef CONFIG_HID_SIMPLE_FF
> +		if (hid->simple && hid->simple->ff_event) {
> +			if (!hid->simple->ff_event(dev, type, code, value));
> +				return 0;
> +		}
> +#else
>  		return hid_ff_event(hid, dev, type, code, value);
> +#endif
> +	}
>  
>  	if (type != EV_LED)
>  		return -1;
> @@ -756,15 +768,63 @@ static int hidinput_input_event(struct i
>  static int hidinput_open(struct input_dev *dev)
>  {
>  	struct hid_device *hid = dev->private;
> +#ifdef CONFIG_HID_SIMPLE_FF
> +	int ret = 0;
> +
> +	if (hid->simple && hid->simple->open)
> +		ret = hid->simple->open(dev);
> +	if (!ret)
> +		return hid_open(hid);
> +	else
> +		return ret;
> +#else
>  	return hid_open(hid);
> +#endif
>  }
>  
>  static void hidinput_close(struct input_dev *dev)
>  {
>  	struct hid_device *hid = dev->private;
> +
> +#ifdef CONFIG_HID_SIMPLE_FF
> +	if (hid->simple && hid->simple->close)
> +		hid->simple->close(dev);
> +#endif
>  	hid_close(hid);
>  }
>  
> +#ifdef CONFIG_HID_SIMPLE_FF
> +static int hidinput_upload_effect(struct input_dev *dev, struct ff_effect *effect)
> +{
> +	struct hid_device *hid;
> +
> +	hid = dev->private;
> +	if (hid->simple && hid->simple->upload_effect)
> +		return hid->simple->upload_effect(dev, effect);
> +	return 0;
> +}
> +
> +static int hidinput_erase_effect(struct input_dev *dev, int effect_id)
> +{
> +	struct hid_device *hid;
> +
> +	hid = dev->private;
> +	if (hid->simple && hid->simple->erase_effect)
> +		return hid->simple->erase_effect(dev, effect_id);
> +	return 0;
> +}
> +
> +static int hidinput_flush(struct input_dev *dev, struct file *filep)
> +{
> +	struct hid_device *hid;
> +
> +	hid = dev->private;
> +	if (hid->simple && hid->simple->flush)
> +		return hid->simple->flush(dev, filep);
> +	return 0;
> +}
> +#endif
> +
>  /*
>   * Register the input device; print a message.
>   * Configure the input layer interface
> @@ -810,7 +870,11 @@ int hidinput_connect(struct hid_device *
>  				input_dev->event = hidinput_input_event;
>  				input_dev->open = hidinput_open;
>  				input_dev->close = hidinput_close;
> -
> +#ifdef CONFIG_HID_SIMPLE_FF			
> +				input_dev->upload_effect = hidinput_upload_effect;
> +				input_dev->erase_effect = hidinput_erase_effect;
> +				input_dev->flush = hidinput_flush;
> +#endif
>  				input_dev->name = hid->name;
>  				input_dev->phys = hid->phys;
>  				input_dev->uniq = hid->uniq;
> @@ -849,6 +913,293 @@ int hidinput_connect(struct hid_device *
>  	return 0;
>  }
>  
> +#ifdef CONFIG_HID_SIMPLE
> +int hidinput_simple_driver_init(struct hidinput_simple_driver *drv)
> +{
> +	if (unlikely(!drv))
> +		return -EINVAL;
> +	INIT_LIST_HEAD(&drv->node);
> +	INIT_LIST_HEAD(&drv->raw_devices);
> +	drv->flags = 0;
> +	return 0;
> +}
> +
> +#define SET_BIT (1)
> +#define CLR_BIT (0)
> +static void inline hidinput_simple_configure_one_usage(int op, 
> +						struct input_dev *input,
> +						struct hid_usage *usage,
> +						struct usage_block *usage_block)
> +{
> +	unsigned long *bits;
> +	int flag;
> +	struct hid_device *hid;
> +	
> +	hid = input->private;
> +	switch (usage_block->event) {
> +		case EV_KEY:
> +			flag = HIDINPUT_SIMPLE_KEYBIT;
> +			bits = input->keybit;
> +			break;
> +		case EV_REL:
> +			flag = HIDINPUT_SIMPLE_RELBIT;
> +			bits = input->relbit;
> +			break;
> +		case EV_ABS:
> +			flag = HIDINPUT_SIMPLE_ABSBIT;
> +			bits = input->relbit;
> +			break;
> +		case EV_MSC:
> +			flag = HIDINPUT_SIMPLE_MSCBIT;
> +			bits = input->absbit;
> +			break;
> +		case EV_SW:
> +			flag = HIDINPUT_SIMPLE_SWBIT;
> +			bits = input->swbit;
> +			break;
> +		case EV_LED:
> +			flag = HIDINPUT_SIMPLE_LEDBIT;
> +			bits = input->ledbit;
> +			break;
> +		case EV_SND:
> +			flag = HIDINPUT_SIMPLE_SNDBIT;
> +			bits = input->sndbit;
> +			break;
> +#ifdef CONFIG_HID_SIMPLE_FF
> +		case EV_FF:
> +			flag = HIDINPUT_SIMPLE_FFBIT;
> +			bits = input->ffbit;
> +			break;
> +		case EV_FF_STATUS:
> +			flag = HIDINPUT_SIMPLE_FFSTSBIT;
> +			bits = NULL;
> +			break;
> +#endif
> +		default:
> +			return;
> +	}
> +
> +	if (SET_BIT == op) {
> +		usage->code = usage_block->code;
> +		usage->type = usage_block->event;
> +		if (bits)
> +			set_bit(usage_block->code, bits);
> +		if (!test_and_set_bit(usage_block->event, input->evbit))
> +			set_bit(flag, &hid->simple->flags);
> +	}
> +	else if (CLR_BIT == op) {
> +		usage->code = 0;
> +		usage->type = 0;
> +		if (bits)
> +			clear_bit(usage_block->code, bits);
> +		if (test_and_clear_bit(flag, &hid->simple->flags))
> +			clear_bit(usage_block->event, input->evbit);
> +	}
> +}
> +
> +static do_usage_t hidinput_simple_driver_configure_usage_prep(
> +							struct hid_device *hid,
> +							int *op)
> +{
> +	do_usage_t do_usage;
> +	
> +	if (!hid->simple)
> +		return NULL;
> +
> +	if (test_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags)) {
> +		do_usage = hid->simple->setup_usage;
> +		*op = SET_BIT;
> +	}
> +	else {
> +		do_usage = hid->simple->clear_usage;
> +		*op = CLR_BIT;
> +	}
> +	return do_usage;
> +}
> +
> +static void __hidinput_simple_driver_configure_usage(int op,
> +						struct hid_field *field,
> +						struct hid_usage *hid_usage)
> +{
> +	struct input_dev *input = field->hidinput->input;
> +	struct hid_device *hid = input->private;
> +	struct usage_block *usage_block;
> +	struct usage_page_block *page_block;
> +	int page;
> +	int usage;
> +	
> +	page = (hid_usage->hid & HID_USAGE_PAGE);
> +	usage = (hid_usage->hid & HID_USAGE);
> +	page_block = hid->simple->usage_page_table;
> +	for (;page_block && page_block->usage_blockes;page_block++) {
> +		if (page_block->page != page)
> +			continue;
> +		usage_block = page_block->usage_blockes;
> +		for (; usage_block && usage_block->usage; usage_block++) {
> +			if (usage_block->usage != usage)
> +				continue;
> +			hidinput_simple_configure_one_usage(op, input, 
> +						hid_usage, usage_block);
> +		}
> +	}
> +}
> +
> +/*
> + *  To give one simple device a configure usage chance.
> + *  The framework of this function come from hidinput_connect()
> + */
> +void hidinput_simple_driver_configure_usage(struct hid_device *hid)
> +{
> +	struct hid_report *report;
> +	int i, j, k;
> +	do_usage_t do_usage;
> +	int op;
> +
> +	if (!hid->simple)
> +		return;
> +
> +	do_usage = hidinput_simple_driver_configure_usage_prep(hid, &op);
> +
> +	for (i = 0; i < hid->maxcollection; i++)
> +		if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
> +			hid->collection[i].type==HID_COLLECTION_PHYSICAL)
> +			if (IS_INPUT_APPLICATION(hid->collection[i].usage))
> +				break;
> +
> +	if (i == hid->maxcollection)
> +		return;
> +
> +	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
> +		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
> +			if (!report->maxfield)
> +				continue;
> +
> +			for (i = 0; i < report->maxfield; i++)
> +				for (j = 0; j < report->field[i]->maxusage; j++) {
> +					__hidinput_simple_driver_configure_usage(op, report->field[i], report->field[i]->usage + j);
> +					if (do_usage)
> +						do_usage(report->field[i],
> +						report->field[i]->usage + j);
> +				}
> +		}
> +
> +	return;
> +}
> +#undef SET_BIT
> +#undef CLR_BIT
> +
> +int hidinput_simple_driver_push(struct hid_device *hid, 
> +					struct hidinput_simple_driver *simple,
> +					struct matched_device *matched)
> +{
> +	struct raw_simple_device *raw_simple;
> +	
> +	raw_simple = kmalloc(sizeof(struct raw_simple_device), GFP_KERNEL);
> +	if (!raw_simple)
> +		return -ENOMEM;
> +	raw_simple->intf = matched->intf;
> +	hid = usb_get_intfdata(matched->intf);
> +	hid->simple = simple;
> +	list_add(&raw_simple->node, &simple->raw_devices);
> +	return 0;
> +}
> +
> +void hidinput_simple_driver_pop(struct hid_device *hid,
> +					struct matched_device *matched)
> +{
> +	struct list_head *node;
> +	struct raw_simple_device *raw_simple=NULL;
> +
> +	list_for_each (node, &hid->simple->raw_devices) {
> +		raw_simple = list_entry(node, struct raw_simple_device, node);
> +		if (raw_simple && raw_simple->intf == matched->intf) {
> +			hid->simple = NULL;
> +			list_del(&raw_simple->node);
> +			kfree(raw_simple);
> +			return;
> +		}
> +	}
> +}
> +
> +void hidinput_simple_driver_clear(struct hidinput_simple_driver *simple)
> +{
> +	struct raw_simple_device *raw_simple;
> +	struct hid_device *hid;
> +
> +	while (!list_empty_careful(&simple->raw_devices)) {
> +		raw_simple = list_entry(simple->raw_devices.next, 
> +					struct raw_simple_device, node);
> +		hid = usb_get_intfdata (raw_simple->intf);
> +		if (hid) {
> +			if (hid->simple) {
> +				BUG_ON(hid->simple != simple);
> +				hid->simple = NULL;
> +			}
> +			hidinput_simple_driver_clear_usage(hid);
> +			hidinput_simple_driver_disconnect(hid);
> +		}
> +		list_del_init(simple->raw_devices.next);
> +	}
> +}
> +
> +int hidinput_simple_driver_connect(struct hidinput_simple_driver *simple, 
> +						struct hid_device *hid)
> +{
> +	struct hid_input *hidinput, *next;
> +	int ret = -ENODEV;
> +
> +	if (!simple)
> +		goto exit;
> +	if (!simple->connect) {
> +		ret = 0;
> +		goto exit;
> +	}
> +
> +	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
> +		if (!simple->connect(hid, hidinput)) {
> +			hid->simple = simple;
> +			ret = 0;
> +		}
> +	}
> +exit:
> +	set_bit(HIDINPUT_SIMPLE_CONNECTED, &simple->flags);
> +	return ret;
> +}
> +
> +
> +void hidinput_simple_driver_disconnect(struct hid_device *hid)
> +{
> +	struct hid_input *hidinput, *next;
> +
> +	if (!hid || !hid->simple)
> +		return;
> +
> +	if (!hid->simple->disconnect)
> +		goto exit;
> +	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
> +		hid->simple->disconnect(hid, hidinput);
> +	}
> +exit:
> +	clear_bit(HIDINPUT_SIMPLE_CONNECTED, &hid->simple->flags);
> +	return;
> +}
> +
> +struct hid_input* hidinput_simple_inputdev_to_hidinput(struct input_dev *dev)
> +{
> +	struct hid_device *hid = dev->private;
> +	struct list_head *iter;
> +	struct hid_input *hidinput;
> +	
> +	list_for_each(iter, &hid->inputs) {
> +		hidinput = list_entry(iter, struct hid_input, list);
> +		if (hidinput->input == dev)
> +			return hidinput;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(hidinput_simple_inputdev_to_hidinput);
> +#endif
> +
>  void hidinput_disconnect(struct hid_device *hid)
>  {
>  	struct hid_input *hidinput, *next;
> diff -Naurp linux-2.6.17.7/drivers/usb/input.orig/hid-simple.h linux-2.6.17.7/drivers/usb/input/hid-simple.h
> --- linux-2.6.17.7/drivers/usb/input.orig/hid-simple.h	1970-01-01 08:00:00.000000000 +0800
> +++ linux-2.6.17.7/drivers/usb/input/hid-simple.h	2006-08-15 09:43:09.000000000 +0800
> @@ -0,0 +1,162 @@
> +#ifdef CONFIG_HID_SIMPLE
> +/*
> + *  NOTE:
> + *	For use me , you must include hid.h in your source first. 
> + */
> +#ifndef __HID_SIMPLE_H
> +#define __HID_SIMPLE_H
> +
> +#ifdef __KERNEL__
> +
> +#include <linux/usb.h>
> +
> +/***** The public interface for simple device driver *****/
> +struct usage_block {
> +	int usage; /* usage code */
> +	int value; /* not used, for F_EVENT_BY_VALUE in future  */
> +	int event; /* input event type, e.g. EV_KEY. */
> +	int code;  /* input subsystem code, e.g. KEY_F1. */
> +	int flags; /* not used */
> +};
> +
> +struct usage_page_block {
> +	int page; /* usage page code */
> +	int flags; /* not used */
> +	struct usage_block *usage_blockes;
> +};
> +
> +/* usage_block flags list */
> +#define F_EVENT_BY_VALUE (0x1) /* submit input event by usage_block.value, 
> +				  not implement yet */
> +
> +#define USAGE_BLOCK(i_usage, i_value, i_event, i_code, i_flags) \
> +	{\
> +		.usage = (i_usage),\
> +		.value = (i_value),\
> +		.event = (i_event),\
> +		.code = (i_code),\
> +		.flags = (i_flags),\
> +	}
> +
> +#define USAGE_BLOCK_NULL {}
> +
> +#define USAGE_PAGE_BLOCK(i_page, i_usage_blockes) \
> +	{\
> +		.page = (i_page),\
> +		.usage_blockes = (i_usage_blockes),\
> +	}
> +
> +#define USAGE_PAGE_BLOCK_NULL {}
> +
> +#define __SIMPLE_DRIVER_INIT \
> +	.owner = THIS_MODULE,
> +
> +struct hidinput_simple_driver {
> +/* private */
> +	struct module *owner;
> +	struct list_head node; /* link with simple_drivers_list */
> +	struct list_head raw_devices;
> +	unsigned long flags;
> +/* public */
> +	char *name;
> +	int (*connect)(struct hid_device *, struct hid_input *);	
> +	void (*disconnect)(struct hid_device *, struct hid_input *);
> +	void (*setup_usage)(struct hid_field *,   struct hid_usage *);
> +	void (*clear_usage)(struct hid_field *,   struct hid_usage *);
> +	int (*pre_event)(const struct hid_device *, const struct hid_field *,
> +					const struct hid_usage *, const __s32,
> +					const struct pt_regs *regs);
> +	int (*post_event)(const struct hid_device *, const struct hid_field *,
> +					const struct hid_usage *, const __s32,
> +					const struct pt_regs *regs);
> +#ifdef CONFIG_HID_SIMPLE_FF
> +	int (*open)(struct input_dev *dev);
> +	void (*close)(struct input_dev *dev);
> +        int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
> +        int (*erase_effect)(struct input_dev *dev, int effect_id);
> +	int (*flush)(struct input_dev *dev, struct file *file);
> +	int (*ff_event)(struct input_dev *dev, int type, int code, int value);
> +#endif
> +	struct usb_device_id *id_table;
> +	struct usage_page_block *usage_page_table;
> +	void *private;
> +};
> +
> +
> +int hidinput_register_simple_driver(struct hidinput_simple_driver *device);
> +void hidinput_unregister_simple_driver(struct hidinput_simple_driver *device);
> +struct hid_input* hidinput_simple_inputdev_to_hidinput(struct input_dev *dev);
> +
> +/********************* The public section end ***********/
> +
> +/***** The private section for simple device driver implement only *****/
> +
> +/* 
> + *  matched_device record one device which hid-subsystem handle, it may 
> + *  be one simple device can not handle.
> + *
> + *  The element of matched_device list is inserted at hidinput_connect(), 
> + *  and is removed  at hidinput_disconnect().
> + */ 
> +struct matched_device {
> +	struct usb_interface *intf;
> +	struct list_head node;
> +};
> +
> +/* 
> + *  raw_simple_driver record one device which hid simple device handle.
> + *  It used as one member of hid_simple_driver.
> + */ 
> +
> +struct raw_simple_device {
> +	struct usb_interface *intf;
> +	struct list_head node;
> +};
> +
> +void hidinput_simple_driver_configure_usage(struct hid_device *hid);
> +int hidinput_simple_driver_init(struct hidinput_simple_driver *simple);
> +int hidinput_simple_driver_push(struct hid_device *hid,
> +				struct hidinput_simple_driver *simple,
> +				struct matched_device *dev);
> +void hidinput_simple_driver_pop(struct hid_device *hid,
> +				struct matched_device *dev);
> +void hidinput_simple_driver_clear(struct hidinput_simple_driver *simple);
> +int hidinput_simple_driver_connect(struct hidinput_simple_driver *simple, 
> +							struct hid_device *hid);
> +void hidinput_simple_driver_disconnect(struct hid_device *hid);
> +
> +/* simple driver internal flags */
> +#define HIDINPUT_SIMPLE_SETUP_USAGE	(0x0)
> +#define HIDINPUT_SIMPLE_KEYBIT	(0x1)
> +#define HIDINPUT_SIMPLE_RELBIT	(0x2)
> +#define HIDINPUT_SIMPLE_ABSBIT	(0x3)
> +#define HIDINPUT_SIMPLE_MSCBIT	(0x4)
> +#define HIDINPUT_SIMPLE_SWBIT	(0x5)
> +#define HIDINPUT_SIMPLE_LEDBIT	(0x6)
> +#define HIDINPUT_SIMPLE_SNDBIT	(0x7)
> +#ifdef CONFIG_HID_SIMPLE_FF
> +#define HIDINPUT_SIMPLE_FFBIT	(0x8)
> +#define HIDINPUT_SIMPLE_FFSTSBIT	(0x9)
> +#endif
> +#define HIDINPUT_SIMPLE_CONNECTED	(0x1f)
> +
> +static void inline hidinput_simple_driver_setup_usage(struct hid_device *hid)
> +{
> +	if (hid && hid->simple) {
> +		set_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags);
> +		hidinput_simple_driver_configure_usage(hid);
> +	}
> +}
> +
> +static void inline hidinput_simple_driver_clear_usage(struct hid_device *hid)
> +{
> +	if (hid && hid->simple) {
> +		clear_bit(HIDINPUT_SIMPLE_SETUP_USAGE, &hid->simple->flags);
> +		hidinput_simple_driver_configure_usage(hid);
> +	}
> +}
> +
> +/***** The private section end.  *****/
> +#endif /* __KERNEL__ */
> +#endif /* __HID_SIMPLE_H */
> +#endif /* CONFIG_HID_SIMPLE */

I'll repeat that word again, this code looks uncleanly because of many
ifdefs scattered around.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-usb-devel] [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core)
       [not found]   ` <44E2B9D0.7030109@ccoss.com.cn>
@ 2006-08-16  8:35     ` Greg KH
  2006-08-16  9:14       ` raise_sail
  0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2006-08-16  8:35 UTC (permalink / raw)
  To: liyu; +Cc: Alexey Dobriyan, liyu, Vojtech Pavlik, linux-kernel,
	linux-usb-devel

On Wed, Aug 16, 2006 at 02:23:12PM +0800, liyu wrote:
> 
> Well, Where I can get some guide for how use #ifdef/#if ?

Documentation/CodingStyle.

Basically, don't use it in .c files, but only in .h files if necessary.

> Also, I found I can not send mail to <linux-kernel@vger.kernel.org> now,
> the reject reply like this:
> 
> Connected to 209.132.176.167 but sender was rejected.
> Remote host said: 553 5.7.1 Hello [210.76.114.181], for your MAIL FROM address <liyu@ccoss.com.cn> policy analysis reported: Your address is not liked source for email
> 
> 
> Is it looked my mail as spam mail? Who should I send to for help me
> resolving this problem?

Go here:
	http://vger.kernel.org/mxverify.html
to see how to fix this up.

good luck,

greg k-h

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-usb-devel] [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core)
  2006-08-16  8:35     ` [linux-usb-devel] " Greg KH
@ 2006-08-16  9:14       ` raise_sail
  2006-08-16 14:51         ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: raise_sail @ 2006-08-16  9:14 UTC (permalink / raw)
  To: Greg KH
  Cc: liyu, Alexey Dobriyan, Vojtech Pavlik, linux-kernel,
	linux-usb-devel


Greg KH wrote:
> Go here:
> 	http://vger.kernel.org/mxverify.html
> to see how to fix this up.
>
>   
That test site reply me "Apparently OK!", however, I still can not
send/receive any mail from LKML.

Also, I will review CodingStyle. Sorry for uncleanly code.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [linux-usb-devel] [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core)
  2006-08-16  9:14       ` raise_sail
@ 2006-08-16 14:51         ` Dmitry Torokhov
  0 siblings, 0 replies; 5+ messages in thread
From: Dmitry Torokhov @ 2006-08-16 14:51 UTC (permalink / raw)
  To: raise_sail
  Cc: Greg KH, liyu, Alexey Dobriyan, Vojtech Pavlik, linux-kernel,
	linux-usb-devel

On Wednesday 16 August 2006 05:14, raise_sail@163.com wrote:
> 
> Greg KH wrote:
> > Go here:
> > 	http://vger.kernel.org/mxverify.html
> > to see how to fix this up.
> >
> >   
> That test site reply me "Apparently OK!", however, I still can not
> send/receive any mail from LKML.
> 
> Also, I will review CodingStyle. Sorry for uncleanly code.
> 

Hi,

Just an overall comment. I like the idea of simple plugins for HID but we
somehow need to allow them be built as modules and loaded on demand so
when I plug a device that needs special handling an appropriate piece
will get loaded and attached to the HID driver before my device is bound
to it. Built-ins are not very nice when you look from a distribution POV
becuase they have to enable every option and there are qute a few of devices
that need special handling. 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-08-16 14:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-16  2:09 [PATCH] usb: The HID Simple Driver Interface 0.3.1 (core) liyu
2006-08-16  3:00 ` Alexey Dobriyan
     [not found]   ` <44E2B9D0.7030109@ccoss.com.cn>
2006-08-16  8:35     ` [linux-usb-devel] " Greg KH
2006-08-16  9:14       ` raise_sail
2006-08-16 14:51         ` Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox