RK3588 Android13 RM500U-CN移植

1. Kernel修改

1.1 根据原理图配置引脚

参考lte_rm310配置

 Rockchip 4g modem device tree bindings

Required properties:
- compatible : "4g-modem-platdata"

Optional properties:
- 4G,vbat-gpio : 4g modem vbat gpio
- 4G,power-gpio : 4g modem power enable/disable gpio
- 4G,reset-gpio : 4g modem reset gpio

Example:

        4G-Modem {
                compatible="4g-modem-platdata";
                4G,vbat-gpio = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
                4G,power-gpio = <&gpio0 RK_PC0 GPIO_ACTIVE_LOW>;
                4G,reset-gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_LOW>;
        }

若走Pcie协议,还需要配置Pcie相关dts

1.2 添加RM500U-CN vid pid

--- a/kernel-5.10/drivers/usb/serial/option.c
+++ b/kernel-5.10/drivers/usb/serial/option.c
@@ -1183,6 +1183,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x0900, 0xff, 0x00, 0x00) },

        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
@@ -2230,6 +2231,10 @@ static struct usb_serial_driver option_1port_device = {
        .suspend           = usb_wwan_suspend,
        .resume            = usb_wwan_resume,
 #endif
+#if 1 //Added by Quectel
+        .reset_resume = usb_wwan_resume,
+#endif
+
 };

--- a/kernel-5.10/drivers/usb/serial/usb_wwan.c
+++ b/kernel-5.10/drivers/usb/serial/usb_wwan.c
@@ -481,6 +481,14 @@ 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) {
+               struct usb_device_descriptor *desc = &serial->dev->descriptor;
+
+               if (desc->idVendor == cpu_to_le16(0x2C7C))
+                       urb->transfer_flags |= URB_ZERO_PACKET;
+       }
+#endif
        return urb;
 }

1.3 增加qmi_wwan_q驱动

移远提供的驱动:Quectel_Linux_Android_QMI_WWAN_Driver_V1.2.6.zip

--- a/kernel-5.10/drivers/net/usb/Makefile
+++ b/kernel-5.10/drivers/net/usb/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_USB_NET_CX82310_ETH)     += cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)  += cdc_ncm.o
 obj-$(CONFIG_USB_NET_HUAWEI_CDC_NCM)   += huawei_cdc_ncm.o
 obj-$(CONFIG_USB_VL600)                += lg-vl600.o
+obj-$(CONFIG_USB_NET_QMI_WWAN)  += qmi_wwan_q.o
 obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
 obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
 obj-$(CONFIG_USB_NET_CH9200)   += ch9200.o

1.4 添加PCIe驱动

将驱动压缩包 Quectel_Linux&Android_SPRD_PCIE_Driver 解压至 Linux 源码 drivers
目录下,并在该目录下的 Makefile 文件中添加如下内容后直接编译即可。
若 PCIe 驱动被正确移植并编译成功,上位机设备的 dev 目录下会生成 spipe_nr0-14、stty_nr0-31、
snv_nr、slog_nr 和 sdiag_nr 等设备节点,同时生成 pciex(网卡名称,“x”的范围为 0~3)、sipa_dummy
等网卡。

2. Android修改

2.1 配置ril-daemon

--- a/hardware/ril/rild/rild.rc
+++ b/hardware/ril/rild/rild.rc
@@ -1,5 +1,5 @@
-service vendor.ril-daemon /vendor/bin/hw/rild
+service ril-daemon /vendor/bin/hw/rild -l /vendor/lib64/hw/libreference-ril-quectel.so
     class main
-    user radio
-    group radio cache inet misc audio log readproc wakelock
+    user root
+    group radio cache inet misc audio sdcard_rw log
     capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW

2.2 配置IRadio

--- a/device/rockchip/common/4g_modem/manifest.xml
+++ b/device/rockchip/common/4g_modem/manifest.xml
@@ -4,6 +4,7 @@
         hwbinder
         @1.1::IRadio/slot1
         @1.1::IRadio/slot2
+        @1.5::IRadio/slot1
         @1.2::ISap/slot1
     
     

--- a/device/rockchip/common/BoardConfig.mk
+++ b/device/rockchip/common/BoardConfig.mk
@@ -297,7 +297,7 @@ BOARD_FORCE_UDISK_VISIBLE ?= true
 BOARD_DISABLE_SAFE_MODE ?= true

 #enable 3g dongle
-BOARD_HAVE_DONGLE ?= false
+BOARD_HAVE_DONGLE ?= true

 #for boot and shutdown animation ringing
 BOOT_SHUTDOWN_ANIMATION_RINGING ?= false
@@ -328,7 +328,7 @@ BOARD_BLUETOOTH_LE_SUPPORT ?= true
 BOARD_WIFI_SUPPORT ?= true

 #for rk 4g modem
-BOARD_HAS_RK_4G_MODEM ?= false
+BOARD_HAS_RK_4G_MODEM ?= true

 #for rk DLNA
 PRODUCT_HAVE_DLNA ?= false

--- a/device/rockchip/common/modules/4g_modem.mk
+++ b/device/rockchip/common/modules/4g_modem.mk
@@ -27,6 +27,15 @@ PRODUCT_PACKAGES += \
     [email protected] \
     [email protected]

+PRODUCT_PACKAGES += \
+    [email protected] \
+    [email protected] \
+    [email protected] \
+    [email protected] \
+    [email protected] \
+    [email protected] \
+    libhwbinder.vendor

2.3 配置SELinux 权限

1.AT拨号权限
--- a/device/rockchip/common/rootdir/ueventd.rockchip.rc
+++ b/device/rockchip/common/rootdir/ueventd.rockchip.rc
@@ -79,6 +79,25 @@
 /dev/ttyUSB8              0660   radio         radio
 /dev/ttyUSB9              0660   radio         radio

+#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
+
+/dev/stty_nr*             0660   radio         radio
+/dev/spipe_nr*            0660   radio         radio
+/dev/snv_nr               0660   radio         radio
+/dev/sdiag_nr             0660   radio         radio
+/dev/slog_nr              0660   radio         radio

2.  selinux 权限 
--- a/device/rockchip/common/sepolicy/private/file_contexts
+++ b/device/rockchip/common/sepolicy/private/file_contexts
@@ -3,3 +3,17 @@

 # All Rockchip configs
 /data/misc/cfg_rockchip(/.*)?                   u:object_r:rockchip_config_data_file:s0
+
+# quectel port
+/dev/ttyUSB[0-9] u:object_r:radio_device:s0
+/dev/ttyACM[0-9] u:object_r:radio_device:s0
+/dev/cdc-wdm[0-9] u:object_r:radio_device:s0
+/dev/qcqmi[0-9] u:object_r:radio_device:s0
+/vendor/bin/hw/rild u:object_r:rild_exec:s0
+/dev/socket/rildOemHook u:object_r:rild_socket:s0
+#PCIe
+/dev/mhi_DUN u:object_r:radio_device:s0
+/dev/mhi_DIAG u:object_r:radio_device:s0
+/dev/mhi_BHI u:object_r:radio_device:s0
+/dev/mhi_LOOPBACK u:object_r:radio_device:s0
+/dev/mhi_QMI0 u:object_r:radio_device:s0

3.rild.te文件
--- a/system/sepolicy/vendor/rild.te
+++ b/system/sepolicy/vendor/rild.te
@@ -6,4 +6,7 @@ net_domain(rild)
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 type rild_exec, exec_type, vendor_file_type, file_type;
+
+allow rild self:packet_socket { create bind write read };
+
 init_daemon_domain(rild)

4. 修改usb节点名称
system/core
--- a/system/core/init/devices.cpp
+++ b/system/core/init/devices.cpp
@@ -550,6 +550,12 @@ 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")) {
         // ignore other USB events
         return;

2.4 添加libreference.so

移远提供ril库: Quectel_Android_RIL_Driver_V3.5.66.zip

--- a/vendor/rockchip/common/phone/phone.mk
+++ b/vendor/rockchip/common/phone/phone.mk
@@ -17,6 +17,11 @@ PRODUCT_COPY_FILES += \
     $(CUR_PATH)/phone/lib/libril-dts4108c.so:system/lib/libril.so
 endif

+PRODUCT_COPY_FILES += \
+    $(CUR_PATH)/phone/lib/libreference-ril-quectel.so:vendor/lib64/hw/libreference-ril-quectel.so \
+    $(CUR_PATH)/phone/lib/libril.so:vendor/lib64/libril.so \
+    $(CUR_PATH)/phone/etc/ql-ril.conf:system/etc/ql-ril.conf
+

3. 编译及运行报错处理

3.1 [email protected]::IRadio相关报错

相关报错:init: Control message: Could not find '[email protected]::IRadio/slot1' for ctl.interface_start from pid: 149 (/system/bin/hwservicemanager)

--- a/system/core/init/init.cpp
+++ b/system/core/init/init.cpp
@@ -435,9 +435,13 @@ static bool HandleControlMessage(std::string_view message, const std::string& na
         service = ServiceList::GetInstance().FindService(name);
     }

+    char tmp[256];
+    strcpy(tmp,name.c_str());
     if (service == nullptr) {
-        LOG(ERROR) << "Control message: Could not find '" << name << "' for ctl." << message
+        if(strcmp(tmp,"[email protected]::IRadio/slot1")!= 0){
+             LOG(ERROR) << "Control message: Could not find '" << name << "' for ctl." << message
                    << " from pid: " << from_pid << " (" << process_cmdline << ")";
+       }
         return false;
     }

@@ -456,6 +460,9 @@ static bool HandleControlMessage(std::string_view message, const std::string& na
         return false;
     }

+    if(strcmp(tmp,"[email protected]::IRadio/slot1")== 0)
+        return true;
+
     LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
               << "' from pid: " << from_pid << " (" << process_cmdline << ")";
     return true;

--- a/system/hwservicemanager/ServiceManager.cpp
+++ b/system/hwservicemanager/ServiceManager.cpp
@@ -251,15 +251,19 @@ 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
+    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([=] {
         if (!SetProperty("ctl.interface_start", fqName + "/" + name)) {
-            LOG(INFO) << "Tried to start " << fqName << "/" << name
+            if(strcmp(fqName.c_str(),"[email protected]::IRadio")!= 0){
+                LOG(INFO) << "Tried to start " << fqName << "/" << name
                       << " as a lazy service, but was unable to. Usually this happens when a "
                          "service is not installed, but if the service is intended to be used as a "
                          "lazy service, then it may be configured incorrectly.";
+               }
         }
     }).detach();
 }

--- a/system/libhidl/transport/ServiceManagement.cpp
+++ b/system/libhidl/transport/ServiceManagement.cpp
@@ -661,7 +661,8 @@ 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);
     }

@@ -746,6 +747,17 @@ sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string&

     sp sm;
     Transport transport = Transport::EMPTY;
+
+   if((access("dev/cdc-wdm0",F_OK))!=-1){
+        ALOGD("dev file  dev/cdc-wdm0 exist.");
+    } else{
+        if(strcmp(descriptor.c_str(),"[email protected]::IRadio") == 0 || strcmp(descriptor.c_str(),"[email protected]::IRadio") == 0 || \
+           strcmp(descriptor.c_str(),"[email protected]::IOemHook")== 0) {
+            ALOGD("dev file  dev/cdc-wdm0 is not exist.");
+            return nullptr;
+        }
+    }
+
     if (kIsRecovery) {
         transport = Transport::PASSTHROUGH;
     } else {
@@ -813,7 +825,8 @@ 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 */);
         }
     }

--- a/hardware/interfaces/compatibility_matrices/compatibility_matrix.7.xml
+++ b/hardware/interfaces/compatibility_matrices/compatibility_matrix.7.xml
@@ -524,6 +524,57 @@
             default
         
     
+    
+        android.hardware.radio
+        1.1
+        1.2
+        1.3
+        1.4
+        1.5
+        1.6
+        
+            IRadio
+            slot1
+            slot2
+            slot3
+        
+    
+    
+        android.hardware.radio
+        1.2
+        
+            ISap
+            slot1
+        
+       
+    
+       android.hardware.radio.deprecated
+        1.0
+        
+        IOemHook
+        slot1
+        
+    
+    
+        android.hardware.radio.config
+        
+               1.0
+        1.1
+        
+            IRadioConfig
+            default
+        
+    
+    
+        android.hardware.radio.config
+        1.3
+        
+            IRadioConfig
+            default
+        
+    
     
         android.hardware.radio.data
         1

3.2 打开BOARD_HAVE_DONGLE 和BOARD_HAS_RK_4G_MODEM,usb_modeswitch编译异常

--- a/external/usb_modeswitch/usb_dongle/Android.mk
+++ b/external/usb_modeswitch/usb_dongle/Android.mk
@@ -19,7 +19,7 @@ common_shared_libraries := \

 common_cflags := -Werror -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter

-common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-*
+#common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-*
 common_local_tidy_checks := -*,clang-analyzer-security*,cert-*,-cert-err34-c,-cert-err58-cpp
 common_local_tidy_checks += ,-cert-env33-c

diff --git a/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c b/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c
index ba5be82ad5..c4dde8f797 100644
--- a/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c
+++ b/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c
@@ -509,8 +509,8 @@ int main(int argc, char **argv)
                exit(1);
        }

-       if (verbose)
-               libusb_set_debug(ctx, 3);
+       //if (verbose)
+               //libusb_set_debug(ctx, 3);

        if (mbim) {
                printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) );

若添加移远 libril.so编译报错
rename from hardware/ril/libril/Android.mk to hardware/ril/libril/Android.mk.bk

4. 上网验证

注意:仅当模块在 PCIe EP 模式下时,方可实现发送 AT 命令、抓取日志、拨号上网等功能。若模块处于RC 模式,执行 AT+QCFG=“pcie/mode”,0 并重启模块将 PCIe 模式切换至 EP 模式。以 RG500U-CN 模块为例,设备 ID 为 0x16c3,0xabcd,如正确识别到模块的设备 ID,则表示 PCIe 模式切换成功。

USB协议拨号上网:
RK3588 Android13 RM500U-CN移植_第1张图片
PCie协议拨号上网
RK3588 Android13 RM500U-CN移植_第2张图片

你可能感兴趣的:(android)