RK3568移远4G模块EC20

1 DTS

本dts的内容不是必须的,也可以自己手动拉gpio去操控。

  rk_modem: rk-modem {
    compatible="4g-modem-platdata";
    4G,vbat-gpio = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
    //4G,power-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
    4G,reset-gpio = <&gpio2 RK_PD7 GPIO_ACTIVE_HIGH>;
    status = "okay";
  };

对应的驱动为:kernel/drivers/net/lte/lte_rm310.c

2 内核驱动

新一点的内核(包含3568的4.19)都是已经包含了移远的option驱动的,无需再添加vid和pid。但是零包机制、电源管理以及第四个用于usbnet的口相关的代码还是有必要加上去的。即:

kernel/drivers/usb/serial/option.c

static struct usb_serial_driver option_1port_device = {
  .driver = {
    .owner =  THIS_MODULE,
    .name =    "option1",
  },
  .description       = "GSM modem (1-port)",
  .id_table          = option_ids,
  .num_ports         = 1,
  .probe             = option_probe,
  .open              = usb_wwan_open,
  .close             = usb_wwan_close,
  .dtr_rts     = usb_wwan_dtr_rts,
  .write             = usb_wwan_write,
  .write_room        = usb_wwan_write_room,
  .chars_in_buffer   = usb_wwan_chars_in_buffer,
  .tiocmget          = usb_wwan_tiocmget,
  .tiocmset          = usb_wwan_tiocmset,
  .ioctl             = usb_wwan_ioctl,
  .attach            = option_attach,
  .release           = option_release,
  .port_probe        = usb_wwan_port_probe,
  .port_remove     = usb_wwan_port_remove,
  .read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
  .suspend           = usb_wwan_suspend,
  .resume            = usb_wwan_resume,
+#if 1 //Added by Quectel
+  .reset_resume = usb_wwan_resume,
+#endif
#endif
};

static int option_probe(struct usb_serial *serial,
      const struct usb_device_id *id)
{
  struct usb_interface_descriptor *iface_desc =
        &serial->interface->cur_altsetting->desc;
  unsigned long device_flags = id->driver_info;

  /* Never bind to the CD-Rom emulation interface  */
  if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
    return -ENODEV;

  /*
   * Don't bind reserved interfaces (like network ones) which often have
   * the same class/subclass/protocol as the serial interfaces.  Look at
   * the Windows driver .INF files for reserved interface numbers.
   */
  if (iface_is_reserved(device_flags, iface_desc->bInterfaceNumber))
    return -ENODEV;

  /*
   * Allow matching on bNumEndpoints for devices whose interface numbers
   * can change (e.g. Quectel EP06).
   */
  if (device_flags & NUMEP2 && iface_desc->bNumEndpoints != 2)
    return -ENODEV;

+#if 1 //Added by Quectel
+  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

  /* Store the device flags so we can use them during attach. */
  usb_set_serial_data(serial, (void *)device_flags);

  return 0;
}

rk3568/kernel/drivers/usb/serial/usb_wwan.c

static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
              int endpoint,
              int dir, void *ctx, char *buf, int len,
              void (*callback) (struct urb *))
{
  struct usb_serial *serial = port->serial;
  struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
  struct urb *urb;
  struct usb_device_descriptor *desc = &serial->dev->descriptor;

  urb = usb_alloc_urb(0, GFP_KERNEL);  /* No ISO */
  if (!urb)
    return NULL;

  usb_fill_bulk_urb(urb, serial->dev,
        usb_sndbulkpipe(serial->dev, endpoint) | dir,
        buf, len, callback, ctx);

  if (intfdata->use_zlp && dir == USB_DIR_OUT)
    urb->transfer_flags |= URB_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 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;
}

添加好虚拟出的各个串口后,要加入usbnet的驱动,可以使用GobiNet或者wwan。Gobinet是以前Linux内核没有添加相关驱动时的产物。目前使用wwan比较多。找到移远提供的qmai_wwan_q.c放入kernel/drivers/net/usb文件夹下,并修改Makefile:

+obj-$(CONFIG_USB_NET_QMI_WWAN)  += qmi_wwan_q.o #最好放在qmi_wwan.o之前
obj-$(CONFIG_USB_NET_QMI_WWAN)  += qmi_wwan.o

此驱动会生成wwan0(用ifconfig -a可以看到),以及/dev/cdc-wdm0设备。在Android中,需要修改部分代码才可以添加此设备:

rk3568/system/core/init/devices.cpp

void DeviceHandler::HandleUevent(const Uevent& uevent) {
    ...
    if (uevent.subsystem == "block") {
        block = true;
        devpath = "/dev/block/" + Basename(uevent.path);

        if (StartsWith(uevent.path, "/devices")) {
            links = GetBlockDeviceSymlinks(uevent);
        }
    } else if (const auto subsystem =
                   std::find(subsystems_.cbegin(), subsystems_.cend(), uevent.subsystem);
               subsystem != subsystems_.cend()) {
        devpath = subsystem->ParseDevPath(uevent);
    } else if (uevent.subsystem == "usb") {
        if (!uevent.device_name.empty()) {
            devpath = "/dev/" + uevent.device_name;
        } else {
            // This imitates the file system that would be created
            // if we were using devfs instead.
            // Minors are broken up into groups of 128, starting at "001"
            int bus_id = uevent.minor / 128 + 1;
            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;
    } else {
        devpath = "/dev/" + Basename(uevent.path);
    }
  ...
}


至于ECM等驱动也都是usbnet使用的,可以选择不添加。

3 Android

3.1 复制文件

首先要找到FAE要到适合自己android版本的对应的资料,其中包括文档、ril库等。

将libreference-ril.so拷贝并改名为:vendor/rockchip/common/phone/lib/libreference-ril-quel.so

将ql-ril.conf拷贝至:vendor/rockchip/common/phone/lib/ql-ril.conf

3.2 设置资源文件将复制的目标路径

rk3568/vendor/rockchip/common/phone/phone.mk

#########################################################
#   3G Dongle SUPPORT
#########################################################
#PRODUCT_COPY_FILES += \
    $(CUR_PATH)/phone/etc/ppp/ip-down:system/etc/ppp/ip-down \
    $(CUR_PATH)/phone/etc/ppp/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
PRODUCT_COPY_FILES += \
     $(CUR_PATH)/phone/lib/libreference-ril-quel.so:vendor/lib64/libreference-ril-quel.so \
      $(CUR_PATH)/phone/lib/ql-ril.conf:system/etc/ql-ril.conf

3.3 SELINUX和rild服务

selinux部分需要注意的是通常文件最后需要有一个空行作为结尾。

device/rockchip/common/ueventd.rockchip.rc

+/dev/ttyACM*              0660   radio    radio
+/dev/cdc-wdm*              0660   radio    radio
+/dev/qcqmi*              0660   radio    radio
+/dev/cdc-acm*              0660   radio    radio
+/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
+
device/rockchip/common/sepolicy/private/file_contexts

+/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
+
system/sepolicy/vendor/rild.te

+allow rild self:packet_socket { create bind write read };
+

对应rild可以修改为:

rk3568/hardware/ril/rild/rild.rc

-#service vendor.ril-daemon /vendor/bin/hw/rild
-#    class main
-#    user radio
-#    group radio cache inet misc audio log readproc wakelock
-#    capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW

+service ril-daemon /vendor/bin/hw/rild -l /vendor/lib64/libreference-ril-quel.so
+    class main
+    user radio
+    group radio cache inet misc audio sdcard_rw log
+    capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW

3.4 修改BoardConfig.mk

SDK默认4G和dongle是关闭的,需要开启:

device/rockchip/common/BoardConfig.mk

-BOARD_HAS_RK_4G_MODEM ?= false
+BOARD_HAS_RK_4G_MODEM ?= true
-BOARD_HAVE_DONGLE ?= false
+BOARD_HAVE_DONGLE ?= true

external/usb_modeswitch/usb_dongle/Android.mk

-#common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-*

3.5 修改device.mk

rk3568/device/rockchip/rk356x/device.mk

PRODUCT_PROPERTY_OVERRIDES += \
                ro.ril.ecclist=112,911 \
                ro.opengles.version=196610 \
                wifi.interface=wlan0 \
+                rild.libpath=/vendor/lib64/libreference-ril-quel.so    \
+                rild.libargs=-d /dev/ttyUSB2    \
rk3568/device/rockchip/common/device.mk

ifeq ($(strip $(BOARD_HAS_RK_4G_MODEM)),true)
PRODUCT_PACKAGES += \
    CarrierDefaultApp \
    CarrierConfig \
    rild \
-      librk-ril\
+    libreference-ril-quel   \
    dhcpcd

PRODUCT_COPY_FILES += vendor/rockchip/common/phone/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml

PRODUCT_PACKAGES += \
    android.hardware.radio@1.2-radio-service \
    android.hardware.radio.config@1.0-service

PRODUCT_PROPERTY_OVERRIDES += \
    ro.boot.noril=false \
    ro.telephony.default_network=9

ifeq ($(strip $(TARGET_ARCH)), arm64)
PRODUCT_PROPERTY_OVERRIDES += \
-     vendor.rild.libpath=/vendor/lib64/librk-ril.so
+    vendor.rild.libpath=/vendor/lib64/libreference-ril-quel.so

3.6 修改manifest.xml

device/rockchip/common/4g_modem/manifest.xml

    <hal format="hidl">
        <name>android.hardware.radio.deprecated</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>IOemHook</name>
            <instance>slot1</instance>
        </interface>
    </hal>
    <hal format="hidl">
-          <name>android.hardware.radio.config</name>
+        <name>android.hardware.radio</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
-            <name>IRadioConfig</name>
+            <name>IRadio</name>
-            <instance>default</instance>
+            <instance>slot1</instance>
+        </interface>
    </hal>
</manifest>

3.7 启动脚本去掉ril-daemon

device/rockchip/common/init.rk30board.rc

# for telephony function
-#on property:ro.boot.noril=true
-#    setprop ro.radio.noril true
-#   stop ril-daemon

3.8使能电话进程

3.8.1 设置→网络和互联网里没有“移动网络”选项

rk3568/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>
  </string-array>

3.8.2 移动网络里没有APN选项

rk3568/device/rockchip/common/overlay/frameworks/base/core/res/res/values/config.xml

-<bool name="config_voice_capable">false</bool>
+<bool name="config_voice_capable">true</bool>

3.8.3 移动信号图无信号

rk3568/vendor/rockchip/common/phone/lib/ql-ril.conf
# 打开如下选项
LTE_Is_Report_SignalStrength=1

4 调试方式

4.1 内核

ls /dev/ | grep ttyUSB   // 可以看到ttyUSB0-3说明成功注册上option驱动,其中/dev/ttyUSB2为AT指令口,可以收发AT指令。

ifconfig -a  //如果可以看到wwan0则成功注册了 qmi_wwan驱动
# 如果正在运行rild可能导致抢AT指令资源,可以通过stop ril-daemon来先停止此服务

# AT指令简单的测试
> microcom /dev/ttyUSB2
ate1
AT
OK  //看到OK说明AT指令收发成功

4.2 logcat

logcat -b radio  // ril log
logcat -c -b radio // 清除之前的log

5 参考文档

移远官方:

Quectel_UMTS_LTE_5G_Linux_USB_Driver_User_Guide_V3.0

Android RILDriver User Guide

RK官方:

Rockchip_RM310_4G模块配置说明

Rockchip_Introduction_3G_Dongle_Configuration_CN&EN

他人博客:

RK3568-ANDROID11-4G-EC20-(详细步骤)_旋风旋风的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值