Android-vold源码分析之连接电脑OTG(11)
作者:gzshun. 原創作品,轉載請標明出處!
來源:http://blog.csdn.net/gzshun
OTG是on-the-go的簡稱,是2001年由USB Implementers Forum公布,主要應用于各種不同的設備或移動設備間的聯接,進行數據交換。特別是PDA、移動電話、消費類設備。改變如數碼照相機、攝像機、打印機等設備間多種不同制式連接器,多達7種制式的存儲卡間數據交換的不便。
對OTG介紹比較詳細的在USB的官網,詳細請見英文文檔:http://www.usb.org/developers/onthego/。以下是官網的一個簡要的介紹,貼出來看看:
USB On-The-Go and Embedded Host
Virtually every portable device now uses USB for PC connectivity. As these products increase in popularity, there is a growing need for them to communicate both with USB peripherals and directly with each other when a PC is not available. There is also an increase in the number of other, non-PC hosts (Embedded Hosts) which support USB in order to connect to USB peripherals.
The USB On-The-Go and Embedded Host Supplements addresses these scenarios by allowing portable devices and non-PC hosts to have the following enhancements:
Targeted host capability to communicate with selected other USB peripherals
Support for direct connections between OTG devices
Power saving features to preserve battery life
Revision 2.0 of the USB On-The-Go and Embedded Host Supplement to the USB 2.0 Specification applies to products operating at low-speed, full-speed and high-speed and is released, including applicable ECNs and errata, as part of the USB 2.0 Specification package. The corresponding OTG Adopters Agreement is also available.
Revision 1.0 of the USB On-The-Go and Embedded Host Supplement to the USB 3.0 Specification enhances these scenarios by adding SuperSpeed capability to USB On-The-Go and is released as part of the USB 3.0 Specification package. The corresponding Adopters Agreement for USB OTG 3.0 is the USB 3.0 Adopters Agreement.
這里寫得很清楚,OTG主要是實現可移動設備點對點的數據共享,不需要再依賴于PC機第三方的識別或者操作。平時經常從電腦下載MP3格式的音樂到phone or Pad,都是經過USB線來連接電腦,電腦可以識別到設備里面的存儲設備,或者手機與手機的連接,這就是OTG功能。
這是一個在線瀏覽Linux內核源碼的網站:http://lxr.linux.no/。
Linux內核早就提供了OTG的驅動,在http://lxr.linux.no/linux+v3.1.6/drivers/usb/gadget/目錄下,Linux將usb與otg兩個功能模塊給獨立開了,主要的驅動是file_storage.c,該驅動主要負責終端設備的存儲設備節點的操作,比如,從電腦,在該終端的磁盤上面創建文件,都會通過這個驅動來完成存儲任務。另外一個驅動主要是負責USB通信的,是結尾為"_udc.c"的驅動源碼,該目錄下有好幾個以"_udc.c"結尾的文件,這是針對不同型號的處理器而增加的,不同廠家提供不同的驅動。
這里只是簡單的介紹,Android在vold中處理otg,就是將要共享的磁盤設備寫到一個標志文件里面,再廣播一下大容量存儲連接的狀態。
一、連接電腦;先來看看源碼:
else if (!strcmp(argv[1], "share")) {
?? ?if (argc != 4) {
?? ?cli->sendMsg(ResponseCode::CommandSyntaxError,
?? ?"Usage: volume share <path> <method>", false);
?? ?return 0;
?? ?}
?? ?rc = vm->shareVolume(argv[2], argv[3]);
}
進入shareVolume函數中,該函數判斷一下sd卡的狀態,如果不存在設備,或者sd卡不是出于空閑狀態,那么就返回失敗。
int VolumeManager::shareVolume(const char *label, const char *method) {
? ? Volume *v = lookupVolume(label);
?
? ? if (!v) {
? ? ? ? errno = ENOENT;
? ? ? ? return -1;
? ? }
?
? ? /*
? ? ?* Eventually, we'll want to support additional share back-ends,
? ? ?* some of which may work while the media is mounted. For now,
? ? ?* we just support UMS
? ? ?*/
? ? if (strcmp(method, "ums")) {
? ? ? ? errno = ENOSYS;
? ? ? ? return -1;
? ? }
?
? ? if (v->getState() == Volume::State_NoMedia) {
? ? ? ? errno = ENODEV;
? ? ? ? return -1;
? ? }
?
? ? if (v->getState() != Volume::State_Idle) {
? ? ? ? // You need to unmount manually befoe sharing
? ? ? ? errno = EBUSY;
? ? ? ? return -1;
? ? }
? ? /*getDiskDevice函數直接返回sd卡的設備號。*/
? ? dev_t d = v->getDiskDevice();
? ? if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
? ? ? ? // This volume does not support raw disk access
? ? ? ? errno = EINVAL;
? ? ? ? return -1;
? ? }
?
? ? int fd;
? ? char nodepath[255];
? ? snprintf(nodepath,
? ? ? ? ? ? ?sizeof(nodepath), "/dev/block/vold/%d:%d",
? ? ? ? ? ? ?MAJOR(d), MINOR(d));
? ? /*比較重要的在這里,想要實現讓電腦識別到Android系統中的sd卡,
? ? 那么就必須將sd卡的設備節點路徑寫到以下文件中去,這樣才能打開
? ? 大容量存儲的功能,也就是OTG*/
? ? if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
? ? ? ? ? ? ? ? ? ?O_WRONLY)) < 0) {
? ? ? ? SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
? ? ? ? return -1;
? ? }
?
? ? if (write(fd, nodepath, strlen(nodepath)) < 0) {
? ? ? ? SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
?
? ? close(fd);
? ? /*handleVolumeShared函數在Volume中,是一個虛函數,在子類DirectVolume中
? ? 實現,也就是廣播一些ums的狀態。*/
? ? v->handleVolumeShared();
? ? return 0;
}
如果有Android手機的用戶,可以看到系統中存在/sys/devices/platform/usb_mass_storage/lun0/file這么一個文件,Java層可能沒有權限訪問該文件。最近發現,Java想要訪問系統的文件,或者操作命令都要賦以最高權限(0777)才能訪問或執行,真是麻煩。
void DirectVolume::handleVolumeShared() {
?? ?setState(Volume::State_Shared);
}
二、斷開連接;
int VolumeManager::unshareVolume(const char *label, const char *method) {
? ? Volume *v = lookupVolume(label);
?
? ? if (!v) {
? ? ? ? errno = ENOENT;
? ? ? ? return -1;
? ? }
?
? ? if (strcmp(method, "ums")) {
? ? ? ? errno = ENOSYS;
? ? ? ? return -1;
? ? }
?
? ? if (v->getState() != Volume::State_Shared) {
? ? ? ? errno = EINVAL;
? ? ? ? return -1;
? ? }
?
? ? int fd;
? ? if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
? ? ? ? SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
? ? ? ? return -1;
? ? }
?
? ? char ch = 0;
? ? /*如果要斷開連接,可以在電腦安全刪除,然后Android系統會提示用戶點擊掛載sd卡,因為
? ? 在電腦使用sd卡的情況下,手機是不能對sd卡操作的,多處操作磁盤,會造成數據同步錯誤。
? ? 就在斷開電腦,進入手機使用模式時,將/sys/devices/platform/usb_mass_storage/lun0/file
? ? 寫為空了*/
? ? if (write(fd, &ch, 1) < 0) {
? ? ? ? SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
? ? ? ? close(fd);
? ? ? ? return -1;
? ? }
?
? ? close(fd);
? ? /*再廣播otg斷開狀態*/
? ? v->handleVolumeUnshared();
? ? return 0;
}
void DirectVolume::handleVolumeUnshared() {
?? ?setState(Volume::State_Idle);
}
這里已經分析完在CommandListener::VolumeCmd::runCommand函數的實現的所有操作了,然后程序將命令的執行結果通知Framework,源碼:
if (!rc) {
? ? ? ? cli->sendMsg(ResponseCode::CommandOkay, "volume operation succeeded", false);
? ? } else {
? ? ? ? int erno = errno;
? ? ? ? rc = ResponseCode::convertFromErrno();
? ? ? ? cli->sendMsg(rc, "volume operation failed", true);
}
磁盤操作的命令圓滿結束,下一篇文章繼續分析Framework與vold的通信。待續。
————————————————
版權聲明:本文為CSDN博主「gzshun」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/gzshun/article/details/7171781
總結
以上是生活随笔為你收集整理的Android-vold源码分析之连接电脑OTG(11)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html 5 触摸屏事件
- 下一篇: la force Comicsonair