mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-15 08:14:28 +08:00
Add MCAP instance management
This commit is contained in:
parent
f5d82ee872
commit
49cbd0ac7b
@ -107,7 +107,7 @@ builtin_nodist =
|
||||
mcap_sources =
|
||||
|
||||
if MCAP
|
||||
mcap_sources += health/mcap_lib.h \
|
||||
mcap_sources += health/mcap_lib.h health/mcap_internal.h \
|
||||
health/mcap.h health/mcap.c
|
||||
endif
|
||||
|
||||
|
154
health/mcap.c
154
health/mcap.c
@ -33,8 +33,33 @@
|
||||
|
||||
#include "btio.h"
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#include "mcap.h"
|
||||
#include "mcap_lib.h"
|
||||
#include "mcap_internal.h"
|
||||
|
||||
#define MCAP_ERROR g_quark_from_static_string("mcap-error-quark")
|
||||
|
||||
|
||||
static void mcap_mcl_shutdown(struct mcap_mcl *mcl)
|
||||
{
|
||||
/* TODO: implement mcap_mcl_shutdown */
|
||||
}
|
||||
|
||||
void mcap_mcl_unref(struct mcap_mcl *mcl)
|
||||
{
|
||||
/* TODO: implement mcap_mcl_unref */
|
||||
}
|
||||
|
||||
static void confirm_dc_event_cb(GIOChannel *chan, gpointer user_data)
|
||||
{
|
||||
/* TODO: implement confirm_dc_event_cb */
|
||||
}
|
||||
|
||||
static void confirm_mcl_event_cb(GIOChannel *chan, gpointer user_data)
|
||||
{
|
||||
/* TODO: implement confirm_mcl_event_cb */
|
||||
}
|
||||
|
||||
struct mcap_instance *mcap_create_instance(bdaddr_t *src,
|
||||
BtIOSecLevel sec,
|
||||
@ -47,11 +72,134 @@ struct mcap_instance *mcap_create_instance(bdaddr_t *src,
|
||||
gpointer user_data,
|
||||
GError **gerr)
|
||||
{
|
||||
/* TODO: Create mcap_create_instance */
|
||||
return NULL;
|
||||
struct mcap_instance *ms;
|
||||
|
||||
if (sec < BT_IO_SEC_MEDIUM) {
|
||||
g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
|
||||
"Security level can't be minor of %d",
|
||||
BT_IO_SEC_MEDIUM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(mcl_connected && mcl_reconnected &&
|
||||
mcl_disconnected && mcl_uncached)) {
|
||||
g_set_error(gerr, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
|
||||
"The callbacks can't be null");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ms = g_new0(struct mcap_instance, 1);
|
||||
|
||||
bacpy(&ms->src, src);
|
||||
|
||||
ms->sec = sec;
|
||||
ms->mcl_connected_cb = mcl_connected;
|
||||
ms->mcl_reconnected_cb = mcl_reconnected;
|
||||
ms->mcl_disconnected_cb = mcl_disconnected;
|
||||
ms->mcl_uncached_cb = mcl_uncached;
|
||||
ms->user_data = user_data;
|
||||
|
||||
/* Listen incoming connections in control channel */
|
||||
ms->ccio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_mcl_event_cb, ms,
|
||||
NULL, gerr,
|
||||
BT_IO_OPT_SOURCE_BDADDR, &ms->src,
|
||||
BT_IO_OPT_PSM, ccpsm,
|
||||
BT_IO_OPT_MTU, MCAP_CC_MTU,
|
||||
BT_IO_OPT_SEC_LEVEL, sec,
|
||||
BT_IO_OPT_INVALID);
|
||||
if (!ms->ccio) {
|
||||
error("%s", (*gerr)->message);
|
||||
g_free(ms);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Listen incoming connections in data channels */
|
||||
ms->dcio = bt_io_listen(BT_IO_L2CAP, NULL, confirm_dc_event_cb, ms,
|
||||
NULL, gerr,
|
||||
BT_IO_OPT_SOURCE_BDADDR, &ms->src,
|
||||
BT_IO_OPT_PSM, dcpsm,
|
||||
BT_IO_OPT_MTU, MCAP_DC_MTU,
|
||||
BT_IO_OPT_SEC_LEVEL, sec,
|
||||
BT_IO_OPT_INVALID);
|
||||
if (!ms->dcio) {
|
||||
g_io_channel_shutdown(ms->ccio, TRUE, NULL);
|
||||
g_io_channel_unref(ms->ccio);
|
||||
ms->ccio = NULL;
|
||||
error("%s", (*gerr)->message);
|
||||
g_free(ms);
|
||||
return NULL;
|
||||
}
|
||||
/* Initialize random seed to generate mdlids for this instance */
|
||||
srand(time(NULL));
|
||||
return ms;
|
||||
}
|
||||
|
||||
void mcap_release_instance(struct mcap_instance *mi)
|
||||
{
|
||||
/* TODO: Create mcap_release_instance */
|
||||
GSList *l;
|
||||
|
||||
if (!mi)
|
||||
return;
|
||||
|
||||
if (mi->ccio) {
|
||||
g_io_channel_shutdown(mi->ccio, TRUE, NULL);
|
||||
g_io_channel_unref(mi->ccio);
|
||||
mi->ccio = NULL;
|
||||
}
|
||||
|
||||
if (mi->dcio) {
|
||||
g_io_channel_shutdown(mi->dcio, TRUE, NULL);
|
||||
g_io_channel_unref(mi->dcio);
|
||||
mi->dcio = NULL;
|
||||
}
|
||||
|
||||
for (l = mi->mcls; l; l = l->next) {
|
||||
mcap_mcl_shutdown(l->data);
|
||||
mcap_mcl_unref(l->data);
|
||||
}
|
||||
g_slist_free(mi->mcls);
|
||||
mi->mcls = NULL;
|
||||
|
||||
for (l = mi->cached; l; l = l->next)
|
||||
mcap_mcl_unref(l->data);
|
||||
g_slist_free(mi->cached);
|
||||
mi->cached = NULL;
|
||||
|
||||
g_free(mi);
|
||||
}
|
||||
|
||||
uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err)
|
||||
{
|
||||
uint16_t lpsm;
|
||||
|
||||
if (!(mi && mi->ccio)) {
|
||||
g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
|
||||
"Invalid MCAP instance");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_io_get(mi->ccio, BT_IO_L2CAP, err,
|
||||
BT_IO_OPT_PSM, &lpsm,
|
||||
BT_IO_OPT_INVALID);
|
||||
if (*err)
|
||||
return 0;
|
||||
return lpsm;
|
||||
}
|
||||
|
||||
uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err)
|
||||
{
|
||||
uint16_t lpsm;
|
||||
|
||||
if (!(mi && mi->dcio)) {
|
||||
g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_ARGS,
|
||||
"Invalid MCAP instance");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_io_get(mi->dcio, BT_IO_L2CAP, err,
|
||||
BT_IO_OPT_PSM, &lpsm,
|
||||
BT_IO_OPT_INVALID);
|
||||
if (*err)
|
||||
return 0;
|
||||
return lpsm;
|
||||
}
|
||||
|
@ -31,6 +31,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* maximum transmission unit for channels */
|
||||
#define MCAP_CC_MTU 48
|
||||
#define MCAP_DC_MTU L2CAP_DEFAULT_MTU
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
52
health/mcap_internal.h
Normal file
52
health/mcap_internal.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
*
|
||||
* MCAP for BlueZ - Bluetooth protocol stack for Linux
|
||||
*
|
||||
* Copyright (C) 2010 GSyC/LibreSoft, Universidad Rey Juan Carlos.
|
||||
*
|
||||
* Authors:
|
||||
* Santiago Carot-Nemesio <sancane at gmail.com>
|
||||
* Jose Antonio Santos-Cadenas <santoscadenas at gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MCAP_INTERNAL_H
|
||||
#define __MCAP_INTERNAL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct mcap_instance {
|
||||
bdaddr_t src; /* Source address */
|
||||
GIOChannel *ccio; /* Control Channel IO */
|
||||
GIOChannel *dcio; /* Data Channel IO */
|
||||
GSList *mcls; /* MCAP instance list */
|
||||
GSList *cached; /* List with all cached MCLs (MAX_CACHED macro) */
|
||||
BtIOSecLevel sec; /* Security level */
|
||||
mcap_mcl_event_cb mcl_connected_cb; /* New MCL connected */
|
||||
mcap_mcl_event_cb mcl_reconnected_cb; /* Old MCL has been reconnected */
|
||||
mcap_mcl_event_cb mcl_disconnected_cb; /* MCL disconnected */
|
||||
mcap_mcl_event_cb mcl_uncached_cb; /* MCL has been removed from MCAP cache */
|
||||
gpointer user_data; /* Data to be provided in callbacks */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MCAP_INTERNAL_H */
|
@ -31,11 +31,38 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* MCAP Error Response Codes */
|
||||
MCAP_ERROR_INVALID_OP_CODE = 1,
|
||||
MCAP_ERROR_INVALID_PARAM_VALUE,
|
||||
MCAP_ERROR_INVALID_MDEP,
|
||||
MCAP_ERROR_MDEP_BUSY,
|
||||
MCAP_ERROR_INVALID_MDL,
|
||||
MCAP_ERROR_MDL_BUSY,
|
||||
MCAP_ERROR_INVALID_OPERATION,
|
||||
MCAP_ERROR_RESOURCE_UNAVAILABLE,
|
||||
MCAP_ERROR_UNSPECIFIED_ERROR,
|
||||
MCAP_ERROR_REQUEST_NOT_SUPPORTED,
|
||||
MCAP_ERROR_CONFIGURATION_REJECTED,
|
||||
/* MCAP Internal Errors */
|
||||
MCAP_ERROR_INVALID_ARGS,
|
||||
MCAP_ERROR_ALREADY_EXISTS,
|
||||
MCAP_ERROR_REQ_IGNORED,
|
||||
MCAP_ERROR_MCL_CLOSED,
|
||||
MCAP_ERROR_FAILED
|
||||
} McapError;
|
||||
|
||||
struct mcap_instance;
|
||||
struct mcap_mcl;
|
||||
|
||||
/************ Callbacks ************/
|
||||
|
||||
/* mcl callbacks */
|
||||
|
||||
typedef void (* mcap_mcl_event_cb) (struct mcap_mcl *mcl, gpointer data);
|
||||
|
||||
/************ Operations ************/
|
||||
|
||||
/* MCAP main operations */
|
||||
|
||||
struct mcap_instance *mcap_create_instance(bdaddr_t *src,
|
||||
@ -50,6 +77,9 @@ struct mcap_instance *mcap_create_instance(bdaddr_t *src,
|
||||
|
||||
void mcap_release_instance(struct mcap_instance *mi);
|
||||
|
||||
uint16_t mcap_get_ctrl_psm(struct mcap_instance *mi, GError **err);
|
||||
uint16_t mcap_get_data_psm(struct mcap_instance *mi, GError **err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user