赞
踩
官网电话子系统框架图
南向ril_adapter库框架图
ril_adapter分为三部分hril_hdf、hril、vendorlib。
hril_hdf
hdf驱动接口。hdi服务(drivers/peripheral/ril/interfaces/hdi_service/src/ril_driver.cpp)调用InitRilAdapter和ReleaseRilAdapter使用ril_adapter的功能。
hril:
负责与电话子系统框架层core_service模块ipc通信,接收框架层指令、返回指令执行结果。
vendorlib:
厂商库,通过usb串口,发送at指令,接收串口回传信息。
hril_hdf主要功能是加载vendorlib,库的名称默认是libril_vendor.z.so,对应vendorlib。
修改默认厂商库加载路径有两种方法:
修改base/telephony/ril_adapter/services/hril_hdf/include/modem_adapter.h,添加厂商库配置
UsbDeviceInfo g_usbModemVendorInfo[] = {
// MEIG modem
{.idVendor = MEIG_VENDOR_ID, .idProduct = MEIG_PRODUCT_ID_SLM790, .libPath = "libril_vendor.z.so"},
// Fibocom modem
{.idVendor = FIBOCOM_VENDOR_ID, .idProduct = FIBOCOM_PRODUCT_ID_NL668, .libPath = "libfibocom_ril.z.so"},
// my modem
{.idVendor = MY_VENDOR_ID, .idProduct = MY_PRODUCT_ID, .libPath = "libril_vendor_my.z.so"},
};
vendorid和productid可以在hdc shell下通过lsusb查看。
修改base/telephony/ril_adapter/services/hril_hdf/src/hril_hdf.c,新增vendorid和productid判断逻辑。
这里笔者选择通过libusb来获取usb信息,主要代码如下:
static UsbDeviceInfo *GetPresetInformationByInt(const int32_t idVendor, const int32_t idProduct)
{
UsbDeviceInfo *uDevInfo = NULL;
for (uint32_t i = 0; i < sizeof(g_usbModemVendorInfo) / sizeof(UsbDeviceInfo); i++) {
if (g_usbModemVendorInfo[i].idVendor == idVendor && g_usbModemVendorInfo[i].idProduct == idProduct) {
TELEPHONY_LOGI("find usb device index=%{public}d", i);
uDevInfo = &g_usbModemVendorInfo[i];
break;
}
}
return uDevInfo;
}
#include <libusb/libusb.h>
static UsbDeviceInfo *GetUsbDeviceInfo(void)
{
UsbDeviceInfo *uDevInfo = NULL;
libusb_context *ctx = NULL;
libusb_device **devs;
ssize_t cnt;
// 初始化libusb
if (libusb_init(&ctx) < 0) {
TELEPHONY_LOGE("libusb_init failed");
return NULL;
}
// 获取已连接的USB设备列表
cnt = libusb_get_device_list(ctx, &devs);
if (cnt < 0) {
TELEPHONY_LOGE("libusb_get_device_list failed");
libusb_exit(ctx);
return NULL;
}
TELEPHONY_LOGI("usb device list:");
// 遍历设备列表并输出信息
for (ssize_t i = 0; i < cnt; i++) {
libusb_device *dev = devs[i];
struct libusb_device_descriptor desc;
// 获取设备描述符
if (libusb_get_device_descriptor(dev, &desc) < 0) {
TELEPHONY_LOGE("libusb_get_device_descriptor failed");
continue;
}
// 打印设备信息
TELEPHONY_LOGI("USB Device %{public}zd : ID 0x%{public}04x:0x%{public}04x ADDR:%{public}d", i + 1, desc.idVendor, desc.idProduct, libusb_get_device_address(dev));
uDevInfo = GetPresetInformationByInt(desc.idVendor, desc.idProduct);
if (uDevInfo)
{
TELEPHONY_LOGI("USB Device found!");
break;
}
}
// 释放设备列表
libusb_free_device_list(devs, 1);
// 退出libusb
libusb_exit(ctx);
return uDevInfo;
}
由于原vendorlib是适配美格SLM790模组的,在硬件不同的情况下,需要修改或新增厂商库。
厂商库框架:
修改方案:
初始化at修改
修改base/telephony/ril_adapter/services/vendor/src/vendor_adapter.c文件,
修改ModemInit()函数,这里是初始化时发送给modem的at指令,根据厂商提供的信息,删除报错的at,增加和修改部分的at命令。
各模块at修改
AT+开头指令为3GPP规定的AT指令,modem基本都会支持。
搜索全部的AT^开头的指令,将其修改为modem手册上对应的AT。
例如,获取sim卡类型的AT指令,如果没有该AT,可以直接返回类型,如下:
static int32_t GetSimType(void)
{
return HRIL_SIM_TYPE_USIM;
}
构造at指令回复信息
有一些AT底层无法执行,可以构造虚假回复消息,发送空数据给框架层。
例如:
struct ReportInfo reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_SUCCESS, HRIL_RESPONSE, 0);
OnSimReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
如果业务流程修改较大,无法在ril_adapter满足要求,建议修改电话子系统的框架层代码。
但如果只是修改at发送和接收就能满足业务流程,则不需要修改框架层代码。
综上,按照该方案修改的电话子系统可以做到一个板卡硬件通过usb接入不同的modem,均可以识别加载,实现电话子系统功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。