diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-04-28 17:50:17 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-08 15:58:16 -0400 |
commit | 9a91a04a95d30a18909e2aec9d7b17b4c86088a7 (patch) | |
tree | e0c260031fe79ceaa8cb858b7316ce43974cef08 | |
parent | 4519de9a0478d8de438f8b80ab2e94668ef63ab4 (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.h | 9 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 80 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 83 |
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); | |||
449 | void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); | 449 | void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); |
450 | int __l2cap_wait_ack(struct sock *sk); | 450 | int __l2cap_wait_ack(struct sock *sk); |
451 | 451 | ||
452 | struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); | ||
453 | struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); | ||
454 | struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen); | ||
455 | int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len); | ||
456 | void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); | ||
457 | void l2cap_streaming_send(struct l2cap_chan *chan); | ||
458 | int l2cap_ertm_send(struct l2cap_chan *chan); | ||
459 | |||
460 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); | 452 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); |
461 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); | 453 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); |
462 | 454 | ||
@@ -470,5 +462,6 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk); | |||
470 | void __l2cap_chan_close(struct l2cap_chan *chan, int reason); | 462 | void __l2cap_chan_close(struct l2cap_chan *chan, int reason); |
471 | void l2cap_chan_destroy(struct l2cap_chan *chan); | 463 | void l2cap_chan_destroy(struct l2cap_chan *chan); |
472 | int l2cap_chan_connect(struct l2cap_chan *chan); | 464 | int l2cap_chan_connect(struct l2cap_chan *chan); |
465 | int 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 | ||
1538 | int 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 | |||
1538 | static void l2cap_chan_ready(struct sock *sk) | 1618 | static 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 | |||
772 | done: | ||
773 | release_sock(sk); | 696 | release_sock(sk); |
774 | return err; | 697 | return err; |
775 | } | 698 | } |