diff mbox series

usb: misc: Add driver for Motorola Solutions security accessories

Message ID 20231215211218.2313996-1-Yinghua.Yang@motorolasolutions.com (mailing list archive)
State New, archived
Headers show
Series usb: misc: Add driver for Motorola Solutions security accessories | expand

Commit Message

Yinghua Yang Dec. 15, 2023, 9:12 p.m. UTC
New USB driver that sets power/control to autosuspend for Motorola
Solutions security accessories. The new driver only changes the power
control for specific USB devices, normal read/write/ioctl of the usb
device uses the unmodified usbfs.

The rationale for a vendor specific driver was to allow for autosuspend
behavior on Linux installations that are battery powered and do not
allow user modifications to udev settings (e.g. embedded Linux, Android,
etc.). The idealistic generic approach that would allow any USB device
that supports autosuspend to change the power control could not be found
without a change to the USB standard or substantial change to the usbfs
architecture.

Signed-off-by: Yinghua Yang <Yinghua.Yang@motorolasolutions.com>
---
 MAINTAINERS                 |   6 +++
 drivers/usb/misc/Kconfig    |  10 ++++
 drivers/usb/misc/Makefile   |   1 +
 drivers/usb/misc/motsolsa.c | 100 ++++++++++++++++++++++++++++++++++++
 4 files changed, 117 insertions(+)
 create mode 100644 drivers/usb/misc/motsolsa.c

Comments

Alan Stern Dec. 15, 2023, 10:46 p.m. UTC | #1
On Fri, Dec 15, 2023 at 03:12:10PM -0600, Yinghua Yang wrote:
> New USB driver that sets power/control to autosuspend for Motorola
> Solutions security accessories. The new driver only changes the power
> control for specific USB devices, normal read/write/ioctl of the usb
> device uses the unmodified usbfs.
> 
> The rationale for a vendor specific driver was to allow for autosuspend
> behavior on Linux installations that are battery powered and do not
> allow user modifications to udev settings (e.g. embedded Linux, Android,
> etc.). The idealistic generic approach that would allow any USB device
> that supports autosuspend to change the power control could not be found
> without a change to the USB standard or substantial change to the usbfs
> architecture.
> 
> Signed-off-by: Yinghua Yang <Yinghua.Yang@motorolasolutions.com>
> ---

It seems silly to write a kernel driver for this.  Isn't there any way
to handle it in userspace?  All you would need is a simple shell
script.

Alan Stern
Alan Stern Dec. 16, 2023, 5:19 p.m. UTC | #2
Please use Reply-To-All so that your message goes to the mailing list as 
well as to me.

On Fri, Dec 15, 2023 at 05:17:02PM -0600, Yinghua Yang Yang wrote:
> I would prefer an easier way too. On a linux platform where udev is
> supported, a udev rule can be used to set the power/control flag. But on
> the platform I am using, the udev is not available and I don't have root
> access. Do you have any suggestions?

I can't really suggest anything without knowing more about your
userspace environment.  It's very unusual to be in a situation where
you are allowed to modify the kernel by adding a new driver but you
aren't allowed to modify the userspace by adding a new shell script!

Alan Stern

> On Fri, Dec 15, 2023 at 4:46 PM Alan Stern <stern@rowland.harvard.edu>
> wrote:
> 
> > On Fri, Dec 15, 2023 at 03:12:10PM -0600, Yinghua Yang wrote:
> > > New USB driver that sets power/control to autosuspend for Motorola
> > > Solutions security accessories. The new driver only changes the power
> > > control for specific USB devices, normal read/write/ioctl of the usb
> > > device uses the unmodified usbfs.
> > >
> > > The rationale for a vendor specific driver was to allow for autosuspend
> > > behavior on Linux installations that are battery powered and do not
> > > allow user modifications to udev settings (e.g. embedded Linux, Android,
> > > etc.). The idealistic generic approach that would allow any USB device
> > > that supports autosuspend to change the power control could not be found
> > > without a change to the USB standard or substantial change to the usbfs
> > > architecture.
> > >
> > > Signed-off-by: Yinghua Yang <Yinghua.Yang@motorolasolutions.com>
> > > ---
> >
> > It seems silly to write a kernel driver for this.  Isn't there any way
> > to handle it in userspace?  All you would need is a simple shell
> > script.
> >
> > Alan Stern
> >
> 
> -- 
> 
> 
> *For more information on how and why we collect your personal 
> information, please visit our Privacy Policy 
> <https://www.motorolasolutions.com/en_us/about/privacy-policy.html?elqTrackId=8980d888905940e39a2613a7a3dcb0a7&elqaid=2786&elqat=2#privacystatement>.*
Greg Kroah-Hartman Dec. 17, 2023, 8:29 a.m. UTC | #3
On Sat, Dec 16, 2023 at 12:15:35PM -0600, Yinghua Yang Yang wrote:
> I would prefer an easier way too. On a linux platform where udev
> is supported, a udev rule can be used to set the power/control flag. But on
> the platform I am using, the udev is not available and I don't have
> root access.
> If this driver is accepted by the Linux kernel, we hope the driver will
> subsequently be picked up by the platform's hardware vendor. With that, any
> USB device that is specified by this driver when plugged into the platform,
> auto suspend will be enabled on it.
> 
> Any suggestions will be appreciated.

As Alan says, please just fix your userspace to properly enable the
correct setting, no need for a kernel change at all.

You have the contacts and interactions to work with the hardware vendor,
don't use the kernel community as a "back door" to circumvent that.

thanks,

greg k-h
Greg Kroah-Hartman Dec. 18, 2023, 6:50 a.m. UTC | #4
On Sun, Dec 17, 2023 at 09:56:34PM -0600, Yinghua Yang Yang wrote:

<snip>

For some reason you sent this in html format, which the mailing lists
reject, and you top-posted, making it hard to respond.  Please fix up
and resend so that everyone on the mailing lists can respond properly.

thanks,

greg k-h
Alan Stern Dec. 18, 2023, 5:57 p.m. UTC | #5
On Sun, Dec 17, 2023 at 09:56:34PM -0600, Yinghua Yang Yang wrote:
> Is there a way to set the auto suspend mode for a usb device without root
> permission? I think this is a general question for many usb devices.
> According to the Linux Kernel document
> https://www.kernel.org/doc/Documentation/usb/power-management.txt, by
> default the kernel disables autosuspend for all devices. So there are many
> usb devices that support autosuspend but by default autosuspend is
> disabled. In order to support autosuspend on those devices, are the only
> solutions 1) obtain root permission and write ../power/control file using a
> script

It doesn't have to be a script; any sort of program can do it.  A 
power-management daemon such as PowerTOP, for example.

>  2) work with the hardware vendor on a driver/kernel to write the
> autosuspend flag?

That would be kind of silly.  After all, if the vendor is willing to 
work with you on a kernel driver, they certainly ought to be willing to 
work with you on installing a power-management userspace program.  And 
installing a program should be much easier than getting a new driver 
into the kernel.

But to answer your question -- Yes, the only ways to modify the 
autosuspend settings are from userspace or from within the kernel.

Alan Stern
Greg Kroah-Hartman Dec. 19, 2023, 6:02 a.m. UTC | #6
On Mon, Dec 18, 2023 at 05:44:35PM -0600, Yinghua Yang Yang wrote:
> Not sure what happened to the email. I was just replying using gmail's web
> interface and did not do anything special.

Yes, and by default, gmail sends stuff in html format, which the mailing
lists reject, you will have to change that if you wish to participate in
kernel development, as the documentation describes.

thanks,

greg k-h
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index e2c6187a3ac8..eb9ad6ab9c20 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22423,6 +22423,12 @@  S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
 F:	sound/usb/midi.*
 
+USB MOTOROLA SOLUTIONS SECURITY ACCESSORIES DRIVER
+M:	Yinghua Yang <Yinghua.Yang@motorolasolutions.com>
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+F:	drivers/usb/misc/motsolsa.c
+
 USB NETWORKING DRIVERS
 L:	linux-usb@vger.kernel.org
 S:	Odd Fixes
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index c510af7baa0d..cb1fa63cc0d1 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -331,3 +331,13 @@  config USB_ONBOARD_HUB
 	  this config will enable the driver and it will automatically
 	  match the state of the USB subsystem. If this driver is a
 	  module it will be called onboard_usb_hub.
+
+config USB_MOTSOL_SA
+	tristate "Motorola Solutions Security Accessories Driver"
+	help
+	  Say Y here if you want to enables auto suspend mode for
+	  Motorola Solutions Security Accessory devices.
+
+	  The new driver only changes the power control for specific
+	  USB devices, normal read/write/ioctl of the usb device uses
+	  the unmodified usbfs.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 0bc732bcb162..4e639693b8c5 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -34,3 +34,4 @@  obj-$(CONFIG_USB_SISUSBVGA)		+= sisusbvga/
 obj-$(CONFIG_USB_LINK_LAYER_TEST)	+= lvstest.o
 obj-$(CONFIG_BRCM_USB_PINMAP)		+= brcmstb-usb-pinmap.o
 obj-$(CONFIG_USB_ONBOARD_HUB)		+= onboard_usb_hub.o
+obj-$(CONFIG_USB_MOTSOL_SA)		+= motsolsa.o
diff --git a/drivers/usb/misc/motsolsa.c b/drivers/usb/misc/motsolsa.c
new file mode 100644
index 000000000000..69f6be9bd8d1
--- /dev/null
+++ b/drivers/usb/misc/motsolsa.c
@@ -0,0 +1,100 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for setting auto suspend mode for Motorola Solutions security accessories
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#define DRIVER_DESC "Motorola Solutions security accessory driver"
+
+static int motsol_sa_probe(struct usb_interface *interface,
+			 const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+
+	dev_dbg(&(interface)->dev, "probe (%04X:%04X)\n", id->idVendor,
+		id->idProduct);
+	usb_enable_autosuspend(udev);
+	return 0;
+}
+
+static void motsol_sa_disconnect(struct usb_interface *interface)
+{
+	dev_dbg(&(interface)->dev, "disconnect\n");
+}
+
+#define MOTSOL_VENDOR_ID 0x0cad
+#define MOTSOL_SA_PRODUCT_ID 0x01901
+
+static struct usb_device_id motsol_sa_table[] = {
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 1) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 2) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 3) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 4) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 5) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 6) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 7) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 8) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 9) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 10) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 11) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 12) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 13) },
+	{ USB_DEVICE(MOTSOL_VENDOR_ID, MOTSOL_SA_PRODUCT_ID + 14) },
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, motsol_sa_table);
+
+#ifdef CONFIG_PM
+static int motsol_sa_suspend(struct usb_interface *interface,
+			   pm_message_t message)
+{
+	dev_dbg(&(interface)->dev, "suspend");
+	return 0;
+}
+
+static int motsol_sa_resume(struct usb_interface *interface)
+{
+	dev_dbg(&(interface)->dev, "resume");
+	return 0;
+}
+#else
+#define motsol_sa_suspend NULL
+#define motsol_sa_resume NULL
+#endif
+
+static struct usb_driver motsol_sa_driver = {
+	.name = "motsol_sa",
+	.id_table = motsol_sa_table,
+	.probe = motsol_sa_probe,
+	.suspend = motsol_sa_suspend,
+	.resume = motsol_sa_resume,
+	.reset_resume = motsol_sa_resume,
+	.supports_autosuspend = 1,
+	.disconnect = motsol_sa_disconnect,
+};
+
+static int __init motsol_sa_init(void)
+{
+	int ret = -1;
+
+	ret = usb_register(&motsol_sa_driver);
+	pr_debug("%s: %s\n", KBUILD_MODNAME, DRIVER_DESC);
+	return ret;
+}
+
+static void __exit motsol_sa_exit(void)
+{
+	usb_deregister(&motsol_sa_driver);
+	pr_debug("%s driver deregistered\n", motsol_sa_driver.name);
+}
+
+module_init(motsol_sa_init);
+module_exit(motsol_sa_exit);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");