1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2004-2010 Marcel Holtmann <marcel (at) holtmann.org> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 */ 22 23 #include "ipc.h" 24 25 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 26 27 /* This table contains the string representation for messages types */ 28 static const char *strtypes[] = { 29 "BT_REQUEST", 30 "BT_RESPONSE", 31 "BT_INDICATION", 32 "BT_ERROR", 33 }; 34 35 /* This table contains the string representation for messages names */ 36 static const char *strnames[] = { 37 "BT_GET_CAPABILITIES", 38 "BT_OPEN", 39 "BT_SET_CONFIGURATION", 40 "BT_NEW_STREAM", 41 "BT_START_STREAM", 42 "BT_STOP_STREAM", 43 "BT_SUSPEND_STREAM", 44 "BT_RESUME_STREAM", 45 "BT_CONTROL", 46 }; 47 48 int bt_audio_service_open(void) 49 { 50 int sk; 51 int err; 52 struct sockaddr_un addr = { 53 AF_UNIX, BT_IPC_SOCKET_NAME 54 }; 55 56 sk = socket(PF_LOCAL, SOCK_STREAM, 0); 57 if (sk < 0) { 58 err = errno; 59 fprintf(stderr, "%s: Cannot open socket: %s (%d)\n", 60 __FUNCTION__, strerror(err), err); 61 errno = err; 62 return -1; 63 } 64 65 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 66 err = errno; 67 fprintf(stderr, "%s: connect() failed: %s (%d)\n", 68 __FUNCTION__, strerror(err), err); 69 close(sk); 70 errno = err; 71 return -1; 72 } 73 74 return sk; 75 } 76 77 int bt_audio_service_close(int sk) 78 { 79 return close(sk); 80 } 81 82 int bt_audio_service_get_data_fd(int sk) 83 { 84 char cmsg_b[CMSG_SPACE(sizeof(int))], m; 85 int err, ret; 86 struct iovec iov = { &m, sizeof(m) }; 87 struct msghdr msgh; 88 struct cmsghdr *cmsg; 89 90 memset(&msgh, 0, sizeof(msgh)); 91 msgh.msg_iov = &iov; 92 msgh.msg_iovlen = 1; 93 msgh.msg_control = &cmsg_b; 94 msgh.msg_controllen = CMSG_LEN(sizeof(int)); 95 96 ret = recvmsg(sk, &msgh, 0); 97 if (ret < 0) { 98 err = errno; 99 fprintf(stderr, "%s: Unable to receive fd: %s (%d)\n", 100 __FUNCTION__, strerror(err), err); 101 errno = err; 102 return -1; 103 } 104 105 /* Receive auxiliary data in msgh */ 106 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; 107 cmsg = CMSG_NXTHDR(&msgh, cmsg)) { 108 if (cmsg->cmsg_level == SOL_SOCKET 109 && cmsg->cmsg_type == SCM_RIGHTS) { 110 memcpy(&ret, CMSG_DATA(cmsg), sizeof(int)); 111 return ret; 112 } 113 } 114 115 errno = EINVAL; 116 return -1; 117 } 118 119 const char *bt_audio_strtype(uint8_t type) 120 { 121 if (type >= ARRAY_SIZE(strtypes)) 122 return NULL; 123 124 return strtypes[type]; 125 } 126 127 const char *bt_audio_strname(uint8_t name) 128 { 129 if (name >= ARRAY_SIZE(strnames)) 130 return NULL; 131 132 return strnames[name]; 133 } 134