本分析基于android4.0.4代码,高通8260平台
//插入usb a cable前的状态是 OTG_STATE_B_IDLE
static void msm_otg_sm_work(struct work_struct *w)
{
switch (state) {
case OTG_STATE_UNDEFINED:
{
if (!dev->otg.host || !is_host())
set_bit(ID, &dev->inputs);//什么都不插入,初始化时会设置该位
if (dev->otg.gadget && is_b_sess_vld())
set_bit(B_SESS_VLD, &dev->inputs);
}
spin_lock_irqsave(&dev->lock, flags);
if ((test_bit(ID, &dev->inputs)) &&
!test_bit(ID_A, &dev->inputs)) {
dev->otg.state = OTG_STATE_B_IDLE;//什么都不插入,初始化时的状态
}
work = 1;
break;
case OTG_STATE_B_IDLE:
dev->otg.default_a = 0;
..............
else {//初始时,会停留在OTG_STATE_B_IDLE状态并睡眠
msm_otg_set_power(&dev->otg, 0);
pr_debug("entering into lpm\n");
pr_info("%s: -->>entering into lpm.\n",__func__);
msm_otg_put_suspend(dev);
if (dev->pdata->ldo_set_voltage)
dev->pdata->ldo_set_voltage(3075);
}
break;
}
if (work)
queue_work(dev->wq, &dev->sm_work);
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------
//插入usb a cable前的状态是 OTG_STATE_B_IDLE
static void msm_otg_sm_work(struct work_struct *w)
{
switch (state) {
case OTG_STATE_B_IDLE:
dev->otg.default_a = 0;
if (!test_bit(ID, &dev->inputs) || test_bit(ID_A, &dev->inputs)) {//此时的id=0
pr_debug("!id || id_A\n");
clear_bit(B_BUS_REQ, &dev->inputs);
otg_reset(&dev->otg, 0);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_IDLE;//状态迁移到OTG_STATE_A_IDLE,迁移到a idle
spin_unlock_irqrestore(&dev->lock, flags);
msm_otg_set_power(&dev->otg, 0);
work = 1;
}
break;
//继续调度work
case OTG_STATE_A_IDLE:
dev->otg.default_a = 1;
if (!test_bit(A_BUS_DROP, &dev->inputs) &&
(test_bit(A_SRP_DET, &dev->inputs) ||
test_bit(A_BUS_REQ, &dev->inputs))) {//A_BUS_REQ = 1
pr_debug("!a_bus_drop && (a_srp_det || a_bus_req)\n");
clear_bit(A_SRP_DET, &dev->inputs);
/* Disable SRP detection */
writel((readl(USB_OTGSC) & ~OTGSC_INTR_STS_MASK) &
~OTGSC_DPIE, USB_OTGSC);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_WAIT_VRISE;//状态迁移到OTG_STATE_A_WAIT_VRISE,等待电压达到a的门限
spin_unlock_irqrestore(&dev->lock, flags);
/* ACA: ID_A: Stop charging untill enumeration */
if (test_bit(ID_A, &dev->inputs))
msm_otg_set_power(&dev->otg, 0);
else
dev->pdata->vbus_power(USB_PHY_INTEGRATED, 1);
msm_otg_start_timer(dev, TA_WAIT_VRISE, A_WAIT_VRISE);
/* no need to schedule work now */
}
break;
case OTG_STATE_A_WAIT_VRISE:
if (test_bit(A_VBUS_VLD, &dev->inputs)) {
pr_debug("a_vbus_vld\n");
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_WAIT_BCON;//状态迁移到OTG_STATE_A_WAIT_BCON,等待外围设备插入
spin_unlock_irqrestore(&dev->lock, flags);
if (TA_WAIT_BCON > 0)
msm_otg_start_timer(dev, TA_WAIT_BCON,
A_WAIT_BCON);
/* Start HCD to detect peripherals. */
pr_info("%s:----------->>>>>>>>%d.\n",__func__,__LINE__);
msm_otg_start_host(&dev->otg, REQUEST_START);//在这里启动主机控制器
}
break;
//插入usb a cable时状态迁移到此,下面分析插入u盘的状态迁移
case OTG_STATE_A_WAIT_BCON:
if (test_bit(B_CONN, &dev->inputs)) {
pr_debug("b_conn\n");
msm_otg_del_timer(dev);
/* HCD is added already. just move to
* A_HOST state.
*/
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_HOST;//状态迁移到OTG_STATE_A_HOST,作为主机开始工作
spin_unlock_irqrestore(&dev->lock, flags);
if (test_bit(ID_A, &dev->inputs)) {
atomic_set(&dev->chg_type, USB_CHG_TYPE__SDP);
msm_otg_set_power(&dev->otg,
USB_IDCHG_MIN - get_aca_bmaxpower(dev));
}
}
break;
//拔出u盘时
case OTG_STATE_A_HOST:
if (!test_bit(B_CONN, &dev->inputs)) {
pr_debug("!b_conn\n");
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_WAIT_BCON;//状态迁移到等待外围设备插入
spin_unlock_irqrestore(&dev->lock, flags);
if (TA_WAIT_BCON > 0)
msm_otg_start_timer(dev, TA_WAIT_BCON, A_WAIT_BCON);
}
break;
//其中插入,拔出u盘触发的条件是通知链
static int usbdev_notify(struct notifier_block *self,
unsigned long action, void *device)
{
enum usb_otg_state state;
struct msm_otg *dev = container_of(self, struct msm_otg, usbdev_nb);
struct usb_device *udev = device;
int work = 1;
spin_lock_irqsave(&dev->lock, flags);
state = dev->otg.state;//当前的状态机状态
spin_unlock_irqrestore(&dev->lock, flags);
switch (state) {
case OTG_STATE_A_WAIT_BCON:
if (action == USB_DEVICE_ADD) {//u盘插入时会设置dev->inputs相应的位
pr_debug("B_CONN set\n");
set_bit(B_CONN, &dev->inputs);
...........
}
break;
case OTG_STATE_A_HOST:
if (action == USB_DEVICE_REMOVE) {//u盘拔出时会清除dev->inputs相应的位
pr_debug("B_CONN clear\n");
clear_bit(B_CONN, &dev->inputs);
set_aca_bmaxpower(dev, 0);
}
break;
default:
work = 0;
break;
}
do_work:
if (work) {
wake_lock(&dev->wlock);
queue_work(dev->wq, &dev->sm_work);//调度work,改变状态机的迁移状态
}
}
//拔掉hub时的状态
case OTG_STATE_A_WAIT_BCON:
if ((test_bit(ID, &dev->inputs) &&//拔出时id =1
!test_bit(ID_A, &dev->inputs)) ||
test_bit(A_BUS_DROP, &dev->inputs) ||
test_bit(A_WAIT_BCON, &dev->tmouts)) {
pr_debug("id_f/b/c || a_bus_drop ||"
"a_wait_bcon_tmout\n");
if (test_bit(A_WAIT_BCON, &dev->tmouts))
msm_otg_send_event(&dev->otg,
OTG_EVENT_DEV_CONN_TMOUT);
msm_otg_del_timer(dev);
clear_bit(A_BUS_REQ, &dev->inputs);
msm_otg_start_host(&dev->otg, REQUEST_STOP);
/* Reset both phy and link */
otg_reset(&dev->otg, 1);
/* ACA: ID_A with NO accessory, just the A plug is
* attached to ACA: Use IDCHG_MAX for charging
*/
if (test_bit(ID_A, &dev->inputs))
msm_otg_set_power(&dev->otg, USB_IDCHG_MAX);
else
dev->pdata->vbus_power(USB_PHY_INTEGRATED, 0);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_WAIT_VFALL;//状态机迁移,等待a的电压门限降下
spin_unlock_irqrestore(&dev->lock, flags);
msm_otg_start_timer(dev, TA_WAIT_VFALL, A_WAIT_VFALL);
}
break;
//等待电压将下来
case OTG_STATE_A_WAIT_VFALL:
if (test_bit(A_WAIT_VFALL, &dev->tmouts)) {
clear_bit(A_VBUS_VLD, &dev->inputs);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_A_IDLE;//继续迁移到a idle
spin_unlock_irqrestore(&dev->lock, flags);
work = 1;
}
break;
//状态机继续迁移
case OTG_STATE_A_IDLE:
dev->otg.default_a = 1;
if (test_bit(ID, &dev->inputs) &&//id = 1
!test_bit(ID_A, &dev->inputs)) {
pr_debug("id && !id_a\n");
dev->otg.default_a = 0;
otg_reset(&dev->otg, 0);
spin_lock_irqsave(&dev->lock, flags);
dev->otg.state = OTG_STATE_B_IDLE;//迁移到b idle
spin_unlock_irqrestore(&dev->lock, flags);
msm_otg_set_power(&dev->otg, 0);
work = 1;
}
break;
}
if (work)
queue_work(dev->wq, &dev->sm_work);
}
阅读(3215) | 评论(4) | 转发(1) |