1 /* Copyright (c) 2012-2015, 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 36 #include "mm_camera_dbg.h" 37 #include "mm_camera_sock.h" 38 #include "cam_types.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 CDBG_ERROR("%s: unknown socket type =%d", __func__, sock_type); 66 return -1; 67 } 68 socket_fd = socket(AF_UNIX, sktype, 0); 69 if (socket_fd < 0) { 70 CDBG_ERROR("%s: error create socket fd =%d", __func__, 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 CDBG_ERROR("%s: socket_fd=%d %s ", __func__, socket_fd, strerror(errno)); 83 } 84 85 CDBG("%s: socket_fd=%d %s", __func__, 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 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=%llu", __func__, 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 CDBG("%s: Got ctrl msg pointer", __func__); 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 CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp))); 156 } else { 157 CDBG("%s: ctrl msg NULL", __func__); 158 return -1; 159 } 160 } 161 162 return sendmsg(fd, &(msgh), 0); 163 } 164 165 /*=========================================================================== 166 * FUNCTION : mm_camera_socket_recvmsg 167 * 168 * DESCRIPTION: receive msg from domain socket. 169 * @fd : socket fd 170 * @msg : pointer to mm_camera_sock_msg_packet_t to hold incoming msg, 171 * need be allocated by the caller 172 * @buf_size: the size of the buf that holds incoming msg 173 * @rcvdfd : pointer to hold recvd file descriptor if not NULL. 174 * 175 * RETURN : the total bytes of received msg 176 *==========================================================================*/ 177 int mm_camera_socket_recvmsg( 178 int fd, 179 void *msg, 180 uint32_t buf_size, 181 int *rcvdfd) 182 { 183 struct msghdr msgh; 184 struct iovec iov[1]; 185 struct cmsghdr *cmsghp = NULL; 186 char control[CMSG_SPACE(sizeof(int))]; 187 int rcvd_fd = -1; 188 int rcvd_len = 0; 189 190 if ( (msg == NULL) || (buf_size <= 0) ) { 191 CDBG_ERROR(" %s: msg buf is NULL", __func__); 192 return -1; 193 } 194 195 memset(&msgh, 0, sizeof(msgh)); 196 msgh.msg_name = NULL; 197 msgh.msg_namelen = 0; 198 msgh.msg_control = control; 199 msgh.msg_controllen = sizeof(control); 200 201 iov[0].iov_base = msg; 202 iov[0].iov_len = buf_size; 203 msgh.msg_iov = iov; 204 msgh.msg_iovlen = 1; 205 206 if ( (rcvd_len = recvmsg(fd, &(msgh), 0)) <= 0) { 207 CDBG_ERROR(" %s: recvmsg failed", __func__); 208 return rcvd_len; 209 } 210 211 CDBG("%s: msg_ctrl %p len %zd", __func__, msgh.msg_control, 212 msgh.msg_controllen); 213 214 if( ((cmsghp = CMSG_FIRSTHDR(&msgh)) != NULL) && 215 (cmsghp->cmsg_len == CMSG_LEN(sizeof(int))) ) { 216 if (cmsghp->cmsg_level == SOL_SOCKET && 217 cmsghp->cmsg_type == SCM_RIGHTS) { 218 CDBG("%s: CtrlMsg is valid", __func__); 219 rcvd_fd = *((int *) CMSG_DATA(cmsghp)); 220 CDBG("%s: Receieved fd=%d", __func__, rcvd_fd); 221 } else { 222 CDBG_ERROR("%s: Unexpected Control Msg. Line=%d", __func__, __LINE__); 223 } 224 } 225 226 if (rcvdfd) { 227 *rcvdfd = rcvd_fd; 228 } 229 230 return rcvd_len; 231 } 232