static int v4l2_g_ctrl(GstImxV4l2VideoSrc *v4l2src, int id, int *value) { struct v4l2_control control; int ret; control.id = id; ret = ioctl(GST_IMX_FD_OBJECT_GET_FD(v4l2src->fd_obj_v4l), VIDIOC_G_CTRL, &control); if (ret < 0) GST_LOG_OBJECT(v4l2src, "VIDIOC_G_CTRL(%s) failed", ctrl_name(id)); else { GST_LOG_OBJECT(v4l2src, "VIDIOC_G_CTRL(%s) returned %d", ctrl_name(id), control.value); *value = control.value; } return ret; }
static inline int v4l2_s_ctrl(GstImxV4l2VideoSrc *v4l2src, int id, int value) { struct v4l2_control control; int ret; GST_LOG_OBJECT(v4l2src, "VIDIOC_S_CTRL(%s, %d)", ctrl_name(id), value); control.id = id; control.value = value; ret = ioctl(GST_IMX_FD_OBJECT_GET_FD(v4l2src->fd_obj_v4l), VIDIOC_S_CTRL, &control); if (ret < 0) GST_LOG_OBJECT(v4l2src, "VIDIOC_S_CTRL(%s, %d) failed", ctrl_name(id), value); else GST_LOG_OBJECT(v4l2src, "VIDIOC_S_CTRL(%s, %d) succeed", ctrl_name(id), value); return ret; }
/* * Handles merlin control events inside the module. Control events * that relate to cross-host communication only never reaches this. */ void handle_control(merlin_node *node, merlin_event *pkt) { const char *ctrl; if (!pkt) { lerr("handle_control() called with NULL packet"); return; } ctrl = ctrl_name(pkt->hdr.code); linfo("Received control packet code %d (%s) from %s", pkt->hdr.code, ctrl, node ? node->name : "local Merlin daemon"); /* protect against bogus headers */ if (!node && (pkt->hdr.code == CTRL_INACTIVE || pkt->hdr.code == CTRL_ACTIVE)) { lerr("Received %s with unknown node id %d", ctrl, pkt->hdr.selection); return; } switch (pkt->hdr.code) { case CTRL_INACTIVE: /* * must memset() node->info before the disconnect handler * so we discard it in the peer id calculation dance if * we get data from it before it sends us a CTRL_ACTIVE * packet */ memset(&node->info, 0, sizeof(node->info)); node_set_state(node, STATE_NONE, "Received CTRL_INACTIVE"); break; case CTRL_ACTIVE: /* * Only mark the node as connected if the CTRL_ACTIVE packet * checks out properly and the info is new. If it *is* new, * we must re-do the peer assignment thing. */ if (!handle_ctrl_active(node, pkt)) { node_set_state(node, STATE_CONNECTED, "Received CTRL_ACTIVE"); assign_peer_ids(); } break; case CTRL_STALL: ctrl_stall_start(); break; case CTRL_RESUME: ctrl_stall_stop(); assign_peer_ids(); break; case CTRL_STOP: linfo("Received (and ignoring) CTRL_STOP event. What voodoo is this?"); break; default: lwarn("Unknown control code: %d", pkt->hdr.code); } }
/* * wraps io_send_all() and adds proper error handling when we run * into sending errors. It's up to the caller to poll the socket * for writability, or pass the proper flags and ignore errors */ int node_send(merlin_node *node, void *data, int len, int flags) { merlin_event *pkt = (merlin_event *)data; int sent, sd = 0; if (!node || node->sock < 0) return 0; if (len >= HDR_SIZE && pkt->hdr.type == CTRL_PACKET) { ldebug("Sending %s to %s", ctrl_name(pkt->hdr.code), node->name); if (pkt->hdr.code == CTRL_ACTIVE) { merlin_nodeinfo *info = (merlin_nodeinfo *)&pkt->body; ldebug(" start time: %lu.%lu", info->start.tv_sec, info->start.tv_usec); ldebug(" config hash: %s", tohex(info->config_hash, 20)); ldebug(" config mtime: %lu", info->last_cfg_change); } } sent = io_send_all(node->sock, data, len); /* success. Should be the normal case */ if (sent == len) { node->stats.bytes.sent += sent; node->last_action = node->last_sent = time(NULL); return sent; } /* * partial writes and complete failures can only be handled * by disconnecting and re-syncing the stream */ sd = node->sock; node_disconnect(node, "Partial or failed write() (sent=%d; len=%d): %s", sent, len, strerror(errno)); if (sent < 0) { /* if we would have blocked, we simply return 0 */ if (errno == EAGAIN || errno == EWOULDBLOCK) return 0; /* otherwise we log the error and disconnect the node */ lerr("Failed to send(%d, %p, %d, %d) to %s: %s", sd, data, len, flags, node->name, strerror(errno)); return sent; } /* partial write. ugh... */ lerr("Partial send() to %s. %d of %d bytes sent", node->name, sent, len); return -1; }