From owner-freebsd-usb@FreeBSD.ORG Tue Jul 31 03:19:57 2012 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 9BC13106566B; Tue, 31 Jul 2012 03:19:57 +0000 (UTC) (envelope-from takawata@init-main.com) Received: from sana.init-main.com (unknown [IPv6:2001:240:28::1]) by mx1.freebsd.org (Postfix) with ESMTP id 1B6488FC0C; Tue, 31 Jul 2012 03:19:56 +0000 (UTC) Received: from ns.init-main.com (localhost [127.0.0.1]) by sana.init-main.com (8.14.3/8.14.3) with ESMTP id q6V3JC6a014526; Tue, 31 Jul 2012 12:19:12 +0900 (JST) (envelope-from takawata@ns.init-main.com) Message-Id: <201207310319.q6V3JC6a014526@sana.init-main.com> To: freebsd-acpi@freebsd.org, freebsd-usb@freebsd.org Date: Tue, 31 Jul 2012 12:19:12 +0900 From: Takanori Watanabe Cc: Subject: USB ACPI namespace mapping. X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 31 Jul 2012 03:19:57 -0000 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 #include +#include #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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +#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