赞
踩
目录
Android.mk(在 runtime-ril-port 目录下)
这个补丁是我加在全志A40 4.4上面的做模块动态适配的 , 毋庸置疑 后面的Android 版本也是适用的 , 比如rockchip 也是没问题的 只是我懒得搞了而已。
调试4G模块非常简单 只是说早期模块经常切换 , 换了还得换固件 , 固件其实只是更换了so库而已。因为kernel driver 已经对vid/pid进行了适配。
这个补丁是直接在hal 层rild 做的vid/pid 然后选择so库文件的。
这个补丁主要修改了 Android RIL (Radio Interface Layer) 的部分代码,以支持动态切换不同的 3G/4G 模块。
android/hardware/ril/include/runtime/runtime.h
android/hardware/ril/rild/Android.mk
android/hardware/ril/rild/rild.c
android/hardware/ril/runtime-ril-port/Android.mk
android/hardware/ril/runtime-ril-port/runtime_port.c
runtime.h
这是一个新文件,定义了一些函数和变量,用于启动 uevent 监视器,获取当前的 3G 端口设备,数据和类型。
Android.mk
(在 rild 目录下)在这个 makefile 文件中,添加了 libruntime-ril-port
到 LOCAL_SHARED_LIBRARIES
,这样 rild 就可以链接到这个新的库。
rild.c
这个文件中的修改主要是在 rild 的主函数中,添加了对 3G 模块类型的检测,并根据检测到的模块类型,动态地设置 RIL 库的路径。此外,还添加了对 uevent 的监视,当检测到 3G 模块的变化时,会重新启动 rild。
Android.mk
(在 runtime-ril-port 目录下)这是一个新文件,用于编译 runtime_port.c
,生成 libruntime-ril-port
库。
runtime_port.c
这是一个新文件,实现了在 runtime.h
中定义的函数。这些函数主要用于检测当前的 3G 模块类型,以及启动对 uevent 的监视。
runtime_port.c
中的 modem_3g_device_table
。- diff --git a/android/hardware/ril/include/runtime/runtime.h b/android/hardware/ril/include/runtime/runtime.h
- new file mode 100755
- index 0000000000..c381b4f2f8
- --- /dev/null
- +++ b/android/hardware/ril/include/runtime/runtime.h
- @@ -0,0 +1,22 @@
- +/*
- + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
- + */
- +
- +#ifndef RUNTIME_H
- +#define RUNTIME_H
- +
- +extern int start_uevent_monitor(void);
- +extern const char *runtime_3g_port_device(void);
- +extern const char *runtime_3g_port_data(void);
- +extern int runtime_3g_port_type(void);
- +enum {
- + ME909S_MODEM = 0,
- + U9300C_MODEM,
- + EC20_MODEM,
- + EM8000_MODEM,
- + UNKNOWN_MODEM,
- +};
- +
- +extern int current_modem_type;
- +
- +#endif
- diff --git a/android/hardware/ril/rild/Android.mk b/android/hardware/ril/rild/Android.mk
- index d8ca6d368d..83c0a1a130 100755
- --- a/android/hardware/ril/rild/Android.mk
- +++ b/android/hardware/ril/rild/Android.mk
- @@ -13,7 +13,8 @@ LOCAL_SHARED_LIBRARIES := \
- liblog \
- libcutils \
- libril \
- - libdl
- + libdl \
- + libruntime-ril-port
-
- # temporary hack for broken vendor rils
- #LOCAL_WHOLE_STATIC_LIBRARIES := \
- diff --git a/android/hardware/ril/rild/rild.c b/android/hardware/ril/rild/rild.c
- index 4a555f275c..e79cd3cb71 100755
- --- a/android/hardware/ril/rild/rild.c
- +++ b/android/hardware/ril/rild/rild.c
- @@ -36,10 +36,19 @@
- #include "hardware/qemu_pipe.h"
-
- #include "radio_monitor.h"
- -
- +#include <runtime/runtime.h>
- #define LIB_PATH_PROPERTY "rild.libpath"
- #define LIB_ARGS_PROPERTY "rild.libargs"
- #define MAX_LIB_ARGS 16
- +#define MAX_POLL_DEVICE_CNT 8
- +
- +
- +
- +
- +#define REFERENCE_RIL_ME909S_PATH "/system/lib/libreference_me909s-ril.so"
- +#define REFERENCE_RIL_U9300C_PATH "/system/lib/libreference_u9300c-ril.so"
- +#define REFERENCE_RIL_EC20_PATH "/system/lib/libreference_ec20-ril.so"
- +#define REFERENCE_RIL_EM8000_PATH "/system/lib/libreference_em8000-ril.so"
-
- static void usage(const char *argv0)
- {
- @@ -64,6 +73,7 @@ static struct RIL_Env s_rilEnv = {
- RIL_onUnsolicitedResponse,
- RIL_requestTimedCallback
- };
- +static int s_poll_device_cnt = 0;
-
- extern void RIL_startEventLoop();
-
- @@ -109,44 +119,21 @@ int main(int argc, char **argv)
- char libPath[PROPERTY_VALUE_MAX];
- unsigned char hasLibArgs = 0;
- int ret = 0;
- + int modem_type = UNKNOWN_MODEM;
- int i;
- char platform[PROPERTY_VALUE_MAX] = {0};
-
- //is telephony platform?
- if(property_get("ro.sw.embeded.telephony", platform, NULL)){
- if(strcmp(platform, "true")) {
- - RLOGI("platform: wifi-only");
- + RLOGI("platform: wifi-only --1");
- radio_monitor();
- }else{
- - RLOGI("platform: telephony");
- + RLOGI("platform: telephony --2");
- }
- }
-
- -#if 0
- - umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
- - for (i = 1; i < argc ;) {
- - if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
- - rilLibPath = argv[i + 1];
- - i += 2;
- - } else if (0 == strcmp(argv[i], "--")) {
- - i++;
- - hasLibArgs = 1;
- - break;
- - } else {
- - usage(argv[0]);
- - }
- - }
-
- - if (rilLibPath == NULL) {
- - if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
- - // No lib sepcified on the command line, and nothing set in props.
- - // Assume "no-ril" case.
- - goto done;
- - } else {
- - rilLibPath = libPath;
- - }
- - }
- -#else
- ret = property_get(LIB_PATH_PROPERTY, libPath, NULL);
- if (ret <= 0) {
- /* nothing to do */
- @@ -174,9 +161,62 @@ int main(int argc, char **argv)
- RLOGD("err: get rilLibPath failed\n");
- goto done;
- }
- + ///$shh$20180906$add$Dynamic switching module$
- + //Wait for device ready.
- + // if (rilLibPath == NULL) {
- + while(UNKNOWN_MODEM == modem_type){
- + modem_type = runtime_3g_port_type();
- + ALOGD("111 -Couldn't find proper modem, retrying...");
- + s_poll_device_cnt++;
- + if (s_poll_device_cnt > MAX_POLL_DEVICE_CNT){
- + /*
- + *Maybe no device right now, start to monitor
- + *hotplug event later.
- + */
- + start_uevent_monitor();
- + goto done;
- + }
- + sleep(5);
- + }
- + //}
-
- -#endif
- - RLOGD("\nrilLibPath = %s\n\n", rilLibPath);
- + start_uevent_monitor();
- +
- + switch (modem_type){
- + case ME909S_MODEM:
- + {
- + rilLibPath = REFERENCE_RIL_ME909S_PATH;
- + break;
- + }
- + case U9300C_MODEM:
- + {
- + rilLibPath = REFERENCE_RIL_U9300C_PATH;
- + break;
- + }
- + case EC20_MODEM:
- + {
- + rilLibPath = REFERENCE_RIL_EC20_PATH;
- + break;
- + }
- + case EM8000_MODEM:
- + {
- + rilLibPath = REFERENCE_RIL_EM8000_PATH;
- + printf("");
- + break;
- + }
- +
- + if (rilLibPath == NULL) {
- + if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
- + // No lib sepcified on the command line, and nothing set in props.
- + // Assume "no-ril" case.
- + goto done;
- + } else {
- + rilLibPath = libPath;
- + }
- + }
- + }
- + RLOGD("shh->rilLibPath:%s,modem_type=%d",rilLibPath,modem_type);
- + ///$shh$20180906$add$Dynamic switching module$
-
- /* special override when in the emulator */
- #if 0 //ignore this by SW
- diff --git a/android/hardware/ril/runtime-ril-port/Android.mk b/android/hardware/ril/runtime-ril-port/Android.mk
- new file mode 100755
- index 0000000000..fdf21f4844
- --- /dev/null
- +++ b/android/hardware/ril/runtime-ril-port/Android.mk
- @@ -0,0 +1,19 @@
- +# Copyright 2006 The Android Open Source Project
- +
- +LOCAL_PATH:= $(call my-dir)
- +include $(CLEAR_VARS)
- +
- +LOCAL_SRC_FILES:= \
- + runtime_port.c
- +
- +LOCAL_SHARED_LIBRARIES := \
- + libutils \
- + libcutils
- +
- +LOCAL_CFLAGS :=
- +
- +LOCAL_MODULE_TAGS := optional
- +LOCAL_MODULE:= libruntime-ril-port
- +
- +
- +include $(BUILD_SHARED_LIBRARY)
- diff --git a/android/hardware/ril/runtime-ril-port/runtime_port.c b/android/hardware/ril/runtime-ril-port/runtime_port.c
- new file mode 100755
- index 0000000000..f7682c7df1
- --- /dev/null
- +++ b/android/hardware/ril/runtime-ril-port/runtime_port.c
- @@ -0,0 +1,452 @@
- +/*
- + * Licensed under the Apache License, Version 2.0 (the "License");
- + * you may not use this file except in compliance with the License.
- + * You may obtain a copy of the License at
- + *
- + * http://www.apache.org/licenses/LICENSE-2.0
- + *
- + * Unless required by applicable law or agreed to in writing, software
- + * distributed under the License is distributed on an "AS IS" BASIS,
- + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- + * See the License for the specific language governing permissions and
- + * limitations under the License.
- + */
- +
- +/*
- + * Copyright 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
- + */
- +
- +#include <stdio.h>
- +#include <string.h>
- +#include <stdlib.h>
- +#include <dirent.h>
- +#include <errno.h>
- +#include <fcntl.h>
- +#define LOG_TAG "RIL"
- +#include <utils/Log.h>
- +
- +#include <pthread.h>
- +#include <sys/types.h>
- +#include <sys/socket.h>
- +#include <sys/poll.h>
- +#include <linux/netlink.h>
- +
- +#include <signal.h>
- +#include <unistd.h>
- +#include <runtime/runtime.h>
- +
- +int current_modem_type = UNKNOWN_MODEM;
- +
- +#define FAKE_PORT "/dev/ttyFAKEPort"
- +/* Rild need a fake port to pass continue init job,
- + * return a fake port make it runable.
- + * Or the system will enter 15s in early suspend.
- + */
- +
- +struct modem_3g_device {
- + const char *idVendor;
- + const char *idProduct;
- + const char *deviceport; /* sending AT command */
- + const char *dataport; /* sending 3g data */
- + const char *name;
- + const int type;
- +};
- +
- +#define PATH_SIZE 1024
- +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
- +static const char *USB_DIR_BASE = "/sys/bus/usb/devices/";
- +
- +static struct modem_3g_device modem_3g_device_table[] = {
- +
- + {
- + .name = "ME909S_MODEM",
- + .idVendor = "12d1",
- + .idProduct = "15c1",
- + .deviceport = "/dev/ttyUSB0",
- + .dataport = "/dev/ttyUSB2",
- + .type = ME909S_MODEM,
- + },
- +
- +
- + {
- + .name = "U9300C_MODEM",
- + .idVendor = "1c9e",
- + .idProduct = "9b3c",
- + .deviceport = "/dev/ttyUSB1",
- + .dataport = "/dev/ttyUSB2",
- + .type = U9300C_MODEM,
- + },
- + {
- + .name = "EC20_MODEM",
- + .idVendor = "2c7c",
- + .idProduct = "0125",
- + .deviceport = "/dev/ttyUSB0",
- + .dataport = "/dev/ttyUSB2",
- + .type = EC20_MODEM,
- + },
- + {
- + .name = "EM8000_MODEM",
- + .idVendor = "19d2",
- + .idProduct = "0532",
- + .deviceport = "/dev/ttyUSB0",
- + .dataport = "/dev/ttyUSB2",
- + .type = EM8000_MODEM,
- + },
- +};
- +
- +/* -------------------------------------------------------------- */
- +
- +#define DEBUG_UEVENT 0
- +#define UEVENT_PARAMS_MAX 32
- +
- +enum uevent_action { action_add, action_remove, action_change };
- +
- +struct uevent {
- + char *path;
- + enum uevent_action action;
- + char *subsystem;
- + char *param[UEVENT_PARAMS_MAX];
- + unsigned int seqnum;
- +};
- +
- +static void dump_uevent(struct uevent *event);
- +
- +int readfile(char *path, char *content, size_t size)
- +{
- + int ret;
- + FILE *f;
- + f = fopen(path, "r");
- + if (f == NULL)
- + return -1;
- +
- + ret = fread(content, 1, size, f);
- + fclose(f);
- + return ret;
- +}
- +
- +int is_device_equal(struct modem_3g_device *device,
- + const char *idv, const char *idp)
- +{
- + long pvid = 0xffff, ppid = 0xffff;
- + long t_vid, t_pid;
- + if (device == NULL)
- + return 0;
- + t_vid = strtol(device->idVendor, NULL, 16);
- + t_pid = strtol(device->idProduct, NULL, 16);
- + pvid = strtol(idv, NULL, 16);
- + ppid = strtol(idp, NULL, 16);
- +
- + return (t_vid == pvid && t_pid == ppid);
- +}
- +
- +struct modem_3g_device *
- +find_devices_in_table(const char *idvendor, const char *idproduct)
- +{
- + int i;
- + int size = ARRAY_SIZE(modem_3g_device_table);
- + struct modem_3g_device *device;
- +
- + for (i = 0; i < size; i++) {
- + device = &modem_3g_device_table[i];
- +
- + if (is_device_equal(device, idvendor, idproduct)) {
- + ALOGI("Runtime 3G port found matched device with "
- + "Name:%s idVendor:%s idProduct:%s",
- + device->name, device->idVendor, device->idProduct);
- +
- + return device;
- + }
- + }
- +
- + return NULL;
- +}
- +
- +struct modem_3g_device *find_matched_device(void)
- +{
- + struct dirent *dent;
- + DIR *usbdir;
- + struct modem_3g_device *device = NULL;
- + char *path, *path2;
- + char idvendor[64];
- + char idproduct[64];
- + int ret, i;
- +
- + path = malloc(PATH_SIZE);
- + if (!path)
- + return NULL;
- +
- + path2 = malloc(PATH_SIZE);
- + if (!path2) {
- + free(path);
- + return NULL;
- + }
- +
- + usbdir = opendir(USB_DIR_BASE);
- + if (usbdir == NULL) {
- + free(path);
- + free(path2);
- + return NULL;
- + }
- +
- + memset(path, 0, PATH_SIZE);
- + memset(path2, 0, PATH_SIZE);
- +
- + while ((dent = readdir(usbdir)) != NULL) {
- + if (strcmp(dent->d_name, ".") == 0
- + || strcmp(dent->d_name, "..") == 0)
- + continue;
- + memset(idvendor, 0, sizeof(idvendor));
- + memset(idproduct, 0, sizeof(idproduct));
- + path = strcpy(path, USB_DIR_BASE);
- + path = strcat(path, dent->d_name);
- + strcpy(path2, path);
- + path = strcat(path, "/idVendor");
- + path2 = strcat(path2, "/idProduct");
- +
- + ret = readfile(path, idvendor, 4);
- + if (ret <= 0)
- + continue;
- + ret = readfile(path2, idproduct, 4);
- + if (ret <= 0)
- + continue;
- + device = find_devices_in_table(idvendor, idproduct);
- + if (device != NULL)
- + goto out;
- + }
- +
- + if (device == NULL)
- + ALOGI("Runtime 3G can't find supported modem");
- +out:
- + closedir(usbdir);
- + free(path);
- + free(path2);
- +
- + return device;
- +}
- +
- +
- +const char *runtime_3g_port_device(void)
- +{
- + struct modem_3g_device *device;
- + device = find_matched_device();
- + if (device == NULL)
- + return FAKE_PORT;
- +
- + /* Set gobal modem type. */
- + current_modem_type = device->type;
- +
- + ALOGI("Current modem type = %d", current_modem_type);
- +
- + return device->deviceport;
- +}
- +
- +const char *runtime_3g_port_data(void)
- +{
- + struct modem_3g_device *device;
- +
- + device = find_matched_device();
- + if (device == NULL)
- + return FAKE_PORT;
- + return device->dataport;
- +}
- +
- +int runtime_3g_port_type(void)
- +{
- + struct modem_3g_device *device;
- + int type = UNKNOWN_MODEM;
- + if (UNKNOWN_MODEM == current_modem_type){
- + if (NULL != (device = find_matched_device())){
- + /* Set gobal modem type. */
- + type = device->type;
- + }
- + }else{
- + type = current_modem_type;
- + }
- +
- + ALOGI("Current modem type = %d", type);
- +
- + return type;
- +}
- +
- +static void free_uevent(struct uevent *event)
- +{
- + int i;
- + free(event->path);
- + free(event->subsystem);
- + for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
- + if (!event->param[i])
- + break;
- + free(event->param[i]);
- + }
- + free(event);
- +}
- +
- +static int dispatch_uevent(struct uevent *event)
- +{
- + /* if it's a usb tty event in our table. make the rild reboot. */
- + int i;
- + int ret;
- + for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
- + if (!event->param[i])
- + break;
- + if (strncmp(event->param[i], "PRODUCT=", 8) == 0) {
- + char vbuf[5], pbuf[5];
- + ret = sscanf(event->param[i],
- + "PRODUCT=%4s/%4s/", vbuf, pbuf);
- + if (ret < 0)
- + return -1;
- + if (find_devices_in_table(vbuf, pbuf))
- + alarm(1);
- + /* Restart in 1 second, since USB usually have
- + * many devices, this avoid rild restart too
- + * many times. */
- + }
- + }
- + return 0;
- +}
- +
- +int process_uevent_message(int sock)
- +{
- + char buffer[64 * 1024];
- + char *s = buffer, *p;
- + char *end;
- + int count, param_idx = 0, ret;
- + struct uevent *event;
- + count = recv(sock, buffer, sizeof(buffer), 0);
- + if (count < 0) {
- + ALOGE("Error receiving uevent (%s)", strerror(errno));
- + return -errno;
- + }
- + event = malloc(sizeof(struct uevent));
- + if (!event) {
- + ALOGE("Error allcating memroy (%s)", strerror(errno));
- + return -errno;
- + }
- + memset(event, 0, sizeof(struct uevent));
- +
- + end = s + count;
- +
- + for (p = s; *p != '@'; p++)
- + ;
- + p++;
- + event->path = strdup(p);
- + s += strlen(s) + 1;
- +
- + while (s < end) {
- + if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
- + char *a = s + strlen("ACTION=");
- + if (!strcmp(a, "add"))
- + event->action = action_add;
- + else if (!strcmp(a, "change"))
- + event->action = action_change;
- + else if (!strcmp(a, "remove"))
- + event->action = action_remove;
- + } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
- + event->seqnum = atoi(s + strlen("SEQNUM="));
- + else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
- + event->subsystem = strdup(s + strlen("SUBSYSTEM="));
- + else
- + event->param[param_idx++] = strdup(s);
- + s += strlen(s) + 1;
- + }
- +
- + ret = dispatch_uevent(event);
- +#if DEBUG_UEVENT
- + dump_uevent(event);
- +#endif
- + free_uevent(event);
- + return ret;
- +}
- +
- +static void dump_uevent(struct uevent *event)
- +{
- + int i;
- +
- + ALOGD("[UEVENT] Sq: %u S: %s A: %d P: %s",
- + event->seqnum, event->subsystem, event->action, event->path);
- + for (i = 0; i < UEVENT_PARAMS_MAX; i++) {
- + if (!event->param[i])
- + break;
- + ALOGD("%s", event->param[i]);
- + }
- +}
- +
- +void restart_rild(int p)
- +{
- + ALOGI("3G Modem changed,RILD will restart...");
- + exit(-1);
- +}
- +
- +void *usb_tty_monitor_thread(void *arg)
- +{
- + struct sockaddr_nl nladdr;
- + struct pollfd pollfds[2];
- + int uevent_sock;
- + int ret, max = 0;
- + int uevent_sz = 64 * 1024;
- + int timeout = -1;
- + struct sigaction timeoutsigact;
- +
- + ALOGI("3G modem monitor thread is start");
- +
- + timeoutsigact.sa_handler = restart_rild;
- + sigemptyset(&timeoutsigact.sa_mask);
- + sigaddset(&timeoutsigact.sa_mask, SIGALRM);
- + sigaction(SIGALRM, &timeoutsigact, 0);
- +
- + memset(&nladdr, 0, sizeof(nladdr));
- + nladdr.nl_family = AF_NETLINK;
- + nladdr.nl_pid = getpid();
- + nladdr.nl_groups = 0xffffffff;
- +
- + uevent_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
- + if (uevent_sock < 0) {
- + ALOGE(" Netlink socket faild, usb monitor exiting...");
- + return NULL;
- + }
- +
- + if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
- + sizeof(uevent_sz)) < 0) {
- + ALOGE("Unable to set uevent socket options: %s", strerror(errno));
- + return NULL;
- + }
- +
- + if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
- + ALOGE("Unable to bind uevent socket: %s", strerror(errno));
- + return NULL;
- + }
- + pollfds[0].fd = uevent_sock;
- + pollfds[0].events = POLLIN;
- +
- + ret = fcntl(uevent_sock,F_SETFL, O_NONBLOCK);
- + if (ret < 0)
- + ALOGE("Error on fcntl:%s", strerror(errno));
- +
- + while (1) {
- + ret = poll(pollfds, 1, timeout);
- +
- + switch (ret) {
- + case 0:
- + ALOGD("poll timeout");
- + continue;
- + case -1:
- + ALOGD("poll error:%s", strerror(errno));
- + break;
- +
- + default:
- + if (pollfds[0].revents & POLLIN)
- + process_uevent_message(uevent_sock);
- + }
- + }
- +
- + close(uevent_sock);
- +}
- +
- +int start_uevent_monitor(void)
- +{
- + pthread_t pth_uevent_monitor;
- + return pthread_create(&pth_uevent_monitor, NULL,
- + usb_tty_monitor_thread, NULL);
- +}
- +
- +
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。