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 *==========================================================================*/ 51 int 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 *==========================================================================*/ 98 void 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 *==========================================================================*/ 115 int 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 *==========================================================================*/ 176 int 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