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 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html