下面跟踪进入设备控制器时的流程。
static void msm_otg_start_peripheral(struct otg_transceiver *xceiv, int on)
{
struct msm_otg *dev = container_of(xceiv, struct msm_otg, otg);
...........
if (on) {//打开设备控制器
...........
usb_gadget_vbus_connect(xceiv->gadget);
} else {//关闭设备控制器
atomic_set(&dev->chg_type, USB_CHG_TYPE__INVALID);//设置充电器的类型为无效
usb_gadget_vbus_disconnect(xceiv->gadget);
...............
}
}
static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget)
{
if (!gadget->ops->vbus_session)
return -EOPNOTSUPP;
return gadget->ops->vbus_session(gadget, 1);
}
static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
{
if (!gadget->ops->vbus_session)
return -EOPNOTSUPP;
return gadget->ops->vbus_session(gadget, 0);
}
上面两个函数都调用gadget->ops->vbus_session(gadget, 0/1)函数,该函数的回调注册的地方为:
static const struct usb_gadget_ops msm72k_ops = {
.get_frame = msm72k_get_frame,
.vbus_session = msm72k_udc_vbus_session,
.vbus_draw = msm72k_udc_vbus_draw,
.pullup = msm72k_pullup,
.wakeup = msm72k_wakeup,
.set_selfpowered = msm72k_set_selfpowered,
};
static int msm72k_probe(struct platform_device *pdev)
{
.............
ui->gadget.ops = &msm72k_ops;
............
}
看下回调函数的实现:
static int msm72k_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
struct usb_info *ui = container_of(_gadget, struct usb_info, gadget);
struct msm_otg *otg = to_msm_otg(ui->xceiv);
if (is_active || atomic_read(&otg->chg_type) == USB_CHG_TYPE__WALLCHARGER
|| atomic_read(&otg->chg_type) == USB_CHG_TYPE__DOCKCHARGER)
wake_lock(&ui->wlock);//如果为active锁定wakelock
msm_hsusb_set_vbus_state(is_active);
return 0;
}
void msm_hsusb_set_vbus_state(int online)
{
unsigned long flags;
struct usb_info *ui = the_usb_info;
if (online) {//根据online的值,设置ui的状态
ui->usb_state = USB_STATE_POWERED;
ui->flags |= USB_FLAG_VBUS_ONLINE;
} else {
ui->gadget.speed = USB_SPEED_UNKNOWN;
ui->usb_state = USB_STATE_NOTATTACHED;
ui->flags |= USB_FLAG_VBUS_OFFLINE;
}
if (in_interrupt()) {//如果处于中断中,则用系统是schedule_work调度
schedule_work(&ui->work);
} else {//直接调度
spin_unlock_irqrestore(&ui->lock, flags);
usb_do_work(&ui->work);//调度work
return;
}
}
static int __init android_probe(struct platform_device *pdev)
{
usb_composite_register(&android_usb_driver);
usb_gadget_register_driver(&composite_driver);
usb_start(ui);
ui->flags |= USB_FLAG_START;//设置初始flag标记
schedule_work(&ui->work);//调度work----------------------------------------->111
}
//下面看下调度的work
static int usb_get_max_power(struct usb_info *ui)
{
suspended = ui->usb_state == USB_STATE_SUSPENDED ? 1 : 0;//如果为suspend状态,则返回0
configured = atomic_read(&ui->configured);// 如果没有配置也返回0
bmaxpow = ui->b_max_pow;//返回最大值
if (suspended || !configured)
return 0;
return bmaxpow;
}
其中ui->b_max_pow的赋值流程如下:
static irqreturn_t usb_interrupt()//中断中进行枚举
handle_setup(ui);
ui->driver->setup();
composite_setup()//回调函数
static int set_config()
usb_gadget_vbus_draw(gadget, power);//设置能拉到的电流
gadget->ops->vbus_draw(gadget, mA);
msm72k_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
ui->b_max_pow = mA;//保存到ui->b_max_pow中
ui->flags = USB_FLAG_CONFIGURED;//设置flag为config
schedule_work(&ui->work);//调度work
static void usb_do_work(struct work_struct *w)
{
struct usb_info *ui = container_of(w, struct usb_info, work);
struct msm_otg *otg = to_msm_otg(ui->xceiv);
unsigned flags, _vbus;
for (;;) {
flags = ui->flags;//读出flag
ui->flags = 0;//读出后清零
_vbus = is_usb_online(ui);//第一次,结果为_vbus=0,插入是_vbus=1
/* give up if we have nothing to do */
if (flags == 0)//第一再次循环时,走到这里退出for循环
break;
switch (ui->state) {
case USB_STATE_IDLE://初始值为0
if (flags & USB_FLAG_START) {//第一次为USB_FLAG_START
if (!_vbus) {
ui->state = USB_STATE_OFFLINE;//第一次,置usb状态为USB_STATE_OFFLINE
break;//跳出该switch语句
}
break;
case USB_STATE_ONLINE://继续从上一个状态循环
if (atomic_read(&ui->offline_pending)) {//控制器重启的时候会走该分支
switch_set_state(&ui->sdev, 0);
atomic_set(&ui->offline_pending, 0);
}
if (flags & USB_FLAG_VBUS_OFFLINE) {
ui->chg_current = 0;//设置当前充电电流为0
dev_dbg(&ui->pdev->dev,"msm72k_udc: ONLINE -> OFFLINE\n");
atomic_set(&ui->running, 0);//设置running为0
atomic_set(&ui->configured, 0);//设置配置为0
if (ui->driver) {
dev_dbg(&ui->pdev->dev,"usb: notify offline\n");
ui->driver->disconnect(&ui->gadget);//调用driver的断开函数
}
............
msm72k_pullup_internal(&ui->gadget, 0);//下拉D+线电阻
...........
switch_set_state(&ui->sdev, 0);//上报offline的状态
ui->state = USB_STATE_OFFLINE;//设置usb的状态为USB_STATE_OFFLINE
usb_do_work_check_vbus(ui);//判断是否处于离线状态,并设置ui->flags |= USB_FLAG_VBUS_ONLINE,或者USB_FLAG_VBUS_OFFLINE
.................
break;
}
if (flags & USB_FLAG_SUSPEND) {//---------------------->222
int maxpower = usb_get_max_power(ui);//获得最大电流
if (maxpower < 0){//插入usb进入该状态时,进入该分支
break;}
otg_set_power(ui->xceiv, 0);//设置最大电流为0
if (release_wlocks)
wake_unlock(&ui->wlock);
break;
}
if (flags & USB_FLAG_CONFIGURED) {//------------------------------->333
int maxpower = usb_get_max_power(ui);//获得最大电流
switch_set_state(&ui->sdev,atomic_read(&ui->configured));//发送sent uevent SWITCH_NAME=MSM72K_UDC , SWITCH_STATE=online.
ui->chg_current = maxpower;//保存当前的充电电流
if (maxpower < 0)
break;
otg_set_power(ui->xceiv, maxpower);//设置最大电流
break;
}
if (flags & USB_FLAG_RESET) {
dev_dbg(&ui->pdev->dev,"msm72k_udc: ONLINE -> RESET\n");
msm72k_pullup_internal(&ui->gadget, 0);//写寄存器USBCMD_RS,控制D+下拉
usb_reset(ui);//reset udc控制器,并atomic_set(&ui->running, 1);
msm72k_pullup_internal(&ui->gadget, 1);//写寄存器USBCMD_RS,控制D+上拉
dev_dbg(&ui->pdev->dev,"msm72k_udc: RESET -> ONLINE\n");
break;
}
break;
case USB_STATE_OFFLINE:
if ((flags & USB_FLAG_VBUS_ONLINE) && _vbus) {//插入usb cable时进入该分支
...............
dev_dbg(&ui->pdev->dev,"msm72k_udc: OFFLINE -> ONLINE\n");
usb_reset(ui);//reset udc控制器,并atomic_set(&ui->running, 1);
ui->state = USB_STATE_ONLINE;//改变ui->state的状态
usb_do_work_check_vbus(ui);//判断是否处于离线状态,并设置ui->flags |= USB_FLAG_VBUS_ONLINE,或者USB_FLAG_VBUS_OFFLINE
ret = request_irq(otg->irq, usb_interrupt,IRQF_SHARED,ui->pdev->name, ui);//申请irq中断
ui->irq = otg->irq;//保存中断
enable_irq_wake(otg->irq);//设置该irq为系统唤醒源
if (!atomic_read(&ui->softconnect))
break;
msm72k_pullup_internal(&ui->gadget, 1);//把D+数据线拉高
................
}
break;
}
if (is_usb_online(ui))
switch_set_state(&ui->sdev_cable, 1);
else{//第一次初始化时,上报usb cable没有插入的状态
switch_set_state(&ui->sdev_cable, 0);}
}
}
下面分析下状态机的触发流程:
1、android_probe初始化,会调度usb_do_work,当没有usb cable插入的时候,ui->state = USB_STATE_IDLE,ui->flag = USB_FLAG_START,进入状态机,并判断_vbus,由于是第一次,_vbus为0,ui->state = USB_STATE_OFFLINE,然后上报usb cable没有插入,然后再次进入for循环,由于flag值没有变化为0,则跳出该for循环。
2、当插入usb cable时,由于调度了设备控制器的流程,然后调用usb_do_work,设置了标记ui->flags |= USB_FLAG_VBUS_ONLINE;由于没有插入前的状态为ui->state = USB_STATE_OFFLINE,所以
继续进入状态机,设置状态为ui->state = USB_STATE_ONLINE,然后检测flag的状态有没有改变,对ui->flag重新赋值,上报usb cable插入。然后usb_interruput触发了中断,设置ui->flags = USB_FLAG_SUSPEND,然后调度work,再次进入状态机。由于maxpower小于0,则退出switch语句,再次上报usb cable插入。继续进入for循环,由于flag状态没有改变,在退出for循环。在usb_interruput中,接收到端口变化中断,则置ui->flags = USB_FLAG_CONFIGURED,然后调度work,进入状态机,上报online状态。由于maxpower为0,则退出swtich语句,然后上报usb_cable插入。
3、当usb拔出的时候,先收到suspend中断,调度work,然后会关闭设备控制器,设置ui->flags |= USB_FLAG_VBUS_OFFLINE的状态,然后调度usb_do_work,进入状态机,上报offline的状态,设置usb的状态为USB_STATE_OFFLINE,设置running为0等,上报usb cable拔出,继续进入状态机循环,然后没有状态改变时退出for循环。
在usb中断中改变状态,然后调度work
static irqreturn_t usb_interruput(int irq, void *data)//该中断和上面的msm_otg_irq为共享中断,公用中断号132
{
struct usb_info *ui = data;
unsigned n;
unsigned long flags;
n = readl(USB_USBSTS);//读取状态寄存器的值
writel(n, USB_USBSTS);//清除该状态寄存器
if (!atomic_read(&ui->running))//还在重启中是忽略该中断
return IRQ_HANDLED;
if (n & STS_PCI) {//端口变化中断,当端口进入全速或者高速模式时,或者端口退出全速或高速模式由于接收到usb reset信号,或者suspend event。
msm_hsusb_set_speed(ui);//读取硬件寄存器USB_PORTSC,设置端口速度
if (atomic_read(&ui->configured)) {//查看配置是否为1?
wake_lock(&ui->wlock);//锁定wakelock
ui->usb_state = USB_STATE_CONFIGURED;//改变usb状态
ui->flags = USB_FLAG_CONFIGURED;//改变flag标记
ui->driver->resume(&ui->gadget);//唤醒gadget
schedule_work(&ui->work);//调度work------------------------------->333
} else {
msm_hsusb_set_state(USB_STATE_DEFAULT);//如果不为1,则设置the_usb_info->usb_state = USB_STATE_DEFAULT;
}
}
if (n & STS_URI) {//当设备控制器检测到usb reset信号时,执行该分支,并且进入USB_STATE_DEFAULT的状态
dev_dbg(&ui->pdev->dev, "reset\n");
ui->gadget.speed = USB_SPEED_UNKNOWN;//设置usb的速度为unknow
msm_hsusb_set_state(USB_STATE_DEFAULT);//设置usb的状态为默认状态
...............
if (atomic_read(&ui->configured)) {//如果有配置
/*做一些清理工作*/
}
...............
}
if (n & STS_SLI) {//处于suspend状态
dev_dbg(&ui->pdev->dev, "suspend\n");
ui->usb_state = USB_STATE_SUSPENDED;//改变状态
ui->flags = USB_FLAG_SUSPEND;//改变flag
ui->driver->suspend(&ui->gadget);
schedule_work(&ui->work);//调度usb_do_work-------------------------------------------->222
}
if (n & STS_UI) {//由传输事务引起的中断,或者是接收到short packeage.
n = readl(USB_ENDPTSETUPSTAT);
if (n & EPT_RX(0))
handle_setup(ui);//usb枚举过程
n = readl(USB_ENDPTCOMPLETE);
writel(n, USB_ENDPTCOMPLETE);
while (n) {
unsigned bit = __ffs(n);
handle_endpoint(ui, bit);//处理端点传输
n = n & (~(1 << bit));
}
}
return IRQ_HANDLED;
}
阅读(925) | 评论(0) | 转发(0) |