当前位置: 首页 > news >正文

Hypervisor Display架构

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 = <0x3d00000 0x8>, <0x3d8f000 0x4>;reg-names = "hgsl_reg_hwinf", "hgsl_reg_gmucx";qcom,glb-db-senders = <&hgsl_tcsr_sender0&hgsl_tcsr_sender1>;qcom,glb-db-receivers = <&hgsl_tcsr_receiver0&hgsl_tcsr_receiver1>;};

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 < 0) {dev_err(&pdev->dev, "qcom_hgsl_register failed, ret %d\n",ret);return ret;}ret = hgsl_init_context(hgsl_dev);if (ret < 0) {dev_err(&pdev->dev, "hgsl_init_context failed, ret %d\n",ret);goto exit_dereg;}//创建hgsl-release-wq workqueueret = hgsl_init_release_wq(hgsl_dev);if (ret < 0) {dev_err(&pdev->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 < MAX_DB_QUEUE; i++) {mutex_init(&hgsl_dev->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 < 0) {dev_err(&pdev->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 < 0) {dev_err(&pdev->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_structstruct 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(&params, USRPTR(arg), sizeof(params))) {LOGE("failed to copy params from user");ret = -EFAULT;return ret;}//建立hab socketret = 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, &params);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 < 0)LOGE("hsync timeline failed for context %d", params.ctxthandle);}if (ctxt->timeline)params.sync_type = HGSL_SYNC_TYPE_HSYNC;elseparams.sync_type = HGSL_SYNC_TYPE_ISYNC;if (copy_to_user(USRPTR(arg), &params, 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 < HGSL_CONTEXT_NUM)) {_unmap_shadow(ctxt);hgsl_hyp_put_shadowts_mem(hab_channel, &ctxt->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 < 0) {LOGE("Failed to allocate id for hab channel");ret = hab_channel->id;goto out;}//初始化hab_channelret = hgsl_rpc_parcel_init(hab_channel);if (ret) {LOGE("Failed to init parcel");goto out;}//创建hab socketif (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) <= p->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 <= p->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, &params, sizeof(params));if (ret) {LOGE("gsl_rpc_write failed %d", ret);goto out;}//将数据发送通过hab发送到qnx端habmm_socket_sendret = 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;
}

相关文章:

Hypervisor Display架构

Hypervisor Display架构部分 1&#xff0c;所有LA侧的APP与显示相关的调用最终都会交由SurfaceFlinger处理 2&#xff0c;SurfaceFlinger会最终调用android.hardware.graphics.composer2.4-service服务 3&#xff0c;android.hardware.graphics.composer2.4-service服务会调用G…...

基于ssm二手车交易平台的设计论文

摘 要 进入21世纪网络和计算机得到了飞速发展&#xff0c;并和生活进行了紧密的结合。目前&#xff0c;网络的运行速度以达到了千兆&#xff0c;覆盖范围更是深入到生活中的角角落落。这就促使二手交易网站的发展。二手交易网站可以实现远程购物&#xff0c;远程选择喜欢的商品…...

IDEA 设置 SpringBoot logback 彩色日志(附配置文件)

1、背景说明 最开始使用 SpringBoot 时&#xff0c;控制台日志是带彩色的&#xff0c;让人眼前一亮&#x1f604; 后来彩色莫名丢失&#xff0c;由于影响不大&#xff0c;一直没有处理。 2、配置彩色 最近找到了解决方法&#xff08;其实是因为自定义 logback.xml&#xff0…...

数学建模学习笔记-皮尔逊相关系数

内容&#xff1a;皮尔逊相关系数 一.概念&#xff1a;是一个和线性线关的相关性系数 1.协方差概念&#xff1a; 协方差受到量纲的影响因此需要剔除 2.相关性的误区 根据这个结论&#xff0c;我们在计算该系数之前需要确定是否为线性函数 二.相关性的计算 1.Matlab&#xff…...

随笔:集成学习:关于随机森林,梯度提升机的东拉西扯

1.集成学习 这里不会描述算法过程。 当我们有许多学习器对同一个任务做出判断&#xff0c;他们预测的概率可能各不相同&#xff0c;比如预测一个男生(小徐)会不会喜欢另一个女生(小雪)&#xff0c;支持向量机算出来小徐爱上小雪的概率是0.8&#xff0c;朴素贝叶斯认为是0.3&a…...

多款实用个人年终总结模板,助力你的年度汇报!

临近年末&#xff0c;相信很多职场人这阵子都在忙着撰写个人年终总结&#xff0c;这份材料是对自己过去一年的工作进行的回顾和总结。撰写年终总结&#xff0c;其实也是一个非常重要的自我反思过程&#xff0c;可以帮助我们明确自己的目标&#xff0c;找出需要改进的地方&#…...

【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化

引言 动态内存管理的函数有&#xff1a;malloc,calloc,ralloc,free,本文讲解动态内存函数和使用&#xff0c;如何进行动态内存管理,实现通讯录联系人容量的动态化&#xff0c;对常见动态内存错误进行总结。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》…...

Centos9(Stream)配置Let‘s Encrypt (免费https证书)

1. 安装snap&#xff0c;用来安装certbot&#xff1a; sudo dnf install epel-release sudo dnf upgrade sudo yum install snapd sudo systemctl enable --now snapd.socket sudo ln -s /var/lib/snapd/snap /snap snap install core snap refresh core 2. 安装 certbot命令…...

Spring之事务(2)

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…...

嵌入式科普(5)ARM GNU Toolchain相关概念和逻辑

一、目的/概述 二、资料来源 三、逻辑和包含关系 四、Arm GNU Toolchain最常用的命令 嵌入式科普(5)ARM GNU Toolchain相关概念和逻辑 一、目的/概述 对比高集成度的IDE(MDK、IAR等)&#xff0c;Linux开发需要自己写Makefile等多种脚本。eclipse、Visual Studio等需要了解预处…...

Elasticsearch:什么是文本分类?

文本分类定义 - text classification 文本分类是一种机器学习&#xff0c;它将文本文档或句子分类为预定义的类或类别。 它分析文本的内容和含义&#xff0c;然后使用文本标签为其分配最合适的标签。 文本分类的实际应用包括情绪分析&#xff08;确定评论中的正面或负面情绪&…...

指针(3)

C语言昂&#xff0c;指针昂&#xff0c;最喜欢的一集&#xff0c;小时候学这一课我直接取地址了。上一篇博客给大家讲解了不同类型的指针变量的大小&#xff0c;今天来给大家讲解一下根据其所产生的一些性质。&#xff08;往期回顾&#xff1a;指针&#xff08;2&#xff09;-C…...

外汇天眼:我碰到外汇投资骗局了吗?学会这5招,轻松识别外汇诈骗黑平台!

近年来外汇市场因为交易量大、流动性大、不容易被控盘、品种简单、风险相对低等特色&#xff0c;因此吸引不少投资人青睐&#xff0c;成为全球金融市场的热门选择。 然而&#xff0c;市面上充斥许多诈骗集团设立的黑平台&#xff0c;也打着投资外汇的名义行骗&#xff0c;不免会…...

一文解析子网掩码和默认网关,成为网络设置达人

随着互联网的普及&#xff0c;越来越多的人开始接触并使用电脑和网络。然而&#xff0c;对于很多初学者来说&#xff0c;网络设置中的子网掩码和默认网关是两个相对陌生的概念。今天&#xff0c;我们就来深入解析这两个概念&#xff0c;让你轻松掌握网络设置技巧&#xff01; …...

二分查找法详解(6种变形)

前言 在之前的博客中&#xff0c;我给大家介绍了最基础的二分查找法&#xff08;没学的话点我点我&#xff01;&#xff09; 今天我将带大家学习二分法的六种变形如何使用&#xff0c;小伙伴们&#xff0c;快来开始今天的学习吧&#xff01; 文章目录 1&#xff0c;查找第一个…...

uniapp uview 页面多个select组件回显处理,默认选中

<view class"add-item column space-around" click"selectClick(1)"><text class"w-s-color-3 f-28">商品分类</text><view class"w-100 space-between"><!-- 第一个参数为你的单选数组&#xff0c;第二个…...

linux中playbook的控制语句

本章主要介绍 playbook中的控制语句。 使用 when 判断语句 block-rescue判断 循环语句 一个play中可以包含多个task&#xff0c;如果不想所有的task全部执行&#xff0c;可以设置只有满足某个 条件才执行这个task&#xff0c;不满足条件则不执行此task。本章主要讲解when 和 …...

MongoDB介绍

一、MongoDB介绍 1.1 mongoDB介绍 MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB …...

再看参数校验

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 写一个接口&#xff0c…...

计算机存储术语: 扇区,磁盘块,页

扇区(sector) 硬盘的读写以扇区为基本单位。磁盘上的每个磁道被等分为若干个弧段&#xff0c;这些弧段称之为扇区。硬盘的物理读写以扇区为基本单位。通常情况下每个扇区的大小是 512 字节。linux 下可以使用 fdisk -l 了解扇区大小&#xff1a; $ sudo /sbin/fdisk -l Disk …...

解决IDEA编译/启动报错:Abnormal build process termination

报错信息 报错信息如下&#xff1a; Abnormal build process termination: "D:\Software\Java\jdk\bin\java" -Xmx3048m -Djava.awt.headlesstrue -Djava.endorsed.dirs\"\" -Djdt.compiler.useSingleThreadtrue -Dpreload.project.path………………很纳…...

Jetpack DataStore

文章目录 Jetpack DataStore概述DataStore 对比 SP添加依赖库Preferences DataStore路径创建 Preferences DataStore获取数据保存数据修改数据删除数据清除全部数据 Proto DataStore配置AndroidStudio安装插件配置proto文件创建序列化器 创建 Proto DataStore获取数据保存数据修…...

在Portainer创建Nginx容器并部署Web静态站点实现公网访问

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《Linux》《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;…...

泛微e-cology XmlRpcServlet文件读取漏洞复现

漏洞介绍 泛微新一代移动办公平台e-cology不仅组织提供了一体化的协同工作平台,将组织事务逐渐实现全程电子化,改变传统纸质文件、实体签章的方式。泛微OA E-Cology 平台XmRpcServlet接口处存在任意文件读取漏洞&#xff0c;攻击者可通过该漏洞读取系统重要文件 (如数据库配置…...

当下流行的直播技术demo演示

nginx-http-flv-module&#xff08;更新不是很频繁&#xff09; SRS: https://ossrs.net/lts/zh-cn/&#xff08;独立官网&#xff0c;目前最新稳定版version5&#xff09; 基于SRS搭建直播demo演示&#xff1a; 一、搭建流媒体服务器 参见官网&#xff1a;https://ossrs.ne…...

Zabbix自动发现并注册已安装agent的主机

先在被监控主机上安装好zabbix-agent 然后登录zabbix网页 点击发现动作后会出现第三步 然后编辑操作&#xff0c;发现后加入到主机组群 然后编辑发现规则 然后就可以在主机列表中看到被发现的主机。...

Jtti:linux搭建开源ldap服务器的方法

搭建开源LDAP服务器是一种用于集中管理用户身份认证和授权信息的方法。在Linux系统上&#xff0c;OpenLDAP是一个流行的开源LDAP实现&#xff0c;可以用于搭建LDAP服务器。以下是搭建OpenLDAP服务器的基本步骤&#xff1a; 步骤一&#xff1a;安装OpenLDAP 安装OpenLDAP软件包&…...

Gazebo GUI模型编辑器

模型编辑器 现在我们将构建我们的简单机器人。我们将制作一个轮式车辆&#xff0c;并添加一个传感器&#xff0c;使我们能够让机器人跟随一个斑点&#xff08;人&#xff09;。 模型编辑器允许我们直接在图形用户界面 &#xff08;GUI&#xff09; 中构建简单的模型。对于更复…...

pycharm运行正常,但命令行执行提示module不存在的多种解决方式

问题描述 在执行某个测试模块时出现提示&#xff0c;显示自定义模块data不存在&#xff0c;但是在PyCharm下运行正常。错误信息如下&#xff1a; Traceback (most recent call last):File "/run/channelnterface-autocase/testcases/test_chanel_detail.py", line 2…...

GBASE南大通用GBase 8a ODBC的安装文件

GBASE南大通用GBase 8a ODBC 体系结构是基于五个组件&#xff0c;在下图中所示&#xff1a; GBase 8a ODBC 体系结构图  应用 应用是通过调用 ODBC API 实现对 GBase 数据访问的程序。应用使用标准的 ODBC 调用与驱动程序管理器通信。应用并不关心数据存储在哪里&#xff…...

wordpress pdf 加密/网络整合营销理论案例

本文通过介绍 Linux 系统工具&#xff08;Ftkimage、xmount、Volatility、dd、netcat&#xff09;来介绍使用计算机取证的方法和步骤。 硬盘数据的取证是指为了证据保全&#xff0c;确保取证工作造成数据丢失&#xff0c;在获取到证据介质后&#xff0c;首先要做的就是对介质数…...

微网站与手机网站/口碑营销5t理论

http://www.cnblogs.com/chenergougou/p/7056557.html openstack RPC通信 OpenStack 的主要组件有 Nova、Cinder、Neutron、Glance 等&#xff0c;分别负责云平台的计算、存储、网络资源管理。openstack 各组件之间是通过 REST 接口进行相互通信&#xff0c;而各组件内部则采用…...

引航博景网站做的很好吗/java培训机构十强

main.sh 主控制脚本#!/bin/bash# 是否发送邮件的开关(维护模式下我们需要关闭此功能&#xff0c;监控还是继续&#xff0c;但不发任何邮件。)export send1# 过滤ip地址(一旦报警&#xff0c;需要需要知道是哪台机器的IP&#xff0c;没有服务端&#xff0c;全部都是独立运行的。…...

dw中旅游网站怎么做/网站制作大概多少钱

看到oracle官方文档说oracle 11g dataguard在物理standby机器上出于open状态也可以应用redo,所以就在本地试验了下,确实如此,这样既可以应用redo也可以进行数据查询和数据库的备份.既解决了数据的容灾也解决了主数据库的压力.Oracle dataguard 简介 Dataguard分为2类:物理stan…...

高校财务网站建设/时事热点新闻

Android Retrofit详解 文章目录Android Retrofit详解前言使用步骤1.添加Retrofit库的依赖&#xff1a;2.创建用于描述网络请求的接口3.创建Retrofit实例4.发送请求注解第一类&#xff1a;网络请求方法第二类&#xff1a;标记第三类&#xff1a;网络请求参数前言 Retrofit 是一…...

浦东网站建设价格/网络销售渠道有哪些

正常理工科非科班学校水平 强调自己数学能力强&#xff0c;并且数学能力可以变现&#xff0c;而不是单纯的做数学研究。 如果面试官对你经历毫不感兴趣&#xff0c;那么就会问很多计算机基础&#xff0c;或者算法题&#xff0c;up主的方法是尽可能与面试官聊到一起&#xff0c;…...