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 *==========================================================================*/
mm_camera_socket_create(int cam_id,mm_camera_sock_type_t sock_type)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 *==========================================================================*/
mm_camera_socket_close(int fd)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 *==========================================================================*/
mm_camera_socket_sendmsg(int fd,void * msg,uint32_t buf_size,int sendfd)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 valid, 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 *==========================================================================*/
mm_camera_socket_recvmsg(int fd,void * msg,uint32_t buf_size,int * rcvdfd)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