kernel配置
SDK默认的kernel配置已经设置好acm相关功能的,defconfig中主要包括下面几项:
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_VBUS_DRAW=500
CONFIG_USB_G_ANDROID=y
Android层配置
默认的代码Android层已经有配置好的,在device/rockchip/common/init.rk30board.usb.rc 内容如下:
on property:sys.usb.config=acm
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 2207
write /sys/class/android_usb/android0/idProduct 0005
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=acm,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 2207
write /sys/class/android_usb/android0/idProduct 0005
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
功能切换
使用过程用下面的指令进行功能切换:
setprop sys.usb.config acm
setprop sys.usb.config acm,adb
报错及解决方法
切换成acm设备之后可以正常连接PC,kernel log没有明显的报错,接到windows PC可以发现设备,PC的设备管理器显示通用串行设备,正常应该在“端口(COM和LPT)”,重新卸载设备或者更新驱动都不能解决。
问题分析
该SDK的kernel版本是3.10,gadget是在android.c里面实现的,通过跟踪代码发现有个instances变量,该变量可以从应用层调用的,但是应用层并没有操作这个变量,因此会遇到acm驱动没有正常初始化,其代码如下:
static int
acm_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
int i;
int ret = 0;
struct acm_function_config *config = f->config;
config->instances_on = config->instances;
for (i = 0; i < config->instances_on; i++) {
ret = usb_add_function(c, config->f_acm[i]);
if (ret) {
pr_err("Could not bind acm%u config\n", i);
goto err_usb_add_function;
}
}
return 0;
err_usb_add_function:
while (i-- > 0)
usb_remove_function(c, config->f_acm[i]);
return ret;
}
解决方法
-
在Android层操作instances节点,在开启acm的时候使能他,如:
on property:sys.usb.config=acm write /sys/class/android_usb/android0/enable 0 write /sys/class/android_usb/android0/idVendor 2207 write /sys/class/android_usb/android0/idProduct 0005 write /sys/class/android_usb/android0/f_acm/instances 1 write /sys/class/android_usb/android0/functions ${sys.usb.config} write /sys/class/android_usb/android0/enable 1 setprop sys.usb.state ${sys.usb.config} on property:sys.usb.config=acm,adb write /sys/class/android_usb/android0/enable 0 write /sys/class/android_usb/android0/idVendor 2207 write /sys/class/android_usb/android0/idProduct 0005 write /sys/class/android_usb/android0/f_acm/instances 1 write /sys/class/android_usb/android0/functions ${sys.usb.config} write /sys/class/android_usb/android0/enable 1 start adbd setprop sys.usb.state ${sys.usb.config}
但是这样操作会导致系统崩溃,崩溃log如:
[ 70.552704] Unable to handle kernel NULL pointer dereference at virtual address 00000104 [ 70.578967] pgd = c58d0000 [ 70.580643] [00000104] *pgd=7df48835, *pte=00000000, *ppte=00000000 [ 70.587813] Internal error: Oops: 817 [#1] PREEMPT SMP ARM [ 70.592126] Modules linked in: rk915 drmboot(P) [ 70.597721] CPU: 1 PID: 1 Comm: init Tainted: P 3.10.104 #16 [ 70.603122] task: de878000 ti: de85c000 task.ti: de85c000 [ 70.608422] PC is at usb_remove_function+0x30/0x64 [ 70.613200] LR is at dwc_otg_pcd_ep_disable+0xc/0x164 [ 70.618120] pc : [<c04a3d04>] lr : [<c048c0c8>] psr: a00f0013 [ 70.618120] sp : de85deb0 ip : ddcd9220 fp : 00000000 [ 70.629335] r10: 00000100 r9 : 00000200 r8 : c0bd94a0 [ 70.634434] r7 : c0bd9478 r6 : dde96800 r5 : dde91600 r4 : c0bd9478 [ 70.640847] r3 : 00000200 r2 : 00000100 r1 : ddcd9220 r0 : ffffffea [ 70.647217] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 70.654253] Control: 10c5387d Table: 658d006a DAC: 00000015 [ 70.659933] [ 70.659933] PC: 0xc04a3c84: [ 70.664050] 3c84 e594400c e244400c e284300c e1530008 1afffff0 e3a04000 ea000002 e3a03000 [ 70.673321] 3ca4 e584301c e5843020 e1a00004 e8bd85f8 c0a5ccbb c0a5ccc3 c0a5ccc8 c0a5cccd [ 70.681447] 3cc4 c0a5ccd6 c0a5ccdf e3a02000 eaffff9f e92d4038 e1a04000 e5913030 e1a05001 [ 70.689577] 3ce4 e3530000 0a000001 e1a00001 e12fff33 e5952048 e3a03000 e5853050 e595304c [ 70.697705] 3d04 e5823004 e5832000 e3a03c01 e5853048 e3a03c02 e585304c e595301c e3530000 [ 70.705841] 3d24 08bd8038 e1a00004 e1a01005 e12fff33 e8bd8038 e5d03030 e353000f 90802103 [ 70.713971] 3d44 83e00012 95821034 92832001 95c02030 91a00003 e12fff1e e92d4010 e1a03000 [ 70.722122] 3d64 e5902000 e5920014 e3500002 93a0c000 91a0200c 9a00000a e5922010 e3520003 [ 70.730264] [ 70.730264] LR: 0xc048c048: [ 70.733271] c048 eb003e3c e3e0006b ea000012 e5d53011 e20330c0 e3530040 1a000007 e5953000 [ 70.742614] c068 e3a02001 e5d33006 e2433001 e1a03312 e5853040 e3e03000 e5853044 e5940008 [ 70.750802] c088 e2851010 ebffd17b e5940a5c e59d100c eb003e28 e3a00000 e28dd010 e8bd81f0 [ 70.758943] c0a8 c0a24b58 c0a50af7 c0853bf6 c0a5a968 c0a5a985 e92d4073 e1a05000 ebfffb76 [ 70.767090] c0c8 e2504000 0a000051 e5943000 e3530000 0a00004e e28d1004 e5950a5c eb003e02 [ 70.775224] c0e8 e1a00004 ebfffdd3 e5950008 e2841010 ebffd1e5 e5953008 e5932000 e5922118 [ 70.783365] c108 e3520000 0a000009 e5d42010 e0833102 e59301b4 eb003edf e5952008 e5d43010 [ 70.791499] c128 e3a0100c e0232391 e3a02000 e5c320fc e3a03000 e5843000 e5d4300c e3833001 ...... [ 71.451882] [<c04a3d04>] (usb_remove_function+0x30/0x64) from [<c04b0ef0>] (acm_function_unbind_config+0x30/0x50) [ 71.461992] [<c04b0ef0>] (acm_function_unbind_config+0x30/0x50) from [<c04a9ec0>] (android_unbind_config+0x30/0x4c) [ 71.472134] [<c04a9ec0>] (android_unbind_config+0x30/0x4c) from [<c04a434c>] (unbind_config+0xac/0xbc) [ 71.481294] [<c04a434c>] (unbind_config+0xac/0xbc) from [<c04b17ac>] (enable_store+0x11c/0x194) [ 71.489808] [<c04b17ac>] (enable_store+0x11c/0x194) from [<c035dd38>] (dev_attr_store+0x18/0x24) [ 71.498387] [<c035dd38>] (dev_attr_store+0x18/0x24) from [<c0163088>] (sysfs_write_file+0x7c/0xb0) [ 71.507174] [<c0163088>] (sysfs_write_file+0x7c/0xb0) from [<c0111d98>] (vfs_write+0xd4/0x16c) [ 71.515596] [<c0111d98>] (vfs_write+0xd4/0x16c) from [<c01120d8>] (SyS_write+0x3c/0x60) [ 71.523542] [<c01120d8>] (SyS_write+0x3c/0x60) from [<c000db00>] (ret_fast_syscall+0x0/0x38) [ 71.531766] Code: e5952048 e3a03000 e5853050 e595304c (e5823004)
目前找不到解决kernel崩溃的方法。
-
直接在kernel中操作instances节点,在bind的时候加一,在unbind的时候减一,代码修改如下:
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index ca741856..dbcdc68d 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -472,7 +472,8 @@ acm_function_bind_config(struct android_usb_function *f, int ret = 0; struct acm_function_config *config = f->config; - config->instances_on = config->instances; +// config->instances_on = config->instances; + config->instances_on++; for (i = 0; i < config->instances_on; i++) { ret = usb_add_function(c, config->f_acm[i]); if (ret) { @@ -495,6 +496,7 @@ static void acm_function_unbind_config(struct android_usb_function *f, int i; struct acm_function_config *config = f->config; + config->instances_on--; for (i = 0; i < config->instances_on; i++) usb_remove_function(c, config->f_acm[i]); }
经测试未发现异常。