1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@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 */
28static 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 */
36static 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
48int 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
77int bt_audio_service_close(int sk)
78{
79	return close(sk);
80}
81
82int 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
119const char *bt_audio_strtype(uint8_t type)
120{
121	if (type >= ARRAY_SIZE(strtypes))
122		return NULL;
123
124	return strtypes[type];
125}
126
127const char *bt_audio_strname(uint8_t name)
128{
129	if (name >= ARRAY_SIZE(strnames))
130		return NULL;
131
132	return strnames[name];
133}
134