mm_camera_sock.c revision 6f83d735d8e3b918da42e6b559fcd0efb78133e5
1/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <stdio.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <errno.h>
34#include <string.h>
35#include <sys/socket.h>
36#include <sys/uio.h>
37#include <sys/un.h>
38
39#include "mm_camera_dbg.h"
40#include "mm_camera_sock.h"
41
42/*===========================================================================
43 * FUNCTION   : mm_camera_socket_create
44 *
45 * DESCRIPTION: opens a domain socket tied to camera ID and socket type
46 *  @cam_id   : camera ID
47 *  @sock_type: socket type, TCP/UDP
48 *
49 * RETURN     : fd related to the domain socket
50 *==========================================================================*/
51int mm_camera_socket_create(int cam_id, mm_camera_sock_type_t sock_type)
52{
53    int socket_fd;
54    struct sockaddr_un sock_addr;
55    int sktype;
56    int rc;
57
58    switch (sock_type)
59    {
60      case MM_CAMERA_SOCK_TYPE_UDP:
61        sktype = SOCK_DGRAM;
62        break;
63      case MM_CAMERA_SOCK_TYPE_TCP:
64        sktype = SOCK_STREAM;
65        break;
66      default:
67        CDBG_ERROR("%s: unknown socket type =%d", __func__, sock_type);
68        return -1;
69    }
70    socket_fd = socket(AF_UNIX, sktype, 0);
71    if (socket_fd < 0) {
72        CDBG_ERROR("%s: error create socket fd =%d", __func__, socket_fd);
73        return socket_fd;
74    }
75
76    memset(&sock_addr, 0, sizeof(sock_addr));
77    sock_addr.sun_family = AF_UNIX;
78    snprintf(sock_addr.sun_path, UNIX_PATH_MAX, "/data/cam_socket%d", cam_id);
79    if((rc = connect(socket_fd, (struct sockaddr *) &sock_addr,
80      sizeof(sock_addr))) != 0) {
81      close(socket_fd);
82      socket_fd = -1;
83      CDBG_ERROR("%s: socket_fd=%d %s ", __func__, socket_fd, strerror(errno));
84    }
85
86    CDBG("%s: socket_fd=%d %s", __func__, socket_fd, sock_addr.sun_path);
87    return socket_fd;
88}
89
90/*===========================================================================
91 * FUNCTION   : mm_camera_socket_close
92 *
93 * DESCRIPTION:  close domain socket by its fd
94 *   @fd      : file descriptor for the domain socket to be closed
95 *
96 * RETURN     : none
97 *==========================================================================*/
98void mm_camera_socket_close(int fd)
99{
100    if (fd > 0) {
101      close(fd);
102    }
103}
104
105/*===========================================================================
106 * FUNCTION   : mm_camera_socket_sendmsg
107 *
108 * DESCRIPTION:  send msg through domain socket
109 *   @fd      : socket fd
110 *   @msg     : pointer to msg to be sent over domain socket
111 *   @sendfd  : file descriptors to be sent
112 *
113 * RETURN     : the total bytes of sent msg
114 *==========================================================================*/
115int mm_camera_socket_sendmsg(
116  int fd,
117  void *msg,
118  uint32_t buf_size,
119  int sendfd)
120{
121    struct msghdr msgh;
122    struct iovec iov[1];
123    struct cmsghdr * cmsghp = NULL;
124    char control[CMSG_SPACE(sizeof(int))];
125
126    if (msg == NULL) {
127      CDBG("%s: msg is NULL", __func__);
128      return -1;
129    }
130    memset(&msgh, 0, sizeof(msgh));
131    msgh.msg_name = NULL;
132    msgh.msg_namelen = 0;
133
134    iov[0].iov_base = msg;
135    iov[0].iov_len = buf_size;
136    msgh.msg_iov = iov;
137    msgh.msg_iovlen = 1;
138    CDBG("%s: iov_len=%d", __func__, iov[0].iov_len);
139
140    msgh.msg_control = NULL;
141    msgh.msg_controllen = 0;
142
143    /* if sendfd is valid, we need to pass it through control msg */
144    if( sendfd > 0) {
145      msgh.msg_control = control;
146      msgh.msg_controllen = sizeof(control);
147      cmsghp = CMSG_FIRSTHDR(&msgh);
148      if (cmsghp != NULL) {
149        CDBG("%s: Got ctrl msg pointer", __func__);
150        cmsghp->cmsg_level = SOL_SOCKET;
151        cmsghp->cmsg_type = SCM_RIGHTS;
152        cmsghp->cmsg_len = CMSG_LEN(sizeof(int));
153        *((int *)CMSG_DATA(cmsghp)) = sendfd;
154        CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp)));
155      } else {
156        CDBG("%s: ctrl msg NULL", __func__);
157        return -1;
158      }
159    }
160
161    return sendmsg(fd, &(msgh), 0);
162}
163
164/*===========================================================================
165 * FUNCTION   : mm_camera_socket_recvmsg
166 *
167 * DESCRIPTION:  receive msg from domain socket.
168 *   @fd      : socket fd
169 *   @msg     : pointer to mm_camera_sock_msg_packet_t to hold incoming msg,
170 *              need be allocated by the caller
171 *   @buf_size: the size of the buf that holds incoming msg
172 *   @rcvdfd  : pointer to hold recvd file descriptor if not NULL.
173 *
174 * RETURN     : the total bytes of received msg
175 *==========================================================================*/
176int mm_camera_socket_recvmsg(
177  int fd,
178  void *msg,
179  uint32_t buf_size,
180  int *rcvdfd)
181{
182    struct msghdr msgh;
183    struct iovec iov[1];
184    struct cmsghdr *cmsghp = NULL;
185    char control[CMSG_SPACE(sizeof(int))];
186    int rcvd_fd = -1;
187    int rcvd_len = 0;
188
189    if ( (msg == NULL) || (buf_size <= 0) ) {
190      CDBG_ERROR(" %s: msg buf is NULL", __func__);
191      return -1;
192    }
193
194    memset(&msgh, 0, sizeof(msgh));
195    msgh.msg_name = NULL;
196    msgh.msg_namelen = 0;
197    msgh.msg_control = control;
198    msgh.msg_controllen = sizeof(control);
199
200    iov[0].iov_base = msg;
201    iov[0].iov_len = buf_size;
202    msgh.msg_iov = iov;
203    msgh.msg_iovlen = 1;
204
205    if ( (rcvd_len = recvmsg(fd, &(msgh), 0)) <= 0) {
206      CDBG_ERROR(" %s: recvmsg failed", __func__);
207      return rcvd_len;
208    }
209
210    CDBG("%s:  msg_ctrl %p len %d", __func__, msgh.msg_control, msgh.msg_controllen);
211
212    if( ((cmsghp = CMSG_FIRSTHDR(&msgh)) != NULL) &&
213        (cmsghp->cmsg_len == CMSG_LEN(sizeof(int))) ) {
214      if (cmsghp->cmsg_level == SOL_SOCKET &&
215        cmsghp->cmsg_type == SCM_RIGHTS) {
216        CDBG("%s:  CtrlMsg is valid", __func__);
217        rcvd_fd = *((int *) CMSG_DATA(cmsghp));
218        CDBG("%s:  Receieved fd=%d", __func__, rcvd_fd);
219      } else {
220        CDBG_ERROR("%s:  Unexpected Control Msg. Line=%d", __func__, __LINE__);
221      }
222    }
223
224    if (rcvdfd) {
225      *rcvdfd = rcvd_fd;
226    }
227
228    return rcvd_len;
229}
230