Android11 对比 Android7.1 此前使用 ppp拨号协议因涉及权限过多,已经不适用。需要改用 wwan协议(此种方式需要权限较少)。
提示:此文章为 rk3568 移植 ec20,下一篇 [rk3568 移植 n720](https://blog.csdn.net/weixin_35723192/article/details/125591117)。
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -583,6 +583,31 @@ static void option_instat_callback(struct urb *urb);
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(0x1286, 0x4e3c) },
+#if 1 //Added by Quectel
+ { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
+ { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
+ { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20(MDM9215) */
+ { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC20(MDM9x07)/EC25/EG25 */
+ { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */
+ { USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
+ { USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
+ { USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
+ { USB_DEVICE(0x2C7C, 0x030B) }, /* Quectel EG065K/EG060K */
+ { USB_DEVICE(0x2C7C, 0x0512) }, /* Quectel EG12/EP12/EM12/EG16/EG18 */
+ { USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
+ { USB_DEVICE(0x2C7C, 0x0700) }, /* Quectel BG95/BG77/BG600L-M3/BC69 */
+ { USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
+ { USB_DEVICE(0x2C7C, 0x0415) }, /* Quectel AG15 */
+ { USB_DEVICE(0x2C7C, 0x0452) }, /* Quectel AG520 */
+ { USB_DEVICE(0x2C7C, 0x0455) }, /* Quectel AG550 */
+ { USB_DEVICE(0x2C7C, 0x0620) }, /* Quectel EG20 */
+ { USB_DEVICE(0x2C7C, 0x0800) }, /* Quectel RG500/RM500/RG510/RM510 */
+ { USB_DEVICE(0x2C7C, 0x0801) }, /* Quectel RG520/RM520/SG520 */
+ { USB_DEVICE(0x2C7C, 0x6026) }, /* Quectel EC200 */
+ { USB_DEVICE(0x2C7C, 0x6120) }, /* Quectel UC200 */
+ { USB_DEVICE(0x2C7C, 0x6000) }, /* Quectel EC200/UC200 */
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR, .idVendor = 0x2C7C }, /* Match All Quectel Modules */
+#endif
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
@@ -2109,6 +2134,9 @@ static struct usb_serial_driver option_1port_device = {
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
+#if 1 //Added by Quectel
+ .reset_resume = usb_wwan_resume,
+#endif
#endif
};
@@ -2133,6 +2161,35 @@ static int option_probe(struct usb_serial *serial,
&serial->interface->cur_altsetting->desc;
unsigned long device_flags = id->driver_info;
+#if 1 //Added by Quectel
+ //Quectel UC20's interface 4 can be used as USB Network device
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)
+ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+ return -ENODEV;
+
+ //Quectel EC20(MDM9215)'s interface 4 can be used as USB Network device
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)
+ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
+ return -ENODEV;
+
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
+ __u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
+ struct usb_interface_descriptor *intf = &serial->interface->cur_altsetting->desc;
+
+ if (intf->bInterfaceClass != 0xFF || intf->bInterfaceSubClass == 0x42) {
+ //ECM, RNDIS, NCM, MBIM, ACM, UAC, ADB
+ return -ENODEV;
+ }
+
+ if ((idProduct&0xF000) == 0x0000) {
+ //MDM interface 4 is QMI
+ if (intf->bInterfaceNumber == 4 && intf->bNumEndpoints == 3
+ && intf->bInterfaceSubClass == 0xFF && intf->bInterfaceProtocol == 0xFF)
+ return -ENODEV;
+ }
+ }
+#endif
+
/* Never bind to the CD-Rom emulation interface */
if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
return -ENODEV;
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -509,11 +509,22 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
if (intfdata->use_zlp && dir == USB_DIR_OUT)
urb->transfer_flags |= URB_ZERO_PACKET;
+#if 1 //Added by Quectel for Zero Packet
if (dir == USB_DIR_OUT) {
if ((desc->idVendor == cpu_to_le16(0x1286) &&
desc->idProduct == cpu_to_le16(0x4e3c)))
urb->transfer_flags |= URB_ZERO_PACKET;
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9090))
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003))
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215))
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C))
+ urb->transfer_flags |= URB_ZERO_PACKET;
}
+#endif
+
return urb;
}
须用刚下载的 qmi_wwan_q.c 替换原有驱动 qmi_wwan.c, 路径 kernel/drivers/net/usb/qmi_wwan.c
查看原理图中 ec20 模组上电时序控制
EC20 disable 由gpio1_B5控制,设备树中使用 power 控制信号;
EC20 reset 由于gpio1_A2控制,设备树中使用 reset 控制信号;
EC20 供电由于gpio3_A6控制,设备树中使用 vbat 控制信号;
# 新增设备描述节点要 在根节点上添加
/ {
+ rk_modem: rk-modem {
+ compatible="4g-modem-platdata";
+ pinctrl-names = "default";
+ pinctrl-0 = <<e_vbat <e_power_en <e_reset>;
+ 4G,vbat-gpio = <&gpio3 RK_PA6 GPIO_ACTIVE_HIGH>; #ec20 vbat控制pin
+ 4G,power-gpio = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>; #ec20 power控制 pin
+ 4G,reset-gpio = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>; #ec20复位pin
+ };
# 增加pinctrl 设定
&pinctrl {
+ rk-modem {
+ lte_vbat: lte-vbat {
+ rockchip,pins = <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ lte_power_en: lte-power-en {
+ rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ lte_reset: lte-reset {
+ rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
编译内核完成后,刷机验证可正常识别到 ec20, 并生成 /dev/ttyUSBx节点,则证明驱动移植完成。如果所有组 所有者不是radio,则需要添加权限。如果未生成 /dev/cdc-wdm0 节点,请继续 system/core 移植驱动。
$ ls /dev/ttyUSB[0-3] -lh
crw-rw---- 1 radio radio 188, 0 2022-06-22 19:44 /dev/ttyUSB0
crw-rw---- 1 radio radio 188, 1 2022-06-22 19:44 /dev/ttyUSB1
crw-rw---- 1 radio radio 188, 2 2022-06-22 20:05 /dev/ttyUSB2
crw-rw---- 1 radio radio 188, 3 2022-06-22 19:44 /dev/ttyUSB3
$ ls /dev/cdc-wdm* -lh
crw-rw---- 1 radio radio 180, 176 2022-06-23 10:26 /dev/cdc-wdm0
system/core/init/devices.cpp
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -492,6 +492,11 @@ void DeviceHandler::HandleUevent(const Uevent& uevent) {
int device_id = uevent.minor % 128 + 1;
devpath = StringPrintf("/dev/bus/usb/%03d/%03d", bus_id, device_id);
}
+#if 1 //add by quectel for mknod /dev/cdc-wdm0
+ } else if (uevent.subsystem == "usbmisc" && !uevent.device_name.empty()) {
+ devpath = "/dev/" + uevent.device_name;
+#endif
+
} else if (StartsWith(uevent.subsystem, "usb")) {
rk3566 rk3568 在 device/rockchip/common/ueventd.rockchip.rc 加权限
+#quectel port
+/dev/ttyUSB* 0660 radio radio
+/dev/ttyACM* 0660 radio radio
+/dev/cdc-wdm* 0660 radio radio
+/dev/qcqmi* 0660 radio radio
/dev/cdc-acm* 0660 radio radio
#PCIe
/dev/mhi_DUN 0660 radio radio
/dev/mhi_DIAG 0660 radio radio
/dev/mhi_BHI 0660 radio radio
/dev/mhi_LOOPBACK 0660 radio radio
/dev/mhi_QMI0 0660 radio radio
+
# for mali-t764
EC20 相关库以及拨号脚本需要找模组供应商索要相关资料,包含 rild 拨号文件和相关依赖库;部分厂家资料比较齐全,已经写好 seLinux 文件。
特别注意:模组厂家的rild服务因权限不同导致 rild服务缺少 seLinux权限无法正常启动,建议先关闭 seLinux 调试 ;待上网成功后再处理 seLinux 权限
bootargs 增加关闭属性 androidboot.selinux=permissive
--- a/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-android.dtsi
@@ -49,7 +49,7 @@
compatible = "rockchip,android", "rockchip,rk3399";
chosen: chosen {
- bootargs = "earlycon=uart8250,mmio32,0xff1a0000 coherent_pool=1m";
+ bootargs = "earlycon=uart8250,mmio32,0xff1a0000 coherent_pool=1m androidboot.selinux=permissive";
};
kernel/security/commoncap.c
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1147,12 +1147,12 @@ int cap_task_setnice(struct task_struct *p, int nice)
static int cap_prctl_drop(unsigned long cap)
{
struct cred *new;
-
+/*
if (!ns_capable(current_user_ns(), CAP_SETPCAP))
return -EPERM;
if (!cap_valid(cap))
return -EINVAL;
-
+*/
new = prepare_creds();
diff --git a/BoardConfig.mk b/BoardConfig.mk
index 3706d7b7..8099919f 100755
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -59,7 +59,7 @@ BOARD_BOOT_HEADER_VERSION ?= 2
BOARD_MKBOOTIMG_ARGS :=
BOARD_PREBUILT_DTBOIMAGE ?= $(TARGET_DEVICE_DIR)/dtbo.img
BOARD_ROCKCHIP_VIRTUAL_AB_ENABLE ?= false
-BOARD_SELINUX_ENFORCING ?= true
+BOARD_SELINUX_ENFORCING ?= false
编译 userdebug
版本,可以在 root 用户下手动关闭
adb root;adb shell
setenforce 0 #关闭 seLinux
setenforce 1 #开启 seLinux
getenforce
permission #结果显示 已关闭 seLinux
Enforce #结果显示 已开启 seLinux
k3568 为 64bit CPU, 选用下载 rild 驱动包中 libquectel-ril\arm64-v8a\ 中 libreference-ril.so 拷贝到 device/rockchip/common/4g_modem/lib64/ 并重命名为 libreference-ril.ec20.so;
增加 ec20 拨号库拷贝命令和依赖库引用信息 device/rockchip/common/device.mk
diff --git a/device.mk b/device.mk
index 406f19b..c1b5dd3 100755
--- a/device.mk
+++ b/device.mk
@@ -274,11 +274,13 @@ PRODUCT_PROPERTY_OVERRIDES += \
ifeq ($(strip $(TARGET_ARCH)), arm64)
PRODUCT_PROPERTY_OVERRIDES += \
- vendor.rild.libpath=/vendor/lib64/librk-ril.so
+ vendor.rild.libargs=-d /dev/ttyUSB2 \
+ vendor.rild.libpath=/vendor/lib64/hw/libreference-ril.ec20.so
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/4g_modem/bin64/dhcpcd:$(TARGET_COPY_OUT_VENDOR)/bin/dhcpcd \
- $(LOCAL_PATH)/4g_modem/lib64/librk-ril.so:$(TARGET_COPY_OUT_VENDOR)/lib64/librk-ril.so
+ $(LOCAL_PATH)/4g_modem/lib64/librk-ril.so:$(TARGET_COPY_OUT_VENDOR)/lib64/librk-ril.so \
+ $(LOCAL_PATH)/4g_modem/lib64/libreference-ril.ec20.so:$(TARGET_COPY_OUT_VENDOR)/lib64/hw/libreference-ril.ec20.so
else
maniest 增加 HAL 属性信息
device/rockchip/common/4g_modem/manifest.xml
diff --git a/4g_modem/manifest.xml b/4g_modem/manifest.xml
index 9a19b3c..8c93c6b 100644
--- a/4g_modem/manifest.xml
+++ b/4g_modem/manifest.xml
@@ -2,6 +2,11 @@
<hal format="hidl">
<name>android.hardware.radio</name>
<transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ </interface>
<fqname>@1.1::IRadio/slot1</fqname>
<fqname>@1.1::IRadio/slot2</fqname>
<fqname>@1.2::ISap/slot1</fqname>
开启4G 模组相关平台宏定义
device/rockchip/rk356x/rk3566_r/BoardConfig.mk
BoardConfig.mk:18:BOARD_HAS_RK_4G_MODEM := true
rk3568 工具保存在 vendor/rockchip/common/phone 目录中为防止拨号工具不兼容单独增加目录存储 ec20 的相关工具。
rk3568 为 64bit CPU, 选用下载 rild 驱动包中 libquectel-ril\arm64-v8a\ 中 ip-up, ip-down, chat 文件,放到 vendor/rockchip/common/phone/etc/ppp64/ec20 (ec20 须手动创建)。
diff --git a/phone/phone.mk b/phone/phone.mk
index 285d016c..010f87b3 100755
--- a/phone/phone.mk
+++ b/phone/phone.mk
@@ -6,13 +6,13 @@ CUR_PATH := vendor/rockchip/common
#########################################################
ifeq ($(strip $(TARGET_ARCH)), arm64)
PRODUCT_COPY_FILES += \
- $(CUR_PATH)/phone/etc/ppp64/ip-down:system/etc/ppp/ip-down \
- $(CUR_PATH)/phone/etc/ppp64/ip-up:system/etc/ppp/ip-up \
+ $(CUR_PATH)/phone/etc/ppp64/ec20/ip-down:system/etc/ppp/ip-down \
+ $(CUR_PATH)/phone/etc/ppp64/ec20/ip-up:system/etc/ppp/ip-up \
$(CUR_PATH)/phone/etc/ppp/call-pppd:system/etc/ppp/call-pppd \
$(CUR_PATH)/phone/etc/operator_table:system/etc/operator_table \
- $(CUR_PATH)/phone/etc/ppp64/ip-down:system/bin/ip-down \
- $(CUR_PATH)/phone/etc/ppp64/ip-up:system/bin/ip-up \
- $(CUR_PATH)/phone/etc/ppp64/chat:system/bin/chat
+ $(CUR_PATH)/phone/etc/ppp64/ec20/ip-down:system/bin/ip-down \
+ $(CUR_PATH)/phone/etc/ppp64/ec20/ip-up:system/bin/ip-up \
+ $(CUR_PATH)/phone/etc/ppp64/ec20/chat:system/bin/chat
else
PRODUCT_COPY_FILES += \
$(CUR_PATH)/phone/etc/ppp/ip-down:system/etc/ppp/ip-down \
增加 4G modem 网络配置,否则看不到 SIM 卡图标和信号指示
device/rockchip/rk356x/overlay/frameworks/base/core/res/res/values/config.xml
<string-array translatable="false" name="networkAttributes">
<item>"wifi,1,1,2,-1,true"</item>
<item>"mobile,0,0,0,-1,true"</item>
<item>"mobile_mms,2,0,2,60000,false"</item>
<item>"mobile_supl,3,0,2,60000,true"</item>
<item>"mobile_dun,4,0,2,60000,true"</item>
<item>"mobile_hipri,5,0,3,60000,true"</item>
<item>"mobile_fota,10,0,2,60000,true"</item>
<item>"mobile_ims,11,0,2,60000,true"</item>
<item>"mobile_cbs,12,0,2,60000,true"</item>
<item>"bluetooth,7,7,0,-1,true"</item>
<item>"ethernet,9,9,9,-1,true"</item>
<item>"pppoe,15,15,5,-1,true"</item>
</string-array>
查看 LTE 模组运行状态方法
adb root;adb shell
getprop | grep gsm
[gsm.current.phone-type]: [1]
[gsm.network.type]: [LTE]
[gsm.operator.alpha]: [CHN-UNICOM]
[gsm.operator.iso-country]: [cn]
[gsm.operator.isroaming]: [false]
[gsm.operator.numeric]: [46001]
[gsm.sim.operator.alpha]: [China Unicom]
[gsm.sim.operator.iso-country]: [cn]
[gsm.sim.operator.numeric]: [46009]
[gsm.sim.state]: [LOADED]
[gsm.version.baseband]: [EC20CEFILGR06A05M1G]
[gsm.version.ril-impl]: [Quectel_Android_RIL_Driver_V3.3.80]
getprop | grep ril
[gsm.version.ril-impl]: [Quectel_Android_RIL_Driver_V3.3.80]
[init.svc.vendor.ril-daemon]: [running]
[init.svc_debug_pid.vendor.ril-daemon]: [912]
[persist.vendor.ril.gps.enable]: [true]
[ril.function.dataonly]: [1]
[ro.boot.noril]: [false]
[ro.boottime.vendor.ril-daemon]: [4665505471]
[vendor.rild.libargs]: [-d]
[vendor.rild.libpath]: [/vendor/lib64/hw/libreference-ril.ec20.so]
如果 rild 服务显示 stopped;可能因 selinux 权限问题,手动关闭 selinux 再重启 rild
可正常联网;原因定位到 缺少 selinux 权限,后面文章会讲 selinux 权限配置
。
stop vendor.ril-daemon #关闭 rild
start vendor.ril-daemon #开启 rild
init: Control message: Processed ctl.interface_start for '[email protected]::IRadio/slot1' from pid: 159 (/system/bin/hwservicemanager)
356x-rkr10/system/core$ git diff
diff --git a/init/init.cpp b/init/init.cpp
index 29859c5f5..2d0da56a0 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -421,8 +421,10 @@ static bool HandleControlMessage(std::string_view message, const std::string& na
return false;
}
- LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
- << "' from pid: " << from_pid << " (" << process_cmdline << ")";
+ if(strcmp(name.c_str(),"[email protected]::IRadio/slot1") != 0) {
+ LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
+ << "' from pid: " << from_pid << " (" << process_cmdline << ")";
+ }
return true;
}
HidlServiceManagement: Waited one second for [email protected]::IRadio/slot1
HidlServiceManagement: getService: Trying again for [email protected]::IRadio/slot1...
356x-rkr10/system/libhidl$ git diff
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index a7e9626..b0a8c84 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -626,7 +626,9 @@ struct Waiter : IServiceNotification {
break;
}
- LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName;
+ if(strcmp(mInterfaceName.c_str(),"[email protected]::IRadio") != 0) {
+ LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName;
+ }
} while (!timeout);
}
@@ -800,7 +802,9 @@ sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string&
if (vintfLegacy || !retry) break;
if (waiter != nullptr) {
- ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
+ if(strcmp(descriptor.c_str(),"[email protected]::IRadio") != 0) {
+ ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
+ }
waiter->wait(true /* timeout */);
}
}
hwservicemanager: Since [email protected]::IRadio/slot1 is not registered, trying to start it as a lazy HAL.
356x-rkr10/system/hwservicemanager$ git diff
diff --git a/ServiceManager.cpp b/ServiceManager.cpp
index 85d4974..be73f96 100644
--- a/ServiceManager.cpp
+++ b/ServiceManager.cpp
@@ -251,9 +251,11 @@ static void tryStartService(const std::string& fqName, const std::string& name)
// have an 'interface' entry in its .rc file OR if the service is already
// running, then this will be a no-op. So, for instance, if a service is
// deadlocked during startup, you will see this message repeatedly.
- LOG(INFO) << "Since " << fqName << "/" << name
- << " is not registered, trying to start it as a lazy HAL.";
+ if(strcmp(fqName.c_str(),"[email protected]::IRadio") != 0) {
+ LOG(INFO) << "Since " << fqName << "/" << name
+ << " is not registered, trying to start it as a lazy HAL.";
+ }
std::thread([=] {
(void)SetProperty("ctl.interface_start", fqName + "/" + name);
}).detach();
所谓的经验,只不过是坑填多了,某一刻开悟。