mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-07 08:48:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
9
drivers/usb/common/Makefile
Normal file
9
drivers/usb/common/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# Makefile for the usb common parts.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_USB_COMMON) += usb-common.o
|
||||
usb-common-y += common.o
|
||||
usb-common-$(CONFIG_USB_LED_TRIG) += led.o
|
||||
|
||||
obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o
|
179
drivers/usb/common/common.c
Normal file
179
drivers/usb/common/common.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Provides code common for host and device side USB.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* If either host side (ie. CONFIG_USB=y) or device side USB stack
|
||||
* (ie. CONFIG_USB_GADGET=y) is compiled in the kernel, this module is
|
||||
* compiled-in as well. Otherwise, if either of the two stacks is
|
||||
* compiled as module, this file is compiled as module as well.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/of.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
const char *usb_otg_state_string(enum usb_otg_state state)
|
||||
{
|
||||
static const char *const names[] = {
|
||||
[OTG_STATE_A_IDLE] = "a_idle",
|
||||
[OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
|
||||
[OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
|
||||
[OTG_STATE_A_HOST] = "a_host",
|
||||
[OTG_STATE_A_SUSPEND] = "a_suspend",
|
||||
[OTG_STATE_A_PERIPHERAL] = "a_peripheral",
|
||||
[OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
|
||||
[OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
|
||||
[OTG_STATE_B_IDLE] = "b_idle",
|
||||
[OTG_STATE_B_SRP_INIT] = "b_srp_init",
|
||||
[OTG_STATE_B_PERIPHERAL] = "b_peripheral",
|
||||
[OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
|
||||
[OTG_STATE_B_HOST] = "b_host",
|
||||
};
|
||||
|
||||
if (state < 0 || state >= ARRAY_SIZE(names))
|
||||
return "UNDEFINED";
|
||||
|
||||
return names[state];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_otg_state_string);
|
||||
|
||||
static const char *const speed_names[] = {
|
||||
[USB_SPEED_UNKNOWN] = "UNKNOWN",
|
||||
[USB_SPEED_LOW] = "low-speed",
|
||||
[USB_SPEED_FULL] = "full-speed",
|
||||
[USB_SPEED_HIGH] = "high-speed",
|
||||
[USB_SPEED_WIRELESS] = "wireless",
|
||||
[USB_SPEED_SUPER] = "super-speed",
|
||||
};
|
||||
|
||||
const char *usb_speed_string(enum usb_device_speed speed)
|
||||
{
|
||||
if (speed < 0 || speed >= ARRAY_SIZE(speed_names))
|
||||
speed = USB_SPEED_UNKNOWN;
|
||||
return speed_names[speed];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_speed_string);
|
||||
|
||||
const char *usb_state_string(enum usb_device_state state)
|
||||
{
|
||||
static const char *const names[] = {
|
||||
[USB_STATE_NOTATTACHED] = "not attached",
|
||||
[USB_STATE_ATTACHED] = "attached",
|
||||
[USB_STATE_POWERED] = "powered",
|
||||
[USB_STATE_RECONNECTING] = "reconnecting",
|
||||
[USB_STATE_UNAUTHENTICATED] = "unauthenticated",
|
||||
[USB_STATE_DEFAULT] = "default",
|
||||
[USB_STATE_ADDRESS] = "addressed",
|
||||
[USB_STATE_CONFIGURED] = "configured",
|
||||
[USB_STATE_SUSPENDED] = "suspended",
|
||||
};
|
||||
|
||||
if (state < 0 || state >= ARRAY_SIZE(names))
|
||||
return "UNKNOWN";
|
||||
|
||||
return names[state];
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_state_string);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const char *const usb_dr_modes[] = {
|
||||
[USB_DR_MODE_UNKNOWN] = "",
|
||||
[USB_DR_MODE_HOST] = "host",
|
||||
[USB_DR_MODE_PERIPHERAL] = "peripheral",
|
||||
[USB_DR_MODE_OTG] = "otg",
|
||||
};
|
||||
|
||||
/**
|
||||
* of_usb_get_suspend_clk_freq - Get suspend clock frequency
|
||||
*
|
||||
* USB3 core needs 16KHz clock for a small part that operates
|
||||
* when the SS PHY is in its lowest power (P3) state.
|
||||
* USB3 core receives suspend clock and divides it to make 16KHz clock.
|
||||
*/
|
||||
unsigned int of_usb_get_suspend_clk_freq(struct device_node *np)
|
||||
{
|
||||
unsigned int freq;
|
||||
int err;
|
||||
|
||||
err = of_property_read_u32(np, "suspend_clk_freq", &freq);
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
return freq;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_usb_get_suspend_clk_freq);
|
||||
|
||||
/**
|
||||
* of_usb_get_dr_mode - Get dual role mode for given device_node
|
||||
* @np: Pointer to the given device_node
|
||||
*
|
||||
* The function gets phy interface string from property 'dr_mode',
|
||||
* and returns the correspondig enum usb_dr_mode
|
||||
*/
|
||||
enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
|
||||
{
|
||||
const char *dr_mode;
|
||||
int err, i;
|
||||
|
||||
err = of_property_read_string(np, "dr_mode", &dr_mode);
|
||||
if (err < 0)
|
||||
return USB_DR_MODE_UNKNOWN;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++)
|
||||
if (!strcmp(dr_mode, usb_dr_modes[i]))
|
||||
return i;
|
||||
|
||||
return USB_DR_MODE_UNKNOWN;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
|
||||
|
||||
/**
|
||||
* of_usb_get_maximum_speed - Get maximum requested speed for a given USB
|
||||
* controller.
|
||||
* @np: Pointer to the given device_node
|
||||
*
|
||||
* The function gets the maximum speed string from property "maximum-speed",
|
||||
* and returns the corresponding enum usb_device_speed.
|
||||
*/
|
||||
enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
|
||||
{
|
||||
const char *maximum_speed;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = of_property_read_string(np, "maximum-speed", &maximum_speed);
|
||||
if (err < 0)
|
||||
return USB_SPEED_UNKNOWN;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(speed_names); i++)
|
||||
if (strcmp(maximum_speed, speed_names[i]) == 0)
|
||||
return i;
|
||||
|
||||
return USB_SPEED_UNKNOWN;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
|
||||
|
||||
/**
|
||||
* of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
|
||||
* for given targeted hosts (non-PC hosts)
|
||||
* @np: Pointer to the given device_node
|
||||
*
|
||||
* The function gets if the targeted hosts support TPL or not
|
||||
*/
|
||||
bool of_usb_host_tpl_support(struct device_node *np)
|
||||
{
|
||||
if (of_find_property(np, "tpl-support", NULL))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
57
drivers/usb/common/led.c
Normal file
57
drivers/usb/common/led.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* LED Triggers for USB Activity
|
||||
*
|
||||
* Copyright 2014 Michal Sojka <sojka@merica.cz>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define BLINK_DELAY 30
|
||||
|
||||
static unsigned long usb_blink_delay = BLINK_DELAY;
|
||||
|
||||
DEFINE_LED_TRIGGER(ledtrig_usb_gadget);
|
||||
DEFINE_LED_TRIGGER(ledtrig_usb_host);
|
||||
|
||||
void usb_led_activity(enum usb_led_event ev)
|
||||
{
|
||||
struct led_trigger *trig = NULL;
|
||||
|
||||
switch (ev) {
|
||||
case USB_LED_EVENT_GADGET:
|
||||
trig = ledtrig_usb_gadget;
|
||||
break;
|
||||
case USB_LED_EVENT_HOST:
|
||||
trig = ledtrig_usb_host;
|
||||
break;
|
||||
}
|
||||
/* led_trigger_blink_oneshot() handles trig == NULL gracefully */
|
||||
led_trigger_blink_oneshot(trig, &usb_blink_delay, &usb_blink_delay, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_led_activity);
|
||||
|
||||
|
||||
static int __init ledtrig_usb_init(void)
|
||||
{
|
||||
led_trigger_register_simple("usb-gadget", &ledtrig_usb_gadget);
|
||||
led_trigger_register_simple("usb-host", &ledtrig_usb_host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ledtrig_usb_exit(void)
|
||||
{
|
||||
led_trigger_unregister_simple(ledtrig_usb_gadget);
|
||||
led_trigger_unregister_simple(ledtrig_usb_host);
|
||||
}
|
||||
|
||||
module_init(ledtrig_usb_init);
|
||||
module_exit(ledtrig_usb_exit);
|
367
drivers/usb/common/usb-otg-fsm.c
Normal file
367
drivers/usb/common/usb-otg-fsm.c
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* OTG Finite State Machine from OTG spec
|
||||
*
|
||||
* Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* Author: Li Yang <LeoLi@freescale.com>
|
||||
* Jerry Huang <Chang-Ming.Huang@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/otg-fsm.h>
|
||||
|
||||
/* Change USB protocol when there is a protocol change */
|
||||
static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (fsm->protocol != protocol) {
|
||||
VDBG("Changing role fsm->protocol= %d; new protocol= %d\n",
|
||||
fsm->protocol, protocol);
|
||||
/* stop old protocol */
|
||||
if (fsm->protocol == PROTO_HOST)
|
||||
ret = otg_start_host(fsm, 0);
|
||||
else if (fsm->protocol == PROTO_GADGET)
|
||||
ret = otg_start_gadget(fsm, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* start new protocol */
|
||||
if (protocol == PROTO_HOST)
|
||||
ret = otg_start_host(fsm, 1);
|
||||
else if (protocol == PROTO_GADGET)
|
||||
ret = otg_start_gadget(fsm, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fsm->protocol = protocol;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int state_changed;
|
||||
|
||||
/* Called when leaving a state. Do state clean up jobs here */
|
||||
static void otg_leave_state(struct otg_fsm *fsm, enum usb_otg_state old_state)
|
||||
{
|
||||
switch (old_state) {
|
||||
case OTG_STATE_B_IDLE:
|
||||
otg_del_timer(fsm, B_SE0_SRP);
|
||||
fsm->b_se0_srp = 0;
|
||||
fsm->adp_sns = 0;
|
||||
fsm->adp_prb = 0;
|
||||
break;
|
||||
case OTG_STATE_B_SRP_INIT:
|
||||
fsm->data_pulse = 0;
|
||||
fsm->b_srp_done = 0;
|
||||
break;
|
||||
case OTG_STATE_B_PERIPHERAL:
|
||||
break;
|
||||
case OTG_STATE_B_WAIT_ACON:
|
||||
otg_del_timer(fsm, B_ASE0_BRST);
|
||||
fsm->b_ase0_brst_tmout = 0;
|
||||
break;
|
||||
case OTG_STATE_B_HOST:
|
||||
break;
|
||||
case OTG_STATE_A_IDLE:
|
||||
fsm->adp_prb = 0;
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VRISE:
|
||||
otg_del_timer(fsm, A_WAIT_VRISE);
|
||||
fsm->a_wait_vrise_tmout = 0;
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_BCON:
|
||||
otg_del_timer(fsm, A_WAIT_BCON);
|
||||
fsm->a_wait_bcon_tmout = 0;
|
||||
break;
|
||||
case OTG_STATE_A_HOST:
|
||||
otg_del_timer(fsm, A_WAIT_ENUM);
|
||||
break;
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
otg_del_timer(fsm, A_AIDL_BDIS);
|
||||
fsm->a_aidl_bdis_tmout = 0;
|
||||
fsm->a_suspend_req_inf = 0;
|
||||
break;
|
||||
case OTG_STATE_A_PERIPHERAL:
|
||||
otg_del_timer(fsm, A_BIDL_ADIS);
|
||||
fsm->a_bidl_adis_tmout = 0;
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VFALL:
|
||||
otg_del_timer(fsm, A_WAIT_VFALL);
|
||||
fsm->a_wait_vfall_tmout = 0;
|
||||
otg_del_timer(fsm, A_WAIT_VRISE);
|
||||
break;
|
||||
case OTG_STATE_A_VBUS_ERR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when entering a state */
|
||||
static int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
|
||||
{
|
||||
state_changed = 1;
|
||||
if (fsm->otg->phy->state == new_state)
|
||||
return 0;
|
||||
VDBG("Set state: %s\n", usb_otg_state_string(new_state));
|
||||
otg_leave_state(fsm, fsm->otg->phy->state);
|
||||
switch (new_state) {
|
||||
case OTG_STATE_B_IDLE:
|
||||
otg_drv_vbus(fsm, 0);
|
||||
otg_chrg_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
/*
|
||||
* Driver is responsible for starting ADP probing
|
||||
* if ADP sensing times out.
|
||||
*/
|
||||
otg_start_adp_sns(fsm);
|
||||
otg_set_protocol(fsm, PROTO_UNDEF);
|
||||
otg_add_timer(fsm, B_SE0_SRP);
|
||||
break;
|
||||
case OTG_STATE_B_SRP_INIT:
|
||||
otg_start_pulse(fsm);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_UNDEF);
|
||||
otg_add_timer(fsm, B_SRP_FAIL);
|
||||
break;
|
||||
case OTG_STATE_B_PERIPHERAL:
|
||||
otg_chrg_vbus(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_GADGET);
|
||||
otg_loc_conn(fsm, 1);
|
||||
break;
|
||||
case OTG_STATE_B_WAIT_ACON:
|
||||
otg_chrg_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
otg_add_timer(fsm, B_ASE0_BRST);
|
||||
fsm->a_bus_suspend = 0;
|
||||
break;
|
||||
case OTG_STATE_B_HOST:
|
||||
otg_chrg_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 1);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
usb_bus_start_enum(fsm->otg->host,
|
||||
fsm->otg->host->otg_port);
|
||||
break;
|
||||
case OTG_STATE_A_IDLE:
|
||||
otg_drv_vbus(fsm, 0);
|
||||
otg_chrg_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_start_adp_prb(fsm);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VRISE:
|
||||
otg_drv_vbus(fsm, 1);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
otg_add_timer(fsm, A_WAIT_VRISE);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_BCON:
|
||||
otg_drv_vbus(fsm, 1);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
otg_add_timer(fsm, A_WAIT_BCON);
|
||||
break;
|
||||
case OTG_STATE_A_HOST:
|
||||
otg_drv_vbus(fsm, 1);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 1);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
/*
|
||||
* When HNP is triggered while a_bus_req = 0, a_host will
|
||||
* suspend too fast to complete a_set_b_hnp_en
|
||||
*/
|
||||
if (!fsm->a_bus_req || fsm->a_suspend_req_inf)
|
||||
otg_add_timer(fsm, A_WAIT_ENUM);
|
||||
break;
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
otg_drv_vbus(fsm, 1);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
otg_add_timer(fsm, A_AIDL_BDIS);
|
||||
|
||||
break;
|
||||
case OTG_STATE_A_PERIPHERAL:
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_GADGET);
|
||||
otg_drv_vbus(fsm, 1);
|
||||
otg_loc_conn(fsm, 1);
|
||||
otg_add_timer(fsm, A_BIDL_ADIS);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VFALL:
|
||||
otg_drv_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_HOST);
|
||||
otg_add_timer(fsm, A_WAIT_VFALL);
|
||||
break;
|
||||
case OTG_STATE_A_VBUS_ERR:
|
||||
otg_drv_vbus(fsm, 0);
|
||||
otg_loc_conn(fsm, 0);
|
||||
otg_loc_sof(fsm, 0);
|
||||
otg_set_protocol(fsm, PROTO_UNDEF);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fsm->otg->phy->state = new_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* State change judgement */
|
||||
int otg_statemachine(struct otg_fsm *fsm)
|
||||
{
|
||||
enum usb_otg_state state;
|
||||
|
||||
mutex_lock(&fsm->lock);
|
||||
|
||||
state = fsm->otg->phy->state;
|
||||
state_changed = 0;
|
||||
/* State machine state change judgement */
|
||||
|
||||
switch (state) {
|
||||
case OTG_STATE_UNDEFINED:
|
||||
VDBG("fsm->id = %d\n", fsm->id);
|
||||
if (fsm->id)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
else
|
||||
otg_set_state(fsm, OTG_STATE_A_IDLE);
|
||||
break;
|
||||
case OTG_STATE_B_IDLE:
|
||||
if (!fsm->id)
|
||||
otg_set_state(fsm, OTG_STATE_A_IDLE);
|
||||
else if (fsm->b_sess_vld && fsm->otg->gadget)
|
||||
otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
|
||||
else if ((fsm->b_bus_req || fsm->adp_change || fsm->power_up) &&
|
||||
fsm->b_ssend_srp && fsm->b_se0_srp)
|
||||
otg_set_state(fsm, OTG_STATE_B_SRP_INIT);
|
||||
break;
|
||||
case OTG_STATE_B_SRP_INIT:
|
||||
if (!fsm->id || fsm->b_srp_done)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
break;
|
||||
case OTG_STATE_B_PERIPHERAL:
|
||||
if (!fsm->id || !fsm->b_sess_vld)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
else if (fsm->b_bus_req && fsm->otg->
|
||||
gadget->b_hnp_enable && fsm->a_bus_suspend)
|
||||
otg_set_state(fsm, OTG_STATE_B_WAIT_ACON);
|
||||
break;
|
||||
case OTG_STATE_B_WAIT_ACON:
|
||||
if (fsm->a_conn)
|
||||
otg_set_state(fsm, OTG_STATE_B_HOST);
|
||||
else if (!fsm->id || !fsm->b_sess_vld)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
else if (fsm->a_bus_resume || fsm->b_ase0_brst_tmout) {
|
||||
fsm->b_ase0_brst_tmout = 0;
|
||||
otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
|
||||
}
|
||||
break;
|
||||
case OTG_STATE_B_HOST:
|
||||
if (!fsm->id || !fsm->b_sess_vld)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
else if (!fsm->b_bus_req || !fsm->a_conn || fsm->test_device)
|
||||
otg_set_state(fsm, OTG_STATE_B_PERIPHERAL);
|
||||
break;
|
||||
case OTG_STATE_A_IDLE:
|
||||
if (fsm->id)
|
||||
otg_set_state(fsm, OTG_STATE_B_IDLE);
|
||||
else if (!fsm->a_bus_drop && (fsm->a_bus_req ||
|
||||
fsm->a_srp_det || fsm->adp_change || fsm->power_up))
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VRISE);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VRISE:
|
||||
if (fsm->a_vbus_vld)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
|
||||
else if (fsm->id || fsm->a_bus_drop ||
|
||||
fsm->a_wait_vrise_tmout)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_BCON:
|
||||
if (!fsm->a_vbus_vld)
|
||||
otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
|
||||
else if (fsm->b_conn)
|
||||
otg_set_state(fsm, OTG_STATE_A_HOST);
|
||||
else if (fsm->id || fsm->a_bus_drop || fsm->a_wait_bcon_tmout)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
break;
|
||||
case OTG_STATE_A_HOST:
|
||||
if (fsm->id || fsm->a_bus_drop)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
else if ((!fsm->a_bus_req || fsm->a_suspend_req_inf) &&
|
||||
fsm->otg->host->b_hnp_enable)
|
||||
otg_set_state(fsm, OTG_STATE_A_SUSPEND);
|
||||
else if (!fsm->b_conn)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
|
||||
else if (!fsm->a_vbus_vld)
|
||||
otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
|
||||
break;
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
if (!fsm->b_conn && fsm->otg->host->b_hnp_enable)
|
||||
otg_set_state(fsm, OTG_STATE_A_PERIPHERAL);
|
||||
else if (!fsm->b_conn && !fsm->otg->host->b_hnp_enable)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
|
||||
else if (fsm->a_bus_req || fsm->b_bus_resume)
|
||||
otg_set_state(fsm, OTG_STATE_A_HOST);
|
||||
else if (fsm->id || fsm->a_bus_drop || fsm->a_aidl_bdis_tmout)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
else if (!fsm->a_vbus_vld)
|
||||
otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
|
||||
break;
|
||||
case OTG_STATE_A_PERIPHERAL:
|
||||
if (fsm->id || fsm->a_bus_drop)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
else if (fsm->a_bidl_adis_tmout || fsm->b_bus_suspend)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_BCON);
|
||||
else if (!fsm->a_vbus_vld)
|
||||
otg_set_state(fsm, OTG_STATE_A_VBUS_ERR);
|
||||
break;
|
||||
case OTG_STATE_A_WAIT_VFALL:
|
||||
if (fsm->a_wait_vfall_tmout)
|
||||
otg_set_state(fsm, OTG_STATE_A_IDLE);
|
||||
break;
|
||||
case OTG_STATE_A_VBUS_ERR:
|
||||
if (fsm->id || fsm->a_bus_drop || fsm->a_clr_err)
|
||||
otg_set_state(fsm, OTG_STATE_A_WAIT_VFALL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&fsm->lock);
|
||||
|
||||
VDBG("quit statemachine, changed = %d\n", state_changed);
|
||||
return state_changed;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(otg_statemachine);
|
Loading…
Add table
Add a link
Reference in a new issue