aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-04-28 17:50:17 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-08 15:58:16 -0400
commit9a91a04a95d30a18909e2aec9d7b17b4c86088a7 (patch)
treee0c260031fe79ceaa8cb858b7316ce43974cef08
parent4519de9a0478d8de438f8b80ab2e94668ef63ab4 (diff)
Bluetooth: Create l2cap_chan_send()
This move all the sending logic to l2cap_core.c, but we still have a socket dependence there, struct msghdr. It will be removed in some of the further commits. Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r--include/net/bluetooth/l2cap.h9
-rw-r--r--net/bluetooth/l2cap_core.c80
-rw-r--r--net/bluetooth/l2cap_sock.c83
3 files changed, 84 insertions, 88 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index ed75e654ea61..dc721cad7f23 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -449,14 +449,6 @@ void l2cap_cleanup_sockets(void);
449void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); 449void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
450int __l2cap_wait_ack(struct sock *sk); 450int __l2cap_wait_ack(struct sock *sk);
451 451
452struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
453struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
454struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
455int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
456void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
457void l2cap_streaming_send(struct l2cap_chan *chan);
458int l2cap_ertm_send(struct l2cap_chan *chan);
459
460int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); 452int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
461int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); 453int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
462 454
@@ -470,5 +462,6 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk);
470void __l2cap_chan_close(struct l2cap_chan *chan, int reason); 462void __l2cap_chan_close(struct l2cap_chan *chan, int reason);
471void l2cap_chan_destroy(struct l2cap_chan *chan); 463void l2cap_chan_destroy(struct l2cap_chan *chan);
472int l2cap_chan_connect(struct l2cap_chan *chan); 464int l2cap_chan_connect(struct l2cap_chan *chan);
465int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
473 466
474#endif /* __L2CAP_H */ 467#endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 14c760c8ffe7..e65f63130113 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1535,6 +1535,86 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
1535 return size; 1535 return size;
1536} 1536}
1537 1537
1538int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
1539{
1540 struct sock *sk = chan->sk;
1541 struct sk_buff *skb;
1542 u16 control;
1543 int err;
1544
1545 /* Connectionless channel */
1546 if (sk->sk_type == SOCK_DGRAM) {
1547 skb = l2cap_create_connless_pdu(chan, msg, len);
1548 if (IS_ERR(skb))
1549 return PTR_ERR(skb);
1550
1551 l2cap_do_send(chan, skb);
1552 return len;
1553 }
1554
1555 switch (chan->mode) {
1556 case L2CAP_MODE_BASIC:
1557 /* Check outgoing MTU */
1558 if (len > chan->omtu)
1559 return -EMSGSIZE;
1560
1561 /* Create a basic PDU */
1562 skb = l2cap_create_basic_pdu(chan, msg, len);
1563 if (IS_ERR(skb))
1564 return PTR_ERR(skb);
1565
1566 l2cap_do_send(chan, skb);
1567 err = len;
1568 break;
1569
1570 case L2CAP_MODE_ERTM:
1571 case L2CAP_MODE_STREAMING:
1572 /* Entire SDU fits into one PDU */
1573 if (len <= chan->remote_mps) {
1574 control = L2CAP_SDU_UNSEGMENTED;
1575 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
1576 0);
1577 if (IS_ERR(skb))
1578 return PTR_ERR(skb);
1579
1580 __skb_queue_tail(&chan->tx_q, skb);
1581
1582 if (chan->tx_send_head == NULL)
1583 chan->tx_send_head = skb;
1584
1585 } else {
1586 /* Segment SDU into multiples PDUs */
1587 err = l2cap_sar_segment_sdu(chan, msg, len);
1588 if (err < 0)
1589 return err;
1590 }
1591
1592 if (chan->mode == L2CAP_MODE_STREAMING) {
1593 l2cap_streaming_send(chan);
1594 err = len;
1595 break;
1596 }
1597
1598 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
1599 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
1600 err = len;
1601 break;
1602 }
1603
1604 err = l2cap_ertm_send(chan);
1605 if (err >= 0)
1606 err = len;
1607
1608 break;
1609
1610 default:
1611 BT_DBG("bad state %1.1x", chan->mode);
1612 err = -EBADFD;
1613 }
1614
1615 return err;
1616}
1617
1538static void l2cap_chan_ready(struct sock *sk) 1618static void l2cap_chan_ready(struct sock *sk)
1539{ 1619{
1540 struct sock *parent = bt_sk(sk)->parent; 1620 struct sock *parent = bt_sk(sk)->parent;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 290130ca1c4a..0ecf214bd30e 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -673,8 +673,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
673{ 673{
674 struct sock *sk = sock->sk; 674 struct sock *sk = sock->sk;
675 struct l2cap_chan *chan = l2cap_pi(sk)->chan; 675 struct l2cap_chan *chan = l2cap_pi(sk)->chan;
676 struct sk_buff *skb;
677 u16 control;
678 int err; 676 int err;
679 677
680 BT_DBG("sock %p, sk %p", sock, sk); 678 BT_DBG("sock %p, sk %p", sock, sk);
@@ -689,87 +687,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
689 lock_sock(sk); 687 lock_sock(sk);
690 688
691 if (sk->sk_state != BT_CONNECTED) { 689 if (sk->sk_state != BT_CONNECTED) {
692 err = -ENOTCONN; 690 release_sock(sk);
693 goto done; 691 return -ENOTCONN;
694 } 692 }
695 693
696 /* Connectionless channel */ 694 err = l2cap_chan_send(chan, msg, len);
697 if (sk->sk_type == SOCK_DGRAM) {
698 skb = l2cap_create_connless_pdu(chan, msg, len);
699 if (IS_ERR(skb)) {
700 err = PTR_ERR(skb);
701 } else {
702 l2cap_do_send(chan, skb);
703 err = len;
704 }
705 goto done;
706 }
707 695
708 switch (chan->mode) {
709 case L2CAP_MODE_BASIC:
710 /* Check outgoing MTU */
711 if (len > chan->omtu) {
712 err = -EMSGSIZE;
713 goto done;
714 }
715
716 /* Create a basic PDU */
717 skb = l2cap_create_basic_pdu(chan, msg, len);
718 if (IS_ERR(skb)) {
719 err = PTR_ERR(skb);
720 goto done;
721 }
722
723 l2cap_do_send(chan, skb);
724 err = len;
725 break;
726
727 case L2CAP_MODE_ERTM:
728 case L2CAP_MODE_STREAMING:
729 /* Entire SDU fits into one PDU */
730 if (len <= chan->remote_mps) {
731 control = L2CAP_SDU_UNSEGMENTED;
732 skb = l2cap_create_iframe_pdu(chan, msg, len, control,
733 0);
734 if (IS_ERR(skb)) {
735 err = PTR_ERR(skb);
736 goto done;
737 }
738 __skb_queue_tail(&chan->tx_q, skb);
739
740 if (chan->tx_send_head == NULL)
741 chan->tx_send_head = skb;
742
743 } else {
744 /* Segment SDU into multiples PDUs */
745 err = l2cap_sar_segment_sdu(chan, msg, len);
746 if (err < 0)
747 goto done;
748 }
749
750 if (chan->mode == L2CAP_MODE_STREAMING) {
751 l2cap_streaming_send(chan);
752 err = len;
753 break;
754 }
755
756 if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
757 (chan->conn_state & L2CAP_CONN_WAIT_F)) {
758 err = len;
759 break;
760 }
761 err = l2cap_ertm_send(chan);
762
763 if (err >= 0)
764 err = len;
765 break;
766
767 default:
768 BT_DBG("bad state %1.1x", chan->mode);
769 err = -EBADFD;
770 }
771
772done:
773 release_sock(sk); 696 release_sock(sk);
774 return err; 697 return err;
775} 698}