summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Tso <kyletso@google.com>2023-02-18 18:26:40 +0800
committerKyle Tso <kyletso@google.com>2023-05-23 17:53:56 +0800
commit80e2b699bced34fda938ba94712ca41543d198a8 (patch)
treebee582cda238d729460b70b3e71d0e183c56c993
parentdc6412568138c7f3b80ce2b7969629e4320b92cd (diff)
downloadtangorpro-80e2b699bced34fda938ba94712ca41543d198a8.tar.gz
pogo_transport: Register the notifier of USB devices
Register the notifier of adding/removing a USB device from the USB core. Bug: 250518260 Change-Id: Icd7b47a48ee43c77622bf36bc0eb605197e8d92e Signed-off-by: Kyle Tso <kyletso@google.com> (cherry picked from commit e2696396f54858838574a6fb388988e18a778024)
-rw-r--r--pogo/pogo_transport.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/pogo/pogo_transport.c b/pogo/pogo_transport.c
index ddd863e..7e2a1d9 100644
--- a/pogo/pogo_transport.c
+++ b/pogo/pogo_transport.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/regulator/consumer.h>
+#include <linux/usb.h>
#include <linux/usb/tcpm.h>
#include <misc/gvotable.h>
@@ -154,6 +155,9 @@ struct pogo_transport {
*/
bool mock_hid_connected;
struct kthread_worker *wq;
+
+ struct notifier_block udev_nb;
+
/* To read voltage at the pogo pins */
struct power_supply *pogo_psy;
/* Retry when voltage is less than POGO_USB_CAPABLE_THRESHOLD_UV */
@@ -846,6 +850,56 @@ static irqreturn_t pogo_isr(int irq, void *dev_id)
return IRQ_WAKE_THREAD;
}
+static void pogo_transport_udev_add(struct pogo_transport *pogo_transport, struct usb_device *udev)
+{
+ struct usb_interface_descriptor *desc;
+ struct usb_host_config *config;
+ bool audio_dev = false;
+ int i;
+
+ config = udev->config;
+ for (i = 0; i < config->desc.bNumInterfaces; i++) {
+ desc = &config->intf_cache[i]->altsetting->desc;
+ if (desc->bInterfaceClass == USB_CLASS_AUDIO) {
+ audio_dev = true;
+ break;
+ }
+ }
+
+ logbuffer_log(pogo_transport->log, "udev added %04X:%04X %s",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ audio_dev ? "(audio)" : "");
+}
+
+/* notifier callback from usb core */
+static int pogo_transport_udev_notify(struct notifier_block *nb, unsigned long action, void *dev)
+{
+ struct pogo_transport *pogo_transport = container_of(nb, struct pogo_transport, udev_nb);
+ struct usb_device *udev = dev;
+
+ switch (action) {
+ case USB_DEVICE_ADD:
+ /* Don't care about the root hubs. */
+ if (udev->bus->root_hub == udev)
+ break;
+
+ pogo_transport_udev_add(pogo_transport, udev);
+ break;
+ case USB_DEVICE_REMOVE:
+ /* Don't care about the root hubs. */
+ if (udev->bus->root_hub == udev)
+ break;
+
+ logbuffer_log(pogo_transport->log, "udev removed %04X:%04X",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
#if IS_ENABLED(CONFIG_DEBUG_FS)
static int mock_hid_connected_set(void *data, u64 val)
{
@@ -1324,6 +1378,8 @@ static int pogo_transport_probe(struct platform_device *pdev)
register_data_active_callback(data_active_changed, pogo_transport);
register_orientation_callback(orientation_changed, pogo_transport);
+ pogo_transport->udev_nb.notifier_call = pogo_transport_udev_notify;
+ usb_register_notify(&pogo_transport->udev_nb);
/* run once in case orientation has changed before registering the callback */
orientation_changed((void *)pogo_transport);
dev_info(&pdev->dev, "force usb:%d\n", modparam_force_usb ? 1 : 0);
@@ -1349,6 +1405,8 @@ static int pogo_transport_remove(struct platform_device *pdev)
struct pogo_transport *pogo_transport = platform_get_drvdata(pdev);
struct dentry *dentry;
+ usb_unregister_notify(&pogo_transport->udev_nb);
+
#if IS_ENABLED(CONFIG_DEBUG_FS)
dentry = debugfs_lookup("pogo_transport", NULL);
if (IS_ERR(dentry)) {