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