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