Android5.0 OTG模块传输速度
2015-08-25 09:34
726 查看
对OTG的分析:
/article/1391047.html
文章中有提到这部分是在Vold模块中进行处理:
这是一个在线浏览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,就是将要共享的磁盘设备写到一个标志文件里面,再广播一下大容量存储连接的状态。
OTG体系架构:
/article/7829415.html
对OTG的使用
http://www.crifan.com/android_phone_support_usb_host/
Android OTG功能开发
http://happyboy200032.blog.163.com/blog/static/469031132015265541168/
OTG驱动分析:
/article/9637546.html
驱动分析:
/article/9001587.html
/article/3677507.html
http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f7636d918d027fa3c215cc7902155a66e1b821201019d3c0776303ae5e5c9daa702d691765eadb9e871981edd27574de30340141c014&p=882a9645d7d21de70be2966d4c4e92&newp=c9759a46d6c210fc57efdf35554896231610db2151d4d2162e&user=baidu&fm=sc&query=Android+OTG&qid=996d9fd6000ab43f&p1=7
Android4.0 OTG 数据上报过程分析:
http://blog.chinaunix.net/uid-25909619-id-3255681.html
/article/2694054.html
OTG应用开发:
/article/8386969.html
底层插入上报过程分析:
/article/8959982.html
Android USB/MTP相关
/article/9030079.html
Nenux 5支持OTG
http://bbs.gfan.com/android-4257863-1-1.html
应用层分析:
1.首先拿到UsbManager:
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
2.通过PID,VID得到目标设备:
3.通过UsbManager建立设备连接:
4.获取输入输出端点
端点位于USB 外设内部,所有通信数据的来源或目的都基于这些端点,是一个可寻址的FIFO。 每个USB 外设有一个唯一的地址,可能包含最多十六个端点。主机通过发出器件地址和每次数据传输的端点号,向一个具体端点(FIFO)发送数据。
详细参看:
http://wenku.baidu.com/link?url=_GRI7jquZTi6XHe5jo0_KRdfqMJjzbg_uenQ-lmesKKA1xKsBqC8if87tk7ULdEY87M9kKwhJSDyPxqdM2KeqduYyTFI9ftIMb3wFwgSuka
5.从4中的epIn端点中获取数据(这个函数应该是阻塞的):
6.bulkTransfer调用的是native_bulk_request
7.android_hardware_UsbDeviceConnection.cpp中的native_bulk_request:
框架层代码是在\frameworks\base\core\java\android\hardware\usb目录下:
UsbDeviceConnection用来收发数据,在UsbManager中被实例化
/**
* This class is used for sending and receiving data and control messages to a USB device.
* Instances of this class are created by
{@link UsbManager#openDevice}.
*/
UsbDevice包含设备Name,VendorId,ProductId,Class类型,SubClass类型,Protocol类型这六项信息。
Usbmanager通过Bundler机制获取Usb设备的哈希表:
而UsbManager的构造函数为
因此这里调用的mService.getDeviceList(bundler);的实现是在UsbService.java中:
UsbHostManager.java
而Usb设备的侦测和记录是在这个函数里:
这里的interfaceValues包含设备的相关信息,每个设备5项,因此将数组总长度除以5就得到了设备的个数(代码写得不好)在这里,将数组信息转换成UsbInterface类来存储。
这里的endpointValues包含设备的端点信息,每个端点4项,只不过端点个数在interfaceValues中携带了,因此直接取这个数组就能得到设备的各个端点信息。
UsbDevice:
UsbInterface:
UsbEndpoint
从上面的分析也体现了一个设备有多个接口,每个接口有多个端点
Native层的分析
通过Native层的分析可以知道设备信息是怎么报送到java层的:
系统开机时,在UsbHostManager中便启动了一个usb设备相关的服务
跑的是一个jni函数monitorUsbHostBus
jni函数实现是在:com_android_server_UsbHostManager.cpp (\frameworks\base\services\jni)
Usbhost.c (\system\core\libusbhost)
在usbhost.c中可以看到注册了usb_device_added,usb_device_removed两个回调函数。
这里usb_host_load函数中通过notify机制使得设备监听IN_CREATE,IN_DELETE两个类型的事件。监听到事件后通过jni调用java中的相应函数实现回调:
然后再通过usb_host_read_event读取监听的事件
这里要关注下usb_host_context
其中wdd是watch descriptor ,wds是
(Linux notify机制参见:/article/7800985.html,单独博客表述。)
UsbResolverActivity中会通过IUsbmanager.Stub.asInterface(b);获取service
对OTG的分析:
/article/1391047.html
文章中有提到这部分是在Vold模块中进行处理:
这是一个在线浏览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,就是将要共享的磁盘设备写到一个标志文件里面,再广播一下大容量存储连接的状态。
OTG体系架构:
/article/7829415.html
对OTG的使用
http://www.crifan.com/android_phone_support_usb_host/
Android OTG功能开发
http://happyboy200032.blog.163.com/blog/static/469031132015265541168/
OTG驱动分析:
/article/9637546.html
驱动分析:
/article/9001587.html
/article/3677507.html
http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f7636d918d027fa3c215cc7902155a66e1b821201019d3c0776303ae5e5c9daa702d691765eadb9e871981edd27574de30340141c014&p=882a9645d7d21de70be2966d4c4e92&newp=c9759a46d6c210fc57efdf35554896231610db2151d4d2162e&user=baidu&fm=sc&query=Android+OTG&qid=996d9fd6000ab43f&p1=7
Android4.0 OTG 数据上报过程分析:
http://blog.chinaunix.net/uid-25909619-id-3255681.html
/article/2694054.html
OTG应用开发:
/article/8386969.html
底层插入上报过程分析:
/article/8959982.html
Android USB/MTP相关
/article/9030079.html
Nenux 5支持OTG
http://bbs.gfan.com/android-4257863-1-1.html
应用层分析:
1.首先拿到UsbManager:
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
2.通过PID,VID得到目标设备:
HashMap<String,UsbDevice> deviceList = manager.getDeviceList(); Iterator<UsbDevice> deviceIterator = deviceList.values().iterator(); while (deviceIterator.hasNext()) { UsbDevice device = deviceIterator.next(); if((DEVICE_PID == device.getProductId()) && (DEVICE_VID == device.getVendorId()) ) { mUsbDevice = device; break; } }
3.通过UsbManager建立设备连接:
UsbDeviceConnection connection = manager.openDevice(mUsbDevice);
4.获取输入输出端点
private void getEndpoint(UsbDeviceConnection connection, UsbInterface intf) { if (intf.getEndpoint(1) != null) { epOut = intf.getEndpoint(1); } if (intf.getEndpoint(0) != null) { epIn = intf.getEndpoint(0); } }
端点位于USB 外设内部,所有通信数据的来源或目的都基于这些端点,是一个可寻址的FIFO。 每个USB 外设有一个唯一的地址,可能包含最多十六个端点。主机通过发出器件地址和每次数据传输的端点号,向一个具体端点(FIFO)发送数据。
详细参看:
http://wenku.baidu.com/link?url=_GRI7jquZTi6XHe5jo0_KRdfqMJjzbg_uenQ-lmesKKA1xKsBqC8if87tk7ULdEY87M9kKwhJSDyPxqdM2KeqduYyTFI9ftIMb3wFwgSuka
5.从4中的epIn端点中获取数据(这个函数应该是阻塞的):
out = mDeviceConnection.bulkTransfer(epIn, byte2, byte2.length, 0);
6.bulkTransfer调用的是native_bulk_request
/** * Performs a bulk transaction on the given endpoint. * The direction of the transfer is determined by the direction of the endpoint. * * @param endpoint the endpoint for this transaction * @param buffer buffer for data to send or receive * @param offset the index of the first byte in the buffer to send or receive * @param length the length of the data to send or receive * @param timeout in milliseconds * @return length of data transferred (or zero) for success, * or negative value for failure */ public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int offset, int length, int timeout) { checkBounds(buffer, offset, length); return native_bulk_request(endpoint.getAddress(), buffer, offset, length, timeout); }
7.android_hardware_UsbDeviceConnection.cpp中的native_bulk_request:
android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz, jint endpoint, jbyteArray buffer, jint start, jint length, jint timeout) { struct usb_device* device = get_device_from_object(env, thiz); if (!device) { ALOGE("device is closed in native_control_request"); return -1; } jbyte* bufferBytes = NULL; if (buffer) { bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL); } jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout); if (bufferBytes) { env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0); } return result; }8.最后的usb_device_bulk_transfer是Usbhost.c中的函数:
int usb_device_bulk_transfer(struct usb_device *device, int endpoint, void* buffer, int length, unsigned int timeout) { struct usbdevfs_bulktransfer ctrl; // need to limit request size to avoid EINVAL if (length > MAX_USBFS_BUFFER_SIZE) length = MAX_USBFS_BUFFER_SIZE; memset(&ctrl, 0, sizeof(ctrl)); ctrl.ep = endpoint; ctrl.len = length; ctrl.data = buffer; ctrl.timeout = timeout; return ioctl(device->fd, USBDEVFS_BULK, &ctrl); }
框架层代码是在\frameworks\base\core\java\android\hardware\usb目录下:
UsbDeviceConnection用来收发数据,在UsbManager中被实例化
/**
* This class is used for sending and receiving data and control messages to a USB device.
* Instances of this class are created by
{@link UsbManager#openDevice}.
*/
UsbDevice包含设备Name,VendorId,ProductId,Class类型,SubClass类型,Protocol类型这六项信息。
Usbmanager通过Bundler机制获取Usb设备的哈希表:
/** * Returns a HashMap containing all USB devices currently attached. * USB device name is the key for the returned HashMap. * The result will be empty if no devices are attached, or if * USB host mode is inactive or unsupported. * * @return HashMap containing all connected USB devices. */ public HashMap<String,UsbDevice> getDeviceList() { Bundle bundle = new Bundle(); try { mService.getDeviceList(bundle); HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>(); for (String name : bundle.keySet()) { result.put(name, (UsbDevice)bundle.get(name)); } return result; } catch (RemoteException e) { Log.e(TAG, "RemoteException in getDeviceList", e); return null; } }
而UsbManager的构造函数为
/** * Returns a new instance of this class. * * @param context the caller's {@link android.content.Context} * @return UsbManager instance. */ public static UsbManager getInstance(Context context) { IBinder b = ServiceManager.getService(Context.USB_SERVICE); return new UsbManager(context, IUsbManager.Stub.asInterface(b)); }
因此这里调用的mService.getDeviceList(bundler);的实现是在UsbService.java中:
/* Returns a list of all currently attached USB devices (host mdoe) */ @Override public void getDeviceList(Bundle devices) { if (mHostManager != null) { mHostManager.getDeviceList(devices); } }
UsbHostManager.java
// contains all connected USB devices private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>(); ... ... /* Returns a list of all currently attached USB devices */ public void getDeviceList(Bundle devices) { synchronized (mLock) { for (String name : mDevices.keySet()) { devices.putParcelable(name, mDevices.get(name)); } } }
而Usb设备的侦测和记录是在这个函数里:
/* Called from JNI in monitorUsbHostBus() to report new USB devices */ private void usbDeviceAdded(String deviceName, int vendorID, int productID, int deviceClass, int deviceSubclass, int deviceProtocol, /* array of quintuples containing id, class, subclass, protocol and number of endpoints for each interface */ int[] interfaceValues, /* array of quadruples containing address, attributes, max packet size and interval for each endpoint */ int[] endpointValues) { if (isBlackListed(deviceName) || isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) { return; } synchronized (mLock) { if (mDevices.get(deviceName) != null) { Slog.w(TAG, "device already on mDevices list: " + deviceName); return; } int numInterfaces = interfaceValues.length / 5; Parcelable[] interfaces = new UsbInterface[numInterfaces]; try { // repackage interfaceValues as an array of UsbInterface int intf, endp, ival = 0, eval = 0; for (intf = 0; intf < numInterfaces; intf++) { int interfaceId = interfaceValues[ival++]; int interfaceClass = interfaceValues[ival++]; int interfaceSubclass = interfaceValues[ival++]; int interfaceProtocol = interfaceValues[ival++]; int numEndpoints = interfaceValues[ival++]; Parcelable[] endpoints = new UsbEndpoint[numEndpoints]; for (endp = 0; endp < numEndpoints; endp++) { int address = endpointValues[eval++]; int attributes = endpointValues[eval++]; int maxPacketSize = endpointValues[eval++]; int interval = endpointValues[eval++]; endpoints[endp] = new UsbEndpoint(address, attributes, maxPacketSize, interval); } // don't allow if any interfaces are blacklisted if (isBlackListed(interfaceClass, interfaceSubclass, interfaceProtocol)) { return; } interfaces[intf] = new UsbInterface(interfaceId, interfaceClass, interfaceSubclass, interfaceProtocol, endpoints); } } catch (Exception e) { // beware of index out of bound exceptions, which might happen if // a device does not set bNumEndpoints correctly Slog.e(TAG, "error parsing USB descriptors", e); return; } <span style="color:#ff0000;"> UsbDevice device = new UsbDevice(deviceName, vendorID, productID, deviceClass, deviceSubclass, deviceProtocol, interfaces); mDevices.put(deviceName, device); getCurrentSettings().deviceAttached(device);</span> } }
这里的interfaceValues包含设备的相关信息,每个设备5项,因此将数组总长度除以5就得到了设备的个数(代码写得不好)在这里,将数组信息转换成UsbInterface类来存储。
这里的endpointValues包含设备的端点信息,每个端点4项,只不过端点个数在interfaceValues中携带了,因此直接取这个数组就能得到设备的各个端点信息。
UsbDevice:
public class UsbDevice implements Parcelable { private static final String TAG = "UsbDevice"; private final String mName; private final int mVendorId; private final int mProductId; private final int mClass; private final int mSubclass; private final int mProtocol; private final Parcelable[] mInterfaces; }
UsbInterface:
public class UsbInterface implements Parcelable { private final int mId; private final int mClass; private final int mSubclass; private final int mProtocol; private final Parcelable[] mEndpoints; }
UsbEndpoint
public class UsbEndpoint implements Parcelable { private final int mAddress; private final int mAttributes; private final int mMaxPacketSize; private final int mInterval; }
从上面的分析也体现了一个设备有多个接口,每个接口有多个端点
Native层的分析
通过Native层的分析可以知道设备信息是怎么报送到java层的:
系统开机时,在UsbHostManager中便启动了一个usb设备相关的服务
public void systemReady() { synchronized (mLock) { // Create a thread to call into native code to wait for USB host events. // This thread will call us back on usbDeviceAdded and usbDeviceRemoved. Runnable runnable = new Runnable() { public void run() { monitorUsbHostBus(); } }; new Thread(null, runnable, "UsbService host thread").start(); } }
跑的是一个jni函数monitorUsbHostBus
private native void monitorUsbHostBus();
jni函数实现是在:com_android_server_UsbHostManager.cpp (\frameworks\base\services\jni)
static void android_server_UsbHostManager_monitorUsbHostBus(JNIEnv *env, jobject thiz) { struct usb_host_context* context = usb_host_init(); if (!context) { ALOGE("usb_host_init failed"); return; } // this will never return so it is safe to pass thiz directly usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz); }
Usbhost.c (\system\core\libusbhost)
void usb_host_run(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data) { int done; done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data); while (!done) { done = usb_host_read_event(context); } } /* usb_host_run() */
int usb_host_load(struct usb_host_context *context, usb_device_added_cb added_cb, usb_device_removed_cb removed_cb, usb_discovery_done_cb discovery_done_cb, void *client_data) { int done = 0; int i; context->cb_added = added_cb; context->cb_removed = removed_cb; context->data = client_data; D("Created device discovery thread\n"); /* watch for files added and deleted within USB_FS_DIR */ for (i = 0; i < MAX_USBFS_WD_COUNT; i++) context->wds[i] = -1; /* watch the root for new subdirectories */ context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE); if (context->wdd < 0) { fprintf(stderr, "inotify_add_watch failed\n"); if (discovery_done_cb) discovery_done_cb(client_data); return done; } watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT); /* check for existing devices first, after we have inotify set up */ done = find_existing_devices(added_cb, client_data); if (discovery_done_cb) done |= discovery_done_cb(client_data); return done; } /* usb_host_load() */
在usbhost.c中可以看到注册了usb_device_added,usb_device_removed两个回调函数。
这里usb_host_load函数中通过notify机制使得设备监听IN_CREATE,IN_DELETE两个类型的事件。监听到事件后通过jni调用java中的相应函数实现回调:
method_usbDeviceAdded = env->GetMethodID(clazz, "usbDeviceAdded", "(Ljava/lang/String;IIIII[I[I)V"); static int usb_device_added(const char *devname, void* client_data) { ... env->CallVoidMethod(thiz, method_usbDeviceAdded, deviceName, vendorId, productId, deviceClass, deviceSubClass, protocol, interfaceArray, endpointArray); ... }
然后再通过usb_host_read_event读取监听的事件
int usb_host_read_event(struct usb_host_context *context) { struct inotify_event* event; char event_buf[512]; char path[100]; int i, ret, done = 0; int offset = 0; int wd; ret = read(context->fd, event_buf, sizeof(event_buf)); if (ret >= (int)sizeof(struct inotify_event)) { while (offset < ret) { event = (struct inotify_event*)&event_buf[offset]; done = 0; wd = event->wd; if (wd == context->wdd) { if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) { watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT); done = find_existing_devices(context->cb_added, context->data); } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "bus")) { for (i = 0; i < MAX_USBFS_WD_COUNT; i++) { if (context->wds[i] >= 0) { inotify_rm_watch(context->fd, context->wds[i]); context->wds[i] = -1; } } } } else if (wd == context->wds[0]) { i = atoi(event->name); snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name); D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ? "new" : "gone", path, i); if (i > 0 && i < MAX_USBFS_WD_COUNT) { if (event->mask & IN_CREATE) { ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); if (ret >= 0) context->wds[i] = ret; done = find_existing_devices_bus(path, context->cb_added, context->data); } else if (event->mask & IN_DELETE) { inotify_rm_watch(context->fd, context->wds[i]); context->wds[i] = -1; } } } else { for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) { if (wd == context->wds[i]) { snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name); if (event->mask == IN_CREATE) { D("new device %s\n", path); done = context->cb_added(path, context->data); } else if (event->mask == IN_DELETE) { D("gone device %s\n", path); done = context->cb_removed(path, context->data); } } } } offset += sizeof(struct inotify_event) + event->len; } } return done; } /* usb_host_read_event() */
这里要关注下usb_host_context
struct usb_host_context { int fd; usb_device_added_cb cb_added; usb_device_removed_cb cb_removed; void *data; int wds[MAX_USBFS_WD_COUNT]; int wdd; };
其中wdd是watch descriptor ,wds是
(Linux notify机制参见:/article/7800985.html,单独博客表述。)
UsbResolverActivity中会通过IUsbmanager.Stub.asInterface(b);获取service
相关文章推荐
- Android实例-TTabControl的使用(XE8+小米2)
- Android中View转换为Bitmap及getDrawingCache=null的解决方法
- 使用proguard混淆android代码
- 主动通知Android系统图库进行更新
- Android Studio快捷键
- 关于android.view.WindowManager$BadTokenException问题出现以及解决的一些记录
- GridView垂直方向填充
- AndroidStudio
- 解开Android应用程序组件Activity的"singleTask"之谜
- android 学习笔记 数据存储到文件中
- android viewpager嵌套侧滑删除listview冲突问题
- android:padding和android:layout_margin的区别
- android学习之——Android事件处理(监听和回调)
- Android大放送干:书籍、过程、工具等各种全
- Android Overview Screen -- 概览界面
- Android 自定义Activity基类
- Android 自定义主菜单
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.AndroidCaptureC
- android ble 4.0实现自动配对
- 兼容 Android 4.4 透明状态栏与导航栏