android_kernel_oneplus_msm8998/include/linux/usb/usbpd.h
Jack Pham 64d72675d7 usb: pd: Avoid calling SVID disconnect if not previously connected
Only call an SVID handler's disconnect function only if it was
previously connected, i.e. when the state machine had proceeded
received a successful DISCOVER_SVIDs response. This helps to
avoid excessive notification to SVID clients.

While at it, require that .connect and .disconnect callbacks
are supplied during registration. This helps to eliminate NULL
checks each time they are called.

Change-Id: I030153a6b2106a6504ed51b5cb00a27f842e2488
Signed-off-by: Jack Pham <jackp@codeaurora.org>
2016-11-02 20:22:11 -07:00

159 lines
4 KiB
C

/* Copyright (c) 2016, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* 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.
*/
#ifndef __LINUX_USB_USBPD_H
#define __LINUX_USB_USBPD_H
#include <linux/list.h>
struct usbpd;
/* Standard IDs */
#define USBPD_SID 0xff00
/* Structured VDM Command Type */
enum usbpd_svdm_cmd_type {
SVDM_CMD_TYPE_INITIATOR,
SVDM_CMD_TYPE_RESP_ACK,
SVDM_CMD_TYPE_RESP_NAK,
SVDM_CMD_TYPE_RESP_BUSY,
};
/* Structured VDM Commands */
#define USBPD_SVDM_DISCOVER_IDENTITY 0x1
#define USBPD_SVDM_DISCOVER_SVIDS 0x2
#define USBPD_SVDM_DISCOVER_MODES 0x3
#define USBPD_SVDM_ENTER_MODE 0x4
#define USBPD_SVDM_EXIT_MODE 0x5
#define USBPD_SVDM_ATTENTION 0x6
/*
* Implemented by client
*/
struct usbpd_svid_handler {
u16 svid;
/* Notified when VDM session established/reset; must be implemented */
void (*connect)(struct usbpd_svid_handler *hdlr);
void (*disconnect)(struct usbpd_svid_handler *hdlr);
/* Unstructured VDM */
void (*vdm_received)(struct usbpd_svid_handler *hdlr, u32 vdm_hdr,
const u32 *vdos, int num_vdos);
/* Structured VDM */
void (*svdm_received)(struct usbpd_svid_handler *hdlr, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, const u32 *vdos,
int num_vdos);
/* client should leave these blank; private members used by PD driver */
struct list_head entry;
bool discovered;
};
enum plug_orientation {
ORIENTATION_NONE,
ORIENTATION_CC1,
ORIENTATION_CC2,
};
#if IS_ENABLED(CONFIG_USB_PD_POLICY)
/*
* Obtains an instance of usbpd from a DT phandle
*/
struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
const char *phandle);
/*
* Called by client to handle specific SVID messages.
* Specify callback functions in the usbpd_svid_handler argument
*/
int usbpd_register_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
void usbpd_unregister_svid(struct usbpd *pd, struct usbpd_svid_handler *hdlr);
/*
* Transmit a VDM message.
*/
int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
int num_vdos);
/*
* Transmit a Structured VDM message.
*/
int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
const u32 *vdos, int num_vdos);
/*
* Get current status of CC pin orientation.
*
* Return: ORIENTATION_CC1 or ORIENTATION_CC2 if attached,
* otherwise ORIENTATION_NONE if not attached
*/
enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd);
#else
static inline struct usbpd *devm_usbpd_get_by_phandle(struct device *dev,
const char *phandle)
{
return ERR_PTR(-ENODEV);
}
static inline int usbpd_register_svid(struct usbpd *pd,
struct usbpd_svid_handler *hdlr)
{
return -EINVAL;
}
static inline void usbpd_unregister_svid(struct usbpd *pd,
struct usbpd_svid_handler *hdlr)
{
}
static inline int usbpd_send_vdm(struct usbpd *pd, u32 vdm_hdr, const u32 *vdos,
int num_vdos)
{
return -EINVAL;
}
static inline int usbpd_send_svdm(struct usbpd *pd, u16 svid, u8 cmd,
enum usbpd_svdm_cmd_type cmd_type, int obj_pos,
const u32 *vdos, int num_vdos)
{
return -EINVAL;
}
static inline enum plug_orientation usbpd_get_plug_orientation(struct usbpd *pd)
{
return ORIENTATION_NONE;
}
#endif /* IS_ENABLED(CONFIG_USB_PD_POLICY) */
/*
* Additional helpers for Enter/Exit Mode commands
*/
static inline int usbpd_enter_mode(struct usbpd *pd, u16 svid, int mode,
const u32 *vdo)
{
return usbpd_send_svdm(pd, svid, USBPD_SVDM_ENTER_MODE,
SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
}
static inline int usbpd_exit_mode(struct usbpd *pd, u16 svid, int mode,
const u32 *vdo)
{
return usbpd_send_svdm(pd, svid, USBPD_SVDM_EXIT_MODE,
SVDM_CMD_TYPE_INITIATOR, mode, vdo, vdo ? 1 : 0);
}
#endif /* __LINUX_USB_USBPD_H */