Bluetooth: Add l2cap_chan_ops abstraction
Add an abstraction layer between L2CAP core and its users (only l2cap_sock.c now). The first function implemented is new_connection() that replaces calls to l2cap_sock_alloc() in l2cap_core.c Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
@@ -354,6 +354,15 @@ struct l2cap_chan {
|
|||||||
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct list_head global_l;
|
struct list_head global_l;
|
||||||
|
|
||||||
|
void *data;
|
||||||
|
struct l2cap_ops *ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct l2cap_ops {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
struct l2cap_chan *(*new_connection) (void *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct l2cap_conn {
|
struct l2cap_conn {
|
||||||
@@ -460,9 +469,6 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
|
|||||||
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
|
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
|
||||||
|
|
||||||
void l2cap_sock_kill(struct sock *sk);
|
void l2cap_sock_kill(struct sock *sk);
|
||||||
void l2cap_sock_init(struct sock *sk, struct sock *parent);
|
|
||||||
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
|
|
||||||
int proto, gfp_t prio);
|
|
||||||
|
|
||||||
struct l2cap_chan *l2cap_chan_create(struct sock *sk);
|
struct l2cap_chan *l2cap_chan_create(struct sock *sk);
|
||||||
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
|
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
|
||||||
|
@@ -842,18 +842,16 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
|
|||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
|
chan = pchan->ops->new_connection(pchan->data);
|
||||||
if (!sk)
|
if (!chan)
|
||||||
goto clean;
|
goto clean;
|
||||||
|
|
||||||
chan = l2cap_pi(sk)->chan;
|
sk = chan->sk;
|
||||||
|
|
||||||
write_lock_bh(&conn->chan_lock);
|
write_lock_bh(&conn->chan_lock);
|
||||||
|
|
||||||
hci_conn_hold(conn->hcon);
|
hci_conn_hold(conn->hcon);
|
||||||
|
|
||||||
l2cap_sock_init(sk, parent);
|
|
||||||
|
|
||||||
bacpy(&bt_sk(sk)->src, conn->src);
|
bacpy(&bt_sk(sk)->src, conn->src);
|
||||||
bacpy(&bt_sk(sk)->dst, conn->dst);
|
bacpy(&bt_sk(sk)->dst, conn->dst);
|
||||||
|
|
||||||
@@ -2329,10 +2327,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||||||
goto response;
|
goto response;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
|
chan = pchan->ops->new_connection(pchan->data);
|
||||||
if (!sk)
|
if (!chan)
|
||||||
goto response;
|
goto response;
|
||||||
|
|
||||||
|
sk = chan->sk;
|
||||||
|
|
||||||
write_lock_bh(&conn->chan_lock);
|
write_lock_bh(&conn->chan_lock);
|
||||||
|
|
||||||
/* Check if we already have channel with that dcid */
|
/* Check if we already have channel with that dcid */
|
||||||
@@ -2345,9 +2345,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|||||||
|
|
||||||
hci_conn_hold(conn->hcon);
|
hci_conn_hold(conn->hcon);
|
||||||
|
|
||||||
chan = l2cap_pi(sk)->chan;
|
|
||||||
|
|
||||||
l2cap_sock_init(sk, parent);
|
|
||||||
bacpy(&bt_sk(sk)->src, conn->src);
|
bacpy(&bt_sk(sk)->src, conn->src);
|
||||||
bacpy(&bt_sk(sk)->dst, conn->dst);
|
bacpy(&bt_sk(sk)->dst, conn->dst);
|
||||||
chan->psm = psm;
|
chan->psm = psm;
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
#include <net/bluetooth/l2cap.h>
|
#include <net/bluetooth/l2cap.h>
|
||||||
|
|
||||||
static const struct proto_ops l2cap_sock_ops;
|
static const struct proto_ops l2cap_sock_ops;
|
||||||
|
static void l2cap_sock_init(struct sock *sk, struct sock *parent);
|
||||||
|
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
|
||||||
|
|
||||||
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
||||||
{
|
{
|
||||||
@@ -773,6 +775,25 @@ static int l2cap_sock_release(struct socket *sock)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
|
||||||
|
{
|
||||||
|
struct sock *sk, *parent = data;
|
||||||
|
|
||||||
|
sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
|
||||||
|
GFP_ATOMIC);
|
||||||
|
if (!sk)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
l2cap_sock_init(sk, parent);
|
||||||
|
|
||||||
|
return l2cap_pi(sk)->chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct l2cap_ops l2cap_chan_ops = {
|
||||||
|
.name = "L2CAP Socket Interface",
|
||||||
|
.new_connection = l2cap_sock_new_connection_cb,
|
||||||
|
};
|
||||||
|
|
||||||
static void l2cap_sock_destruct(struct sock *sk)
|
static void l2cap_sock_destruct(struct sock *sk)
|
||||||
{
|
{
|
||||||
BT_DBG("sk %p", sk);
|
BT_DBG("sk %p", sk);
|
||||||
@@ -781,7 +802,7 @@ static void l2cap_sock_destruct(struct sock *sk)
|
|||||||
skb_queue_purge(&sk->sk_write_queue);
|
skb_queue_purge(&sk->sk_write_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void l2cap_sock_init(struct sock *sk, struct sock *parent)
|
static void l2cap_sock_init(struct sock *sk, struct sock *parent)
|
||||||
{
|
{
|
||||||
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
||||||
struct l2cap_chan *chan = pi->chan;
|
struct l2cap_chan *chan = pi->chan;
|
||||||
@@ -838,10 +859,14 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
|
|||||||
chan->force_reliable = 0;
|
chan->force_reliable = 0;
|
||||||
chan->flushable = BT_FLUSHABLE_OFF;
|
chan->flushable = BT_FLUSHABLE_OFF;
|
||||||
chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
|
chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default config options */
|
/* Default config options */
|
||||||
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
||||||
|
|
||||||
|
chan->data = sk;
|
||||||
|
chan->ops = &l2cap_chan_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct proto l2cap_proto = {
|
static struct proto l2cap_proto = {
|
||||||
@@ -850,7 +875,7 @@ static struct proto l2cap_proto = {
|
|||||||
.obj_size = sizeof(struct l2cap_pinfo)
|
.obj_size = sizeof(struct l2cap_pinfo)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
|
static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
|
||||||
{
|
{
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
struct l2cap_chan *chan;
|
struct l2cap_chan *chan;
|
||||||
|
Reference in New Issue
Block a user