1 /* Copyright (c) 2012-2016, 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 // System dependencies 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <string.h> 35 36 // Camera dependencies 37 #include "mm_camera_dbg.h" 38 #include "mm_camera_sock.h" 39 40 /*=========================================================================== 41 * FUNCTION : mm_camera_socket_create 42 * 43 * DESCRIPTION: opens a domain socket tied to camera ID and socket type 44 * @cam_id : camera ID 45 * @sock_type: socket type, TCP/UDP 46 * 47 * RETURN : fd related to the domain socket 48 *==========================================================================*/ 49 int mm_camera_socket_create(int cam_id, mm_camera_sock_type_t sock_type) 50 { 51 int socket_fd; 52 mm_camera_sock_addr_t sock_addr; 53 int sktype; 54 int rc; 55 56 switch (sock_type) 57 { 58 case MM_CAMERA_SOCK_TYPE_UDP: 59 sktype = SOCK_DGRAM; 60 break; 61 case MM_CAMERA_SOCK_TYPE_TCP: 62 sktype = SOCK_STREAM; 63 break; 64 default: 65 LOGE("unknown socket type =%d", sock_type); 66 return -1; 67 } 68 socket_fd = socket(AF_UNIX, sktype, 0); 69 if (socket_fd < 0) { 70 LOGE("error create socket fd =%d", socket_fd); 71 return socket_fd; 72 } 73 74 memset(&sock_addr, 0, sizeof(sock_addr)); 75 sock_addr.addr_un.sun_family = AF_UNIX; 76 snprintf(sock_addr.addr_un.sun_path, 77 UNIX_PATH_MAX, QCAMERA_DUMP_FRM_LOCATION"cam_socket%d", cam_id); 78 rc = connect(socket_fd, &sock_addr.addr, sizeof(sock_addr.addr_un)); 79 if (0 != rc) { 80 close(socket_fd); 81 socket_fd = -1; 82 LOGE("socket_fd=%d %s ", socket_fd, strerror(errno)); 83 } 84 85 LOGD("socket_fd=%d %s", socket_fd, 86 sock_addr.addr_un.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 size_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 LOGD("msg is NULL"); 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 LOGD("iov_len=%llu", 139 (unsigned long long int)iov[0].iov_len); 140 141 msgh.msg_control = NULL; 142 msgh.msg_controllen = 0; 143 144 /* if sendfd is valid, we need to pass it through control msg */ 145 if( sendfd >= 0) { 146 msgh.msg_control = control; 147 msgh.msg_controllen = sizeof(control); 148 cmsghp = CMSG_FIRSTHDR(&msgh); 149 if (cmsghp != NULL) { 150 LOGD("Got ctrl msg pointer"); 151 cmsghp->cmsg_level = SOL_SOCKET; 152 cmsghp->cmsg_type = SCM_RIGHTS; 153 cmsghp->cmsg_len = CMSG_LEN(sizeof(int)); 154 *((int *)CMSG_DATA(cmsghp)) = sendfd; 155 LOGD("cmsg data=%d", *((int *) CMSG_DATA(cmsghp))); 156 } else { 157 LOGD("ctrl msg NULL"); 158 return -1; 159 } 160 } 161 162 return sendmsg(fd, &(msgh), 0); 163 } 164 165 /*=========================================================================== 166 * FUNCTION : mm_camera_socket_bundle_sendmsg 167 * 168 * DESCRIPTION: send msg through domain socket 169 * @fd : socket fd 170 * @msg : pointer to msg to be sent over domain socket 171 * @sendfds : file descriptors to be sent 172 * @numfds : num of file descriptors to be sent 173 * 174 * RETURN : the total bytes of sent msg 175 *==========================================================================*/ 176 int mm_camera_socket_bundle_sendmsg( 177 int fd, 178 void *msg, 179 size_t buf_size, 180 int sendfds[CAM_MAX_NUM_BUFS_PER_STREAM], 181 int numfds) 182 { 183 struct msghdr msgh; 184 struct iovec iov[1]; 185 struct cmsghdr * cmsghp = NULL; 186 char control[CMSG_SPACE(sizeof(int) * numfds)]; 187 int *fds_ptr = NULL; 188 189 if (msg == NULL) { 190 LOGD("msg is NULL"); 191 return -1; 192 } 193 memset(&msgh, 0, sizeof(msgh)); 194 msgh.msg_name = NULL; 195 msgh.msg_namelen = 0; 196 197 iov[0].iov_base = msg; 198 iov[0].iov_len = buf_size; 199 msgh.msg_iov = iov; 200 msgh.msg_iovlen = 1; 201 LOGD("iov_len=%llu", 202 (unsigned long long int)iov[0].iov_len); 203 204 msgh.msg_control = NULL; 205 msgh.msg_controllen = 0; 206 207 /* if numfds is valid, we need to pass it through control msg */ 208 if (numfds > 0) { 209 msgh.msg_control = control; 210 msgh.msg_controllen = sizeof(control); 211 cmsghp = CMSG_FIRSTHDR(&msgh); 212 if (cmsghp != NULL) { 213 cmsghp->cmsg_level = SOL_SOCKET; 214 cmsghp->cmsg_type = SCM_RIGHTS; 215 cmsghp->cmsg_len = CMSG_LEN(sizeof(int) * numfds); 216 217 fds_ptr = (int*) CMSG_DATA(cmsghp); 218 memcpy(fds_ptr, sendfds, sizeof(int) * numfds); 219 } else { 220 LOGE("ctrl msg NULL"); 221 return -1; 222 } 223 } 224 225 return sendmsg(fd, &(msgh), 0); 226 } 227 228 /*=========================================================================== 229 * FUNCTION : mm_camera_socket_recvmsg 230 * 231 * DESCRIPTION: receive msg from domain socket. 232 * @fd : socket fd 233 * @msg : pointer to mm_camera_sock_msg_packet_t to hold incoming msg, 234 * need be allocated by the caller 235 * @buf_size: the size of the buf that holds incoming msg 236 * @rcvdfd : pointer to hold recvd file descriptor if not NULL. 237 * 238 * RETURN : the total bytes of received msg 239 *==========================================================================*/ 240 int mm_camera_socket_recvmsg( 241 int fd, 242 void *msg, 243 uint32_t buf_size, 244 int *rcvdfd) 245 { 246 struct msghdr msgh; 247 struct iovec iov[1]; 248 struct cmsghdr *cmsghp = NULL; 249 char control[CMSG_SPACE(sizeof(int))]; 250 int rcvd_fd = -1; 251 int rcvd_len = 0; 252 253 if ( (msg == NULL) || (buf_size <= 0) ) { 254 LOGE("msg buf is NULL"); 255 return -1; 256 } 257 258 memset(&msgh, 0, sizeof(msgh)); 259 msgh.msg_name = NULL; 260 msgh.msg_namelen = 0; 261 msgh.msg_control = control; 262 msgh.msg_controllen = sizeof(control); 263 264 iov[0].iov_base = msg; 265 iov[0].iov_len = buf_size; 266 msgh.msg_iov = iov; 267 msgh.msg_iovlen = 1; 268 269 if ( (rcvd_len = recvmsg(fd, &(msgh), 0)) <= 0) { 270 LOGE("recvmsg failed"); 271 return rcvd_len; 272 } 273 274 LOGD("msg_ctrl %p len %zd", msgh.msg_control, 275 msgh.msg_controllen); 276 277 if( ((cmsghp = CMSG_FIRSTHDR(&msgh)) != NULL) && 278 (cmsghp->cmsg_len == CMSG_LEN(sizeof(int))) ) { 279 if (cmsghp->cmsg_level == SOL_SOCKET && 280 cmsghp->cmsg_type == SCM_RIGHTS) { 281 LOGD("CtrlMsg is valid"); 282 rcvd_fd = *((int *) CMSG_DATA(cmsghp)); 283 LOGD("Receieved fd=%d", rcvd_fd); 284 } else { 285 LOGE("Unexpected Control Msg. Line=%d"); 286 } 287 } 288 289 if (rcvdfd) { 290 *rcvdfd = rcvd_fd; 291 } 292 293 return rcvd_len; 294 } 295