LINUX USB 系统(3)

1、     OTG 控制器

                   OTG 的基本概念

    首先,提出一个问题, OTG EHCI/OHCI/UHCI 是同一类概念吗?

那我们先看一看 OTG 能做些什么。

OTG 中,我们一般不把设备叫做主设备或从设备,而称作 A-DEVICE B-DEVICE 。一般而言, A-DEVICE 作主, B-DEVICE 作从,但也不能这样绑定, A-DEVICE 也可以作从,这时 A-DEVICE 仍要为总线提供电力。

OTG 设备使用插头中的 ID 引脚来区分 A/B Device ID 接地被称作为 A-Device, 为连接时候的 USB Host A-Device 始终为总线提供电力。 ID 悬空被称作为 B-Device, 为连接时候的 USB Device( 作从 ) ,设备的 USB Host/USB Device 角色可以通过 HNP 切换。

OTG Device :使用 Micro AB 插座,可以在运行时切换 Host/Device
仅外设 B-Device :仅仅能作为外设的 B-Device (分为插头一体和插头线缆分离的)。

可见, OTG 主要是负责控制器状态的切换,这种切换要根据接入的设备来判断。 OTG 主要使用在嵌入式设备中,说到嵌入式不能不提降低功耗了,所以仅有 ID 线的检测还是不够的。

 

OTG 中的三大协议

SRP Session Request Protocol ):
B-Device
使用。通过数据线上的脉冲,请求 A-Device 打开 VBUS 并且开始-个 Session Session 为从 VBUS 打开到关闭这一段时间。

支持: A-Device 允许回应 SRP B-Device (包括仅能作为外设的 B-Device ),允许发起 SRP 。一个能够支持 HNP B- Device 应该能够发起 SRP 。当 A 插头插入时关闭 VBus Host 必须支持回应 SRP VBus 总是打开的 Host 不必响应 SRP

 

ADP Attach Detection Protocol ):

提供设备检测是否有对端设备插入。

 

HNP Host Negotiation Protocol ):

OTG 设备通过 HNP 来切换 Host/Device 角色。

 

OTG 不同连接方式的不同过程

 

OTG Device /Embedded Host 与 仅作为外设的 B-device (带 A 插头型)

Host 端检测到 A 插头插入,停止 ADP ,打开 VBus ,因为 B-Device A 插头与设备作为一体,此时 B-Device 必定与 A 插头连接, Host 检测到外设连接,开始枚举。
 

OTG Device/Embedded Host 与 仅作为外设的 B-device A 插头为线缆连接)

Host 段检测到 A 插头插入,停止 ADP ,打开 VBus ,如果 B-Device 是线缆连接完毕在将 A 插头插入则整个连接过程与上面无异,因为此 时 B-Device 可能还没有插入插头,则设备连接超时, VBus 再次关闭,等待下一次 ADP 的改变(线缆连接完毕),再次打开 VBus ,此时开始正常总 线枚举。

 

OTG Device OTG Device

Host 端检测到插头插入,则打开 VBus ,如果没有外设检测到,则关闭 VBus ,打开 ADP Probing Device 端检测到插头插入,则打开 SRP ,如果线缆没有插入,则 SRP 超时, Device 端开始进行 ADP Probing ,当线缆连接完毕, Device 端侦测到 ADP 变化,发送 SRP 请求 Host 打开 VBus Host 回应 SRP 并且打开 VBus ,完成设备 连接。

从上面的过程可以看出, ADP SRP 的目的都是为了节能,平时 VBus 上的供电是并没有打开的,而且在空闲一段时间后 VBus 也会自动关闭。在 VBus 不供电的情 况下就需要靠 ADP SRP 来检测外设并打开 VBus 的供电。如果 VBus 上一直有电流供应, ADP SRP 就无用武之地了。可见,在嵌入式的世界里,确实要精打细算, ADP SRP 是何等的复杂,这么复杂的设计仅是为了省几毫安的电流。

回来我们前面的问题, OTG EHCI/UHCI/OHCI 是同一类的概念吗?

OTG 的作用只是负责切换主从状态的切换,同时,在功耗方面也有要求, OTG 要求 vbus 不能像 PC 那样永远供电,所以这样就需要有一套设备发现机制,这就是 SRP ADP 了。 OTG 也允许同进充许同类设备进行数据传输( A TO A , 这就是 HNP 发挥作用的时候了。

OTG 己经发现设备, VBUS 供电开启,系统处于 HOST DEVICE 状态,这时 OTG 的使命就完成了,接下来的工作就交给主控制器( EHCI/OHCI/UHIC )或从控制器了。

所以 OTG 的主要是在设备接入的那一刻起作用,此后 USB 还是要按传统的 HOST/DEVICE 的方式来通讯。当然,有些 OTG 控制器会集成一些 HOST 控制器的功能,这些控制器并不符合任何一种标准,一旦遇到这种 OTG 控制器,驱动开发人员就要倒霉了。 USB 系统中最复杂的就是主控制器了,如果与主控制器与 USB 标准有出入,就无法重用大量成熟的控制代码,驱动开发人员就需要重新去研究整个 USB 协义,这无疑是一份耗时耗力不讨好的活。

 

                   Linux 下的 OTG 架构

内核 定义了一个 struct otg_transceiver 的结构体,这个结构体描述的 OTG 需要支持的接口

struct otg_transceiver {

    struct device       *dev;

    const char      *label;

 

    u8          default_a;

    enum usb_otg_state  state; // 记录 OTG 控制器的状态,在实际的处理中这个比较重要。

 

    struct usb_bus      *host;

    struct usb_gadget   *gadget;

 

    /* to pass extra port status to the root hub */

    u16         port_status;

    u16         port_change;

 

    /* bind/unbind the host controller */

    int (*set_host)(struct otg_transceiver *otg,

                struct usb_bus *host);// 这个接口用来启用或禁用主控制器,是关键的接口

 

    /* bind/unbind the peripheral controller */

    int (*set_peripheral)(struct otg_transceiver *otg,

                struct usb_gadget *gadget);

 

    /* effective for B devices, ignored for A-peripheral */

    int (*set_power)(struct otg_transceiver *otg,

                unsigned mA);// 一般用来设置 vbus 上的供电

 

    /* for non-OTG B devices: set transceiver into suspend mode */

    int (*set_suspend)(struct otg_transceiver *otg,

                int suspend);

// 下面是 OTG 的三大高级功能的接口。

    /* for B devices only:  start session with A-Host */

    int (*start_srp)(struct otg_transceiver *otg);

 

    /* start or continue HNP role switch */

    int (*start_hnp)(struct otg_transceiver *otg);

 

    /* b device disconnect during hnp */

    int (*disconnect)(struct otg_transceiver *otg);

 

    /* b device connect */

    int (*connect)(struct otg_transceiver *otg, struct usb_device *udev);

 

    /* host suspend the bus during hnp */

    int     (*host_suspend)(struct otg_transceiver *otg);

 

    /* hand interrupt related to usb otg */

    int (*otg_interrupt)(struct otg_transceiver *otg);// 中断处理接口

};


上表的结构体很清晰的描述了 OTG 的功能,只要实现几个重要的接口,就能把你的 OTG 控制器和 linux 系统联接起来。

系统中作了如下定义:

   struct otg_transceiver *xceiv;

这个定义就是一个 OTG 控制器的对像,然后使用 otg_set_transceiver 来实现这两者之间的联接。

 

注:转载请注明出处 datangsoc@hotmail.com

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值