I'm trying to map USB devices and hub into acpi handle,
and I want ideas to cope with a problem.

The problem is that there is no easy way to get port number from 
child usb device in hub device. 
usb_attach_arg structure have one, but invalidate after probe and attach.

And, furthermore, which device_t instance should I register to acpi
device handle to cope with ACPI docking station framework.

The code I wrote is as follows.


Index: usb_hub.c
===================================================================
--- usb_hub.c   (revision 238557)
+++ usb_hub.c   (working copy)
@@ -69,10 +69,11 @@
 
 #include <dev/usb/usb_controller.h>
 #include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_hub_private.h>
 
 #define        UHUB_INTR_INTERVAL 250          /* ms */
-#define        UHUB_N_TRANSFER 1
 
+
 #ifdef USB_DEBUG
 static int uhub_debug = 0;
 
@@ -90,42 +91,15 @@
     &usb_power_timeout, 0, "USB power timeout");
 #endif
 
-struct uhub_current_state {
-       uint16_t port_change;
-       uint16_t port_status;
-};
-
-struct uhub_softc {
-       struct uhub_current_state sc_st;/* current state */
-       device_t sc_dev;                /* base device */
-       struct mtx sc_mtx;              /* our mutex */
-       struct usb_device *sc_udev;     /* USB device */
-       struct usb_xfer *sc_xfer[UHUB_N_TRANSFER];      /* interrupt xfer */
-       uint8_t sc_flags;
-#define        UHUB_FLAG_DID_EXPLORE 0x01
-       char    sc_name[32];
-};
-
 #define        UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
 #define        UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
 #define        UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
 #define        UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT)
 #define        UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB)
 
-/* prototypes for type checking: */
-
-static device_probe_t uhub_probe;
-static device_attach_t uhub_attach;
-static device_detach_t uhub_detach;
-static device_suspend_t uhub_suspend;
-static device_resume_t uhub_resume;
-
-static bus_driver_added_t uhub_driver_added;
-static bus_child_location_str_t uhub_child_location_string;
-static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
-
 static usb_callback_t uhub_intr_callback;
 
+
 static void usb_dev_resume_peer(struct usb_device *udev);
 static void usb_dev_suspend_peer(struct usb_device *udev);
 static uint8_t usb_peer_should_wakeup(struct usb_device *udev);
@@ -164,7 +138,7 @@
        {0, 0}
 };
 
-static driver_t uhub_driver = {
+driver_t uhub_driver = {
        .name = "uhub",
        .methods = uhub_methods,
        .size = sizeof(struct uhub_softc)
@@ -821,8 +795,7 @@
        return (USB_ERR_NORMAL_COMPLETION);
 }
 
-static int
-uhub_probe(device_t dev)
+int uhub_probe(device_t dev)
 {
        struct usb_attach_arg *uaa = device_get_ivars(dev);
 
@@ -835,7 +808,7 @@
         */
        if (uaa->info.bConfigIndex == 0 &&
            uaa->info.bDeviceClass == UDCLASS_HUB)
-               return (0);
+               return (BUS_PROBE_GENERIC);
 
        return (ENXIO);
 }
@@ -900,8 +873,7 @@
 
        return (err);
 }
-
-static int
+int
 uhub_attach(device_t dev)
 {
        struct uhub_softc *sc = device_get_softc(dev);
@@ -1204,7 +1176,8 @@
  * Called from process context when the hub is gone.
  * Detach all devices on active ports.
  */
-static int
+
+int
 uhub_detach(device_t dev)
 {
        struct uhub_softc *sc = device_get_softc(dev);
@@ -1241,7 +1214,7 @@
        return (0);
 }
 
-static int
+int
 uhub_suspend(device_t dev)
 {
        DPRINTF("\n");
@@ -1249,7 +1222,7 @@
        return (0);
 }
 
-static int
+int
 uhub_resume(device_t dev)
 {
        DPRINTF("\n");
@@ -1257,7 +1230,7 @@
        return (0);
 }
 
-static void
+void
 uhub_driver_added(device_t dev, driver_t *driver)
 {
        usb_needs_explore_all();
@@ -1302,7 +1275,7 @@
        res->portno = 0;
 }
 
-static int
+int
 uhub_child_location_string(device_t parent, device_t child,
     char *buf, size_t buflen)
 {
@@ -1338,7 +1311,7 @@
        return (0);
 }
 
-static int
+int
 uhub_child_pnpinfo_string(device_t parent, device_t child,
     char *buf, size_t buflen)
 {
Index: usb_hub_acpi.c
===================================================================
--- usb_hub_acpi.c      (revision 0)
+++ usb_hub_acpi.c      (revision 0)
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 2012 Takanori Watanabe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_ioctl.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_hub.h>
+#include <dev/usb/usb_util.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_transfer.h>
+#include <dev/usb/usb_dynamic.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <dev/acpica/acpivar.h>
+#include <dev/usb/usb_hub_private.h>
+
+
+#define MAX_PORT 32
+
+struct uhub_acpi_softc{
+       struct uhub_softc base; /*must be first member*/
+       ACPI_HANDLE hub_handle;
+       ACPI_HANDLE port_handle[MAX_PORT];
+};
+
+static int
+uhub_acpi_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+       struct uhub_acpi_softc *sc = device_get_softc(dev);
+       struct usb_attach_arg *ivars = device_get_ivars(child);
+       
+       switch (which) {
+       case ACPI_IVAR_HANDLE:
+#if 0   /*XXX*/  
+               *result = (uintptr_t)sc->port_handle[ivars->port];
+#endif
+               return (0);
+       }
+       return ENXIO;
+}
+
+static ACPI_STATUS uhub_acpi_port_probe(ACPI_HANDLE handle, UINT32 level, void 
*context, void **status)
+{
+       ACPI_DEVICE_INFO *devinfo;
+       device_t dev =(device_t)context;
+       struct uhub_acpi_softc *sc = device_get_softc(dev);
+       
+       
+       if(AcpiGetObjectInfo(handle, &devinfo))
+               return AE_OK;
+       if(!(devinfo->Valid&ACPI_VALID_ADR)){
+               return AE_OK;
+       }
+       if(devinfo->Address == 0){
+               device_printf(dev, "port 0 is root hub only\n");
+               return AE_OK;
+       }
+
+       if(devinfo->Address > MAX_PORT){
+               device_printf(dev, "Too high port in the hub %lld\n",
+                             devinfo->Address);
+               return AE_OK;
+       }
+       device_printf(dev, "%s at  port %lld\n", acpi_name(handle),
+                     devinfo->Address);
+       sc->port_handle[devinfo->Address -1] = handle;
+
+       return AE_OK;
+}
+
+static ACPI_STATUS uhub_root_acpi_handle(ACPI_HANDLE handle, UINT32 level, 
void *context, void **status)
+{
+       ACPI_DEVICE_INFO *devinfo;
+
+       *status = NULL;
+
+       if(AcpiGetObjectInfo(handle, &devinfo))
+               return AE_OK;
+       if(!(devinfo->Valid&ACPI_VALID_ADR)){
+               return AE_OK;
+       }
+       if(devinfo->Address != 0){
+               printf("Non zero Address for root hub %llx\n",
+                      devinfo->Address);
+               return AE_OK;
+       }
+       *status = (void *)handle;
+       return AE_CTRL_TERMINATE;
+}
+
+static ACPI_HANDLE uhub_acpi_my_handle(device_t dev)
+{
+
+       ACPI_HANDLE h,childh;
+
+       if(strcmp(device_get_name(device_get_parent(dev)), "usbus") ==0){
+               h = acpi_get_handle(device_get_parent(device_get_parent(dev)));
+               AcpiWalkNamespace(ACPI_TYPE_DEVICE, h, 1, 
+                                 uhub_root_acpi_handle,
+                                 NULL,dev, &childh);
+
+       }else{
+               childh =  acpi_get_handle(dev);
+       }
+
+       return childh;
+}
+
+static int
+uhub_acpi_probe(device_t dev)
+{
+       struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+       if (uaa->usb_mode != USB_MODE_HOST)
+               return (ENXIO);
+
+
+       if(uhub_acpi_my_handle(dev) == NULL){
+               return ENXIO;
+       }
+       device_printf(dev, "ACPI capable\n");
+       /*
+        * The subclass for USB HUBs is currently ignored because it
+        * is 0 for some and 1 for others.
+        */
+
+       if (uaa->info.bConfigIndex == 0 &&
+           uaa->info.bDeviceClass == UDCLASS_HUB){
+               return (0);
+       }
+
+       return (ENXIO);
+}
+static int  uhub_acpi_attach(device_t dev)
+{
+       struct uhub_acpi_softc *sc = device_get_softc(dev);
+       sc->hub_handle = uhub_acpi_my_handle(dev);
+       device_printf(dev, "PATH:%s\n", acpi_name(sc->hub_handle));
+       
+       AcpiWalkNamespace(ACPI_TYPE_DEVICE, sc->hub_handle, 1, 
+                         uhub_acpi_port_probe,
+                         NULL,dev, NULL);
+       
+       
+       return uhub_attach(dev);
+}
+
+
+static int
+uhub_acpi_child_location_string(device_t parent, device_t child,
+    char *buf, size_t buflen)
+{
+
+       int len = 0;
+#if 0   /*XXX*/
+       struct uhub_acpi_softc *sc = device_get_softc(child);
+       struct usb_attach_arg *uaa = device_get_ivars(child);
+
+       len = snprintf(buf, buflen,
+                      "handle=%s ", acpi_name(sc->port_handle[uaa->port]));
+#endif
+       return uhub_child_location_string(parent, child, 
+                                         buf + len, buflen - len);
+}
+
+
+static device_method_t uhub_acpi_methods[] = {
+       DEVMETHOD(device_probe, uhub_acpi_probe),
+       DEVMETHOD(device_attach, uhub_acpi_attach),
+
+       DEVMETHOD(bus_read_ivar, uhub_acpi_read_ivar),
+       DEVMETHOD(bus_child_location_str, uhub_acpi_child_location_string),
+
+       {0, 0}
+};
+
+static devclass_t uhub_devclass;
+DECLARE_CLASS(uhub_driver);
+
+DEFINE_CLASS_1(uhub, uhub_acpi_driver, uhub_acpi_methods, 
+              sizeof(struct uhub_acpi_softc),uhub_driver);
+
+DRIVER_MODULE(uhub_acpi, usbus, uhub_acpi_driver, uhub_devclass, 0, 0);
+DRIVER_MODULE(uhub_acpi, uhub, uhub_acpi_driver, uhub_devclass, NULL, 0);
Index: usb_hub_private.h
===================================================================
--- usb_hub_private.h   (revision 0)
+++ usb_hub_private.h   (revision 0)
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2012 Takanori Watanabe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _USB_HUB_PRIVATE_H
+#define _USB_HUB_PRIVATE_H
+
+#define        UHUB_N_TRANSFER 1
+struct uhub_current_state {
+       uint16_t port_change;
+       uint16_t port_status;
+};
+
+struct uhub_softc {
+       struct uhub_current_state sc_st;/* current state */
+       device_t sc_dev;                /* base device */
+       struct mtx sc_mtx;              /* our mutex */
+       struct usb_device *sc_udev;     /* USB device */
+       struct usb_xfer *sc_xfer[UHUB_N_TRANSFER];      /* interrupt xfer */
+       uint8_t sc_flags;
+#define        UHUB_FLAG_DID_EXPLORE 0x01
+       char    sc_name[32];
+};
+
+
+device_probe_t uhub_probe;
+device_attach_t uhub_attach;
+device_detach_t uhub_detach;
+device_suspend_t uhub_suspend;
+device_resume_t uhub_resume;
+
+bus_driver_added_t uhub_driver_added;
+bus_child_location_str_t uhub_child_location_string;
+bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
+
+#endif
_______________________________________________
freebsd-acpi@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-acpi
To unsubscribe, send any mail to "freebsd-acpi-unsubscr...@freebsd.org"

Reply via email to