Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / profiles / audio / control.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2006-2010  Nokia Corporation
6  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7  *  Copyright (C) 2011  Texas Instruments, Inc.
8  *
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <assert.h>
35 #include <signal.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39
40 #include <glib.h>
41 #include <dbus/dbus.h>
42
43 #include "lib/bluetooth.h"
44 #include "lib/sdp.h"
45 #include "lib/sdp_lib.h"
46 #include "lib/uuid.h"
47
48 #include "gdbus/gdbus.h"
49
50 #include "src/adapter.h"
51 #include "src/device.h"
52 #include "src/profile.h"
53 #include "src/service.h"
54 #include "src/log.h"
55 #include "src/error.h"
56 #include "src/sdpd.h"
57 #include "src/uuid-helper.h"
58 #include "src/dbus-common.h"
59
60 #include "avctp.h"
61 #include "control.h"
62 #include "player.h"
63
64 static GSList *devices = NULL;
65
66 struct control {
67         struct btd_device *dev;
68         struct avctp *session;
69         struct btd_service *target;
70         struct btd_service *remote;
71         unsigned int avctp_id;
72         const char *player;
73 };
74
75 static void state_changed(struct btd_device *dev, avctp_state_t old_state,
76                                         avctp_state_t new_state, int err,
77                                         void *user_data)
78 {
79         struct control *control = user_data;
80         DBusConnection *conn = btd_get_dbus_connection();
81         const char *path = device_get_path(dev);
82
83         switch (new_state) {
84         case AVCTP_STATE_DISCONNECTED:
85                 control->session = NULL;
86                 control->player = NULL;
87
88                 g_dbus_emit_property_changed(conn, path,
89                                         AUDIO_CONTROL_INTERFACE, "Connected");
90                 g_dbus_emit_property_changed(conn, path,
91                                         AUDIO_CONTROL_INTERFACE, "Player");
92
93                 break;
94         case AVCTP_STATE_CONNECTING:
95                 if (control->session)
96                         break;
97
98                 control->session = avctp_get(dev);
99
100                 break;
101         case AVCTP_STATE_CONNECTED:
102                 g_dbus_emit_property_changed(conn, path,
103                                         AUDIO_CONTROL_INTERFACE, "Connected");
104                 break;
105         case AVCTP_STATE_BROWSING_CONNECTING:
106         case AVCTP_STATE_BROWSING_CONNECTED:
107         default:
108                 return;
109         }
110 }
111
112 int control_connect(struct btd_service *service)
113 {
114         struct control *control = btd_service_get_user_data(service);
115
116         if (control->session)
117                 return -EALREADY;
118
119         control->session = avctp_connect(control->dev);
120         if (!control->session)
121                 return -EIO;
122
123         return 0;
124 }
125
126 int control_disconnect(struct btd_service *service)
127 {
128         struct control *control = btd_service_get_user_data(service);
129
130         if (!control->session)
131                 return -ENOTCONN;
132
133         avctp_disconnect(control->session);
134
135         return 0;
136 }
137
138 static DBusMessage *key_pressed(DBusConnection *conn, DBusMessage *msg,
139                                                 uint8_t op, void *data)
140 {
141         struct control *control = data;
142         int err;
143
144         if (!control->session)
145                 return btd_error_not_connected(msg);
146
147         if (!control->target)
148                 return btd_error_not_supported(msg);
149
150         err = avctp_send_passthrough(control->session, op);
151         if (err < 0)
152                 return btd_error_failed(msg, strerror(-err));
153
154         return dbus_message_new_method_return(msg);
155 }
156
157 static DBusMessage *control_volume_up(DBusConnection *conn, DBusMessage *msg,
158                                                                 void *data)
159 {
160         return key_pressed(conn, msg, AVC_VOLUME_UP, data);
161 }
162
163 static DBusMessage *control_volume_down(DBusConnection *conn, DBusMessage *msg,
164                                                                 void *data)
165 {
166         return key_pressed(conn, msg, AVC_VOLUME_DOWN, data);
167 }
168
169 static DBusMessage *control_play(DBusConnection *conn, DBusMessage *msg,
170                                                                 void *data)
171 {
172         return key_pressed(conn, msg, AVC_PLAY, data);
173 }
174
175 static DBusMessage *control_pause(DBusConnection *conn, DBusMessage *msg,
176                                                                 void *data)
177 {
178         return key_pressed(conn, msg, AVC_PAUSE, data);
179 }
180
181 static DBusMessage *control_stop(DBusConnection *conn, DBusMessage *msg,
182                                                                 void *data)
183 {
184         return key_pressed(conn, msg, AVC_STOP, data);
185 }
186
187 static DBusMessage *control_next(DBusConnection *conn, DBusMessage *msg,
188                                                                 void *data)
189 {
190         return key_pressed(conn, msg, AVC_FORWARD, data);
191 }
192
193 static DBusMessage *control_previous(DBusConnection *conn, DBusMessage *msg,
194                                                                 void *data)
195 {
196         return key_pressed(conn, msg, AVC_BACKWARD, data);
197 }
198
199 static DBusMessage *control_fast_forward(DBusConnection *conn, DBusMessage *msg,
200                                                                 void *data)
201 {
202         return key_pressed(conn, msg, AVC_FAST_FORWARD, data);
203 }
204
205 static DBusMessage *control_rewind(DBusConnection *conn, DBusMessage *msg,
206                                                                 void *data)
207 {
208         return key_pressed(conn, msg, AVC_REWIND, data);
209 }
210
211 static gboolean control_property_get_connected(
212                                         const GDBusPropertyTable *property,
213                                         DBusMessageIter *iter, void *data)
214 {
215         struct control *control = data;
216         dbus_bool_t value = (control->session != NULL);
217
218         dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value);
219
220         return TRUE;
221 }
222
223 static gboolean control_player_exists(const GDBusPropertyTable *property,
224                                                                 void *data)
225 {
226         struct control *control = data;
227
228         return control->player != NULL;
229 }
230
231 static gboolean control_get_player(const GDBusPropertyTable *property,
232                                         DBusMessageIter *iter, void *data)
233 {
234         struct control *control = data;
235
236         if (!control->player)
237                 return FALSE;
238
239         dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
240                                                         &control->player);
241
242         return TRUE;
243 }
244
245 static const GDBusMethodTable control_methods[] = {
246         { GDBUS_DEPRECATED_METHOD("Play", NULL, NULL, control_play) },
247         { GDBUS_DEPRECATED_METHOD("Pause", NULL, NULL, control_pause) },
248         { GDBUS_DEPRECATED_METHOD("Stop", NULL, NULL, control_stop) },
249         { GDBUS_DEPRECATED_METHOD("Next", NULL, NULL, control_next) },
250         { GDBUS_DEPRECATED_METHOD("Previous", NULL, NULL, control_previous) },
251         { GDBUS_DEPRECATED_METHOD("VolumeUp", NULL, NULL, control_volume_up) },
252         { GDBUS_DEPRECATED_METHOD("VolumeDown", NULL, NULL,
253                                                         control_volume_down) },
254         { GDBUS_DEPRECATED_METHOD("FastForward", NULL, NULL,
255                                                         control_fast_forward) },
256         { GDBUS_DEPRECATED_METHOD("Rewind", NULL, NULL, control_rewind) },
257         { }
258 };
259
260 static const GDBusPropertyTable control_properties[] = {
261         { "Connected", "b", control_property_get_connected },
262         { "Player", "o", control_get_player, NULL, control_player_exists },
263         { }
264 };
265
266 static void path_unregister(void *data)
267 {
268         struct control *control = data;
269
270         DBG("Unregistered interface %s on path %s",  AUDIO_CONTROL_INTERFACE,
271                                                 device_get_path(control->dev));
272
273         if (control->session)
274                 avctp_disconnect(control->session);
275
276         avctp_remove_state_cb(control->avctp_id);
277
278         if (control->target)
279                 btd_service_unref(control->target);
280
281         if (control->remote)
282                 btd_service_unref(control->remote);
283
284         devices = g_slist_remove(devices, control);
285         g_free(control);
286 }
287
288 void control_unregister(struct btd_service *service)
289 {
290         struct btd_device *dev = btd_service_get_device(service);
291
292         g_dbus_unregister_interface(btd_get_dbus_connection(),
293                                                 device_get_path(dev),
294                                                 AUDIO_CONTROL_INTERFACE);
295 }
296
297 static struct control *find_control(struct btd_device *dev)
298 {
299         GSList *l;
300
301         for (l = devices; l; l = l->next) {
302                 struct control *control = l->data;
303
304                 if (control->dev == dev)
305                         return control;
306         }
307
308         return NULL;
309 }
310
311 static struct control *control_init(struct btd_service *service)
312 {
313         struct control *control;
314         struct btd_device *dev = btd_service_get_device(service);
315
316         control = find_control(dev);
317         if (control != NULL)
318                 return control;
319
320         control = g_new0(struct control, 1);
321
322         if (!g_dbus_register_interface(btd_get_dbus_connection(),
323                                         device_get_path(dev),
324                                         AUDIO_CONTROL_INTERFACE,
325                                         control_methods, NULL,
326                                         control_properties, control,
327                                         path_unregister)) {
328                 g_free(control);
329                 return NULL;
330         }
331
332         DBG("Registered interface %s on path %s", AUDIO_CONTROL_INTERFACE,
333                                                         device_get_path(dev));
334
335         control->dev = dev;
336         control->avctp_id = avctp_add_state_cb(dev, state_changed, control);
337         devices = g_slist_prepend(devices, control);
338
339         return control;
340 }
341
342 int control_init_target(struct btd_service *service)
343 {
344         struct control *control;
345
346         control = control_init(service);
347         if (control == NULL)
348                 return -EINVAL;
349
350         control->target = btd_service_ref(service);
351
352         btd_service_set_user_data(service, control);
353
354         return 0;
355 }
356
357 int control_init_remote(struct btd_service *service)
358 {
359         struct control *control;
360
361         control = control_init(service);
362         if (control == NULL)
363                 return -EINVAL;
364
365         control->remote = btd_service_ref(service);
366
367         btd_service_set_user_data(service, control);
368
369         return 0;
370 }
371
372 int control_set_player(struct btd_service *service, const char *path)
373 {
374         struct control *control = btd_service_get_user_data(service);
375
376         if (!control->session)
377                 return -ENOTCONN;
378
379         if (g_strcmp0(control->player, path) == 0)
380                 return -EALREADY;
381
382         control->player = path;
383
384         g_dbus_emit_property_changed(btd_get_dbus_connection(),
385                                         device_get_path(control->dev),
386                                         AUDIO_CONTROL_INTERFACE, "Player");
387
388         return 0;
389 }