/** * rpmsg_ns_callback * * This callback handles name service announcement from the remote device * and creates/deletes rpmsg channels. * * @param server_chnl - pointer to server channel control block. * @param data - pointer to received messages * @param len - length of received data * @param priv - any private data * @param src - source address * * @return void */ void rpmsg_ns_callback(struct rpmsg_channel *server_chnl, void *data, int len, void *priv, unsigned long src) { struct remote_device *rdev; struct rpmsg_channel *rp_chnl; struct rpmsg_ns_msg *ns_msg; struct llist *node; rdev = (struct remote_device *) priv; //FIXME: This assumes same name string size for channel name both on master //and remote. If this is not the case then we will have to parse the //message contents. ns_msg = (struct rpmsg_ns_msg *) data; ns_msg->name[len - 1] = '\0'; if (ns_msg->flags & RPMSG_NS_DESTROY) { node = rpmsg_rdev_get_chnl_node_from_id(rdev, ns_msg->name); if (node) { rp_chnl = (struct rpmsg_channel *) node->data; if (rdev->channel_destroyed) { rdev->channel_destroyed(rp_chnl); } rpmsg_destroy_ept(rp_chnl->rp_ept); _rpmsg_delete_channel(rp_chnl); } } else { rp_chnl = _rpmsg_create_channel(rdev, ns_msg->name, 0x00, ns_msg->addr); if (rp_chnl) { rp_chnl->state = RPMSG_CHNL_STATE_ACTIVE; /* Create default endpoint for channel */ rp_chnl->rp_ept = rpmsg_create_ept(rp_chnl, rdev->default_cb, rdev, RPMSG_ADDR_ANY); if (rp_chnl->rp_ept) { rp_chnl->src = rp_chnl->rp_ept->addr; /* * Echo back the NS message to remote in order to * complete the connection stage. Remote will know the endpoint * address from this point onward which will enable it to send * message without waiting for any application level message from * master. */ rpmsg_send(rp_chnl,data,len); if (rdev->channel_created) { rdev->channel_created(rp_chnl); } } } } }
/** * _rpmsg_delete_channel * * Deletes given rpmsg channel. * * @param rp_chnl - pointer to rpmsg channel to delete * * return - none */ void _rpmsg_delete_channel(struct rpmsg_channel * rp_chnl) { struct llist *node; if (rp_chnl) { node = rpmsg_rdev_get_chnl_node_from_id(rp_chnl->rdev, rp_chnl->name); if (node) { env_lock_mutex(rp_chnl->rdev->lock); remove_from_list(&rp_chnl->rdev->rp_channels, node); env_unlock_mutex(rp_chnl->rdev->lock); env_free_memory(node); } env_free_memory(rp_chnl); } }