是USB-On-The-Go 的縮寫,
為USB 規格中的一個延伸,
擁有USB OTG功能的系統,(例如: 手機)
可以根據ID pin狀態的不同,
自行切換為host端或者client端,
已達到不同的目的使用.
例如:
a. 以手機接電腦,
手機會切換為client端,
這時可以把手機當隨身碟使用
b. 以手機接隨身碟,
手機會轉為host端,
讓手機能夠不透過電腦直接存取隨身碟裡面資料,
Google Git 上面可找到otg.c
可以讓我們
從驅動程式原始碼認識USB OTG
/** | |
* ci_otg_work - perform otg (vbus/id) event handle | |
* @work: work struct | |
*/ | |
static void ci_otg_work(struct work_struct *work) | |
{ | |
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); | |
if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) { | |
enable_irq(ci->irq); | |
return; | |
} | |
if (ci->id_event) { | |
ci->id_event = false; | |
ci_handle_id_switch(ci); | |
} else if (ci->b_sess_valid_event) { | |
ci->b_sess_valid_event = false; | |
ci_handle_vbus_change(ci); | |
} else | |
dev_err(ci->dev, "unexpected event occurs at %s\n", __func__); | |
enable_irq(ci->irq); | |
} | |
系統偵測到事件觸發,
執行ci_handle_id_switch(ci);
#define CI_VBUS_STABLE_TIMEOUT_MS 5000 | |
static void ci_handle_id_switch(struct ci_hdrc *ci) | |
{ | |
enum ci_role role = ci_otg_role(ci); | |
if (role != ci->role) { | |
dev_dbg(ci->dev, "switching from %s to %s\n", | |
ci_role(ci)->name, ci->roles[role]->name); | |
ci_role_stop(ci); | |
/* wait vbus lower than OTGSC_BSV */ | |
hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0, | |
CI_VBUS_STABLE_TIMEOUT_MS); | |
ci_role_start(ci, role); | |
} | |
} |
根據ID pin 腳位的不同
會選擇USB功能為:
CI_ROLE_GADGET (client)
CI_ROLE_HOST (host)
/** | |
* ci_otg_role - pick role based on ID pin state | |
* @ci: the controller | |
*/ | |
enum ci_role ci_otg_role(struct ci_hdrc *ci) | |
{ | |
enum ci_role role = hw_read_otgsc(ci, OTGSC_ID) | |
? CI_ROLE_GADGET | |
: CI_ROLE_HOST; | |
return role; | |
} | |
接著driver 會將此變化傳到應用層,
如果是Android 系統,
USB功能的變化就會傳給Android 做相對應的處理
如果是Android 系統,
USB功能的變化就會傳給Android 做相對應的處理