Commit 099284bd authored by John W. Linville's avatar John W. Linville
parents 073730d7 4ebaa4ed
...@@ -163,7 +163,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb) ...@@ -163,7 +163,7 @@ static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
struct ath_struct *ath = hu->priv; struct ath_struct *ath = hu->priv;
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) { if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
kfree(skb); kfree_skb(skb);
return 0; return 0;
} }
...@@ -217,7 +217,7 @@ static struct hci_uart_proto athp = { ...@@ -217,7 +217,7 @@ static struct hci_uart_proto athp = {
.flush = ath_flush, .flush = ath_flush,
}; };
int ath_init(void) int __init ath_init(void)
{ {
int err = hci_uart_register_proto(&athp); int err = hci_uart_register_proto(&athp);
...@@ -229,7 +229,7 @@ int ath_init(void) ...@@ -229,7 +229,7 @@ int ath_init(void)
return err; return err;
} }
int ath_deinit(void) int __exit ath_deinit(void)
{ {
return hci_uart_unregister_proto(&athp); return hci_uart_unregister_proto(&athp);
} }
...@@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = { ...@@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = {
.flush = bcsp_flush .flush = bcsp_flush
}; };
int bcsp_init(void) int __init bcsp_init(void)
{ {
int err = hci_uart_register_proto(&bcsp); int err = hci_uart_register_proto(&bcsp);
...@@ -751,7 +751,7 @@ int bcsp_init(void) ...@@ -751,7 +751,7 @@ int bcsp_init(void)
return err; return err;
} }
int bcsp_deinit(void) int __exit bcsp_deinit(void)
{ {
return hci_uart_unregister_proto(&bcsp); return hci_uart_unregister_proto(&bcsp);
} }
......
...@@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len) ...@@ -151,107 +151,8 @@ static inline int h4_check_data_len(struct h4_struct *h4, int len)
/* Recv data */ /* Recv data */
static int h4_recv(struct hci_uart *hu, void *data, int count) static int h4_recv(struct hci_uart *hu, void *data, int count)
{ {
struct h4_struct *h4 = hu->priv; if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
register char *ptr; BT_ERR("Frame Reassembly Failed");
struct hci_event_hdr *eh;
struct hci_acl_hdr *ah;
struct hci_sco_hdr *sh;
register int len, type, dlen;
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
hu, count, h4->rx_state, h4->rx_count);
ptr = data;
while (count) {
if (h4->rx_count) {
len = min_t(unsigned int, h4->rx_count, count);
memcpy(skb_put(h4->rx_skb, len), ptr, len);
h4->rx_count -= len; count -= len; ptr += len;
if (h4->rx_count)
continue;
switch (h4->rx_state) {
case H4_W4_DATA:
BT_DBG("Complete data");
hci_recv_frame(h4->rx_skb);
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_skb = NULL;
continue;
case H4_W4_EVENT_HDR:
eh = hci_event_hdr(h4->rx_skb);
BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
h4_check_data_len(h4, eh->plen);
continue;
case H4_W4_ACL_HDR:
ah = hci_acl_hdr(h4->rx_skb);
dlen = __le16_to_cpu(ah->dlen);
BT_DBG("ACL header: dlen %d", dlen);
h4_check_data_len(h4, dlen);
continue;
case H4_W4_SCO_HDR:
sh = hci_sco_hdr(h4->rx_skb);
BT_DBG("SCO header: dlen %d", sh->dlen);
h4_check_data_len(h4, sh->dlen);
continue;
}
}
/* H4_W4_PACKET_TYPE */
switch (*ptr) {
case HCI_EVENT_PKT:
BT_DBG("Event packet");
h4->rx_state = H4_W4_EVENT_HDR;
h4->rx_count = HCI_EVENT_HDR_SIZE;
type = HCI_EVENT_PKT;
break;
case HCI_ACLDATA_PKT:
BT_DBG("ACL packet");
h4->rx_state = H4_W4_ACL_HDR;
h4->rx_count = HCI_ACL_HDR_SIZE;
type = HCI_ACLDATA_PKT;
break;
case HCI_SCODATA_PKT:
BT_DBG("SCO packet");
h4->rx_state = H4_W4_SCO_HDR;
h4->rx_count = HCI_SCO_HDR_SIZE;
type = HCI_SCODATA_PKT;
break;
default:
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
hu->hdev->stat.err_rx++;
ptr++; count--;
continue;
};
ptr++; count--;
/* Allocate packet */
h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
if (!h4->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
h4->rx_state = H4_W4_PACKET_TYPE;
h4->rx_count = 0;
return -ENOMEM;
}
h4->rx_skb->dev = (void *) hu->hdev;
bt_cb(h4->rx_skb)->pkt_type = type;
}
return count; return count;
} }
...@@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = { ...@@ -272,7 +173,7 @@ static struct hci_uart_proto h4p = {
.flush = h4_flush, .flush = h4_flush,
}; };
int h4_init(void) int __init h4_init(void)
{ {
int err = hci_uart_register_proto(&h4p); int err = hci_uart_register_proto(&h4p);
...@@ -284,7 +185,7 @@ int h4_init(void) ...@@ -284,7 +185,7 @@ int h4_init(void)
return err; return err;
} }
int h4_deinit(void) int __exit h4_deinit(void)
{ {
return hci_uart_unregister_proto(&h4p); return hci_uart_unregister_proto(&h4p);
} }
...@@ -517,7 +517,7 @@ static struct hci_uart_proto llp = { ...@@ -517,7 +517,7 @@ static struct hci_uart_proto llp = {
.flush = ll_flush, .flush = ll_flush,
}; };
int ll_init(void) int __init ll_init(void)
{ {
int err = hci_uart_register_proto(&llp); int err = hci_uart_register_proto(&llp);
...@@ -529,7 +529,7 @@ int ll_init(void) ...@@ -529,7 +529,7 @@ int ll_init(void)
return err; return err;
} }
int ll_deinit(void) int __exit ll_deinit(void)
{ {
return hci_uart_unregister_proto(&llp); return hci_uart_unregister_proto(&llp);
} }
...@@ -256,6 +256,7 @@ enum { ...@@ -256,6 +256,7 @@ enum {
HCI_CONN_ENCRYPT_PEND, HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND, HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND, HCI_CONN_MODE_CHANGE_PEND,
HCI_CONN_SCO_SETUP_PEND,
}; };
static inline void hci_conn_hash_init(struct hci_dev *hdev) static inline void hci_conn_hash_init(struct hci_dev *hdev)
...@@ -336,6 +337,7 @@ void hci_acl_connect(struct hci_conn *conn); ...@@ -336,6 +337,7 @@ void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason); void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle); void hci_add_sco(struct hci_conn *conn, __u16 handle);
void hci_setup_sync(struct hci_conn *conn, __u16 handle); void hci_setup_sync(struct hci_conn *conn, __u16 handle);
void hci_sco_setup(struct hci_conn *conn, __u8 status);
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
int hci_conn_del(struct hci_conn *conn); int hci_conn_del(struct hci_conn *conn);
......
...@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) ...@@ -155,6 +155,27 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
} }
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
struct hci_conn *sco = conn->link;
BT_DBG("%p", conn);
if (!sco)
return;
if (!status) {
if (lmp_esco_capable(conn->hdev))
hci_setup_sync(sco, conn->handle);
else
hci_add_sco(sco, conn->handle);
} else {
hci_proto_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
static void hci_conn_timeout(unsigned long arg) static void hci_conn_timeout(unsigned long arg)
{ {
struct hci_conn *conn = (void *) arg; struct hci_conn *conn = (void *) arg;
...@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 ...@@ -385,10 +406,13 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
acl->power_save = 1; acl->power_save = 1;
hci_conn_enter_active_mode(acl); hci_conn_enter_active_mode(acl);
if (lmp_esco_capable(hdev)) if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
hci_setup_sync(sco, acl->handle); /* defer SCO setup until mode change completed */
else set_bit(HCI_CONN_SCO_SETUP_PEND, &acl->pend);
hci_add_sco(sco, acl->handle); return sco;
}
hci_sco_setup(acl, 0x00);
} }
return sco; return sco;
......
...@@ -1149,7 +1149,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ...@@ -1149,7 +1149,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
return -EILSEQ; return -EILSEQ;
do { while (count) {
rem = hci_reassembly(hdev, type, data, count, rem = hci_reassembly(hdev, type, data, count,
type - 1, GFP_ATOMIC); type - 1, GFP_ATOMIC);
if (rem < 0) if (rem < 0)
...@@ -1157,7 +1157,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) ...@@ -1157,7 +1157,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
data += (count - rem); data += (count - rem);
count = rem; count = rem;
} while (count); };
return rem; return rem;
} }
...@@ -1170,7 +1170,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) ...@@ -1170,7 +1170,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
int type; int type;
int rem = 0; int rem = 0;
do { while (count) {
struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY]; struct sk_buff *skb = hdev->reassembly[STREAM_REASSEMBLY];
if (!skb) { if (!skb) {
...@@ -1192,7 +1192,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count) ...@@ -1192,7 +1192,7 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
data += (count - rem); data += (count - rem);
count = rem; count = rem;
} while (count); };
return rem; return rem;
} }
......
...@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) ...@@ -785,9 +785,13 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev); hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) ...@@ -808,9 +812,13 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
hci_dev_lock(hdev); hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -915,20 +923,8 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
} else } else
conn->state = BT_CLOSED; conn->state = BT_CLOSED;
if (conn->type == ACL_LINK) { if (conn->type == ACL_LINK)
struct hci_conn *sco = conn->link; hci_sco_setup(conn, ev->status);
if (sco) {
if (!ev->status) {
if (lmp_esco_capable(hdev))
hci_setup_sync(sco, conn->handle);
else
hci_add_sco(sco, conn->handle);
} else {
hci_proto_connect_cfm(sco, ev->status);
hci_conn_del(sco);
}
}
}
if (ev->status) { if (ev->status) {
hci_proto_connect_cfm(conn, ev->status); hci_proto_connect_cfm(conn, ev->status);
...@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb ...@@ -1481,6 +1477,9 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb
else else
conn->power_save = 0; conn->power_save = 0;
} }
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->pend))
hci_sco_setup(conn, ev->status);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
...@@ -1152,7 +1152,7 @@ int __init rfcomm_init_sockets(void) ...@@ -1152,7 +1152,7 @@ int __init rfcomm_init_sockets(void)
return err; return err;
} }
void rfcomm_cleanup_sockets(void) void __exit rfcomm_cleanup_sockets(void)
{ {
debugfs_remove(rfcomm_sock_debugfs); debugfs_remove(rfcomm_sock_debugfs);
......
...@@ -1153,7 +1153,7 @@ static const struct tty_operations rfcomm_ops = { ...@@ -1153,7 +1153,7 @@ static const struct tty_operations rfcomm_ops = {
.tiocmset = rfcomm_tty_tiocmset, .tiocmset = rfcomm_tty_tiocmset,
}; };
int rfcomm_init_ttys(void) int __init rfcomm_init_ttys(void)
{ {
rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS); rfcomm_tty_driver = alloc_tty_driver(RFCOMM_TTY_PORTS);
if (!rfcomm_tty_driver) if (!rfcomm_tty_driver)
...@@ -1183,7 +1183,7 @@ int rfcomm_init_ttys(void) ...@@ -1183,7 +1183,7 @@ int rfcomm_init_ttys(void)
return 0; return 0;
} }
void rfcomm_cleanup_ttys(void) void __exit rfcomm_cleanup_ttys(void)
{ {
tty_unregister_driver(rfcomm_tty_driver); tty_unregister_driver(rfcomm_tty_driver);
put_tty_driver(rfcomm_tty_driver); put_tty_driver(rfcomm_tty_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment