Hypervisor Display架构部分
1,所有LA侧的APP与显示相关的调用最终都会交由SurfaceFlinger处理
2,SurfaceFlinger会最终调用android.hardware.graphics.composer@2.4-service服务
3,android.hardware.graphics.composer@2.4-service服务会调用GPU&DRM&Qcom的一些列库文件(很遗憾这些库相当一大部分源码是不开源的)
4,libdrm库调用open/ioctl等函数会经过lib_drm_fe库的转接,当然lib_drm_fe会做很多其他适配的工作
5,lib_drm_fe会调用内核HGSL驱动中的hab通信接口与QNX侧的wfd_be服务进行通信
6,wfd_be服务会解析接收到的LA侧的数据包
7,根据数据包中的命令类型调用不同的openwfd接口,需要注意的是,这里的接口是做了一层转换的,举个例子wfdEnumerateDevices_Host,这个接口会进行转换之后真正调用wfdEnumerateDevices函数
8,所有的操作都执行完成之后,如果有必要会唤醒wfd_be的commit&vsync现场,通知openwfd刷新画面
lib_drm_fe会调用内核HGSL驱动中的hab通信接口与QNX侧的wfd_be服务进行通信
sa8295 dtsi配置
direwolf-vm.dtsi msm_gpu_hyp: qcom,hgsl@0x3d00000 { compatible = "qcom,hgsl"; reg = , ; reg-names = "hgsl_reg_hwinf", "hgsl_reg_gmucx"; qcom,glb-db-senders = ; qcom,glb-db-receivers = ; };
kernel/msm-5.4/drivers/soc/qcom/hgsl/hgsl 设备树匹配
static const struct of_device_id qcom_hgsl_of_match[] = { { .compatible = "qcom,hgsl" }, {} }; MODULE_DEVICE_TABLE(of, qcom_hgsl_of_match); static struct platform_driver qcom_hgsl_driver = { .probe = qcom_hgsl_probe, .remove = qcom_hgsl_remove, .driver = { .name = "qcom-hgsl", .of_match_table = qcom_hgsl_of_match, }, }; module_platform_driver(qcom_hgsl_driver);
lagvm/LINUX/android/kernel/msm-5.4/drivers/soc/qcom/hgsl/hgsl.c
static int qcom_hgsl_probe(struct platform_device *pdev) { struct qcom_hgsl *hgsl_dev; int ret; int i; hgsl_dev = devm_kzalloc(&pdev->dev, sizeof(*hgsl_dev), GFP_KERNEL); if (!hgsl_dev) return -ENOMEM; hgsl_dev->dev = &pdev->dev; ret = qcom_hgsl_register(pdev, hgsl_dev); if (ret dev, "qcom_hgsl_register failed, ret %d\n", ret); return ret; } ret = hgsl_init_context(hgsl_dev); if (ret dev, "hgsl_init_context failed, ret %d\n", ret); goto exit_dereg; } //创建hgsl-release-wq workqueue ret = hgsl_init_release_wq(hgsl_dev); if (ret dev, "hgsl_init_release_wq failed, ret %d\n", ret); goto exit_dereg; } hgsl_dev->db_off = hgsl_is_db_off(pdev); idr_init(&hgsl_dev->isync_timeline_idr); spin_lock_init(&hgsl_dev->isync_timeline_lock); for (i = 0; i dbq[i].lock); hgsl_dev->dbq[i].state = DB_STATE_Q_UNINIT; } if (!hgsl_dev->db_off) hgsl_init_global_hyp_channel(hgsl_dev); platform_set_drvdata(pdev, hgsl_dev); return 0; exit_dereg: qcom_hgsl_deregister(pdev); return ret; }
static int qcom_hgsl_register(struct platform_device *pdev, struct qcom_hgsl *hgsl_dev) { int ret; ret = alloc_chrdev_region(&hgsl_dev->device_no, 0, HGSL_DEV_NUM, HGSL_DEVICE_NAME); if (ret dev, "alloc_chrdev_region failed %d\n", ret); return ret; } //创建一个hgsl class节点 hgsl_dev->driver_class = class_create(THIS_MODULE, HGSL_DEVICE_NAME); if (IS_ERR(hgsl_dev->driver_class)) { ret = -ENOMEM; dev_err(&pdev->dev, "class_create failed %d\n", ret); goto exit_unreg_chrdev_region; } //创建一个hgsl 设备 hgsl_dev->class_dev = device_create(hgsl_dev->driver_class, NULL, hgsl_dev->device_no, hgsl_dev, HGSL_DEVICE_NAME); if (IS_ERR(hgsl_dev->class_dev)) { dev_err(&pdev->dev, "class_device_create failed %d\n", ret); ret = -ENOMEM; goto exit_destroy_class; } //注册hgsl 设备操作接口 cdev_init(&hgsl_dev->cdev, &hgsl_fops); hgsl_dev->cdev.owner = THIS_MODULE; //注册hgsl设备 ret = cdev_add(&hgsl_dev->cdev, MKDEV(MAJOR(hgsl_dev->device_no), 0), 1); if (ret dev, "cdev_add failed %d\n", ret); goto exit_destroy_device; } ret = dma_coerce_mask_and_coherent(hgsl_dev->dev, DMA_BIT_MASK(64)); if (ret) LOGW("Failed to set dma mask to 64 bits, ret = %d", ret); return 0; exit_destroy_device: device_destroy(hgsl_dev->driver_class, hgsl_dev->device_no); exit_destroy_class: class_destroy(hgsl_dev->driver_class); exit_unreg_chrdev_region: unregister_chrdev_region(hgsl_dev->device_no, 1); return ret; }
设备注册的操作接口hgsl_fops
static const struct file_operations hgsl_fops = { .owner = THIS_MODULE, .open = hgsl_open, .release = hgsl_release, .read = hgsl_read, .unlocked_ioctl = hgsl_ioctl, .compat_ioctl = hgsl_compat_ioctl };
static int hgsl_open(struct inode *inodep, struct file *filep) { struct hgsl_priv *priv = hgsl_zalloc(sizeof(*priv)); struct qcom_hgsl *hgsl = container_of(inodep->i_cdev, struct qcom_hgsl, cdev); //获取当前进程的pid 和task_struct struct pid *pid = task_tgid(current); struct task_struct *task = pid_task(pid, PIDTYPE_PID); int ret = 0; if (!priv) return -ENOMEM; if (!task) { ret = -EINVAL; goto out; } INIT_LIST_HEAD(&priv->mem_mapped); INIT_LIST_HEAD(&priv->mem_allocated); mutex_init(&priv->lock); priv->pid = task_pid_nr(task); ret = hgsl_hyp_init(&priv->hyp_priv, hgsl->dev, priv->pid, task->comm); if (ret != 0) goto out; priv->dev = hgsl; filep->private_data = priv; out: if (ret != 0) kfree(priv); return ret; }
int hgsl_hyp_init(struct hgsl_hyp_priv_t *priv, struct device *dev, int client_pid, const char * const client_name) { priv->dev = dev; return hgsl_hyp_channel_pool_init(priv, client_pid, client_name); }
//将task_struct 信息与hgsl_hyp_priv_t 绑定 static int hgsl_hyp_channel_pool_init(struct hgsl_hyp_priv_t *priv, int client_pid, const char * const client_name) { INIT_LIST_HEAD(&priv->free_channels); INIT_LIST_HEAD(&priv->busy_channels); mutex_init(&priv->lock); priv->conn_id = 0; strlcpy(priv->client_name, client_name, sizeof(priv->client_name)); priv->client_pid = client_pid; idr_init(&priv->channel_idr); LOGD("pid %d, task name %s" , (int) priv->client_pid, priv->client_name); return 0; }
Libgsl 会使与驱动hgsl交互
static long hgsl_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { return hgsl_ioctl(filep, cmd, arg); }
static long hgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) { int ret; switch (cmd) { case HGSL_IOCTL_ISSUE_IB: ret = hgsl_ioctl_issueib(filep, arg); break; case HGSL_IOCTL_CTXT_CREATE: ret = hgsl_ioctl_ctxt_create(filep, arg); break; case HGSL_IOCTL_CTXT_DESTROY: ret = hgsl_ioctl_ctxt_destroy(filep, arg); break; case HGSL_IOCTL_WAIT_TIMESTAMP: ret = hgsl_ioctl_wait_timestamp(filep, arg); break; case HGSL_IOCTL_READ_TIMESTAMP: ret = hgsl_ioctl_read_timestamp(filep, arg); break; case HGSL_IOCTL_CHECK_TIMESTAMP: ret = hgsl_ioctl_check_timestamp(filep, arg); break; case HGSL_IOCTL_HYP_GENERIC_TRANSACTION: ret = hgsl_ioctl_hyp_generic_transaction(filep, arg); break; case HGSL_IOCTL_GET_SHADOWTS_MEM: ret = hgsl_ioctl_get_shadowts_mem(filep, arg); break; case HGSL_IOCTL_PUT_SHADOWTS_MEM: ret = hgsl_ioctl_put_shadowts_mem(filep, arg); break; case HGSL_IOCTL_MEM_ALLOC: ret = hgsl_ioctl_mem_alloc(filep, arg); break; case HGSL_IOCTL_MEM_FREE: ret = hgsl_ioctl_mem_free(filep, arg); break; case HGSL_IOCTL_MEM_MAP_SMMU: ret = hgsl_ioctl_mem_map_smmu(filep, arg); break; case HGSL_IOCTL_MEM_UNMAP_SMMU: ret = hgsl_ioctl_mem_unmap_smmu(filep, arg); break; case HGSL_IOCTL_MEM_CACHE_OPERATION: ret = hgsl_ioctl_mem_cache_operation(filep, arg); break; case HGSL_IOCTL_ISSUIB_WITH_ALLOC_LIST: ret = hgsl_ioctl_issueib_with_alloc_list(filep, arg); break; case HGSL_IOCTL_GET_SYSTEM_TIME: ret = hgsl_ioctl_get_system_time(filep, arg); break; case HGSL_IOCTL_SYNCOBJ_WAIT_MULTIPLE: ret = hgsl_ioctl_syncobj_wait_multiple(filep, arg); break; case HGSL_IOCTL_PERFCOUNTER_SELECT: ret = hgsl_ioctl_perfcounter_select(filep, arg); break; case HGSL_IOCTL_PERFCOUNTER_DESELECT: ret = hgsl_ioctl_perfcounter_deselect(filep, arg); break; case HGSL_IOCTL_PERFCOUNTER_QUERY_SELECTION: ret = hgsl_ioctl_perfcounter_query_selection(filep, arg); break; case HGSL_IOCTL_PERFCOUNTER_READ: ret = hgsl_ioctl_perfcounter_read(filep, arg); break; case HGSL_IOCTL_SET_METAINFO: ret = hgsl_ioctl_set_metainfo(filep, arg); break; case HGSL_IOCTL_HSYNC_FENCE_CREATE: ret = hgsl_ioctl_hsync_fence_create(filep, arg); break; case HGSL_IOCTL_ISYNC_TIMELINE_CREATE: ret = hgsl_ioctl_isync_timeline_create(filep, arg); break; case HGSL_IOCTL_ISYNC_TIMELINE_DESTROY: ret = hgsl_ioctl_isync_timeline_destroy(filep, arg); break; case HGSL_IOCTL_ISYNC_FENCE_CREATE: ret = hgsl_ioctl_isync_fence_create(filep, arg); break; case HGSL_IOCTL_ISYNC_FENCE_SIGNAL: ret = hgsl_ioctl_isync_fence_signal(filep, arg); break; case HGSL_IOCTL_ISYNC_FORWARD: ret = hgsl_ioctl_isync_forward(filep, arg); break; case HGSL_IOCTL_TIMELINE_CREATE: ret = hgsl_ioctl_timeline_create(filep, arg); break; case HGSL_IOCTL_TIMELINE_SIGNAL: ret = hgsl_ioctl_timeline_signal(filep, arg); break; case HGSL_IOCTL_TIMELINE_QUERY: ret = hgsl_ioctl_timeline_query(filep, arg); break; case HGSL_IOCTL_TIMELINE_WAIT: ret = hgsl_ioctl_timeline_wait(filep, arg); break; default: ret = -ENOIOCTLCMD; } return ret; }
static int hgsl_ioctl_ctxt_create(struct file *filep, unsigned long arg) { struct hgsl_priv *priv = filep->private_data; struct qcom_hgsl *hgsl = priv->dev; struct hgsl_ioctl_ctxt_create_params params; struct hgsl_context *ctxt = NULL; int ret = 0; struct hgsl_hab_channel_t *hab_channel = NULL; bool ctxt_created = false; if (copy_from_user(¶ms, USRPTR(arg), sizeof(params))) { LOGE("failed to copy params from user"); ret = -EFAULT; return ret; } //建立hab socket ret = hgsl_hyp_channel_pool_get(&priv->hyp_priv, 0, &hab_channel); if (ret) { LOGE("Failed to get hab channel %d", ret); goto out; } ctxt = hgsl_zalloc(sizeof(*ctxt)); if (ctxt == NULL) { ret = -ENOMEM; return ret; } if (params.flags & GSL_CONTEXT_FLAG_CLIENT_GENERATED_TS) params.flags |= GSL_CONTEXT_FLAG_USER_GENERATED_TS; if (params.flags & GSL_CONTEXT_FLAG_BIND) { params.flags &= ~GSL_CONTEXT_FLAG_CLIENT_GENERATED_TS; params.flags |= GSL_CONTEXT_FLAG_USER_GENERATED_TS; } //使用hab socket发送数据 ret = hgsl_hyp_ctxt_create(hab_channel, ¶ms); if (ret) goto out; if (params.ctxthandle >= HGSL_CONTEXT_NUM) { LOGE("invalid ctxt id %d", params.ctxthandle); ret = -EINVAL; goto out; } ctxt->context_id = params.ctxthandle; ctxt->devhandle = params.devhandle; ctxt->pid = priv->pid; ctxt->priv = priv; ctxt->flags = params.flags; hgsl_get_shadowts_mem(hab_channel, ctxt); if (hgsl->global_hyp_inited && !hgsl->db_off) hgsl_ctxt_create_dbq(priv, hab_channel, ctxt); kref_init(&ctxt->kref); init_waitqueue_head(&ctxt->wait_q); write_lock(&hgsl->ctxt_lock); if (hgsl->contexts[ctxt->context_id] != NULL) { LOGE("context id %d already created", ctxt->context_id); ret = -EBUSY; write_unlock(&hgsl->ctxt_lock); goto out; } hgsl->contexts[ctxt->context_id] = ctxt; write_unlock(&hgsl->ctxt_lock); ctxt_created = true; if (hgsl_ctxt_use_global_dbq(ctxt)) { ret = hgsl_hsync_timeline_create(ctxt); if (ret timeline) params.sync_type = HGSL_SYNC_TYPE_HSYNC; else params.sync_type = HGSL_SYNC_TYPE_ISYNC; if (copy_to_user(USRPTR(arg), ¶ms, sizeof(params))) { ret = -EFAULT; goto out; } out: LOGD("%d", params.ctxthandle); if (ret) { if (ctxt_created) hgsl_ctxt_destroy(priv, hab_channel, params.ctxthandle, NULL, false); else if (ctxt && (params.ctxthandle shadow_ts_node); hgsl_hyp_ctxt_destroy(hab_channel, ctxt->devhandle, ctxt->context_id, NULL); kfree(ctxt); } LOGE("failed to create context"); } hgsl_hyp_channel_pool_put(hab_channel); return ret; }
int hgsl_hyp_channel_pool_get( struct hgsl_hyp_priv_t *priv, int id, struct hgsl_hab_channel_t **channel) { struct hgsl_hab_channel_t *hab_channel = NULL; int ret = 0; if (!channel) return -EINVAL; mutex_lock(&priv->lock); if (id) { ret = hgsl_hyp_channel_pool_get_by_id(priv, id, &hab_channel); if (ret) LOGE("Failed to find channel %d, ret %d", id, ret); } else { if (list_empty(&priv->free_channels)) { //创建一个channel ret = hgsl_rpc_create_channel(priv, &hab_channel); LOGD("hgsl_rpc_create_channel returned, ret %d hab_channel %p", ret, hab_channel); } else { hab_channel = container_of(priv->free_channels.next, struct hgsl_hab_channel_t, node); if (hab_channel != NULL) { list_del(&hab_channel->node); LOGD("get %p from free pool", hab_channel); } else { ret = -EINVAL; LOGE("invalid hab_channel in the list"); } } if (!ret) list_add_tail(&hab_channel->node, &priv->busy_channels); } if (!ret) { *channel = hab_channel; hab_channel->busy = true; } mutex_unlock(&priv->lock); if ((!ret) && (!id)) { ret = hgsl_rpc_parcel_reset(hab_channel); if (ret) { LOGE("hgsl_rpc_parcel_reset failed %d", ret); hgsl_hyp_channel_pool_put(hab_channel); hab_channel = NULL; } } return ret; }
创建hab_channel
static int hgsl_rpc_create_channel( struct hgsl_hyp_priv_t *priv, struct hgsl_hab_channel_t **channel) { int socket = HAB_INVALID_HANDLE; int ret = -ENOMEM; struct hgsl_hab_channel_t *hab_channel = (struct hgsl_hab_channel_t *)hgsl_zalloc( sizeof(struct hgsl_hab_channel_t)); if (hab_channel == NULL) { LOGE("Failed to allocate hab_channel"); goto out; } hab_channel->socket = HAB_INVALID_HANDLE; hab_channel->priv = priv; hab_channel->busy = false; hab_channel->wait_retry = false; hab_channel->id = idr_alloc(&priv->channel_idr, hab_channel, 1, 0, GFP_NOWAIT); if (hab_channel->id id; goto out; } //初始化hab_channel ret = hgsl_rpc_parcel_init(hab_channel); if (ret) { LOGE("Failed to init parcel"); goto out; } //创建hab socket if (priv->conn_id == 0) { ret = hgsl_rpc_connect(priv, &socket); if (ret) { LOGE("Failed to open socket %d", ret); goto out; } hab_channel->socket = socket; //进行数据通讯 ret = rpc_handshake(priv, hab_channel); if (ret) LOGE("rpc_handshake failed %d", ret); gsl_hab_close(socket); hab_channel->socket = HAB_INVALID_HANDLE; } ret = hgsl_rpc_connect(priv, &socket); if (ret) { LOGE("Failed to open socket %d", ret); goto out; } hab_channel->socket = socket; ret = rpc_sub_handshake(priv, hab_channel); if (ret) { LOGE("sub handshake failed %d", ret); gsl_hab_close(socket); hab_channel->socket = HAB_INVALID_HANDLE; } out: if (ret) { LOGE("Failed to create channel %d exiting", ret); if (hab_channel != NULL) { hgsl_hyp_close_channel(hab_channel); hab_channel = NULL; } } else { *channel = hab_channel; } return ret; }
static int hgsl_rpc_connect(struct hgsl_hyp_priv_t *priv, int *socket) { int err = 0; int tmp_socket = priv->conn_id; LOGI("connecting using conn_id %d", tmp_socket); err = gsl_hab_open(&tmp_socket); LOGI("socket_open err %d, socket %d", err, tmp_socket); *socket = tmp_socket; return err; }
int gsl_hab_open(int *habfd) { int ret = 0; ret = habmm_socket_open(habfd , HAB_MMID_CREATE(MM_GFX, (int)*habfd) , HAB_OPEN_WAIT_TIMEOUT_MS , HABMM_SOCKET_OPEN_FLAGS_SINGLE_BE_SINGLE_FE); LOGD("habmm_socket_open returned with %d, %x", ret, *habfd); return ret; }
根据p->data_pos获取recv到的数据 #define GSL_RPC_READ_ARG(p, id, p_arg, type) \ 152 ({ \ 153 void *p_arg_data = NULL; \ 154 int ret = gsl_rpc_get_arg_ptr(p, id, &p_arg_data, sizeof(type)); \ 155 if (ret == 0) { \ 156 *p_arg = *((type *)p_arg_data); \ 157 } \ 158 \ 159 ret; \ 160 }) static inline int gsl_rpc_get_arg_ptr(struct gsl_hab_payload *p, 105 uint32_t id, void **p_data, size_t size) 106 { 107 int ret = -EINVAL; 108 109 if ((p->data_pos + size + gsl_rpc_header_size) data_size) { 110 struct gsl_rpc_header_t *hdr 111 = (struct gsl_rpc_header_t *)(p->data + p->data_pos); 112 113 if ((hdr->magic == GSL_HAB_DATA_MAGIC) && 114 (hdr->id == id) && (hdr->size == size)) { 115 struct gsl_rpc_footer_t *footer = NULL; 116 uint32_t checksum; 117 118 checksum = gsl_rpc_gen_checksum(&hdr->data, hdr->size); 119 *p_data = (void *)&hdr->data; 120 p->data_pos += size + gsl_rpc_header_size; 121 footer = (struct gsl_rpc_footer_t *) 122 (p->data + p->data_pos); 123 p->data_pos += sizeof(struct gsl_rpc_footer_t); 124 125 if (checksum == footer->checksum) 126 ret = 0; 127 else 128 LOGE("checksum mismatch %d != %d", 129 checksum, footer->checksum); 130 } else { 131 struct gsl_rpc_header_t *call_hdr 132 = (struct gsl_rpc_header_t *)p->data; 133 size_t dump_size 134 = call_hdr->size + gsl_rpc_header_size 135 + sizeof(struct gsl_rpc_footer_t); 136 137 dump_size = (dump_size data_size) ? 138 dump_size : p->data_size; 139 LOGE("@%d: argument type or size mismatch: call id %d", 140 p->data_pos, call_hdr->id); 141 LOGE("size %d magic 0x%X/0x%X, id %d/%d, size %d/%d", 142 call_hdr->size, hdr->magic, GSL_HAB_DATA_MAGIC, 143 hdr->id, id, hdr->size, size); 144 gsl_hab_payload_dump(p, dump_size); 145 } 146 } 147 148 return ret; 149 }
int gsl_rpc_write(struct gsl_hab_payload *p, const void *data, size_t len) { return GSL_RPC_WRITE_DATA(p, GSL_RPC_BLOB_DATA, p_data, len, do {if (data && len) memcpy(p_data, data, len); } while (0)); } #define GSL_RPC_WRITE_DATA(p, type, data_ptr, len, action) \ ({ \ int status = 0; \ \ if ((p->data_pos + gsl_rpc_header_size + len +\ sizeof(struct gsl_rpc_footer_t) > p->data_size)) { \ status = grow_data(p, len); \ } \ \ if (status == 0) { \ struct gsl_rpc_header_t *hdr = (struct gsl_rpc_header_t *) \ (p->data + p->data_pos); \ struct gsl_rpc_footer_t *ftr = (struct gsl_rpc_footer_t *) \ (p->data + p->data_pos + gsl_rpc_header_size + len); \ void *data_ptr = (void *)&hdr->data; \ uint32_t checksum = 0; \ \ action; \ checksum = gsl_rpc_gen_checksum(data_ptr, len); \ hdr->magic = GSL_HAB_DATA_MAGIC; \ hdr->id = type; \ hdr->version = 2; \ hdr->size = len; \ ftr->checksum = checksum; \ p->data_pos += len + gsl_rpc_header_size \ + sizeof(struct gsl_rpc_footer_t); \ } \ \ status; \ })
通过hab发送数据
static int gsl_rpc_send_(const char *fname, int line_num, void *data,157 size_t size, struct hgsl_hab_channel_t *hab_channel) 158 { 159 int ret = gsl_hab_send(hab_channel->socket, 160 (unsigned char *)data, size); 161 162 if (ret) 163 LOGE("failed to send @ %s:%d", fname, line_num); 164 165 return ret; 166 }
int gsl_hab_send(int habfd, unsigned char *p, size_t sz) { return habmm_socket_send(habfd, p, sz, 0); }
通过hab接收数据
static int gsl_rpc_recv_(const char *fname, int line_num, void *data,170 size_t size, struct hgsl_hab_channel_t *hab_channel, int interruptible) 171 { 172 int ret = gsl_hab_recv(hab_channel->socket, 173 (unsigned char *)data, size, interruptible); 174 175 return ret; 176 }
static int gsl_rpc_transact_ext(uint32_t opcode, uint32_t version, struct hgsl_hab_channel_t *hab_channel, bool interruptible) { int ret = -EINVAL; struct gsl_hab_payload *data = &hab_channel->send_buf; struct gsl_hab_payload *reply = &hab_channel->recv_buf; if (data && reply) { void *p_data; uint32_t data_size, max_size; uint32_t recv_opcode; if (hab_channel->wait_retry && interruptible) { ret = 0; } else if (hab_channel->wait_retry) { LOGE("channel is waiting for retry for uninterruptible RPC call"); ret = -EINVAL; goto out; } else { gsl_rpc_set_call_params(data, opcode, version); ret = gsl_rpc_finalize(data); if (!ret) { ret = gsl_rpc_get_data_params(data, &p_data, &data_size, &max_size); } else { LOGE("failed to set footer, err %d", ret); goto out; } if (!ret) { //通过hab_channel发送数据 ret = gsl_rpc_send(p_data, data->data_pos, hab_channel); } else { LOGE("failed to get data params, err %d", ret); goto out; } } if (!ret) { ret = gsl_rpc_get_data_params(reply, &p_data, &data_size, &max_size); } else { LOGE("failed to send data, err %d", ret); goto out; } //接收hab_channel数据 if (!ret) { ret = gsl_rpc_recv(p_data, max_size, hab_channel, interruptible); } else { LOGE("failed to get data params, err %d", ret); goto out; } if (ret == -EINTR) { goto out; } else if (!ret) { //判断是否opcode一致 ret = gsl_rpc_get_call_params(reply, &recv_opcode, NULL); } else { LOGE("failed to recv data, err %d", ret); goto out; } if (!ret) { if (recv_opcode != opcode) { if (opcode != RPC_DISCONNECT) LOGE("recv opcode %d (%s), expected %d (%s)", recv_opcode, hgsl_get_rpc_fname(recv_opcode), opcode, hgsl_get_rpc_fname(opcode)); ret = -EINVAL; } } else { LOGE("failed to parse data, err %d", ret); } } out: return ret; }
通过hypervisor 发送和接收数据
static int rpc_handshake(struct hgsl_hyp_priv_t *priv, struct hgsl_hab_channel_t *hab_channel) { int ret = 0; int rval = GSL_SUCCESS; struct gsl_hab_payload *send_buf = NULL; struct gsl_hab_payload *recv_buf = NULL; struct handshake_params_t params = { 0 }; int tmp = 0; enum gsl_rpc_server_type_t server_type = GSL_RPC_SERVER_TYPE_LAST; enum gsl_rpc_server_mode_t server_mode = GSL_RPC_SERVER_MODE_LAST; RPC_TRACE(); ret = hgsl_rpc_parcel_reset(hab_channel); if (ret) { LOGE("hgsl_rpc_parcel_reset failed %d", ret); goto out; } send_buf = &hab_channel->send_buf; recv_buf = &hab_channel->recv_buf; params.client_type = g_client_type; params.client_version = g_client_version; params.pid = priv->client_pid; params.size = sizeof(params); /* send the current process name to the server */ strlcpy(params.name, priv->client_name, sizeof(params.name)); LOGD("client process name is (%s)", params.name); //将数据写入hab_channel->send_buf中 ret = gsl_rpc_write(send_buf, ¶ms, sizeof(params)); if (ret) { LOGE("gsl_rpc_write failed %d", ret); goto out; } //将数据发送通过hab发送到qnx端habmm_socket_send ret = gsl_rpc_transact_ext(RPC_HANDSHAKE, 1, hab_channel, 0); if (ret) { LOGE("gsl_rpc_transact_ext failed %d", ret); goto out; } //将recv_buf中的数据hdr->data指向rval //如果获取到数据rval不等于GSL_SUCCESS,qnx sent侧发送失败 ret = gsl_rpc_read_int32_l(recv_buf, &rval); if ((!ret) && (rval != GSL_SUCCESS)) { LOGE("BE sent error %d", rval); ret = -EINVAL; } if (!ret) { ret = gsl_rpc_read_int32_l(recv_buf, &priv->conn_id); if (ret) { LOGE("Failed to read conn_id %d", ret); goto out; } ret = gsl_rpc_read_int32_l(recv_buf, &tmp); if (ret) { LOGE("Failed to read server_type %d", ret); goto out; } server_type = (enum gsl_rpc_server_type_t)tmp; ret = gsl_rpc_read_int32_l(recv_buf, &tmp); if (ret) { LOGE("Failed to read server_mode %d", ret); goto out; } server_mode = (enum gsl_rpc_server_mode_t)tmp; LOGI("Successfully connected to server, got connection id %d", priv->conn_id); } else { LOGE("handshake failed, %d", ret); } out: RPC_TRACE_DONE(); return ret; }
发送RPC_CONTEXT_CREATE到qnx be 端
int hgsl_hyp_ctxt_create(struct hgsl_hab_channel_t *hab_channel, struct hgsl_ioctl_ctxt_create_params *hgsl_params) { struct context_create_params_t rpc_params = { 0 }; struct gsl_hab_payload *send_buf = NULL; struct gsl_hab_payload *recv_buf = NULL; int ret = 0; RPC_TRACE(); if (!hab_channel) { LOGE("invalid hab_channel"); ret = -EINVAL; goto out; } ret = hgsl_rpc_parcel_reset(hab_channel); if (ret) { LOGE("hgsl_rpc_parcel_reset failed %d", ret); goto out; } send_buf = &hab_channel->send_buf; recv_buf = &hab_channel->recv_buf; rpc_params.size = sizeof(rpc_params); rpc_params.devhandle = hgsl_params->devhandle; rpc_params.type = hgsl_params->type; rpc_params.flags = hgsl_params->flags; ret = gsl_rpc_write(send_buf, &rpc_params, sizeof(rpc_params)); if (ret) { LOGE("gsl_rpc_write failed, %d", ret); goto out; } ret = gsl_rpc_transact(RPC_CONTEXT_CREATE, hab_channel); if (ret) { LOGE("gsl_rpc_transact failed, %d", ret); goto out; } ret = gsl_rpc_read_uint32_l(recv_buf, &hgsl_params->ctxthandle); if (ret) { LOGE("gsl_rpc_read_uint32_l failed, %d", ret); goto out; } out: RPC_TRACE_DONE(); return ret; }
static int gsl_rpc_transact(uint32_t opcode, struct hgsl_hab_channel_t *hab_channel) { int ret = gsl_rpc_transact_ext(opcode, 0, hab_channel, false); if (ret == -EINTR) { LOGE("noninterruptible transaction was interrupted"); ret = -EINVAL; } return ret; }
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。
还没有评论,来说两句吧...