[PATCH 1/2] Add usb_skelswitch skeleton module to do basic initialization of devices that at first appear as a generic USB device.

From: Michal MalÃ
Date: Sat Jan 23 2016 - 05:35:44 EST


This gets rid of the need to handle such devices in more specific
drivers that will be loaded for no purpose other than to do some basic
initialization on the device.

Signed-off-by: Michal Malà <madcatxster@xxxxxxxxxxxxxxxxxx>
---
drivers/usb/Kconfig | 2 +
drivers/usb/common/Kconfig | 15 +++++++
drivers/usb/common/Makefile | 2 +
drivers/usb/common/usb-skelswitch.c | 81 +++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+)
create mode 100644 drivers/usb/common/Kconfig
create mode 100644 drivers/usb/common/usb-skelswitch.c

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8ed451d..3de5d35 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -78,6 +78,8 @@ if USB

source "drivers/usb/core/Kconfig"

+source "drivers/usb/common/Kconfig"
+
source "drivers/usb/mon/Kconfig"

source "drivers/usb/wusbcore/Kconfig"
diff --git a/drivers/usb/common/Kconfig b/drivers/usb/common/Kconfig
new file mode 100644
index 0000000..6d9ec79
--- /dev/null
+++ b/drivers/usb/common/Kconfig
@@ -0,0 +1,15 @@
+#
+# USB common modules
+#
+
+if USB_COMMON
+
+config USB_SKELSWITCH
+ tristate "Simple USB module for basic device initialization"
+ help
+ Simple module that performs basic initialization on devices that at first
+ appear as a generic USB device.
+
+ Say Y if you intend to use a device that requires this initial switch.
+
+endif # USB_COMMON
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 6bbb3ec..5e7c15a 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -8,3 +8,5 @@ usb-common-$(CONFIG_USB_LED_TRIG) += led.o

obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o
obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o
+
+obj-$(CONFIG_USB_SKELSWITCH) += usb-skelswitch.o
diff --git a/drivers/usb/common/usb-skelswitch.c b/drivers/usb/common/usb-skelswitch.c
new file mode 100644
index 0000000..ae72068
--- /dev/null
+++ b/drivers/usb/common/usb-skelswitch.c
@@ -0,0 +1,81 @@
+#include <linux/module.h>
+#include <linux/usb.h>
+
+MODULE_LICENSE("GPL");
+
+struct usb_skelswitch_product {
+ const u16 idProduct;
+ int (*action)(struct usb_interface *);
+};
+
+struct usb_skelswitch_vendor {
+ const u16 idVendor;
+ const struct usb_skelswitch_product *products;
+};
+
+static const struct usb_device_id usb_skelswitch_table[] = {
+ { }
+};
+
+static const struct usb_skelswitch_vendor usb_skelswitch_vendors[] = {
+ { 0, NULL }
+};
+
+static int usb_skelswitch_process_products(struct usb_interface *intf, const struct usb_skelswitch_product *products, const u16 idProduct)
+{
+ size_t idx = 0;
+ const struct usb_device *udev = interface_to_usbdev(intf);
+
+ while (1) {
+ const struct usb_skelswitch_product *product = &products[idx];
+
+ if (product->idProduct == 0) {
+ dev_err(&udev->dev, "usb_skelswitch: Unhandled idProduct 0x%04x\n", idProduct);
+ return -EINVAL;
+ }
+
+ if (product->idProduct == idProduct) {
+ if (product->action)
+ return product->action(intf);
+ else
+ return 0;
+ }
+
+ idx++;
+ }
+}
+
+static int usb_skelswitch_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ size_t idx = 0;
+ const struct usb_device *udev = interface_to_usbdev(intf);
+
+ while (1) {
+ const struct usb_skelswitch_vendor *vendor = &usb_skelswitch_vendors[idx];
+
+ if (vendor->idVendor == 0) {
+ dev_err(&udev->dev, "Unhandled idVendor 0x%04x", id->idVendor);
+ return -EINVAL;
+ }
+
+ if (id->idVendor == vendor->idVendor)
+ return usb_skelswitch_process_products(intf, vendor->products, id->idProduct);
+
+ idx++;
+ }
+}
+
+static void usb_skelswitch_disconnect(struct usb_interface *intf)
+{
+ (void)intf;
+}
+
+static struct usb_driver usb_skelswitch_driver = {
+ .disconnect = usb_skelswitch_disconnect,
+ .name = "usb_skelswitch",
+ .probe = usb_skelswitch_probe,
+ .id_table = usb_skelswitch_table
+};
+
+module_usb_driver(usb_skelswitch_driver);
+
--
2.7.0