mcap.c revision 3913704e8f6c2ad65060efed8e6588be34380013
1/*
2 *
3 *  MCAP for BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
6 *
7 *  Authors:
8 *  Santiago Carot-Nemesio <sancane at gmail.com>
9 *  Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
10 *
11 *  This program is free software; you can redistribute it and/or modify
12 *  it under the terms of the GNU General Public License as published by
13 *  the Free Software Foundation; either version 2 of the License, or
14 *  (at your option) any later version.
15 *
16 *  This program is distributed in the hope that it will be useful,
17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 *  GNU General Public License for more details.
20 *
21 *  You should have received a copy of the GNU General Public License
22 *  along with this program; if not, write to the Free Software
23 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24 *
25 */
26
27#include "log.h"
28#include "error.h"
29
30#include <netinet/in.h>
31#include <stdlib.h>
32#include <errno.h>
33#include <unistd.h>
34
35#include "btio.h"
36#include <bluetooth/bluetooth.h>
37#include <bluetooth/l2cap.h>
38#include "mcap.h"
39#include "mcap_lib.h"
40#include "mcap_internal.h"
41
42#define RESPONSE_TIMER	6	/* seconds */
43#define MAX_CACHED	10	/* 10 devices */
44
45#define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
46
47#define RELEASE_TIMER(__mcl) do {		\
48	if (__mcl->tid) {			\
49		g_source_remove(__mcl->tid);	\
50		__mcl->tid = 0;			\
51	}					\
52} while(0)
53
54struct connect_mcl {
55	struct mcap_mcl		*mcl;		/* MCL for this operation */
56	mcap_mcl_connect_cb	connect_cb;	/* Connect callback */
57	GDestroyNotify		destroy;	/* Destroy callback */
58	gpointer		user_data;	/* Callback user data */
59};
60
61typedef union {
62	mcap_mdl_operation_cb		op;
63	mcap_mdl_operation_conf_cb	op_conf;
64	mcap_mdl_notify_cb		notify;
65} mcap_cb_type;
66
67struct mcap_mdl_op_cb {
68	struct mcap_mdl		*mdl;		/* MDL for this operation */
69	mcap_cb_type		cb;		/* Operation callback */
70	GDestroyNotify		destroy;	/* Destroy callback */
71	gpointer		user_data;	/* Callback user data */
72};
73
74/* MCAP finite state machine functions */
75static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l);
76static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l);
77static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t l);
78
79static void (*proc_req[])(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len) = {
80	proc_req_connected,
81	proc_req_pending,
82	proc_req_active
83};
84
85static void mcap_cache_mcl(struct mcap_mcl *mcl);
86
87static void default_mdl_connected_cb(struct mcap_mdl *mdl, gpointer data)
88{
89	DBG("MCAP Unmanaged mdl connection");
90}
91
92static void default_mdl_closed_cb(struct mcap_mdl *mdl, gpointer data)
93{
94	DBG("MCAP Unmanaged mdl closed");
95}
96
97static void default_mdl_deleted_cb(struct mcap_mdl *mdl, gpointer data)
98{
99	DBG("MCAP Unmanaged mdl deleted");
100}
101
102static void default_mdl_aborted_cb(struct mcap_mdl *mdl, gpointer data)
103{
104	DBG("MCAP Unmanaged mdl aborted");
105}
106
107static uint8_t default_mdl_conn_req_cb(struct mcap_mcl *mcl,
108						uint8_t mdepid, uint16_t mdlid,
109						uint8_t *conf, gpointer data)
110{
111	DBG("MCAP mdl remote connection aborted");
112	/* Due to this callback isn't managed this request won't be supported */
113	return MCAP_REQUEST_NOT_SUPPORTED;
114}
115
116static uint8_t default_mdl_reconn_req_cb(struct mcap_mdl *mdl,
117						gpointer data)
118{
119	DBG("MCAP mdl remote reconnection aborted");
120	/* Due to this callback isn't managed this request won't be supported */
121	return MCAP_REQUEST_NOT_SUPPORTED;
122}
123
124static void set_default_cb(struct mcap_mcl *mcl)
125{
126	if (!mcl->cb)
127		mcl->cb = g_new0(struct mcap_mdl_cb, 1);
128
129	mcl->cb->mdl_connected = default_mdl_connected_cb;
130	mcl->cb->mdl_closed = default_mdl_closed_cb;
131	mcl->cb->mdl_deleted = default_mdl_deleted_cb;
132	mcl->cb->mdl_aborted = default_mdl_aborted_cb;
133	mcl->cb->mdl_conn_req = default_mdl_conn_req_cb;
134	mcl->cb->mdl_reconn_req = default_mdl_reconn_req_cb;
135}
136
137static char *error2str(uint8_t rc)
138{
139	switch (rc) {
140	case MCAP_SUCCESS:
141		return "Success";
142	case MCAP_INVALID_OP_CODE:
143		return "Invalid Op Code";
144	case MCAP_INVALID_PARAM_VALUE:
145		return "Invalid Parameter Value";
146	case MCAP_INVALID_MDEP:
147		return "Invalid MDEP";
148	case MCAP_MDEP_BUSY:
149		return "MDEP Busy";
150	case MCAP_INVALID_MDL:
151		return "Invalid MDL";
152	case MCAP_MDL_BUSY:
153		return "MDL Busy";
154	case MCAP_INVALID_OPERATION:
155		return "Invalid Operation";
156	case MCAP_RESOURCE_UNAVAILABLE:
157		return "Resource Unavailable";
158	case MCAP_UNSPECIFIED_ERROR:
159		return "Unspecified Error";
160	case MCAP_REQUEST_NOT_SUPPORTED:
161		return "Request Not Supported";
162	case MCAP_CONFIGURATION_REJECTED:
163		return "Configuration Rejected";
164	default:
165		return "Unknown Response Code";
166	}
167}
168
169static gboolean mcap_send_std_opcode(struct mcap_mcl *mcl, void *cmd,
170						uint32_t size, GError **err)
171{
172	if (mcl->state == MCL_IDLE) {
173		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
174							"MCL is not connected");
175		return FALSE;
176	}
177
178	if (mcl->req != MCL_AVAILABLE) {
179		g_set_error(err, MCAP_ERROR, MCAP_ERROR_RESOURCE_UNAVAILABLE,
180							"Pending request");
181		return FALSE;
182	}
183
184	if (!(mcl->ctrl & MCAP_CTRL_STD_OP)) {
185		g_set_error(err, MCAP_ERROR, MCAP_ERROR_REQUEST_NOT_SUPPORTED,
186				"Remote does not support standard opcodes");
187		return FALSE;
188	}
189
190	if (mcl->state == MCL_PENDING) {
191		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_OPERATION,
192			"Not Std Op. Codes can be sent in PENDING State");
193		return FALSE;
194	}
195
196	if (mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), cmd, size) < 0) {
197		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
198					"Command can't be sent, write error");
199		return FALSE;
200	}
201
202	mcl->lcmd = cmd;
203	mcl->req = MCL_WAITING_RSP;
204
205	return TRUE;
206}
207
208static void update_mcl_state(struct mcap_mcl *mcl)
209{
210	GSList *l;
211	struct mcap_mdl *mdl;
212
213	if (mcl->state == MCL_PENDING)
214		return;
215
216	for (l = mcl->mdls; l; l = l->next) {
217		mdl = l->data;
218
219		if (mdl->state == MDL_CONNECTED) {
220			mcl->state = MCL_ACTIVE;
221			return;
222		}
223	}
224
225	mcl->state = MCL_CONNECTED;
226}
227
228static void shutdown_mdl(struct mcap_mdl *mdl)
229{
230	mdl->state = MDL_CLOSED;
231
232	if (mdl->wid) {
233		g_source_remove(mdl->wid);
234		mdl->wid = 0;
235	}
236
237	if (mdl->dc) {
238		g_io_channel_shutdown(mdl->dc, TRUE, NULL);
239		g_io_channel_unref(mdl->dc);
240		mdl->dc = NULL;
241	}
242}
243
244static void free_mdl(struct mcap_mdl *mdl)
245{
246	if (!mdl)
247		return;
248
249	mcap_mcl_unref(mdl->mcl);
250	g_free(mdl);
251}
252
253static gint cmp_mdl_state(gconstpointer a, gconstpointer b)
254{
255	const struct mcap_mdl *mdl = a;
256	const MDLState *st = b;
257
258	if (mdl->state == *st)
259		return 0;
260	else if (mdl->state < *st)
261		return -1;
262	else
263		return 1;
264}
265
266static void free_mcl_priv_data(struct mcap_mcl *mcl)
267{
268	struct mcap_mdl_op_cb *op = mcl->priv_data;
269
270	if (op->destroy)
271		op->destroy(op->user_data);
272
273	g_free(mcl->priv_data);
274	mcl->priv_data = NULL;
275}
276
277static void mcap_notify_error(struct mcap_mcl *mcl, GError *err)
278{
279	struct mcap_mdl_op_cb *con = mcl->priv_data;
280	struct mcap_mdl *mdl;
281	MDLState st;
282	GSList *l;
283
284	if (!con || !mcl->lcmd)
285		return;
286
287	switch (mcl->lcmd[0]) {
288	case MCAP_MD_CREATE_MDL_REQ:
289		st = MDL_WAITING;
290		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
291		mdl = l->data;
292		mcl->mdls = g_slist_remove(mcl->mdls, mdl);
293		free_mdl(mdl);
294		update_mcl_state(mcl);
295		con->cb.op_conf(NULL, 0, err, con->user_data);
296		break;
297	case MCAP_MD_ABORT_MDL_REQ:
298		st = MDL_WAITING;
299		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
300		shutdown_mdl(l->data);
301		update_mcl_state(mcl);
302		con->cb.notify(err, con->user_data);
303		break;
304	case MCAP_MD_DELETE_MDL_REQ:
305		for (l = mcl->mdls; l; l = l->next) {
306			mdl = l->data;
307			if (mdl->state == MDL_DELETING)
308				mdl->state = (mdl->dc) ? MDL_CONNECTED :
309								MDL_CLOSED;
310		}
311		update_mcl_state(mcl);
312		con->cb.notify(err, con->user_data);
313		break;
314	case MCAP_MD_RECONNECT_MDL_REQ:
315		st = MDL_WAITING;
316		l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state);
317		shutdown_mdl(l->data);
318		update_mcl_state(mcl);
319		con->cb.op(NULL, err, con->user_data);
320		break;
321	}
322
323	free_mcl_priv_data(mcl);
324	g_free(mcl->lcmd);
325	mcl->lcmd = NULL;
326}
327
328int mcap_send_data(int sock, const void *buf, uint32_t size)
329{
330	const uint8_t *buf_b = buf;
331	uint32_t sent = 0;
332
333	while (sent < size) {
334		int n = write(sock, buf_b + sent, size - sent);
335		if (n < 0)
336			return -1;
337		sent += n;
338	}
339
340	return 0;
341}
342
343static int mcap_send_cmd(struct mcap_mcl *mcl, uint8_t oc, uint8_t rc,
344					uint16_t mdl, uint8_t *data, size_t len)
345{
346	mcap_rsp *cmd;
347	int sock, sent;
348
349	if (mcl->cc == NULL)
350		return -1;
351
352	sock = g_io_channel_unix_get_fd(mcl->cc);
353
354	cmd = g_malloc(sizeof(mcap_rsp) + len);
355	cmd->op = oc;
356	cmd->rc = rc;
357	cmd->mdl = htons(mdl);
358
359	if (data && len > 0)
360		memcpy(cmd->data, data, len);
361
362	sent = mcap_send_data(sock, cmd, sizeof(mcap_rsp) + len);
363	g_free(cmd);
364
365	return sent;
366}
367
368static struct mcap_mdl *get_mdl(struct mcap_mcl *mcl, uint16_t mdlid)
369{
370	GSList *l;
371	struct mcap_mdl *mdl;
372
373	for (l = mcl->mdls; l; l = l->next) {
374		mdl = l->data;
375		if (mdlid == mdl->mdlid)
376			return mdl;
377	}
378
379	return NULL;
380}
381
382static uint16_t generate_mdlid(struct mcap_mcl *mcl)
383{
384	uint16_t mdlid = mcl->next_mdl;
385	struct mcap_mdl *mdl;
386
387	do {
388		mdl = get_mdl(mcl, mdlid);
389		if (!mdl) {
390			mcl->next_mdl = (mdlid % MCAP_MDLID_FINAL) + 1;
391			return mdlid;
392		} else
393			mdlid = (mdlid % MCAP_MDLID_FINAL) + 1;
394	} while (mdlid != mcl->next_mdl);
395
396	/* No more mdlids availables */
397	return 0;
398}
399
400static mcap_md_req *create_req(uint8_t op, uint16_t mdl_id)
401{
402	mcap_md_req *req_cmd;
403
404	req_cmd = g_new0(mcap_md_req, 1);
405
406	req_cmd->op = op;
407	req_cmd->mdl = htons(mdl_id);
408
409	return req_cmd;
410}
411
412static mcap_md_create_mdl_req *create_mdl_req(uint16_t mdl_id, uint8_t mdep,
413								uint8_t conf)
414{
415	mcap_md_create_mdl_req *req_mdl;
416
417	req_mdl = g_new0(mcap_md_create_mdl_req, 1);
418
419	req_mdl->op = MCAP_MD_CREATE_MDL_REQ;
420	req_mdl->mdl = htons(mdl_id);
421	req_mdl->mdep = mdep;
422	req_mdl->conf = conf;
423
424	return req_mdl;
425}
426
427static gint compare_mdl(gconstpointer a, gconstpointer b)
428{
429	const struct mcap_mdl *mdla = a;
430	const struct mcap_mdl *mdlb = b;
431
432	if (mdla->mdlid == mdlb->mdlid)
433		return 0;
434	else if (mdla->mdlid < mdlb->mdlid)
435		return -1;
436	else
437		return 1;
438}
439
440static gboolean wait_response_timer(gpointer data)
441{
442	struct mcap_mcl *mcl = data;
443
444	GError *gerr = NULL;
445
446	RELEASE_TIMER(mcl);
447
448	g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
449					"Timeout waiting response");
450
451	mcap_notify_error(mcl, gerr);
452
453	g_error_free(gerr);
454	mcl->ms->mcl_disconnected_cb(mcl, mcl->ms->user_data);
455	mcap_cache_mcl(mcl);
456
457	return FALSE;
458}
459
460gboolean mcap_create_mdl(struct mcap_mcl *mcl,
461				uint8_t mdepid,
462				uint8_t conf,
463				mcap_mdl_operation_conf_cb connect_cb,
464				gpointer user_data,
465				GDestroyNotify destroy,
466				GError **err)
467{
468	struct mcap_mdl *mdl;
469	struct mcap_mdl_op_cb *con;
470	mcap_md_create_mdl_req *cmd;
471	uint16_t id;
472
473	id = generate_mdlid(mcl);
474	if (!id) {
475		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
476					"Not more mdlids available");
477		return FALSE;
478	}
479
480	mdl = g_new0(struct mcap_mdl, 1);
481	mdl->mcl = mcap_mcl_ref(mcl);
482	mdl->mdlid = id;
483	mdl->mdep_id = mdepid;
484	mdl->state = MDL_WAITING;
485
486	con = g_new0(struct mcap_mdl_op_cb, 1);
487	con->mdl = mdl;
488	con->cb.op_conf = connect_cb;
489	con->destroy = destroy;
490	con->user_data = user_data;
491
492	cmd = create_mdl_req(id, mdepid, conf);
493	if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_create_mdl_req),
494									err)) {
495		free_mdl(mdl);
496		g_free(con);
497		g_free(cmd);
498		return FALSE;
499	}
500
501	mcl->state = MCL_ACTIVE;
502	mcl->priv_data = con;
503
504	mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
505	mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
506									mcl);
507	return TRUE;
508}
509
510gboolean mcap_reconnect_mdl(struct mcap_mdl *mdl,
511				mcap_mdl_operation_cb reconnect_cb,
512				gpointer user_data,
513				GDestroyNotify destroy,
514				GError **err)
515{
516	struct mcap_mdl_op_cb *con;
517	struct mcap_mcl *mcl = mdl->mcl;
518	mcap_md_req *cmd;
519
520	if (mdl->state != MDL_CLOSED) {
521		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
522					"MDL is not closed");
523		return FALSE;
524	}
525	con = g_new0(struct mcap_mdl_op_cb, 1);
526
527	cmd = create_req(MCAP_MD_RECONNECT_MDL_REQ, mdl->mdlid);
528	if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) {
529		g_free(con);
530		g_free(cmd);
531		return FALSE;
532	}
533
534	mdl->state = MDL_WAITING;
535
536	con->mdl = mdl;
537	con->cb.op = reconnect_cb;
538	con->destroy = destroy;
539	con->user_data = user_data;
540
541	mcl->state = MCL_ACTIVE;
542	mcl->priv_data = con;
543
544	mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
545									mcl);
546	return TRUE;
547}
548
549static gboolean send_delete_req(struct mcap_mcl *mcl,
550						struct mcap_mdl_op_cb *con,
551						uint16_t mdlid,
552						GError **err)
553{
554	mcap_md_req *cmd;
555
556	cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdlid);
557	if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) {
558		g_free(cmd);
559		return FALSE;
560	}
561
562	mcl->priv_data = con;
563
564	mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
565									mcl);
566	return TRUE;
567}
568
569gboolean mcap_delete_all_mdls(struct mcap_mcl *mcl,
570					mcap_mdl_notify_cb delete_cb,
571					gpointer user_data,
572					GDestroyNotify destroy,
573					GError **err)
574{
575	GSList *l;
576	struct mcap_mdl *mdl;
577	struct mcap_mdl_op_cb *con;
578
579	DBG("MCL in state: %d", mcl->state);
580	if (!mcl->mdls) {
581		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
582				"There are not MDLs created");
583		return FALSE;
584	}
585
586	for (l = mcl->mdls; l; l = l->next) {
587		mdl = l->data;
588		if (mdl->state != MDL_WAITING)
589			mdl->state = MDL_DELETING;
590	}
591
592	con = g_new0(struct mcap_mdl_op_cb, 1);
593	con->mdl = NULL;
594	con->cb.notify = delete_cb;
595	con->destroy = destroy;
596	con->user_data = user_data;
597
598
599	if (!send_delete_req(mcl, con, MCAP_ALL_MDLIDS, err)) {
600		g_free(con);
601		return FALSE;
602	}
603
604	return TRUE;
605}
606
607gboolean mcap_delete_mdl(struct mcap_mdl *mdl, mcap_mdl_notify_cb delete_cb,
608							gpointer user_data,
609							GDestroyNotify destroy,
610							GError **err)
611{
612	struct mcap_mcl *mcl= mdl->mcl;
613	struct mcap_mdl_op_cb *con;
614	GSList *l;
615
616	l = g_slist_find(mcl->mdls, mdl);
617
618	if (!l) {
619		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL,
620					"%s" , error2str(MCAP_INVALID_MDEP));
621		return FALSE;
622	}
623
624	if (mdl->state == MDL_WAITING) {
625		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
626							"Mdl is not created");
627		return FALSE;
628	}
629
630	mdl->state = MDL_DELETING;
631
632	con = g_new0(struct mcap_mdl_op_cb, 1);
633	con->mdl = mdl;
634	con->cb.notify = delete_cb;
635	con->destroy = destroy;
636	con->user_data = user_data;
637
638	if (!send_delete_req(mcl, con, mdl->mdlid, err)) {
639		g_free(con);
640		return FALSE;
641	}
642
643	return TRUE;
644}
645
646gboolean mcap_mdl_abort(struct mcap_mdl *mdl, mcap_mdl_notify_cb abort_cb,
647							gpointer user_data,
648							GDestroyNotify destroy,
649							GError **err)
650{
651	struct mcap_mdl_op_cb *con;
652	struct mcap_mcl *mcl = mdl->mcl;
653	mcap_md_req *cmd;
654
655	if (mdl->state != MDL_WAITING) {
656		g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
657							"Mdl in invalid state");
658		return FALSE;
659	}
660
661	con = g_new0(struct mcap_mdl_op_cb, 1);
662	cmd = create_req(MCAP_MD_ABORT_MDL_REQ, mdl->mdlid);
663	if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) {
664		g_free(con);
665		g_free(cmd);
666		return FALSE;
667	}
668
669	con->mdl = mdl;
670	con->cb.notify = abort_cb;
671	con->destroy = destroy;
672	con->user_data = user_data;
673
674	mcl->priv_data = con;
675	mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
676									mcl);
677	return TRUE;
678}
679
680static struct mcap_mcl *find_mcl(GSList *list, const bdaddr_t *addr)
681{
682	GSList *l;
683	struct mcap_mcl *mcl;
684
685	for (l = list; l; l = l->next) {
686		mcl = l->data;
687
688		if (!bacmp(&mcl->addr, addr))
689			return mcl;
690	}
691
692	return NULL;
693}
694
695int mcap_mdl_get_fd(struct mcap_mdl *mdl)
696{
697	if (!mdl || mdl->state != MDL_CONNECTED)
698		return -ENOTCONN;
699
700	return g_io_channel_unix_get_fd(mdl->dc);
701}
702
703uint16_t mcap_mdl_get_mdlid(struct mcap_mdl *mdl)
704{
705	if (!mdl)
706		return MCAP_MDLID_RESERVED;
707
708	return mdl->mdlid;
709}
710
711static void close_mcl(struct mcap_mcl *mcl, gboolean cache_requested)
712{
713	gboolean save = ((!(mcl->ctrl & MCAP_CTRL_FREE)) && cache_requested);
714
715	RELEASE_TIMER(mcl);
716
717	if (mcl->cc) {
718		g_io_channel_shutdown(mcl->cc, TRUE, NULL);
719		g_io_channel_unref(mcl->cc);
720		mcl->cc = NULL;
721	}
722
723	if (mcl->wid) {
724		g_source_remove(mcl->wid);
725		mcl->wid = 0;
726	}
727
728	if (mcl->lcmd) {
729		g_free(mcl->lcmd);
730		mcl->lcmd = NULL;
731	}
732
733	if (mcl->priv_data)
734		free_mcl_priv_data(mcl);
735
736	g_slist_foreach(mcl->mdls, (GFunc) shutdown_mdl, NULL);
737
738	mcap_sync_stop(mcl);
739
740	mcl->state = MCL_IDLE;
741
742	if (save)
743		return;
744
745	g_slist_foreach(mcl->mdls, (GFunc) free_mdl, NULL);
746	g_slist_free(mcl->mdls);
747	mcl->mdls = NULL;
748}
749
750static void mcap_mcl_shutdown(struct mcap_mcl *mcl)
751{
752	close_mcl(mcl, TRUE);
753}
754
755static void mcap_mcl_release(struct mcap_mcl *mcl)
756{
757	close_mcl(mcl, FALSE);
758}
759
760static void mcap_cache_mcl(struct mcap_mcl *mcl)
761{
762	GSList *l;
763	struct mcap_mcl *last;
764	int len;
765
766	if (mcl->ctrl & MCAP_CTRL_CACHED)
767		return;
768
769	mcl->ms->mcls = g_slist_remove(mcl->ms->mcls, mcl);
770
771	if (mcl->ctrl & MCAP_CTRL_NOCACHE) {
772		mcl->ms->cached = g_slist_remove(mcl->ms->cached, mcl);
773		mcap_mcl_release(mcl);
774		mcap_mcl_unref(mcl);
775		return;
776	}
777
778	DBG("Caching MCL");
779
780	len = g_slist_length(mcl->ms->cached);
781	if (len == MAX_CACHED) {
782		/* Remove the latest cached mcl */
783		l = g_slist_last(mcl->ms->cached);
784		last = l->data;
785		mcl->ms->cached = g_slist_remove(mcl->ms->cached, last);
786		last->ctrl &= ~MCAP_CTRL_CACHED;
787		if (last->ctrl & MCAP_CTRL_CONN) {
788			/* We have to release this MCL if */
789			/* connection is not succesful    */
790			last->ctrl |= MCAP_CTRL_FREE;
791		} else {
792			mcap_mcl_release(last);
793			last->ms->mcl_uncached_cb(last, last->ms->user_data);
794		}
795		mcap_mcl_unref(last);
796	}
797
798	mcl->ms->cached = g_slist_prepend(mcl->ms->cached, mcl);
799	mcl->ctrl |= MCAP_CTRL_CACHED;
800	mcap_mcl_shutdown(mcl);
801}
802
803static void mcap_uncache_mcl(struct mcap_mcl *mcl)
804{
805	if (!(mcl->ctrl & MCAP_CTRL_CACHED))
806		return;
807
808	DBG("Got MCL from cache");
809
810	mcl->ms->cached = g_slist_remove(mcl->ms->cached, mcl);
811	mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls, mcl);
812	mcl->ctrl &= ~MCAP_CTRL_CACHED;
813	mcl->ctrl &= ~MCAP_CTRL_FREE;
814}
815
816void mcap_close_mcl(struct mcap_mcl *mcl, gboolean cache)
817{
818	if (!mcl)
819		return;
820
821	if (mcl->ctrl & MCAP_CTRL_FREE) {
822		mcap_mcl_release(mcl);
823		return;
824	}
825
826	if (!cache)
827		mcl->ctrl |= MCAP_CTRL_NOCACHE;
828
829	if (mcl->cc) {
830		g_io_channel_shutdown(mcl->cc, TRUE, NULL);
831		g_io_channel_unref(mcl->cc);
832		mcl->cc = NULL;
833		mcl->state = MCL_IDLE;
834	} else if ((mcl->ctrl & MCAP_CTRL_CACHED) &&
835					(mcl->ctrl & MCAP_CTRL_NOCACHE)) {
836		mcl->ctrl &= ~MCAP_CTRL_CACHED;
837		mcl->ms->cached = g_slist_remove(mcl->ms->cached, mcl);
838		mcap_mcl_release(mcl);
839		mcap_mcl_unref(mcl);
840	}
841}
842
843struct mcap_mcl *mcap_mcl_ref(struct mcap_mcl *mcl)
844{
845	mcl->ref++;
846
847	DBG("mcap_mcl_ref(%p): ref=%d", mcl, mcl->ref);
848
849	return mcl;
850}
851
852void mcap_mcl_unref(struct mcap_mcl *mcl)
853{
854	mcl->ref--;
855
856	DBG("mcap_mcl_unref(%p): ref=%d", mcl, mcl->ref);
857
858	if (mcl->ref > 0)
859		return;
860
861	mcap_mcl_release(mcl);
862
863	g_free(mcl->cb);
864	g_free(mcl);
865}
866
867static gboolean parse_set_opts(struct mcap_mdl_cb *mdl_cb, GError **err,
868						McapMclCb cb1, va_list args)
869{
870	McapMclCb cb = cb1;
871	struct mcap_mdl_cb *c;
872
873	c = g_new0(struct mcap_mdl_cb, 1);
874
875	while (cb != MCAP_MDL_CB_INVALID) {
876		switch (cb) {
877		case MCAP_MDL_CB_CONNECTED:
878			c->mdl_connected = va_arg(args, mcap_mdl_event_cb);
879			break;
880		case MCAP_MDL_CB_CLOSED:
881			c->mdl_closed = va_arg(args, mcap_mdl_event_cb);
882			break;
883		case MCAP_MDL_CB_DELETED:
884			c->mdl_deleted = va_arg(args, mcap_mdl_event_cb);
885			break;
886		case MCAP_MDL_CB_ABORTED:
887			c->mdl_aborted = va_arg(args, mcap_mdl_event_cb);
888			break;
889		case MCAP_MDL_CB_REMOTE_CONN_REQ:
890			c->mdl_conn_req = va_arg(args,
891						mcap_remote_mdl_conn_req_cb);
892			break;
893		case MCAP_MDL_CB_REMOTE_RECONN_REQ:
894			c->mdl_reconn_req = va_arg(args,
895						mcap_remote_mdl_reconn_req_cb);
896			break;
897		default:
898			g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
899						"Unknown option %d", cb);
900			return FALSE;
901		}
902		cb = va_arg(args, int);
903	}
904
905	/* Set new callbacks */
906	if (c->mdl_connected)
907		mdl_cb->mdl_connected = c->mdl_connected;
908	if (c->mdl_closed)
909		mdl_cb->mdl_closed = c->mdl_closed;
910	if (c->mdl_deleted)
911		mdl_cb->mdl_deleted = c->mdl_deleted;
912	if (c->mdl_aborted)
913		mdl_cb->mdl_aborted = c->mdl_aborted;
914	if (c->mdl_conn_req)
915		mdl_cb->mdl_conn_req = c->mdl_conn_req;
916	if (c->mdl_reconn_req)
917		mdl_cb->mdl_reconn_req = c->mdl_reconn_req;
918
919	g_free(c);
920
921	return TRUE;
922}
923
924gboolean mcap_mcl_set_cb(struct mcap_mcl *mcl, gpointer user_data,
925					GError **gerr, McapMclCb cb1, ...)
926{
927	va_list args;
928	gboolean ret;
929
930	va_start(args, cb1);
931	ret = parse_set_opts(mcl->cb, gerr, cb1, args);
932	va_end(args);
933
934	if (!ret)
935		return FALSE;
936
937	mcl->cb->user_data = user_data;
938	return TRUE;
939}
940
941void mcap_mcl_get_addr(struct mcap_mcl *mcl, bdaddr_t *addr)
942{
943	bacpy(addr, &mcl->addr);
944}
945
946static void mcap_del_mdl(gpointer elem, gpointer user_data)
947{
948	struct mcap_mdl *mdl = elem;
949	gboolean notify = *(gboolean *) user_data;
950
951	shutdown_mdl(mdl);
952	if (notify)
953		mdl->mcl->cb->mdl_deleted(mdl, mdl->mcl->cb->user_data);
954
955	free_mdl(mdl);
956}
957
958static gboolean check_cmd_req_length(struct mcap_mcl *mcl, void *cmd,
959				uint32_t rlen, uint32_t explen, uint8_t rspcod)
960{
961	mcap_md_req *req;
962	uint16_t mdl_id;
963
964	if (rlen != explen) {
965		if (rlen >= sizeof(mcap_md_req)) {
966			req = cmd;
967			mdl_id = ntohs(req->mdl);
968		} else {
969			/* We can't get mdlid */
970			mdl_id = MCAP_MDLID_RESERVED;
971		}
972		mcap_send_cmd(mcl, rspcod, MCAP_INVALID_PARAM_VALUE, mdl_id,
973								NULL, 0);
974		return FALSE;
975	}
976	return TRUE;
977}
978
979static void process_md_create_mdl_req(struct mcap_mcl *mcl, void *cmd,
980								uint32_t len)
981{
982	mcap_md_create_mdl_req *req;
983	struct mcap_mdl *mdl;
984	uint16_t mdl_id;
985	uint8_t mdep_id;
986	uint8_t cfga, conf;
987	uint8_t rsp;
988
989	if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_create_mdl_req),
990							MCAP_MD_CREATE_MDL_RSP))
991		return;
992
993	req = cmd;
994	mdl_id = ntohs(req->mdl);
995	if (mdl_id < MCAP_MDLID_INITIAL || mdl_id > MCAP_MDLID_FINAL) {
996		mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL,
997							mdl_id, NULL, 0);
998		return;
999	}
1000
1001	mdep_id = req->mdep;
1002	if (mdep_id > MCAP_MDEPID_FINAL) {
1003		mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDEP,
1004							mdl_id, NULL, 0);
1005		return;
1006	}
1007
1008	mdl = get_mdl(mcl, mdl_id);
1009	if (mdl && (mdl->state == MDL_WAITING || mdl->state == MDL_DELETING )) {
1010		/* Creation request arrives for a MDL that is being managed
1011		* at current moment */
1012		mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_MDL_BUSY,
1013							mdl_id, NULL, 0);
1014		return;
1015	}
1016
1017	cfga = conf = req->conf;
1018	/* Callback to upper layer */
1019	rsp = mcl->cb->mdl_conn_req(mcl, mdep_id, mdl_id, &conf,
1020							mcl->cb->user_data);
1021	if (mcl->state == MCL_IDLE) {
1022		/* MCL has been closed int the callback */
1023		return;
1024	}
1025
1026	if (cfga != 0 && cfga != conf) {
1027		/* Remote device set default configuration but upper profile */
1028		/* has changed it. Protocol Error: force closing the MCL by */
1029		/* remote device using UNSPECIFIED_ERROR response */
1030		mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP,
1031				MCAP_UNSPECIFIED_ERROR, mdl_id, NULL, 0);
1032		return;
1033	}
1034	if (rsp != MCAP_SUCCESS) {
1035		mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id,
1036								NULL, 0);
1037		return;
1038	}
1039
1040	if (!mdl) {
1041		mdl = g_new0(struct mcap_mdl, 1);
1042		mdl->mcl = mcap_mcl_ref(mcl);
1043		mdl->mdlid = mdl_id;
1044		mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
1045	} else if (mdl->state == MDL_CONNECTED) {
1046		/* MCAP specification says that we should close the MCL if
1047		 * it is open when we receive a MD_CREATE_MDL_REQ */
1048		shutdown_mdl(mdl);
1049	}
1050
1051	mdl->mdep_id = mdep_id;
1052	mdl->state = MDL_WAITING;
1053
1054	mcl->state = MCL_PENDING;
1055	mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_SUCCESS, mdl_id,
1056								&conf, 1);
1057}
1058
1059static void process_md_reconnect_mdl_req(struct mcap_mcl *mcl, void *cmd,
1060								uint32_t len)
1061{
1062	mcap_md_req *req;
1063	struct mcap_mdl *mdl;
1064	uint16_t mdl_id;
1065	uint8_t rsp;
1066
1067	if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req),
1068						MCAP_MD_RECONNECT_MDL_RSP))
1069		return;
1070
1071	req = cmd;
1072	mdl_id = ntohs(req->mdl);
1073
1074	mdl = get_mdl(mcl, mdl_id);
1075	if (!mdl) {
1076		mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_INVALID_MDL,
1077							mdl_id, NULL, 0);
1078		return;
1079	} else if (mdl->state == MDL_WAITING || mdl->state == MDL_DELETING ) {
1080		/* Creation request arrives for a MDL that is being managed
1081		* at current moment */
1082		mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_MDL_BUSY,
1083							mdl_id, NULL, 0);
1084		return;
1085	}
1086
1087	/* Callback to upper layer */
1088	rsp = mcl->cb->mdl_reconn_req(mdl, mcl->cb->user_data);
1089	if (mcl->state == MCL_IDLE)
1090		return;
1091
1092	if (rsp != MCAP_SUCCESS) {
1093		mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, rsp, mdl_id,
1094								NULL, 0);
1095		return;
1096	}
1097
1098	if (mdl->state == MDL_CONNECTED)
1099		shutdown_mdl(mdl);
1100
1101	mdl->state = MDL_WAITING;
1102	mcl->state = MCL_PENDING;
1103	mcap_send_cmd(mcl, MCAP_MD_RECONNECT_MDL_RSP, MCAP_SUCCESS, mdl_id,
1104								NULL, 0);
1105}
1106
1107static void process_md_abort_mdl_req(struct mcap_mcl *mcl, void *cmd,
1108								uint32_t len)
1109{
1110	mcap_md_req *req;
1111	GSList *l;
1112	struct mcap_mdl *mdl, *abrt;
1113	uint16_t mdl_id;
1114
1115	if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req),
1116							MCAP_MD_ABORT_MDL_RSP))
1117		return;
1118
1119	req = cmd;
1120	mdl_id = ntohs(req->mdl);
1121	mcl->state = MCL_CONNECTED;
1122	for (l = mcl->mdls; l; l = l->next) {
1123		mdl = l->data;
1124		if (mdl_id == mdl->mdlid && mdl->state == MDL_WAITING) {
1125			abrt = mdl;
1126			if (mcl->state != MCL_CONNECTED)
1127				break;
1128			continue;
1129		}
1130		if (mdl->state == MDL_CONNECTED && mcl->state != MCL_ACTIVE)
1131			mcl->state = MCL_ACTIVE;
1132
1133		if (abrt && mcl->state == MCL_ACTIVE)
1134			break;
1135	}
1136
1137	if (!abrt) {
1138		mcap_send_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_INVALID_MDL,
1139							mdl_id, NULL, 0);
1140		return;
1141	}
1142
1143	mcl->cb->mdl_aborted(abrt, mcl->cb->user_data);
1144	abrt->state = MDL_CLOSED;
1145	mcap_send_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_SUCCESS, mdl_id,
1146								NULL, 0);
1147}
1148
1149static void process_md_delete_mdl_req(struct mcap_mcl *mcl, void *cmd,
1150								uint32_t len)
1151{
1152	mcap_md_req *req;
1153	struct mcap_mdl *mdl, *aux;
1154	uint16_t mdlid;
1155	gboolean notify;
1156	GSList *l;
1157
1158	if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_req),
1159							MCAP_MD_DELETE_MDL_RSP))
1160		return;
1161
1162	req = cmd;
1163	mdlid = ntohs(req->mdl);
1164	if (mdlid == MCAP_ALL_MDLIDS) {
1165		notify = FALSE;
1166		g_slist_foreach(mcl->mdls, mcap_del_mdl, &notify);
1167		g_slist_free(mcl->mdls);
1168		mcl->mdls = NULL;
1169		mcl->state = MCL_CONNECTED;
1170		/* NULL mdl means ALL_MDLS */
1171		mcl->cb->mdl_deleted(NULL, mcl->cb->user_data);
1172		goto resp;
1173	}
1174
1175	if (mdlid < MCAP_MDLID_INITIAL || mdlid > MCAP_MDLID_FINAL) {
1176		mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL,
1177								mdlid, NULL, 0);
1178		return;
1179	}
1180
1181	for (l = mcl->mdls, mdl = NULL; l; l = l->next) {
1182		aux = l->data;
1183		if (aux->mdlid == mdlid) {
1184			mdl = aux;
1185			break;
1186		}
1187	}
1188
1189	if (!mdl || mdl->state == MDL_WAITING) {
1190		mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL,
1191								mdlid, NULL, 0);
1192		return;
1193	}
1194
1195	mcl->mdls = g_slist_remove(mcl->mdls, mdl);
1196	update_mcl_state(mcl);
1197	notify = TRUE;
1198	mcap_del_mdl(mdl, &notify);
1199
1200resp:
1201	mcap_send_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_SUCCESS, mdlid,
1202								NULL, 0);
1203}
1204
1205static void invalid_req_state(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
1206{
1207	uint16_t mdlr;
1208
1209	error("Invalid cmd received (op code = %d) in state %d", cmd[0],
1210								mcl->state);
1211	/* Get previously mdlid sent to generate an appropriate
1212	 * response if it is possible */
1213	mdlr = len < sizeof(mcap_md_req) ? MCAP_MDLID_RESERVED :
1214					ntohs(((mcap_md_req *) cmd)->mdl);
1215	mcap_send_cmd(mcl, cmd[0]+1, MCAP_INVALID_OPERATION, mdlr, NULL, 0);
1216}
1217
1218/* Function used to process commands depending of MCL state */
1219static void proc_req_connected(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
1220{
1221	switch (cmd[0]) {
1222	case MCAP_MD_CREATE_MDL_REQ:
1223		process_md_create_mdl_req(mcl, cmd, len);
1224		break;
1225	case MCAP_MD_RECONNECT_MDL_REQ:
1226		process_md_reconnect_mdl_req(mcl, cmd, len);
1227		break;
1228	case MCAP_MD_DELETE_MDL_REQ:
1229		process_md_delete_mdl_req(mcl, cmd, len);
1230		break;
1231	default:
1232		invalid_req_state(mcl, cmd, len);
1233	}
1234}
1235
1236static void proc_req_pending(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
1237{
1238	if (cmd[0] == MCAP_MD_ABORT_MDL_REQ)
1239		process_md_abort_mdl_req(mcl, cmd, len);
1240	else
1241		invalid_req_state(mcl, cmd, len);
1242}
1243
1244static void proc_req_active(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
1245{
1246	switch (cmd[0]) {
1247	case MCAP_MD_CREATE_MDL_REQ:
1248		process_md_create_mdl_req(mcl, cmd, len);
1249		break;
1250	case MCAP_MD_RECONNECT_MDL_REQ:
1251		process_md_reconnect_mdl_req(mcl, cmd, len);
1252		break;
1253	case MCAP_MD_DELETE_MDL_REQ:
1254		process_md_delete_mdl_req(mcl, cmd, len);
1255		break;
1256	default:
1257		invalid_req_state(mcl, cmd, len);
1258	}
1259}
1260
1261/* Function used to process replies */
1262static gboolean check_err_rsp(struct mcap_mcl *mcl, mcap_rsp *rsp,
1263				uint32_t rlen, uint32_t len, GError **gerr)
1264{
1265	mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd;
1266	gint err = MCAP_ERROR_FAILED;
1267	gboolean close = FALSE;
1268	char *msg;
1269
1270	if (rsp->op == MCAP_ERROR_RSP) {
1271		msg = "MCAP_ERROR_RSP received";
1272		close = FALSE;
1273		goto fail;
1274	}
1275
1276	/* Check if the response matches with the last request */
1277	if (rlen < sizeof(mcap_rsp) || (mcl->lcmd[0] + 1) != rsp->op) {
1278		msg = "Protocol error";
1279		close = FALSE;
1280		goto fail;
1281	}
1282
1283	if (rlen < len) {
1284		msg = "Protocol error";
1285		close = FALSE;
1286		goto fail;
1287	}
1288
1289	if (rsp->mdl != cmdlast->mdl) {
1290		msg = "MDLID received doesn't match with MDLID sent";
1291		close = TRUE;
1292		goto fail;
1293	}
1294
1295	if (rsp->rc == MCAP_REQUEST_NOT_SUPPORTED) {
1296		msg = "Remote does not support opcodes";
1297		mcl->ctrl &= ~MCAP_CTRL_STD_OP;
1298		goto fail;
1299	}
1300
1301	if (rsp->rc == MCAP_UNSPECIFIED_ERROR) {
1302		msg = "Unspecified error";
1303		close = TRUE;
1304		goto fail;
1305	}
1306
1307	if (rsp->rc != MCAP_SUCCESS) {
1308		msg = error2str(rsp->rc);
1309		err = rsp->rc;
1310		goto fail;
1311	}
1312
1313	return FALSE;
1314
1315fail:
1316	g_set_error(gerr, MCAP_ERROR, err, "%s", msg);
1317	return close;
1318}
1319
1320static gboolean process_md_create_mdl_rsp(struct mcap_mcl *mcl,
1321						mcap_rsp *rsp, uint32_t len)
1322{
1323	mcap_md_create_mdl_req *cmdlast = (mcap_md_create_mdl_req *) mcl->lcmd;
1324	struct mcap_mdl_op_cb *conn = mcl->priv_data;
1325	mcap_mdl_operation_conf_cb connect_cb = conn->cb.op_conf;
1326	gpointer user_data = conn->user_data;
1327	struct mcap_mdl *mdl = conn->mdl;
1328	uint8_t conf = cmdlast->conf;
1329	gboolean close;
1330	GError *gerr = NULL;
1331
1332	close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp) + 1, &gerr);
1333	g_free(mcl->lcmd);
1334	mcl->lcmd = NULL;
1335	mcl->req = MCL_AVAILABLE;
1336
1337	if (gerr)
1338		goto fail;
1339
1340	/* Check if preferences changed */
1341	if (conf != 0x00 && rsp->data[0] != conf) {
1342		g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
1343						"Configuration changed");
1344		close = TRUE;
1345		goto fail;
1346	}
1347
1348	connect_cb(mdl, rsp->data[0], gerr, user_data);
1349	return close;
1350
1351fail:
1352	connect_cb(NULL, 0, gerr, user_data);
1353	mcl->mdls = g_slist_remove(mcl->mdls, mdl);
1354	free_mdl(mdl);
1355	g_error_free(gerr);
1356	update_mcl_state(mcl);
1357	return close;
1358}
1359
1360static gboolean process_md_reconnect_mdl_rsp(struct mcap_mcl *mcl,
1361						mcap_rsp *rsp, uint32_t len)
1362{
1363	struct mcap_mdl_op_cb *reconn = mcl->priv_data;
1364	mcap_mdl_operation_cb reconn_cb = reconn->cb.op;
1365	gpointer user_data = reconn->user_data;
1366	struct mcap_mdl *mdl = reconn->mdl;
1367	GError *gerr = NULL;
1368	gboolean close;
1369
1370	close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr);
1371
1372	g_free(mcl->lcmd);
1373	mcl->lcmd = NULL;
1374	mcl->req = MCL_AVAILABLE;
1375
1376	reconn_cb(mdl, gerr, user_data);
1377	if (!gerr)
1378		return close;
1379
1380	g_error_free(gerr);
1381	shutdown_mdl(mdl);
1382	update_mcl_state(mcl);
1383
1384	if (rsp->rc != MCAP_INVALID_MDL)
1385		return close;
1386
1387	/* Remove cached mdlid */
1388	mcl->mdls = g_slist_remove(mcl->mdls, mdl);
1389	mcl->cb->mdl_deleted(mdl, mcl->cb->user_data);
1390	free_mdl(mdl);
1391
1392	return close;
1393}
1394
1395static gboolean process_md_abort_mdl_rsp(struct mcap_mcl *mcl,
1396						mcap_rsp *rsp, uint32_t len)
1397{
1398	struct mcap_mdl_op_cb *abrt = mcl->priv_data;
1399	mcap_mdl_notify_cb abrt_cb = abrt->cb.notify;
1400	gpointer user_data = abrt->user_data;
1401	struct mcap_mdl *mdl = abrt->mdl;
1402	GError *gerr = NULL;
1403	gboolean close;
1404
1405	close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr);
1406
1407	g_free(mcl->lcmd);
1408	mcl->lcmd = NULL;
1409	mcl->req = MCL_AVAILABLE;
1410
1411	abrt_cb(gerr, user_data);
1412	shutdown_mdl(mdl);
1413
1414	if (len >= sizeof(mcap_rsp) && rsp->rc == MCAP_INVALID_MDL) {
1415		mcl->mdls = g_slist_remove(mcl->mdls, mdl);
1416		free_mdl(mdl);
1417	}
1418
1419	if (gerr)
1420		g_error_free(gerr);
1421
1422	update_mcl_state(mcl);
1423
1424	return close;
1425}
1426
1427static void restore_mdl(gpointer elem, gpointer data)
1428{
1429	struct mcap_mdl *mdl = elem;
1430
1431	if (mdl->state == MDL_DELETING) {
1432		if (mdl->dc)
1433			mdl->state = MDL_CONNECTED;
1434		else
1435			mdl->state = MDL_CLOSED;
1436	} else if (mdl->state == MDL_CLOSED)
1437		mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
1438}
1439
1440static gboolean process_md_delete_mdl_rsp(struct mcap_mcl *mcl, mcap_rsp *rsp,
1441								uint32_t len)
1442{
1443	struct mcap_mdl_op_cb *del = mcl->priv_data;
1444	struct mcap_mdl *mdl = del->mdl;
1445	mcap_mdl_notify_cb deleted_cb = del->cb.notify;
1446	gpointer user_data = del->user_data;
1447	mcap_md_req *cmdlast = (mcap_md_req *) mcl->lcmd;
1448	uint16_t mdlid = ntohs(cmdlast->mdl);
1449	GError *gerr = NULL;
1450	gboolean close;
1451	gboolean notify = FALSE;
1452
1453	close = check_err_rsp(mcl, rsp, len, sizeof(mcap_rsp), &gerr);
1454
1455	g_free(mcl->lcmd);
1456	mcl->lcmd = NULL;
1457	mcl->req = MCL_AVAILABLE;
1458
1459	if (gerr) {
1460		if (mdl)
1461			restore_mdl(mdl, NULL);
1462		else
1463			g_slist_foreach(mcl->mdls, restore_mdl, NULL);
1464		deleted_cb(gerr, user_data);
1465		g_error_free(gerr);
1466		return close;
1467	}
1468
1469	if (mdlid == MCAP_ALL_MDLIDS) {
1470		g_slist_foreach(mcl->mdls, mcap_del_mdl, &notify);
1471		g_slist_free(mcl->mdls);
1472		mcl->mdls = NULL;
1473		mcl->state = MCL_CONNECTED;
1474	} else {
1475		mcl->mdls = g_slist_remove(mcl->mdls, mdl);
1476		update_mcl_state(mcl);
1477		mcap_del_mdl(mdl, &notify);
1478	}
1479
1480	deleted_cb(gerr, user_data);
1481
1482	return close;
1483}
1484
1485static void post_process_rsp(struct mcap_mcl *mcl, struct mcap_mdl_op_cb *op)
1486{
1487	if (op->destroy)
1488		op->destroy(op->user_data);
1489
1490	if (mcl->priv_data != op) {
1491		/* Queued MCAP request in some callback. */
1492		/* We sould not delete the mcl private data */
1493		g_free(op);
1494	} else {
1495		/* This is not queued requets. It's safe */
1496		/* delete the mcl private data here. */
1497		g_free(mcl->priv_data);
1498		mcl->priv_data = NULL;
1499	}
1500}
1501
1502static void proc_response(struct mcap_mcl *mcl, void *buf, uint32_t len)
1503{
1504	struct mcap_mdl_op_cb *op = mcl->priv_data;
1505	mcap_rsp *rsp = buf;
1506	gboolean close;
1507
1508	RELEASE_TIMER(mcl);
1509
1510	switch (mcl->lcmd[0] + 1) {
1511	case MCAP_MD_CREATE_MDL_RSP:
1512		close = process_md_create_mdl_rsp(mcl, rsp, len);
1513		post_process_rsp(mcl, op);
1514		break;
1515	case MCAP_MD_RECONNECT_MDL_RSP:
1516		close = process_md_reconnect_mdl_rsp(mcl, rsp, len);
1517		post_process_rsp(mcl, op);
1518		break;
1519	case MCAP_MD_ABORT_MDL_RSP:
1520		close = process_md_abort_mdl_rsp(mcl, rsp, len);
1521		post_process_rsp(mcl, op);
1522		break;
1523	case MCAP_MD_DELETE_MDL_RSP:
1524		close = process_md_delete_mdl_rsp(mcl, rsp, len);
1525		post_process_rsp(mcl, op);
1526		break;
1527	default:
1528		DBG("Unknown cmd response received (op code = %d)", rsp->op);
1529		close = TRUE;
1530		break;
1531	}
1532
1533	if (close) {
1534		mcl->ms->mcl_disconnected_cb(mcl, mcl->ms->user_data);
1535		mcap_cache_mcl(mcl);
1536	}
1537}
1538
1539static void proc_cmd(struct mcap_mcl *mcl, uint8_t *cmd, uint32_t len)
1540{
1541	GError *gerr = NULL;
1542
1543	if (cmd[0] > MCAP_MD_SYNC_INFO_IND ||
1544					(cmd[0] > MCAP_MD_DELETE_MDL_RSP &&
1545					cmd[0] < MCAP_MD_SYNC_CAP_REQ)) {
1546		error("Unknown cmd received (op code = %d)", cmd[0]);
1547		mcap_send_cmd(mcl, MCAP_ERROR_RSP, MCAP_INVALID_OP_CODE,
1548						MCAP_MDLID_RESERVED, NULL, 0);
1549		return;
1550	}
1551
1552	if (cmd[0] >= MCAP_MD_SYNC_CAP_REQ &&
1553					cmd[0] <= MCAP_MD_SYNC_INFO_IND) {
1554		proc_sync_cmd(mcl, cmd, len);
1555		return;
1556	}
1557
1558	if (!(mcl->ctrl & MCAP_CTRL_STD_OP)) {
1559		/* In case the remote device doesn't work correctly */
1560		error("Remote device does not support opcodes, cmd ignored");
1561		return;
1562	}
1563
1564	if (mcl->req == MCL_WAITING_RSP) {
1565		if (cmd[0] & 0x01) {
1566			/* Request arrived when a response is expected */
1567			if (mcl->role == MCL_INITIATOR)
1568				/* ignore */
1569				return;
1570			/* Initiator will ignore our last request */
1571			RELEASE_TIMER(mcl);
1572			mcl->req = MCL_AVAILABLE;
1573			g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_REQ_IGNORED,
1574				"Initiator sent a request with more priority");
1575			mcap_notify_error(mcl, gerr);
1576			proc_req[mcl->state](mcl, cmd, len);
1577			return;
1578		}
1579		proc_response(mcl, cmd, len);
1580	} else if (cmd[0] & 0x01)
1581		proc_req[mcl->state](mcl, cmd, len);
1582}
1583
1584static gboolean mdl_event_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
1585{
1586
1587	struct mcap_mdl *mdl = data;
1588	gboolean notify;
1589
1590	DBG("Close MDL %d", mdl->mdlid);
1591
1592	notify = (mdl->state == MDL_CONNECTED);
1593	shutdown_mdl(mdl);
1594
1595	update_mcl_state(mdl->mcl);
1596
1597	if (notify) {
1598		/*Callback to upper layer */
1599		mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
1600	}
1601
1602	return FALSE;
1603}
1604
1605static void mcap_connect_mdl_cb(GIOChannel *chan, GError *conn_err,
1606								gpointer data)
1607{
1608	struct mcap_mdl_op_cb *con = data;
1609	struct mcap_mdl *mdl = con->mdl;
1610	mcap_mdl_operation_cb cb = con->cb.op;
1611	gpointer user_data = con->user_data;
1612
1613	DBG("mdl connect callback");
1614
1615	if (conn_err) {
1616		DBG("ERROR: mdl connect callback");
1617		mdl->state = MDL_CLOSED;
1618		g_io_channel_unref(mdl->dc);
1619		mdl->dc = NULL;
1620		cb(mdl, conn_err, user_data);
1621		return;
1622	}
1623
1624	mdl->state = MDL_CONNECTED;
1625	mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1626						(GIOFunc) mdl_event_cb, mdl);
1627
1628	cb(mdl, conn_err, user_data);
1629}
1630
1631static void mdl_io_destroy(gpointer data)
1632{
1633	struct mcap_mdl_op_cb *con = data;
1634
1635	if (con->destroy)
1636		con->destroy(con->user_data);
1637
1638	g_free(con);
1639}
1640
1641gboolean mcap_connect_mdl(struct mcap_mdl *mdl, uint8_t mode,
1642					uint16_t dcpsm,
1643					mcap_mdl_operation_cb connect_cb,
1644					gpointer user_data,
1645					GDestroyNotify destroy,
1646					GError **err)
1647{
1648	struct mcap_mdl_op_cb *con;
1649
1650	if (mdl->state != MDL_WAITING) {
1651		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL,
1652					"%s", error2str(MCAP_INVALID_MDL));
1653		return FALSE;
1654	}
1655
1656	if ((mode != L2CAP_MODE_ERTM) && (mode != L2CAP_MODE_STREAMING)) {
1657		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
1658						"Invalid MDL configuration");
1659		return FALSE;
1660	}
1661
1662	con = g_new0(struct mcap_mdl_op_cb, 1);
1663	con->mdl = mdl;
1664	con->cb.op = connect_cb;
1665	con->destroy = destroy;
1666	con->user_data = user_data;
1667
1668	/* TODO: Check if BtIOType is ERTM or Streaming before continue */
1669
1670	mdl->dc = bt_io_connect(BT_IO_L2CAP, mcap_connect_mdl_cb, con,
1671				mdl_io_destroy, err,
1672				BT_IO_OPT_SOURCE_BDADDR, &mdl->mcl->ms->src,
1673				BT_IO_OPT_DEST_BDADDR, &mdl->mcl->addr,
1674				BT_IO_OPT_PSM, dcpsm,
1675				BT_IO_OPT_MTU, MCAP_DC_MTU,
1676				BT_IO_OPT_SEC_LEVEL, mdl->mcl->ms->sec,
1677				BT_IO_OPT_MODE, mode,
1678				BT_IO_OPT_INVALID);
1679	if (!mdl->dc) {
1680		DBG("MDL Connection error");
1681		mdl->state = MDL_CLOSED;
1682		g_free(con);
1683		return FALSE;
1684	}
1685
1686	return TRUE;
1687}
1688
1689static gboolean mcl_control_cb(GIOChannel *chan, GIOCondition cond,
1690								gpointer data)
1691{
1692	GError *gerr = NULL;
1693	struct mcap_mcl *mcl = data;
1694	int sk, len;
1695	uint8_t buf[MCAP_CC_MTU];
1696
1697	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
1698		goto fail;
1699
1700	sk = g_io_channel_unix_get_fd(chan);
1701	len = read(sk, buf, sizeof(buf));
1702	if (len < 0)
1703		goto fail;
1704
1705	proc_cmd(mcl, buf, (uint32_t) len);
1706	return TRUE;
1707
1708fail:
1709	if (mcl->state != MCL_IDLE) {
1710		if (mcl->req == MCL_WAITING_RSP) {
1711			/* notify error in pending callback */
1712			g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_MCL_CLOSED,
1713								"MCL closed");
1714			mcap_notify_error(mcl, gerr);
1715			g_error_free(gerr);
1716		}
1717		mcl->ms->mcl_disconnected_cb(mcl, mcl->ms->user_data);
1718	}
1719	mcap_cache_mcl(mcl);
1720	return FALSE;
1721}
1722
1723static void mcap_connect_mcl_cb(GIOChannel *chan, GError *conn_err,
1724							gpointer user_data)
1725{
1726	char dstaddr[18];
1727	struct connect_mcl *con = user_data;
1728	struct mcap_mcl *aux, *mcl = con->mcl;
1729	mcap_mcl_connect_cb connect_cb = con->connect_cb;
1730	gpointer data = con->user_data;
1731	GError *gerr = NULL;
1732
1733	mcl->ctrl &= ~MCAP_CTRL_CONN;
1734
1735	if (conn_err) {
1736		if (mcl->ctrl & MCAP_CTRL_FREE) {
1737			mcap_mcl_release(mcl);
1738			mcl->ms->mcl_uncached_cb(mcl, mcl->ms->user_data);
1739		}
1740		connect_cb(NULL, conn_err, data);
1741		return;
1742	}
1743
1744	ba2str(&mcl->addr, dstaddr);
1745
1746	aux = find_mcl(mcl->ms->mcls, &mcl->addr);
1747	if (aux) {
1748		/* Double MCL connection case */
1749		error("MCL error: Device %s is already connected", dstaddr);
1750		g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS,
1751					"MCL %s is already connected", dstaddr);
1752		connect_cb(NULL, gerr, data);
1753		g_error_free(gerr);
1754		return;
1755	}
1756
1757	mcl->state = MCL_CONNECTED;
1758	mcl->role = MCL_INITIATOR;
1759	mcl->req = MCL_AVAILABLE;
1760	mcl->ctrl |= MCAP_CTRL_STD_OP;
1761
1762	mcap_sync_init(mcl);
1763
1764	if (mcl->ctrl & MCAP_CTRL_CACHED)
1765		mcap_uncache_mcl(mcl);
1766	else {
1767		mcl->ctrl &= ~MCAP_CTRL_FREE;
1768		mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls,
1769							mcap_mcl_ref(mcl));
1770	}
1771
1772	mcl->wid = g_io_add_watch(mcl->cc,
1773				G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1774				(GIOFunc) mcl_control_cb, mcl);
1775	connect_cb(mcl, gerr, data);
1776}
1777
1778static void set_mdl_properties(GIOChannel *chan, struct mcap_mdl *mdl)
1779{
1780	struct mcap_mcl *mcl = mdl->mcl;
1781
1782	mdl->state = MDL_CONNECTED;
1783	mdl->dc = g_io_channel_ref(chan);
1784	mdl->wid = g_io_add_watch(mdl->dc, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1785						(GIOFunc) mdl_event_cb, mdl);
1786
1787	mcl->state = MCL_ACTIVE;
1788	mcl->cb->mdl_connected(mdl, mcl->cb->user_data);
1789}
1790
1791static void mcl_io_destroy(gpointer data)
1792{
1793	struct connect_mcl *con = data;
1794
1795	mcap_mcl_unref(con->mcl);
1796	if (con->destroy)
1797		con->destroy(con->user_data);
1798	g_free(con);
1799}
1800
1801gboolean mcap_create_mcl(struct mcap_instance *ms,
1802				const bdaddr_t *addr,
1803				uint16_t ccpsm,
1804				mcap_mcl_connect_cb connect_cb,
1805				gpointer user_data,
1806				GDestroyNotify destroy,
1807				GError **err)
1808{
1809	struct mcap_mcl *mcl;
1810	struct connect_mcl *con;
1811
1812	mcl = find_mcl(ms->mcls, addr);
1813	if (mcl) {
1814		g_set_error(err, MCAP_ERROR, MCAP_ERROR_ALREADY_EXISTS,
1815					"MCL is already connected.");
1816		return FALSE;
1817	}
1818
1819	mcl = find_mcl(ms->cached, addr);
1820	if (!mcl) {
1821		mcl = g_new0(struct mcap_mcl, 1);
1822		mcl->ms = ms;
1823		mcl->state = MCL_IDLE;
1824		bacpy(&mcl->addr, addr);
1825		set_default_cb(mcl);
1826		mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1;
1827	}
1828
1829	mcl->ctrl |= MCAP_CTRL_CONN;
1830
1831	con = g_new0(struct connect_mcl, 1);
1832	con->mcl = mcap_mcl_ref(mcl);
1833	con->connect_cb = connect_cb;
1834	con->destroy = destroy;
1835	con->user_data = user_data;
1836
1837	mcl->cc = bt_io_connect(BT_IO_L2CAP, mcap_connect_mcl_cb, con,
1838				mcl_io_destroy, err,
1839				BT_IO_OPT_SOURCE_BDADDR, &ms->src,
1840				BT_IO_OPT_DEST_BDADDR, addr,
1841				BT_IO_OPT_PSM, ccpsm,
1842				BT_IO_OPT_MTU, MCAP_CC_MTU,
1843				BT_IO_OPT_SEC_LEVEL, ms->sec,
1844				BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
1845				BT_IO_OPT_INVALID);
1846	if (!mcl->cc) {
1847		mcl->ctrl &= ~MCAP_CTRL_CONN;
1848		if (mcl->ctrl & MCAP_CTRL_FREE) {
1849			mcap_mcl_release(mcl);
1850			mcl->ms->mcl_uncached_cb(mcl, mcl->ms->user_data);
1851		}
1852		mcap_mcl_unref(con->mcl);
1853		g_free(con);
1854		return FALSE;
1855	}
1856
1857	return TRUE;
1858}
1859
1860static void connect_dc_event_cb(GIOChannel *chan, GError *gerr,
1861							gpointer user_data)
1862{
1863	struct mcap_instance *ms = user_data;
1864	struct mcap_mcl *mcl;
1865	struct mcap_mdl *mdl;
1866	GError *err = NULL;
1867	bdaddr_t dst;
1868	GSList *l;
1869
1870	if (gerr)
1871		return;
1872
1873	bt_io_get(chan, BT_IO_L2CAP, &err,
1874			BT_IO_OPT_DEST_BDADDR, &dst,
1875			BT_IO_OPT_INVALID);
1876	if (err) {
1877		error("%s", err->message);
1878		g_error_free(err);
1879		goto drop;
1880	}
1881
1882	mcl = find_mcl(ms->mcls, &dst);
1883	if (!mcl || mcl->state != MCL_PENDING)
1884		goto drop;
1885
1886	for (l = mcl->mdls; l; l = l->next) {
1887		mdl = l->data;
1888		if (mdl->state == MDL_WAITING) {
1889			set_mdl_properties(chan, mdl);
1890			return;
1891		}
1892	}
1893
1894drop:
1895	g_io_channel_shutdown(chan, TRUE, NULL);
1896}
1897
1898static void set_mcl_conf(GIOChannel *chan, struct mcap_mcl *mcl)
1899{
1900	gboolean reconn;
1901
1902	mcl->state = MCL_CONNECTED;
1903	mcl->role = MCL_ACCEPTOR;
1904	mcl->req = MCL_AVAILABLE;
1905	mcl->cc = g_io_channel_ref(chan);
1906	mcl->ctrl |= MCAP_CTRL_STD_OP;
1907
1908	mcap_sync_init(mcl);
1909
1910	reconn = (mcl->ctrl & MCAP_CTRL_CACHED);
1911	if (reconn)
1912		mcap_uncache_mcl(mcl);
1913	else
1914		mcl->ms->mcls = g_slist_prepend(mcl->ms->mcls,
1915							mcap_mcl_ref(mcl));
1916
1917	mcl->wid = g_io_add_watch(mcl->cc,
1918			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1919			(GIOFunc) mcl_control_cb, mcl);
1920
1921	/* Callback to report new MCL */
1922	if (reconn)
1923		mcl->ms->mcl_reconnected_cb(mcl, mcl->ms->user_data);
1924	else
1925		mcl->ms->mcl_connected_cb(mcl, mcl->ms->user_data);
1926}
1927
1928static void connect_mcl_event_cb(GIOChannel *chan, GError *gerr,
1929							gpointer user_data)
1930{
1931	struct mcap_instance *ms = user_data;
1932	struct mcap_mcl *mcl;
1933	bdaddr_t dst;
1934	char address[18], srcstr[18];
1935	GError *err = NULL;
1936
1937	if (gerr)
1938		return;
1939
1940	bt_io_get(chan, BT_IO_L2CAP, &err,
1941			BT_IO_OPT_DEST_BDADDR, &dst,
1942			BT_IO_OPT_DEST, address,
1943			BT_IO_OPT_INVALID);
1944	if (err) {
1945		error("%s", err->message);
1946		g_error_free(err);
1947		goto drop;
1948	}
1949
1950	ba2str(&ms->src, srcstr);
1951	mcl = find_mcl(ms->mcls, &dst);
1952	if (mcl) {
1953		error("Control channel already created with %s on adapter %s",
1954				address, srcstr);
1955		goto drop;
1956	}
1957
1958	mcl = find_mcl(ms->cached, &dst);
1959	if (!mcl) {
1960		mcl = g_new0(struct mcap_mcl, 1);
1961		mcl->ms = ms;
1962		bacpy(&mcl->addr, &dst);
1963		set_default_cb(mcl);
1964		mcl->next_mdl = (rand() % MCAP_MDLID_FINAL) + 1;
1965	}
1966
1967	set_mcl_conf(chan, mcl);
1968
1969	return;
1970drop:
1971	g_io_channel_shutdown(chan, TRUE, NULL);
1972}
1973
1974struct mcap_instance *mcap_create_instance(bdaddr_t *src,
1975					BtIOSecLevel sec,
1976					uint16_t ccpsm,
1977					uint16_t dcpsm,
1978					mcap_mcl_event_cb mcl_connected,
1979					mcap_mcl_event_cb mcl_reconnected,
1980					mcap_mcl_event_cb mcl_disconnected,
1981					mcap_mcl_event_cb mcl_uncached,
1982					mcap_info_ind_event_cb mcl_sync_info_ind,
1983					gpointer user_data,
1984					GError **gerr)
1985{
1986	struct mcap_instance *ms;
1987
1988	if (sec < BT_IO_SEC_MEDIUM) {
1989		g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
1990				"Security level can't be minor of %d",
1991				BT_IO_SEC_MEDIUM);
1992		return NULL;
1993	}
1994
1995	if (!(mcl_connected && mcl_reconnected &&
1996			mcl_disconnected && mcl_uncached)) {
1997		g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
1998				"The callbacks can't be null");
1999		return NULL;
2000	}
2001
2002	ms = g_new0(struct mcap_instance, 1);
2003
2004	bacpy(&ms->src, src);
2005
2006	ms->sec = sec;
2007	ms->mcl_connected_cb = mcl_connected;
2008	ms->mcl_reconnected_cb = mcl_reconnected;
2009	ms->mcl_disconnected_cb = mcl_disconnected;
2010	ms->mcl_uncached_cb = mcl_uncached;
2011	ms->mcl_sync_infoind_cb = mcl_sync_info_ind;
2012	ms->user_data = user_data;
2013	ms->csp_enabled = FALSE;
2014
2015	/* Listen incoming connections in control channel */
2016	ms->ccio = bt_io_listen(BT_IO_L2CAP, connect_mcl_event_cb, NULL, ms,
2017				NULL, gerr,
2018				BT_IO_OPT_SOURCE_BDADDR, &ms->src,
2019				BT_IO_OPT_PSM, ccpsm,
2020				BT_IO_OPT_MTU, MCAP_CC_MTU,
2021				BT_IO_OPT_SEC_LEVEL, sec,
2022				BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
2023				BT_IO_OPT_INVALID);
2024	if (!ms->ccio) {
2025		error("%s", (*gerr)->message);
2026		g_free(ms);
2027		return NULL;
2028	}
2029
2030	/* Listen incoming connections in data channels */
2031	ms->dcio = bt_io_listen(BT_IO_L2CAP, connect_dc_event_cb, NULL, ms,
2032				NULL, gerr,
2033				BT_IO_OPT_SOURCE_BDADDR, &ms->src,
2034				BT_IO_OPT_PSM, dcpsm,
2035				BT_IO_OPT_MTU, MCAP_DC_MTU,
2036				BT_IO_OPT_SEC_LEVEL, sec,
2037				BT_IO_OPT_INVALID);
2038	if (!ms->dcio) {
2039		g_io_channel_shutdown(ms->ccio, TRUE, NULL);
2040		g_io_channel_unref(ms->ccio);
2041		ms->ccio = NULL;
2042		error("%s", (*gerr)->message);
2043		g_free(ms);
2044		return NULL;
2045	}
2046
2047	/* Initialize random seed to generate mdlids for this instance */
2048	srand(time(NULL));
2049
2050	return ms;
2051}
2052
2053void mcap_release_instance(struct mcap_instance *mi)
2054{
2055	GSList *l;
2056
2057	if (!mi)
2058		return;
2059
2060	if (mi->ccio) {
2061		g_io_channel_shutdown(mi->ccio, TRUE, NULL);
2062		g_io_channel_unref(mi->ccio);
2063		mi->ccio = NULL;
2064	}
2065
2066	if (mi->dcio) {
2067		g_io_channel_shutdown(mi->dcio, TRUE, NULL);
2068		g_io_channel_unref(mi->dcio);
2069		mi->dcio = NULL;
2070	}
2071
2072	for (l = mi->mcls; l; l = l->next) {
2073		mcap_mcl_release(l->data);
2074		mcap_mcl_unref(l->data);
2075	}
2076	g_slist_free(mi->mcls);
2077	mi->mcls = NULL;
2078
2079	for (l = mi->cached; l; l = l->next) {
2080		mcap_mcl_release(l->data);
2081		mcap_mcl_unref(l->data);
2082	}
2083	g_slist_free(mi->cached);
2084	mi->cached = NULL;
2085
2086	g_free(mi);
2087}
2088
2089uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err)
2090{
2091	uint16_t lpsm;
2092
2093	if (!(mi && mi->ccio)) {
2094		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
2095			"Invalid MCAP instance");
2096		return 0;
2097	}
2098
2099	if (!bt_io_get(mi->ccio, BT_IO_L2CAP, err,
2100			BT_IO_OPT_PSM, &lpsm,
2101			BT_IO_OPT_INVALID))
2102		return 0;
2103
2104	return lpsm;
2105}
2106
2107uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err)
2108{
2109	uint16_t lpsm;
2110
2111	if (!(mi && mi->dcio)) {
2112		g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
2113			"Invalid MCAP instance");
2114		return 0;
2115	}
2116
2117	if (!bt_io_get(mi->dcio, BT_IO_L2CAP, err,
2118			BT_IO_OPT_PSM, &lpsm,
2119			BT_IO_OPT_INVALID))
2120		return 0;
2121
2122	return lpsm;
2123}
2124