编程接口的变化
为了支持OTG特性,编程接口上作了尽可能小的改动。这些改动并不会改变已有的编程模型:主机端仍然会用
urb和usb_device,设备端仍然会用ueb_request和usb_gadget。从某些角度来说,也许我们更希望将urb变成类似urb_gadget这样的轻量级模型,这样在主机和设备端就可以有对称的编程接口。但是现在还没必要去这样做。
设备端:usb设备控制器(USB Device Controller)
在gadget接口中新添了一些OTG状态标志和usb_gadget_*()调用。用户接口通过OTG状态标志来报告OTG设备的需要,而新增的gadget调用用来支持新的USB状态的转变(一些调用也可以支持non-OTG系统)。除了is_otg标志,其他的状态标志还局限于gadget driver参与HNP时:(1)在收到SET_CONFIGURATION请求之后或(2)在挂起之前(只有在这两种情况下gadget driver才会修改状态标志)。另外,一旦HNP曾经使能,只有当设备重枚举后才能屏蔽HNP。
usb/gadget.h
struct usb_gadget{
...
unsigned is_otg:1;
unsigned is_a_periphera:1;
unsigned b_hnp_enable:1;
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
...
}
/*由外接USB收发器使用*/
int usb_gadget_vbus_connect(struct usb_gadget *gadget);
int usb_gadget_vbus_disconnect(struct usb_gadget *gadget);
/*SET_CONFIGURATION时调用*/
int usb_gadget_vbus_draw(struct usb_gadget *gadget);
/*逻辑上控制USB D+ 拉高*/
int usb_gadget_connect(struct usb_gadget *gadget);
int usb_gadget_disconnect(struct usb_gadget *gadget);
另外,usb_gadget_wakeup()作为可以引起SRP的方式。如果设备处于挂起状态,会用到远程唤醒(OTG设备并不总是需要主机端才能唤醒),如果Vbus上没有电流,可以用SRP来代替。
外设端:Gadget Drivers
可以参考Gadget Zero中的变化,通过omap_udc完成OTG相关属性操作。gadget zero可以有效的通过USBCV OTG tests。所有的基于OTG功能硬件的USB Gadget drivers都要作类似以下的变化。
(1) 当gadget->is_otg为真时,在每个configuration中提供一个OTG descriptor
(2) SET_CONFIGURATION时,通过用户接口(printk,LED,etc)报告HNP有效.
(3) 通过用户接口,就像报告suspend开始时那样报告HNP角色转换的开始(B外设变为B主机,或A外设 变成A主机).
要注意的是:这个gadget driver框架不能处理OTG的SRP-only(那需要另外的gadget标志)。同时,也不能为OTG提供gadgetfs.
主机端:usbcore
OTG枚举(Ebumeratiob)和目标设备列表(Targeted Peripherals)
USB枚举(khubd和usb_new_device)需要的改动
(1) 当一个OTG A-host枚举一个OTG dual-role设备时,(它们直接通过root hub相联).在发出SET_CONFIGURATION之前要置HNP使能位.在这里,会立刻置B-Periperal的b_hnp_enable位.
(2) 检查OTG目标设备列表Targeted Peripherals):drivers/usb/core/otg_whitelist.h
(3) 如果设备属于OTG目标设备列表,那末就允许configure
(4) 如果不属于OTG目标设备列表中的设备,就会告知你.此时,dual-role设备可以立刻通过hnp转换成host角色.目的是为了防止原来的A-host在dual-role设备的whitelist中.
(5) OTG控制器driver要有叫HCD立刻开始枚举的能力.
usb_bus接口新增了一些属性,以满足在枚举时可以设置对应的OTG状态位.
struct usb_bus{
...
u8 otg_port; //插入Mini-AB插头的端口号
unsigned is_b_host:1;//表示该设备相对于A-host是否更像B-Host.该位在hnp角色转换时置位.
unsigned b_hnp_enable:1; //表示A-host是否使能B-Peripheral的HNP
...
}
CONFIG_USB_SUSPEND
HNP需要usbcore提供suspend/resume的支持,在drivers/usb/core/driver.c中定义了:
extern int usb_suspend_device(struct usb_device *dev, u32 state);
extern int usb_resume_device(struct usb_device *dev);
以usb_suspend_device为例,当HNP无效时:在挂起这个设备之前要挂起设备的每个活跃的接口,如果该设备是usb hub则还要挂起hub的每个子设备。当HNP有效时:挂起会触发设备角色的转变。A-host变为A-peripheral,或B-host变为B-peripheral,此时host的root hub会通过一些特殊的机制(如otg_transceiver接口)来通知OTG controller开始HNP会话.
电源管理
由于OTG产品通常都是电池供电,所以有必要在不用的时候将他挂起来延长电池带电时间(事实上不光OTG产品如此).目前,usbcore已经可以监控一个hub的电流,并且当一个hub端口的电流超出预算时会发出警告(但不会中断).root hub可以指定他的电流预算的值比如8mA.目前在usbcore不能支持主机端的SRP,但底层的OTG controller可以处理.这意味着hub driver不会完全准确的了解到OTG端口的电流状态.所以说,在这方面还有很多工作要做,以使SRP在hub driver这一层完全实现.
主机端:USB设备驱动(USB Device Drivriers)
有疑问加站长微信联系(非本文作者)