aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/core/hub.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hub.h')
-rw-r--r--drivers/usb/core/hub.h343
1 files changed, 147 insertions, 196 deletions
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index de8081f065e..326308e5396 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -1,205 +1,156 @@
-#ifndef __LINUX_HUB_H
-#define __LINUX_HUB_H
-
/*
- * Hub protocol and driver data structures.
+ * usb hub driver head file
*
- * Some of these are known to the "virtual root hub" code
- * in host controller drivers.
- */
-
-#include <linux/list.h>
-#include <linux/workqueue.h>
-#include <linux/compiler.h> /* likely()/unlikely() */
-
-/*
- * Hub request types
- */
-
-#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
-#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
-
-/*
- * Hub class requests
- * See USB 2.0 spec Table 11-16
- */
-#define HUB_CLEAR_TT_BUFFER 8
-#define HUB_RESET_TT 9
-#define HUB_GET_TT_STATE 10
-#define HUB_STOP_TT 11
-
-/*
- * Hub Class feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define C_HUB_LOCAL_POWER 0
-#define C_HUB_OVER_CURRENT 1
-
-/*
- * Port feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define USB_PORT_FEAT_CONNECTION 0
-#define USB_PORT_FEAT_ENABLE 1
-#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */
-#define USB_PORT_FEAT_OVER_CURRENT 3
-#define USB_PORT_FEAT_RESET 4
-#define USB_PORT_FEAT_L1 5 /* L1 suspend */
-#define USB_PORT_FEAT_POWER 8
-#define USB_PORT_FEAT_LOWSPEED 9
-/* This value was never in Table 11-17 */
-#define USB_PORT_FEAT_HIGHSPEED 10
-/* This value is also fake */
-#define USB_PORT_FEAT_SUPERSPEED 11
-#define USB_PORT_FEAT_C_CONNECTION 16
-#define USB_PORT_FEAT_C_ENABLE 17
-#define USB_PORT_FEAT_C_SUSPEND 18
-#define USB_PORT_FEAT_C_OVER_CURRENT 19
-#define USB_PORT_FEAT_C_RESET 20
-#define USB_PORT_FEAT_TEST 21
-#define USB_PORT_FEAT_INDICATOR 22
-#define USB_PORT_FEAT_C_PORT_L1 23
-
-/*
- * Hub Status and Hub Change results
- * See USB 2.0 spec Table 11-19 and Table 11-20
- */
-struct usb_port_status {
- __le16 wPortStatus;
- __le16 wPortChange;
-} __attribute__ ((packed));
-
-/*
- * wPortStatus bit field
- * See USB 2.0 spec Table 11-21
- */
-#define USB_PORT_STAT_CONNECTION 0x0001
-#define USB_PORT_STAT_ENABLE 0x0002
-#define USB_PORT_STAT_SUSPEND 0x0004
-#define USB_PORT_STAT_OVERCURRENT 0x0008
-#define USB_PORT_STAT_RESET 0x0010
-#define USB_PORT_STAT_L1 0x0020
-/* bits 6 to 7 are reserved */
-#define USB_PORT_STAT_POWER 0x0100
-#define USB_PORT_STAT_LOW_SPEED 0x0200
-#define USB_PORT_STAT_HIGH_SPEED 0x0400
-#define USB_PORT_STAT_TEST 0x0800
-#define USB_PORT_STAT_INDICATOR 0x1000
-/* bits 13 to 15 are reserved */
-
-/*
- * wPortChange bit field
- * See USB 2.0 spec Table 11-22
- * Bits 0 to 4 shown, bits 5 to 15 are reserved
- */
-#define USB_PORT_STAT_C_CONNECTION 0x0001
-#define USB_PORT_STAT_C_ENABLE 0x0002
-#define USB_PORT_STAT_C_SUSPEND 0x0004
-#define USB_PORT_STAT_C_OVERCURRENT 0x0008
-#define USB_PORT_STAT_C_RESET 0x0010
-#define USB_PORT_STAT_C_L1 0x0020
-
-/*
- * wHubCharacteristics (masks)
- * See USB 2.0 spec Table 11-13, offset 3
- */
-#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
-#define HUB_CHAR_COMPOUND 0x0004 /* D2 */
-#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */
-#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */
-#define HUB_CHAR_PORTIND 0x0080 /* D7 */
-
-struct usb_hub_status {
- __le16 wHubStatus;
- __le16 wHubChange;
-} __attribute__ ((packed));
-
-/*
- * Hub Status & Hub Change bit masks
- * See USB 2.0 spec Table 11-19 and Table 11-20
- * Bits 0 and 1 for wHubStatus and wHubChange
- * Bits 2 to 15 are reserved for both
- */
-#define HUB_STATUS_LOCAL_POWER 0x0001
-#define HUB_STATUS_OVERCURRENT 0x0002
-#define HUB_CHANGE_LOCAL_POWER 0x0001
-#define HUB_CHANGE_OVERCURRENT 0x0002
-
-
-/*
- * Hub descriptor
- * See USB 2.0 spec Table 11-13
- */
-
-#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
-#define USB_DT_HUB_NONVAR_SIZE 7
-
-struct usb_hub_descriptor {
- __u8 bDescLength;
- __u8 bDescriptorType;
- __u8 bNbrPorts;
- __le16 wHubCharacteristics;
- __u8 bPwrOn2PwrGood;
- __u8 bHubContrCurrent;
- /* add 1 bit for hub status change; round to bytes */
- __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
- __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
-} __attribute__ ((packed));
-
-
-/* port indicator status selectors, tables 11-7 and 11-25 */
-#define HUB_LED_AUTO 0
-#define HUB_LED_AMBER 1
-#define HUB_LED_GREEN 2
-#define HUB_LED_OFF 3
-
-enum hub_led_mode {
- INDICATOR_AUTO = 0,
- INDICATOR_CYCLE,
- /* software blinks for attention: software, hardware, reserved */
- INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF,
- INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF,
- INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF
-} __attribute__ ((packed));
-
-struct usb_device;
-
-/* Transaction Translator Think Times, in bits */
-#define HUB_TTTT_8_BITS 0x00
-#define HUB_TTTT_16_BITS 0x20
-#define HUB_TTTT_24_BITS 0x40
-#define HUB_TTTT_32_BITS 0x60
-
-/*
- * As of USB 2.0, full/low speed devices are segregated into trees.
- * One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
- * The other type grows from high speed hubs when they connect to
- * full/low speed devices using "Transaction Translators" (TTs).
+ * Copyright (C) 1999 Linus Torvalds
+ * Copyright (C) 1999 Johannes Erdfelt
+ * Copyright (C) 1999 Gregory P. Smith
+ * Copyright (C) 2001 Brad Hards (bhards@bigpond.net.au)
+ * Copyright (C) 2012 Intel Corp (tianyu.lan@intel.com)
+ *
+ * move struct usb_hub to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * TTs should only be known to the hub driver, and high speed bus
- * drivers (only EHCI for now). They affect periodic scheduling and
- * sometimes control/bulk error recovery.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*/
-struct usb_tt {
- struct usb_device *hub; /* upstream highspeed hub */
- int multi; /* true means one TT per port */
- unsigned think_time; /* think time in ns */
-
- /* for control/bulk error recovery (CLEAR_TT_BUFFER) */
- spinlock_t lock;
- struct list_head clear_list; /* of usb_tt_clear */
- struct work_struct clear_work;
+
+#include <linux/usb.h>
+#include <linux/usb/ch11.h>
+#include <linux/usb/hcd.h>
+#include "usb.h"
+
+struct usb_hub {
+ struct device *intfdev; /* the "interface" device */
+ struct usb_device *hdev;
+ struct kref kref;
+ struct urb *urb; /* for interrupt polling pipe */
+
+ /* buffer for urb ... with extra space in case of babble */
+ u8 (*buffer)[8];
+ union {
+ struct usb_hub_status hub;
+ struct usb_port_status port;
+ } *status; /* buffer for status reports */
+ struct mutex status_mutex; /* for the status buffer */
+
+ int error; /* last reported error */
+ int nerrors; /* track consecutive errors */
+
+ struct list_head event_list; /* hubs w/data or errs ready */
+ unsigned long event_bits[1]; /* status change bitmask */
+ unsigned long change_bits[1]; /* ports with logical connect
+ status change */
+ unsigned long removed_bits[1]; /* ports with a "removed"
+ device present */
+ unsigned long wakeup_bits[1]; /* ports that have signaled
+ remote wakeup */
+ unsigned long power_bits[1]; /* ports that are powered */
+ unsigned long child_usage_bits[1]; /* ports powered on for
+ children */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
+
+ struct usb_hub_descriptor *descriptor; /* class descriptor */
+ struct usb_tt tt; /* Transaction Translator */
+
+ unsigned mA_per_port; /* current for each child */
+#ifdef CONFIG_PM
+ unsigned wakeup_enabled_descendants;
+#endif
+
+ unsigned limited_power:1;
+ unsigned quiescing:1;
+ unsigned disconnected:1;
+ unsigned in_reset:1;
+
+ unsigned quirk_check_port_auto_suspend:1;
+
+ unsigned has_indicators:1;
+ u8 indicator[USB_MAXCHILDREN];
+ struct delayed_work leds;
+ struct delayed_work init_work;
+ struct usb_port **ports;
};
-struct usb_tt_clear {
- struct list_head clear_list;
- unsigned tt;
- u16 devinfo;
- struct usb_hcd *hcd;
- struct usb_host_endpoint *ep;
+/**
+ * struct usb port - kernel's representation of a usb port
+ * @child: usb device attached to the port
+ * @dev: generic device interface
+ * @port_owner: port's owner
+ * @peer: related usb2 and usb3 ports (share the same connector)
+ * @req: default pm qos request for hubs without port power control
+ * @connect_type: port's connect type
+ * @location: opaque representation of platform connector location
+ * @status_lock: synchronize port_event() vs usb_port_{suspend|resume}
+ * @portnum: port index num based one
+ * @is_superspeed cache super-speed status
+ */
+struct usb_port {
+ struct usb_device *child;
+ struct device dev;
+ struct usb_dev_state *port_owner;
+ struct usb_port *peer;
+ struct dev_pm_qos_request *req;
+ enum usb_port_connect_type connect_type;
+ usb_port_location_t location;
+ struct mutex status_lock;
+ u8 portnum;
+ unsigned int is_superspeed:1;
};
-extern int usb_hub_clear_tt_buffer(struct urb *urb);
-extern void usb_ep0_reinit(struct usb_device *);
+#define to_usb_port(_dev) \
+ container_of(_dev, struct usb_port, dev)
+
+extern int usb_hub_create_port_device(struct usb_hub *hub,
+ int port1);
+extern void usb_hub_remove_port_device(struct usb_hub *hub,
+ int port1);
+extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
+ int port1, bool set);
+extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
+extern int hub_port_debounce(struct usb_hub *hub, int port1,
+ bool must_be_connected);
+extern int usb_clear_port_feature(struct usb_device *hdev,
+ int port1, int feature);
+
+static inline bool hub_is_port_power_switchable(struct usb_hub *hub)
+{
+ __le16 hcs;
+
+ if (!hub)
+ return false;
+ hcs = hub->descriptor->wHubCharacteristics;
+ return (le16_to_cpu(hcs) & HUB_CHAR_LPSM) < HUB_CHAR_NO_LPSM;
+}
+
+static inline int hub_is_superspeed(struct usb_device *hdev)
+{
+ return hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS;
+}
+
+static inline unsigned hub_power_on_good_delay(struct usb_hub *hub)
+{
+ unsigned delay = hub->descriptor->bPwrOn2PwrGood * 2;
+
+ /* Wait at least 100 msec for power to become stable */
+ return max(delay, 100U);
+}
+
+static inline int hub_port_debounce_be_connected(struct usb_hub *hub,
+ int port1)
+{
+ return hub_port_debounce(hub, port1, true);
+}
+
+static inline int hub_port_debounce_be_stable(struct usb_hub *hub,
+ int port1)
+{
+ return hub_port_debounce(hub, port1, false);
+}
-#endif /* __LINUX_HUB_H */