提交 686ebf28 编写于 作者: U Ulisses Furquim 提交者: Gustavo F. Padovan

Bluetooth: Make HCI call directly into SCO and L2CAP event functions

The struct hci_proto and all related register/unregister and dispatching
code was removed. HCI core code now call directly the SCO and L2CAP
event functions.
Signed-off-by: NUlisses Furquim <ulisses@profusion.mobi>
Acked-by: NMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: NGustavo F. Padovan <padovan@profusion.mobi>
上级 68a8aea4
...@@ -28,10 +28,6 @@ ...@@ -28,10 +28,6 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <net/bluetooth/hci.h> #include <net/bluetooth/hci.h>
/* HCI upper protocols */
#define HCI_PROTO_L2CAP 0
#define HCI_PROTO_SCO 1
/* HCI priority */ /* HCI priority */
#define HCI_PRIO_MAX 7 #define HCI_PRIO_MAX 7
...@@ -330,12 +326,24 @@ struct hci_chan { ...@@ -330,12 +326,24 @@ struct hci_chan {
unsigned int sent; unsigned int sent;
}; };
extern struct hci_proto *hci_proto[];
extern struct list_head hci_dev_list; extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list; extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_dev_list_lock;
extern rwlock_t hci_cb_list_lock; extern rwlock_t hci_cb_list_lock;
/* ----- HCI interface to upper protocols ----- */
extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status);
extern int l2cap_disconn_ind(struct hci_conn *hcon);
extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason);
extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);
extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags);
extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
/* ----- Inquiry cache ----- */ /* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */ #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */ #define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
...@@ -677,53 +685,40 @@ void hci_conn_del_sysfs(struct hci_conn *conn); ...@@ -677,53 +685,40 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) #define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE)
/* ----- HCI protocols ----- */ /* ----- HCI protocols ----- */
struct hci_proto {
char *name;
unsigned int id;
unsigned long flags;
void *priv;
int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr,
__u8 type);
int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn);
int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb,
__u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
int (*security_cfm) (struct hci_conn *conn, __u8 status,
__u8 encrypt);
};
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
__u8 type) __u8 type)
{ {
register struct hci_proto *hp; switch (type) {
int mask = 0; case ACL_LINK:
return l2cap_connect_ind(hdev, bdaddr);
hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->connect_ind)
mask |= hp->connect_ind(hdev, bdaddr, type);
hp = hci_proto[HCI_PROTO_SCO]; case SCO_LINK:
if (hp && hp->connect_ind) case ESCO_LINK:
mask |= hp->connect_ind(hdev, bdaddr, type); return sco_connect_ind(hdev, bdaddr);
return mask; default:
BT_ERR("unknown link type %d", type);
return -EINVAL;
}
} }
static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
{ {
register struct hci_proto *hp; switch (conn->type) {
case ACL_LINK:
case LE_LINK:
l2cap_connect_cfm(conn, status);
break;
hp = hci_proto[HCI_PROTO_L2CAP]; case SCO_LINK:
if (hp && hp->connect_cfm) case ESCO_LINK:
hp->connect_cfm(conn, status); sco_connect_cfm(conn, status);
break;
hp = hci_proto[HCI_PROTO_SCO]; default:
if (hp && hp->connect_cfm) BT_ERR("unknown link type %d", conn->type);
hp->connect_cfm(conn, status); break;
}
if (conn->connect_cfm_cb) if (conn->connect_cfm_cb)
conn->connect_cfm_cb(conn, status); conn->connect_cfm_cb(conn, status);
...@@ -731,31 +726,29 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) ...@@ -731,31 +726,29 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
static inline int hci_proto_disconn_ind(struct hci_conn *conn) static inline int hci_proto_disconn_ind(struct hci_conn *conn)
{ {
register struct hci_proto *hp; if (conn->type != ACL_LINK && conn->type != LE_LINK)
int reason = HCI_ERROR_REMOTE_USER_TERM; return HCI_ERROR_REMOTE_USER_TERM;
hp = hci_proto[HCI_PROTO_L2CAP]; return l2cap_disconn_ind(conn);
if (hp && hp->disconn_ind)
reason = hp->disconn_ind(conn);
hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->disconn_ind)
reason = hp->disconn_ind(conn);
return reason;
} }
static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
{ {
register struct hci_proto *hp; switch (conn->type) {
case ACL_LINK:
case LE_LINK:
l2cap_disconn_cfm(conn, reason);
break;
hp = hci_proto[HCI_PROTO_L2CAP]; case SCO_LINK:
if (hp && hp->disconn_cfm) case ESCO_LINK:
hp->disconn_cfm(conn, reason); sco_disconn_cfm(conn, reason);
break;
hp = hci_proto[HCI_PROTO_SCO]; default:
if (hp && hp->disconn_cfm) BT_ERR("unknown link type %d", conn->type);
hp->disconn_cfm(conn, reason); break;
}
if (conn->disconn_cfm_cb) if (conn->disconn_cfm_cb)
conn->disconn_cfm_cb(conn, reason); conn->disconn_cfm_cb(conn, reason);
...@@ -763,21 +756,16 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) ...@@ -763,21 +756,16 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
{ {
register struct hci_proto *hp;
__u8 encrypt; __u8 encrypt;
if (conn->type != ACL_LINK && conn->type != LE_LINK)
return;
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return; return;
encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
l2cap_security_cfm(conn, status, encrypt);
hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
if (conn->security_cfm_cb) if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status); conn->security_cfm_cb(conn, status);
...@@ -786,23 +774,15 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) ...@@ -786,23 +774,15 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt) __u8 encrypt)
{ {
register struct hci_proto *hp; if (conn->type != ACL_LINK && conn->type != LE_LINK)
return;
hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
hp = hci_proto[HCI_PROTO_SCO]; l2cap_security_cfm(conn, status, encrypt);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
if (conn->security_cfm_cb) if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status); conn->security_cfm_cb(conn, status);
} }
int hci_register_proto(struct hci_proto *hproto);
int hci_unregister_proto(struct hci_proto *hproto);
/* ----- HCI callbacks ----- */ /* ----- HCI callbacks ----- */
struct hci_cb { struct hci_cb {
struct list_head list; struct list_head list;
......
...@@ -69,10 +69,6 @@ DEFINE_RWLOCK(hci_dev_list_lock); ...@@ -69,10 +69,6 @@ DEFINE_RWLOCK(hci_dev_list_lock);
LIST_HEAD(hci_cb_list); LIST_HEAD(hci_cb_list);
DEFINE_RWLOCK(hci_cb_list_lock); DEFINE_RWLOCK(hci_cb_list_lock);
/* HCI protocols */
#define HCI_MAX_PROTO 2
struct hci_proto *hci_proto[HCI_MAX_PROTO];
/* HCI notifiers list */ /* HCI notifiers list */
static ATOMIC_NOTIFIER_HEAD(hci_notifier); static ATOMIC_NOTIFIER_HEAD(hci_notifier);
...@@ -1830,43 +1826,6 @@ EXPORT_SYMBOL(hci_recv_stream_fragment); ...@@ -1830,43 +1826,6 @@ EXPORT_SYMBOL(hci_recv_stream_fragment);
/* ---- Interface to upper protocols ---- */ /* ---- Interface to upper protocols ---- */
/* Register/Unregister protocols. */
int hci_register_proto(struct hci_proto *hp)
{
int err = 0;
BT_DBG("%p name %s id %d", hp, hp->name, hp->id);
if (hp->id >= HCI_MAX_PROTO)
return -EINVAL;
if (!hci_proto[hp->id])
hci_proto[hp->id] = hp;
else
err = -EEXIST;
return err;
}
EXPORT_SYMBOL(hci_register_proto);
int hci_unregister_proto(struct hci_proto *hp)
{
int err = 0;
BT_DBG("%p name %s id %d", hp, hp->name, hp->id);
if (hp->id >= HCI_MAX_PROTO)
return -EINVAL;
if (hci_proto[hp->id])
hci_proto[hp->id] = NULL;
else
err = -ENOENT;
return err;
}
EXPORT_SYMBOL(hci_unregister_proto);
int hci_register_cb(struct hci_cb *cb) int hci_register_cb(struct hci_cb *cb)
{ {
BT_DBG("%p name %s", cb, cb->name); BT_DBG("%p name %s", cb, cb->name);
...@@ -2470,16 +2429,11 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2470,16 +2429,11 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
if (conn) { if (conn) {
register struct hci_proto *hp;
hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
/* Send to upper protocol */ /* Send to upper protocol */
hp = hci_proto[HCI_PROTO_L2CAP]; l2cap_recv_acldata(conn, skb, flags);
if (hp && hp->recv_acldata) { return;
hp->recv_acldata(conn, skb, flags);
return;
}
} else { } else {
BT_ERR("%s ACL packet for unknown connection handle %d", BT_ERR("%s ACL packet for unknown connection handle %d",
hdev->name, handle); hdev->name, handle);
...@@ -2508,14 +2462,9 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2508,14 +2462,9 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
if (conn) { if (conn) {
register struct hci_proto *hp;
/* Send to upper protocol */ /* Send to upper protocol */
hp = hci_proto[HCI_PROTO_SCO]; sco_recv_scodata(conn, skb);
if (hp && hp->recv_scodata) { return;
hp->recv_scodata(conn, skb);
return;
}
} else { } else {
BT_ERR("%s SCO packet for unknown connection handle %d", BT_ERR("%s SCO packet for unknown connection handle %d",
hdev->name, handle); hdev->name, handle);
......
...@@ -4413,14 +4413,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -4413,14 +4413,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
/* ---- L2CAP interface with lower layer (HCI) ---- */ /* ---- L2CAP interface with lower layer (HCI) ---- */
static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
{ {
int exact = 0, lm1 = 0, lm2 = 0; int exact = 0, lm1 = 0, lm2 = 0;
struct l2cap_chan *c; struct l2cap_chan *c;
if (type != ACL_LINK)
return -EINVAL;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
/* Find listening sockets and check their link_mode */ /* Find listening sockets and check their link_mode */
...@@ -4447,15 +4444,12 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) ...@@ -4447,15 +4444,12 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return exact ? lm1 : lm2; return exact ? lm1 : lm2;
} }
static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{ {
struct l2cap_conn *conn; struct l2cap_conn *conn;
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;
if (!status) { if (!status) {
conn = l2cap_conn_add(hcon, status); conn = l2cap_conn_add(hcon, status);
if (conn) if (conn)
...@@ -4466,27 +4460,22 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) ...@@ -4466,27 +4460,22 @@ static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
return 0; return 0;
} }
static int l2cap_disconn_ind(struct hci_conn *hcon) int l2cap_disconn_ind(struct hci_conn *hcon)
{ {
struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_conn *conn = hcon->l2cap_data;
BT_DBG("hcon %p", hcon); BT_DBG("hcon %p", hcon);
if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn) if (!conn)
return HCI_ERROR_REMOTE_USER_TERM; return HCI_ERROR_REMOTE_USER_TERM;
return conn->disc_reason; return conn->disc_reason;
} }
static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{ {
BT_DBG("hcon %p reason %d", hcon, reason); BT_DBG("hcon %p reason %d", hcon, reason);
if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
return -EINVAL;
l2cap_conn_del(hcon, bt_to_errno(reason)); l2cap_conn_del(hcon, bt_to_errno(reason));
return 0; return 0;
} }
...@@ -4507,7 +4496,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) ...@@ -4507,7 +4496,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
} }
} }
static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
{ {
struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_conn *conn = hcon->l2cap_data;
struct l2cap_chan *chan; struct l2cap_chan *chan;
...@@ -4607,7 +4596,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -4607,7 +4596,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
return 0; return 0;
} }
static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
{ {
struct l2cap_conn *conn = hcon->l2cap_data; struct l2cap_conn *conn = hcon->l2cap_data;
...@@ -4754,17 +4743,6 @@ static const struct file_operations l2cap_debugfs_fops = { ...@@ -4754,17 +4743,6 @@ static const struct file_operations l2cap_debugfs_fops = {
static struct dentry *l2cap_debugfs; static struct dentry *l2cap_debugfs;
static struct hci_proto l2cap_hci_proto = {
.name = "L2CAP",
.id = HCI_PROTO_L2CAP,
.connect_ind = l2cap_connect_ind,
.connect_cfm = l2cap_connect_cfm,
.disconn_ind = l2cap_disconn_ind,
.disconn_cfm = l2cap_disconn_cfm,
.security_cfm = l2cap_security_cfm,
.recv_acldata = l2cap_recv_acldata
};
int __init l2cap_init(void) int __init l2cap_init(void)
{ {
int err; int err;
...@@ -4773,13 +4751,6 @@ int __init l2cap_init(void) ...@@ -4773,13 +4751,6 @@ int __init l2cap_init(void)
if (err < 0) if (err < 0)
return err; return err;
err = hci_register_proto(&l2cap_hci_proto);
if (err < 0) {
BT_ERR("L2CAP protocol registration failed");
bt_sock_unregister(BTPROTO_L2CAP);
goto error;
}
if (bt_debugfs) { if (bt_debugfs) {
l2cap_debugfs = debugfs_create_file("l2cap", 0444, l2cap_debugfs = debugfs_create_file("l2cap", 0444,
bt_debugfs, NULL, &l2cap_debugfs_fops); bt_debugfs, NULL, &l2cap_debugfs_fops);
...@@ -4788,19 +4759,11 @@ int __init l2cap_init(void) ...@@ -4788,19 +4759,11 @@ int __init l2cap_init(void)
} }
return 0; return 0;
error:
l2cap_cleanup_sockets();
return err;
} }
void l2cap_exit(void) void l2cap_exit(void)
{ {
debugfs_remove(l2cap_debugfs); debugfs_remove(l2cap_debugfs);
if (hci_unregister_proto(&l2cap_hci_proto) < 0)
BT_ERR("L2CAP protocol unregistration failed");
l2cap_cleanup_sockets(); l2cap_cleanup_sockets();
} }
......
...@@ -893,15 +893,12 @@ static void sco_conn_ready(struct sco_conn *conn) ...@@ -893,15 +893,12 @@ static void sco_conn_ready(struct sco_conn *conn)
} }
/* ----- SCO interface with lower layer (HCI) ----- */ /* ----- SCO interface with lower layer (HCI) ----- */
static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr)
{ {
register struct sock *sk; register struct sock *sk;
struct hlist_node *node; struct hlist_node *node;
int lm = 0; int lm = 0;
if (type != SCO_LINK && type != ESCO_LINK)
return -EINVAL;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
/* Find listening sockets */ /* Find listening sockets */
...@@ -921,13 +918,9 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) ...@@ -921,13 +918,9 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
return lm; return lm;
} }
static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{ {
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return -EINVAL;
if (!status) { if (!status) {
struct sco_conn *conn; struct sco_conn *conn;
...@@ -940,19 +933,15 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) ...@@ -940,19 +933,15 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
return 0; return 0;
} }
static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{ {
BT_DBG("hcon %p reason %d", hcon, reason); BT_DBG("hcon %p reason %d", hcon, reason);
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return -EINVAL;
sco_conn_del(hcon, bt_to_errno(reason)); sco_conn_del(hcon, bt_to_errno(reason));
return 0; return 0;
} }
static int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
{ {
struct sco_conn *conn = hcon->sco_data; struct sco_conn *conn = hcon->sco_data;
...@@ -1028,15 +1017,6 @@ static const struct net_proto_family sco_sock_family_ops = { ...@@ -1028,15 +1017,6 @@ static const struct net_proto_family sco_sock_family_ops = {
.create = sco_sock_create, .create = sco_sock_create,
}; };
static struct hci_proto sco_hci_proto = {
.name = "SCO",
.id = HCI_PROTO_SCO,
.connect_ind = sco_connect_ind,
.connect_cfm = sco_connect_cfm,
.disconn_cfm = sco_disconn_cfm,
.recv_scodata = sco_recv_scodata
};
int __init sco_init(void) int __init sco_init(void)
{ {
int err; int err;
...@@ -1051,13 +1031,6 @@ int __init sco_init(void) ...@@ -1051,13 +1031,6 @@ int __init sco_init(void)
goto error; goto error;
} }
err = hci_register_proto(&sco_hci_proto);
if (err < 0) {
BT_ERR("SCO protocol registration failed");
bt_sock_unregister(BTPROTO_SCO);
goto error;
}
if (bt_debugfs) { if (bt_debugfs) {
sco_debugfs = debugfs_create_file("sco", 0444, sco_debugfs = debugfs_create_file("sco", 0444,
bt_debugfs, NULL, &sco_debugfs_fops); bt_debugfs, NULL, &sco_debugfs_fops);
...@@ -1081,9 +1054,6 @@ void __exit sco_exit(void) ...@@ -1081,9 +1054,6 @@ void __exit sco_exit(void)
if (bt_sock_unregister(BTPROTO_SCO) < 0) if (bt_sock_unregister(BTPROTO_SCO) < 0)
BT_ERR("SCO socket unregistration failed"); BT_ERR("SCO socket unregistration failed");
if (hci_unregister_proto(&sco_hci_proto) < 0)
BT_ERR("SCO protocol unregistration failed");
proto_unregister(&sco_proto); proto_unregister(&sco_proto);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册