static int oem_rapi_client_streaming_function_ret(struct msm_rpc_client *client, struct msm_rpc_xdr *xdr, void *data) { struct oem_rapi_client_streaming_func_ret *ret = data; uint32_t temp; /* out_len */ xdr_recv_pointer(xdr, (void **)&(ret->out_len), sizeof(uint32_t), xdr_recv_uint32); if (ret->out_len && *ret->out_len /*&&ret->output*/) xdr_recv_bytes(xdr, (void **)&ret->output, &temp); return 0; }
/* TODO: check where to allocate memory for return */ static int oem_rapi_client_cb(struct msm_rpc_client *client, struct rpc_request_hdr *req, struct msm_rpc_xdr *xdr) { uint32_t cb_id, accept_status; int rc; void *cb_func; uint32_t temp; struct oem_rapi_client_streaming_func_cb_arg arg; struct oem_rapi_client_streaming_func_cb_ret ret; arg.input = NULL; ret.out_len = NULL; ret.output = NULL; xdr_recv_uint32(xdr, &cb_id); /* cb_id */ xdr_recv_uint32(xdr, &arg.event); /* enum */ xdr_recv_uint32(xdr, (uint32_t *)(&arg.handle)); /* handle */ xdr_recv_uint32(xdr, &arg.in_len); /* in_len */ xdr_recv_bytes(xdr, (void **)&arg.input, &temp); /* input */ xdr_recv_uint32(xdr, &arg.out_len_valid); /* out_len */ if (arg.out_len_valid) { ret.out_len = kmalloc(sizeof(*ret.out_len), GFP_KERNEL); if (!ret.out_len) { accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR; goto oem_rapi_send_ack; } } xdr_recv_uint32(xdr, &arg.output_valid); /* out */ if (arg.output_valid) { xdr_recv_uint32(xdr, &arg.output_size); /* ouput_size */ ret.output = kmalloc(arg.output_size, GFP_KERNEL); if (!ret.output) { accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR; goto oem_rapi_send_ack; } } cb_func = msm_rpc_get_cb_func(client, cb_id); if (cb_func) { rc = ((int (*)(struct oem_rapi_client_streaming_func_cb_arg *, struct oem_rapi_client_streaming_func_cb_ret *)) cb_func)(&arg, &ret); if (rc) accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR; else accept_status = RPC_ACCEPTSTAT_SUCCESS; } else accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR; oem_rapi_send_ack: xdr_start_accepted_reply(xdr, accept_status); if (accept_status == RPC_ACCEPTSTAT_SUCCESS) { uint32_t temp = sizeof(uint32_t); xdr_send_pointer(xdr, (void **)&(ret.out_len), temp, xdr_send_uint32); /* output */ if (ret.output && ret.out_len) xdr_send_bytes(xdr, (const void **)&ret.output, ret.out_len); else { temp = 0; xdr_send_uint32(xdr, &temp); } } rc = xdr_send_msg(xdr); if (rc) pr_err("%s: sending reply failed: %d\n", __func__, rc); kfree(arg.input); kfree(ret.out_len); kfree(ret.output); return 0; }