赞
踩
本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
新一点的内核(包含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使用的,可以选择不添加。
首先要找到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
- 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
-
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
-
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-*
-
- 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
-
- 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>
-
- device/rockchip/common/init.rk30board.rc
-
- # for telephony function
- -#on property:ro.boot.noril=true
- -# setprop ro.radio.noril true
- -# stop ril-daemon
-
- 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>
- 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>
-
- rk3568/vendor/rockchip/common/phone/lib/ql-ril.conf
- # 打开如下选项
- LTE_Is_Report_SignalStrength=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指令收发成功
-
- logcat -b radio // ril log
- logcat -c -b radio // 清除之前的log
-
移远官方:
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
他人博客:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。