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