hab 通信
不同服务的physical channel不同,比如摄像头服务有专门的physical channel,硬编解码服务也有专门的物理channel;不同的物理chanel用MMID标志
其次是virtual channel,不同的vcID对应不同的业务。Front end(也即guestOS端)想start/stop控制back-end端的摄像头。那么分配一个vcid,然后再发起一个分配请求到back-end.back-end收到请求后,也会给自己分配一个vcid,这样俩端分别保存有自己的vcid和对端的vcid。相当于俩端建立了一个连接。
guest 端定义mmid
kernel_platform/msm-kernel/include/uapi/linux/habmmid.h
#define MM_DISP_START 30
#define MM_MISC_START 600
#define MM_MISC 601
#define MM_MISC_TEE_CONN_ID 0x20
#define MM_MISC_RTC_CONN_ID 0x21
申明hab 接口
kernel_platform/msm-kernel/include/linux/habmm.h
用户层实现hab 接口 libuhab.so
vendor/qcom/proprietary/mm-hab/uhab/uhab.c
驱动层实现khab接口
kernel_platform/msm-kernel/drivers/soc/qcom/hab/khab.c
kernel_platform/msm-kernel/drivers/soc/qcom/hab/hab.c
kernel_platform/msm-kernel/drivers/soc/qcom/hab/hab_linux.c
ab_linux.c 里面创建hab cdev
static int __init hab_init(void)
/sys/class/hab
/sys/devices/virtual/hab
hab 发送消息通道
vendor/mega/drivers/msg_channel/src/msg_channel.c
用户层和driver 通过 节点 /dev/hab 通讯
#ifdef __QNXNTO__
#define HAB_DEVNODE "/dev/hab/hab"
host 端定义mmid 跟guest 端一样
qnx/hlos_dev_qnx/apps/qnx_ap/AMSS/multimedia/hab/driver/public/amss/multimedia/uhab/habmmid.h
申明hab 接口
qnx/hlos_dev_qnx/apps/qnx_ap/AMSS/multimedia/hab/driver/public/amss/multimedia/uhab/habmm.h
qnx/hlos_dev_qnx/apps/qnx_ap/AMSS/multimedia/hab/driver/public/amss/multimedia/uhab/hab_ioctl.h
client 层实现hab 接口
qnx/hlos_dev_qnx/apps/qnx_ap/AMSS/platform/qal/clients/uhab/uhab.c
驱动层实现hab
qnx/hlos_dev_qnx/apps/qnx_ap/AMSS/multimedia/hab/driver/hab.c
qnx 应用端
qnx/XXX/apps/systime/src/systime_hab.c
#define SYSTIME_HAB_CONN_ID MM_MISC_RTC_CONN_ID
static void *systime_hab_thread(void *arg)
{
systime_conf_t* systime = (systime_conf_t*)arg;
int32_t ret = 0;
int32_t handle = 0;
systime_hab_msg_t hab_msg;
uint32_t msg_size = 0;
pthread_t tid = pthread_self();
pthread_detach(tid);
pthread_setname_np(tid, "systime_hab");
/*
* We need to handle Android VM reboot event.
* If Android VM reboots, we have to re-establish HAB connection.
*/
while (1)
{
ret = habmm_socket_open(&handle,
HAB_MMID_CREATE(MM_MISC, SYSTIME_HAB_CONN_ID),
(uint32_t)-1,
HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_FE);
if (ret < 0)
{
LOGE("HAB socket_open failed, %d, %d, ret=%d", MM_MISC, SYSTIME_HAB_CONN_ID, ret);
sleep(1);
continue;
}
guest 端应用
hwclock 调用通过/dev/rtc 调用到rtc-f3 驱动
调用堆栈
hwclock-8794 [000] ..... 18063.116289: rtc_set_time: UTC (1739852807) (0)
hwclock-8794 [000] ...1. 18063.116293: <stack trace>
=> trace_event_raw_event_rtc_time_alarm_class
=> rtc_set_time
=> rtc_dev_ioctl
=> __arm64_sys_ioctl
=> invoke_syscall
=> el0_svc_common.llvm.9556644876231995270
=> do_el0_svc
=> el0_svc
=> el0t_64_sync_handler
=> el0t_64_sync
vendor/mega/drivers/XXX_rtc/src/rtc-fe.c
#define SYSTIME_HAB_CONN_ID MM_MISC_RTC_CONN_ID
static int hab_connect_thread(void* data) {
int ret;
struct rtc_fe_priv* rtc_data = (struct rtc_fe_priv*)data;
rtc_data->hab_status = HAB_STATUS_BLOCKED;
ret = habmm_socket_open(&(rtc_data->hab_handle),
HAB_MMID_CREATE(MM_MISC, SYSTIME_HAB_CONN_ID),
(unsigned int)-1,
HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_FE);
if (ret < 0) {
printk(KERN_ERR "%s,%d, HAB socket_open failed, %d, %d, ret=%d\n",
__FILE__, __LINE__, MM_MISC, SYSTIME_HAB_CONN_ID, ret);
return -1;
}
rtc_data->hab_status = HAB_STATUS_CONNECTED;
complete(&(rtc_data->wait));
return 0;
}
static int rtc_fe_set_time(struct device *dev, struct rtc_time *tm)
{
struct rtc_fe_hab_msg hab_msg;
struct rtc_fe_priv *data;
int ret = 0;
data = dev_get_drvdata(dev);
hab_msg.op_code = SYSTIME_HAB_MSG_OPCODE_WR_RTC_TIME;
hab_msg.time = (time_t)rtc_tm_to_time64(tm);
ret = rtc_fe_send_msg(&hab_msg, data);
if (ret < 0)
{
printk(KERN_ERR "%s,%d, Failed to send cmd %d\n",
__FILE__, __LINE__, hab_msg.op_code);
return -1;
}
printk(KERN_INFO "%s,%d - end.\n", __FILE__, __LINE__);
return 0;
}
1、驱动里面通过创建一个内核线程,调用habmm_socket_open
habmm_socket_open(&(rtc_data->hab_handle),
HAB_MMID_CREATE(MM_MISC, SYSTIME_HAB_CONN_ID),
(unsigned int)-1,
HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_FE);
hab_linux.c 在__init__段阶段就创建好了mmid 对应的hab 字符设备;通过khab.c 调用habmm_socket_open,再调用到hdb.c 中hab_vchan_open,这里会找到mmid 对应的hab设备再获取对应的pchan(物理通道),再创建该次通信的vchan(虚拟通道)
803 if (pchan->is_be)
804 vchan = backend_listen(ctx, mmid,
805 timeout, flags);
806 else
807 vchan = frontend_open(ctx, mmid,
808 HABCFG_VMID_DONT_CARE, flags);
https://zhuanlan.zhihu.com/p/15695052933
高通guestOS与hostOS通信框架HAB源码分析——概述_高通hab-CSDN博客
Qnx wfd_be & wfd_fe Android 通讯-CSDN博客
2、建立hab 连接后,调用habmm_socket_send发送数据
ret = habmm_socket_send(data->hab_handle, (void *)hab_msg, msg_size, 0);
3、通过habmm_socket_recv 不断查询返回结果
/* wait and receive the reply HAB msg from QNX */
while (1) {
msg_size = sizeof(struct rtc_fe_hab_msg);
ret = habmm_socket_recv(data->hab_handle,
(void *)hab_msg,
&msg_size,
(unsigned int)-1,
HABMM_SOCKET_RECV_FLAGS_NON_BLOCKING);