Merge 4.6-rc5 into usb-next
We want the USB fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
commit
69b4269eff
@ -314,7 +314,7 @@ void qset_free_std(struct whc *whc, struct whc_std *std)
|
|||||||
kfree(std->bounce_buf);
|
kfree(std->bounce_buf);
|
||||||
}
|
}
|
||||||
if (std->pl_virt) {
|
if (std->pl_virt) {
|
||||||
if (std->dma_addr)
|
if (!dma_mapping_error(whc->wusbhc.dev, std->dma_addr))
|
||||||
dma_unmap_single(whc->wusbhc.dev, std->dma_addr,
|
dma_unmap_single(whc->wusbhc.dev, std->dma_addr,
|
||||||
std->num_pointers * sizeof(struct whc_page_list_entry),
|
std->num_pointers * sizeof(struct whc_page_list_entry),
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
@ -535,9 +535,11 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u
|
|||||||
list_for_each_entry(std, &qset->stds, list_node) {
|
list_for_each_entry(std, &qset->stds, list_node) {
|
||||||
if (std->ntds_remaining == -1) {
|
if (std->ntds_remaining == -1) {
|
||||||
pl_len = std->num_pointers * sizeof(struct whc_page_list_entry);
|
pl_len = std->num_pointers * sizeof(struct whc_page_list_entry);
|
||||||
std->ntds_remaining = ntds--;
|
|
||||||
std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt,
|
std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt,
|
||||||
pl_len, DMA_TO_DEVICE);
|
pl_len, DMA_TO_DEVICE);
|
||||||
|
if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr))
|
||||||
|
return -EFAULT;
|
||||||
|
std->ntds_remaining = ntds--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -618,6 +620,8 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset,
|
|||||||
|
|
||||||
std->dma_addr = dma_map_single(&whc->umc->dev, std->bounce_buf, std->len,
|
std->dma_addr = dma_map_single(&whc->umc->dev, std->bounce_buf, std->len,
|
||||||
is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_out ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
|
if (dma_mapping_error(&whc->umc->dev, std->dma_addr))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
if (qset_fill_page_list(whc, std, mem_flags) < 0)
|
if (qset_fill_page_list(whc, std, mem_flags) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -1768,7 +1768,7 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci,
|
|||||||
if (trb_comp_code == COMP_TX_ERR ||
|
if (trb_comp_code == COMP_TX_ERR ||
|
||||||
trb_comp_code == COMP_BABBLE ||
|
trb_comp_code == COMP_BABBLE ||
|
||||||
trb_comp_code == COMP_SPLIT_ERR)
|
trb_comp_code == COMP_SPLIT_ERR)
|
||||||
/* The 0.96 spec says a babbling control endpoint
|
/* The 0.95 spec says a babbling control endpoint
|
||||||
* is not halted. The 0.96 spec says it is. Some HW
|
* is not halted. The 0.96 spec says it is. Some HW
|
||||||
* claims to be 0.95 compliant, but it halts the control
|
* claims to be 0.95 compliant, but it halts the control
|
||||||
* endpoint anyway. Check if a babble halted the
|
* endpoint anyway. Check if a babble halted the
|
||||||
|
@ -388,7 +388,6 @@ err_files:
|
|||||||
err_port:
|
err_port:
|
||||||
dev_set_drvdata(&udev->dev, NULL);
|
dev_set_drvdata(&udev->dev, NULL);
|
||||||
usb_put_dev(udev);
|
usb_put_dev(udev);
|
||||||
kthread_stop_put(sdev->ud.eh);
|
|
||||||
|
|
||||||
busid_priv->sdev = NULL;
|
busid_priv->sdev = NULL;
|
||||||
stub_device_free(sdev);
|
stub_device_free(sdev);
|
||||||
@ -449,7 +448,7 @@ static void stub_disconnect(struct usb_device *udev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If usb reset is called from event handler */
|
/* If usb reset is called from event handler */
|
||||||
if (busid_priv->sdev->ud.eh == current)
|
if (usbip_in_eh(current))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* shutdown the current connection */
|
/* shutdown the current connection */
|
||||||
|
@ -769,12 +769,19 @@ EXPORT_SYMBOL_GPL(usbip_recv_xbuff);
|
|||||||
|
|
||||||
static int __init usbip_core_init(void)
|
static int __init usbip_core_init(void)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
|
pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
|
||||||
|
ret = usbip_init_eh();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit usbip_core_exit(void)
|
static void __exit usbip_core_exit(void)
|
||||||
{
|
{
|
||||||
|
usbip_finish_eh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +267,6 @@ struct usbip_device {
|
|||||||
struct task_struct *tcp_tx;
|
struct task_struct *tcp_tx;
|
||||||
|
|
||||||
unsigned long event;
|
unsigned long event;
|
||||||
struct task_struct *eh;
|
|
||||||
wait_queue_head_t eh_waitq;
|
wait_queue_head_t eh_waitq;
|
||||||
|
|
||||||
struct eh_ops {
|
struct eh_ops {
|
||||||
@ -313,10 +312,13 @@ void usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
|
|||||||
int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
|
int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
|
||||||
|
|
||||||
/* usbip_event.c */
|
/* usbip_event.c */
|
||||||
|
int usbip_init_eh(void);
|
||||||
|
void usbip_finish_eh(void);
|
||||||
int usbip_start_eh(struct usbip_device *ud);
|
int usbip_start_eh(struct usbip_device *ud);
|
||||||
void usbip_stop_eh(struct usbip_device *ud);
|
void usbip_stop_eh(struct usbip_device *ud);
|
||||||
void usbip_event_add(struct usbip_device *ud, unsigned long event);
|
void usbip_event_add(struct usbip_device *ud, unsigned long event);
|
||||||
int usbip_event_happened(struct usbip_device *ud);
|
int usbip_event_happened(struct usbip_device *ud);
|
||||||
|
int usbip_in_eh(struct task_struct *task);
|
||||||
|
|
||||||
static inline int interface_to_busnum(struct usb_interface *interface)
|
static inline int interface_to_busnum(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2008 Takahiro Hirofuchi
|
* Copyright (C) 2003-2008 Takahiro Hirofuchi
|
||||||
|
* Copyright (C) 2015 Nobuo Iwata
|
||||||
*
|
*
|
||||||
* This is free software; you can redistribute it and/or modify
|
* This is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -19,17 +20,68 @@
|
|||||||
|
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
#include "usbip_common.h"
|
#include "usbip_common.h"
|
||||||
|
|
||||||
static int event_handler(struct usbip_device *ud)
|
struct usbip_event {
|
||||||
{
|
struct list_head node;
|
||||||
usbip_dbg_eh("enter\n");
|
struct usbip_device *ud;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
static DEFINE_SPINLOCK(event_lock);
|
||||||
* Events are handled by only this thread.
|
static LIST_HEAD(event_list);
|
||||||
*/
|
|
||||||
while (usbip_event_happened(ud)) {
|
static void set_event(struct usbip_device *ud, unsigned long event)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ud->lock, flags);
|
||||||
|
ud->event |= event;
|
||||||
|
spin_unlock_irqrestore(&ud->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unset_event(struct usbip_device *ud, unsigned long event)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ud->lock, flags);
|
||||||
|
ud->event &= ~event;
|
||||||
|
spin_unlock_irqrestore(&ud->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usbip_device *get_event(void)
|
||||||
|
{
|
||||||
|
struct usbip_event *ue = NULL;
|
||||||
|
struct usbip_device *ud = NULL;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&event_lock, flags);
|
||||||
|
if (!list_empty(&event_list)) {
|
||||||
|
ue = list_first_entry(&event_list, struct usbip_event, node);
|
||||||
|
list_del(&ue->node);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&event_lock, flags);
|
||||||
|
|
||||||
|
if (ue) {
|
||||||
|
ud = ue->ud;
|
||||||
|
kfree(ue);
|
||||||
|
}
|
||||||
|
return ud;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct task_struct *worker_context;
|
||||||
|
|
||||||
|
static void event_handler(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct usbip_device *ud;
|
||||||
|
|
||||||
|
if (worker_context == NULL) {
|
||||||
|
worker_context = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ud = get_event()) != NULL) {
|
||||||
usbip_dbg_eh("pending event %lx\n", ud->event);
|
usbip_dbg_eh("pending event %lx\n", ud->event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -38,79 +90,102 @@ static int event_handler(struct usbip_device *ud)
|
|||||||
*/
|
*/
|
||||||
if (ud->event & USBIP_EH_SHUTDOWN) {
|
if (ud->event & USBIP_EH_SHUTDOWN) {
|
||||||
ud->eh_ops.shutdown(ud);
|
ud->eh_ops.shutdown(ud);
|
||||||
ud->event &= ~USBIP_EH_SHUTDOWN;
|
unset_event(ud, USBIP_EH_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the device. */
|
/* Reset the device. */
|
||||||
if (ud->event & USBIP_EH_RESET) {
|
if (ud->event & USBIP_EH_RESET) {
|
||||||
ud->eh_ops.reset(ud);
|
ud->eh_ops.reset(ud);
|
||||||
ud->event &= ~USBIP_EH_RESET;
|
unset_event(ud, USBIP_EH_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark the device as unusable. */
|
/* Mark the device as unusable. */
|
||||||
if (ud->event & USBIP_EH_UNUSABLE) {
|
if (ud->event & USBIP_EH_UNUSABLE) {
|
||||||
ud->eh_ops.unusable(ud);
|
ud->eh_ops.unusable(ud);
|
||||||
ud->event &= ~USBIP_EH_UNUSABLE;
|
unset_event(ud, USBIP_EH_UNUSABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop the error handler. */
|
/* Stop the error handler. */
|
||||||
if (ud->event & USBIP_EH_BYE)
|
if (ud->event & USBIP_EH_BYE)
|
||||||
return -1;
|
usbip_dbg_eh("removed %p\n", ud);
|
||||||
|
|
||||||
|
wake_up(&ud->eh_waitq);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int event_handler_loop(void *data)
|
|
||||||
{
|
|
||||||
struct usbip_device *ud = data;
|
|
||||||
|
|
||||||
while (!kthread_should_stop()) {
|
|
||||||
wait_event_interruptible(ud->eh_waitq,
|
|
||||||
usbip_event_happened(ud) ||
|
|
||||||
kthread_should_stop());
|
|
||||||
usbip_dbg_eh("wakeup\n");
|
|
||||||
|
|
||||||
if (event_handler(ud) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbip_start_eh(struct usbip_device *ud)
|
int usbip_start_eh(struct usbip_device *ud)
|
||||||
{
|
{
|
||||||
init_waitqueue_head(&ud->eh_waitq);
|
init_waitqueue_head(&ud->eh_waitq);
|
||||||
ud->event = 0;
|
ud->event = 0;
|
||||||
|
|
||||||
ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
|
|
||||||
if (IS_ERR(ud->eh)) {
|
|
||||||
pr_warn("Unable to start control thread\n");
|
|
||||||
return PTR_ERR(ud->eh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usbip_start_eh);
|
EXPORT_SYMBOL_GPL(usbip_start_eh);
|
||||||
|
|
||||||
void usbip_stop_eh(struct usbip_device *ud)
|
void usbip_stop_eh(struct usbip_device *ud)
|
||||||
{
|
{
|
||||||
if (ud->eh == current)
|
unsigned long pending = ud->event & ~USBIP_EH_BYE;
|
||||||
return; /* do not wait for myself */
|
|
||||||
|
|
||||||
kthread_stop(ud->eh);
|
if (!(ud->event & USBIP_EH_BYE))
|
||||||
usbip_dbg_eh("usbip_eh has finished\n");
|
usbip_dbg_eh("usbip_eh stopping but not removed\n");
|
||||||
|
|
||||||
|
if (pending)
|
||||||
|
usbip_dbg_eh("usbip_eh waiting completion %lx\n", pending);
|
||||||
|
|
||||||
|
wait_event_interruptible(ud->eh_waitq, !(ud->event & ~USBIP_EH_BYE));
|
||||||
|
usbip_dbg_eh("usbip_eh has stopped\n");
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usbip_stop_eh);
|
EXPORT_SYMBOL_GPL(usbip_stop_eh);
|
||||||
|
|
||||||
|
#define WORK_QUEUE_NAME "usbip_event"
|
||||||
|
|
||||||
|
static struct workqueue_struct *usbip_queue;
|
||||||
|
static DECLARE_WORK(usbip_work, event_handler);
|
||||||
|
|
||||||
|
int usbip_init_eh(void)
|
||||||
|
{
|
||||||
|
usbip_queue = create_singlethread_workqueue(WORK_QUEUE_NAME);
|
||||||
|
if (usbip_queue == NULL) {
|
||||||
|
pr_err("failed to create usbip_event\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void usbip_finish_eh(void)
|
||||||
|
{
|
||||||
|
flush_workqueue(usbip_queue);
|
||||||
|
destroy_workqueue(usbip_queue);
|
||||||
|
usbip_queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void usbip_event_add(struct usbip_device *ud, unsigned long event)
|
void usbip_event_add(struct usbip_device *ud, unsigned long event)
|
||||||
{
|
{
|
||||||
|
struct usbip_event *ue;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&ud->lock, flags);
|
if (ud->event & USBIP_EH_BYE)
|
||||||
ud->event |= event;
|
return;
|
||||||
wake_up(&ud->eh_waitq);
|
|
||||||
spin_unlock_irqrestore(&ud->lock, flags);
|
set_event(ud, event);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&event_lock, flags);
|
||||||
|
|
||||||
|
list_for_each_entry_reverse(ue, &event_list, node) {
|
||||||
|
if (ue->ud == ud)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ue = kmalloc(sizeof(struct usbip_event), GFP_ATOMIC);
|
||||||
|
if (ue == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ue->ud = ud;
|
||||||
|
|
||||||
|
list_add_tail(&ue->node, &event_list);
|
||||||
|
queue_work(usbip_queue, &usbip_work);
|
||||||
|
|
||||||
|
out:
|
||||||
|
spin_unlock_irqrestore(&event_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usbip_event_add);
|
EXPORT_SYMBOL_GPL(usbip_event_add);
|
||||||
|
|
||||||
@ -127,3 +202,12 @@ int usbip_event_happened(struct usbip_device *ud)
|
|||||||
return happened;
|
return happened;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usbip_event_happened);
|
EXPORT_SYMBOL_GPL(usbip_event_happened);
|
||||||
|
|
||||||
|
int usbip_in_eh(struct task_struct *task)
|
||||||
|
{
|
||||||
|
if (task == worker_context)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(usbip_in_eh);
|
||||||
|
@ -893,7 +893,6 @@ out:
|
|||||||
error_nodev:
|
error_nodev:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wusb_dev_sysfs_rm(wusb_dev);
|
|
||||||
error_add_sysfs:
|
error_add_sysfs:
|
||||||
wusb_dev_bos_rm(wusb_dev);
|
wusb_dev_bos_rm(wusb_dev);
|
||||||
error_bos_add:
|
error_bos_add:
|
||||||
|
@ -105,6 +105,13 @@
|
|||||||
#define USB_REQ_LOOPBACK_DATA_READ 0x16
|
#define USB_REQ_LOOPBACK_DATA_READ 0x16
|
||||||
#define USB_REQ_SET_INTERFACE_DS 0x17
|
#define USB_REQ_SET_INTERFACE_DS 0x17
|
||||||
|
|
||||||
|
/* specific requests for USB Power Delivery */
|
||||||
|
#define USB_REQ_GET_PARTNER_PDO 20
|
||||||
|
#define USB_REQ_GET_BATTERY_STATUS 21
|
||||||
|
#define USB_REQ_SET_PDO 22
|
||||||
|
#define USB_REQ_GET_VDM 23
|
||||||
|
#define USB_REQ_SEND_VDM 24
|
||||||
|
|
||||||
/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
|
/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
|
||||||
* used by hubs to put ports into a new L1 suspend state, except that it
|
* used by hubs to put ports into a new L1 suspend state, except that it
|
||||||
* forgot to define its number ...
|
* forgot to define its number ...
|
||||||
@ -165,6 +172,22 @@
|
|||||||
#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */
|
#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */
|
||||||
#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */
|
#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Feature selectors from Table 9-8 USB Power Delivery spec
|
||||||
|
*/
|
||||||
|
#define USB_DEVICE_BATTERY_WAKE_MASK 40
|
||||||
|
#define USB_DEVICE_OS_IS_PD_AWARE 41
|
||||||
|
#define USB_DEVICE_POLICY_MODE 42
|
||||||
|
#define USB_PORT_PR_SWAP 43
|
||||||
|
#define USB_PORT_GOTO_MIN 44
|
||||||
|
#define USB_PORT_RETURN_POWER 45
|
||||||
|
#define USB_PORT_ACCEPT_PD_REQUEST 46
|
||||||
|
#define USB_PORT_REJECT_PD_REQUEST 47
|
||||||
|
#define USB_PORT_PORT_PD_RESET 48
|
||||||
|
#define USB_PORT_C_PORT_PD_CHANGE 49
|
||||||
|
#define USB_PORT_CABLE_PD_RESET 50
|
||||||
|
#define USB_DEVICE_CHARGING_POLICY 54
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||||
* @bRequestType: matches the USB bmRequestType field
|
* @bRequestType: matches the USB bmRequestType field
|
||||||
@ -913,6 +936,104 @@ struct usb_ssp_cap_descriptor {
|
|||||||
#define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */
|
#define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Power Delivery Capability Descriptor:
|
||||||
|
* Defines capabilities for PD
|
||||||
|
*/
|
||||||
|
/* Defines the various PD Capabilities of this device */
|
||||||
|
#define USB_PD_POWER_DELIVERY_CAPABILITY 0x06
|
||||||
|
/* Provides information on each battery supported by the device */
|
||||||
|
#define USB_PD_BATTERY_INFO_CAPABILITY 0x07
|
||||||
|
/* The Consumer characteristics of a Port on the device */
|
||||||
|
#define USB_PD_PD_CONSUMER_PORT_CAPABILITY 0x08
|
||||||
|
/* The provider characteristics of a Port on the device */
|
||||||
|
#define USB_PD_PD_PROVIDER_PORT_CAPABILITY 0x09
|
||||||
|
|
||||||
|
struct usb_pd_cap_descriptor {
|
||||||
|
__u8 bLength;
|
||||||
|
__u8 bDescriptorType;
|
||||||
|
__u8 bDevCapabilityType; /* set to USB_PD_POWER_DELIVERY_CAPABILITY */
|
||||||
|
__u8 bReserved;
|
||||||
|
__le32 bmAttributes;
|
||||||
|
#define USB_PD_CAP_BATTERY_CHARGING (1 << 1) /* supports Battery Charging specification */
|
||||||
|
#define USB_PD_CAP_USB_PD (1 << 2) /* supports USB Power Delivery specification */
|
||||||
|
#define USB_PD_CAP_PROVIDER (1 << 3) /* can provide power */
|
||||||
|
#define USB_PD_CAP_CONSUMER (1 << 4) /* can consume power */
|
||||||
|
#define USB_PD_CAP_CHARGING_POLICY (1 << 5) /* supports CHARGING_POLICY feature */
|
||||||
|
#define USB_PD_CAP_TYPE_C_CURRENT (1 << 6) /* supports power capabilities defined in the USB Type-C Specification */
|
||||||
|
|
||||||
|
#define USB_PD_CAP_PWR_AC (1 << 8)
|
||||||
|
#define USB_PD_CAP_PWR_BAT (1 << 9)
|
||||||
|
#define USB_PD_CAP_PWR_USE_V_BUS (1 << 14)
|
||||||
|
|
||||||
|
__le16 bmProviderPorts; /* Bit zero refers to the UFP of the device */
|
||||||
|
__le16 bmConsumerPorts;
|
||||||
|
__le16 bcdBCVersion;
|
||||||
|
__le16 bcdPDVersion;
|
||||||
|
__le16 bcdUSBTypeCVersion;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct usb_pd_cap_battery_info_descriptor {
|
||||||
|
__u8 bLength;
|
||||||
|
__u8 bDescriptorType;
|
||||||
|
__u8 bDevCapabilityType;
|
||||||
|
/* Index of string descriptor shall contain the user friendly name for this battery */
|
||||||
|
__u8 iBattery;
|
||||||
|
/* Index of string descriptor shall contain the Serial Number String for this battery */
|
||||||
|
__u8 iSerial;
|
||||||
|
__u8 iManufacturer;
|
||||||
|
__u8 bBatteryId; /* uniquely identifies this battery in status Messages */
|
||||||
|
__u8 bReserved;
|
||||||
|
/*
|
||||||
|
* Shall contain the Battery Charge value above which this
|
||||||
|
* battery is considered to be fully charged but not necessarily
|
||||||
|
* “topped off.”
|
||||||
|
*/
|
||||||
|
__le32 dwChargedThreshold; /* in mWh */
|
||||||
|
/*
|
||||||
|
* Shall contain the minimum charge level of this battery such
|
||||||
|
* that above this threshold, a device can be assured of being
|
||||||
|
* able to power up successfully (see Battery Charging 1.2).
|
||||||
|
*/
|
||||||
|
__le32 dwWeakThreshold; /* in mWh */
|
||||||
|
__le32 dwBatteryDesignCapacity; /* in mWh */
|
||||||
|
__le32 dwBatteryLastFullchargeCapacity; /* in mWh */
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct usb_pd_cap_consumer_port_descriptor {
|
||||||
|
__u8 bLength;
|
||||||
|
__u8 bDescriptorType;
|
||||||
|
__u8 bDevCapabilityType;
|
||||||
|
__u8 bReserved;
|
||||||
|
__u8 bmCapabilities;
|
||||||
|
/* port will oerate under: */
|
||||||
|
#define USB_PD_CAP_CONSUMER_BC (1 << 0) /* BC */
|
||||||
|
#define USB_PD_CAP_CONSUMER_PD (1 << 1) /* PD */
|
||||||
|
#define USB_PD_CAP_CONSUMER_TYPE_C (1 << 2) /* USB Type-C Current */
|
||||||
|
__le16 wMinVoltage; /* in 50mV units */
|
||||||
|
__le16 wMaxVoltage; /* in 50mV units */
|
||||||
|
__u16 wReserved;
|
||||||
|
__le32 dwMaxOperatingPower; /* in 10 mW - operating at steady state */
|
||||||
|
__le32 dwMaxPeakPower; /* in 10mW units - operating at peak power */
|
||||||
|
__le32 dwMaxPeakPowerTime; /* in 100ms units - duration of peak */
|
||||||
|
#define USB_PD_CAP_CONSUMER_UNKNOWN_PEAK_POWER_TIME 0xffff
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct usb_pd_cap_provider_port_descriptor {
|
||||||
|
__u8 bLength;
|
||||||
|
__u8 bDescriptorType;
|
||||||
|
__u8 bDevCapabilityType;
|
||||||
|
__u8 bReserved1;
|
||||||
|
__u8 bmCapabilities;
|
||||||
|
/* port will oerate under: */
|
||||||
|
#define USB_PD_CAP_PROVIDER_BC (1 << 0) /* BC */
|
||||||
|
#define USB_PD_CAP_PROVIDER_PD (1 << 1) /* PD */
|
||||||
|
#define USB_PD_CAP_PROVIDER_TYPE_C (1 << 2) /* USB Type-C Current */
|
||||||
|
__u8 bNumOfPDObjects;
|
||||||
|
__u8 bReserved2;
|
||||||
|
__le32 wPowerDataObject[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Precision time measurement capability descriptor: advertised by devices and
|
* Precision time measurement capability descriptor: advertised by devices and
|
||||||
* hubs that support PTM
|
* hubs that support PTM
|
||||||
|
Loading…
Reference in New Issue
Block a user