aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-04-11 13:48:43 -0400
committerGustavo Padovan <gustavo@padovan.org>2012-05-09 00:40:31 -0400
commitb76bbd6657a2dd7545686ba9ad59625f44192146 (patch)
tree8a7ea12a3688fefb53c997b715ee9a5629191693 /net/bluetooth/l2cap_core.c
parent3c588192b5e5328cdfc8e299c55477004d397208 (diff)
Bluetooth: Functions for handling ERTM control fields
These functions encode or decode ERTM control fields (extended or enhanced) to or from the new l2cap_ctrl structure. Signed-off-by: Mat Martineau <mathewm@codeaurora.org> Acked-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 041ebed9e647..913cec3e52d7 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -786,6 +786,117 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control)
786 l2cap_send_sframe(chan, control); 786 l2cap_send_sframe(chan, control);
787} 787}
788 788
789static u16 __pack_enhanced_control(struct l2cap_ctrl *control)
790{
791 u16 packed;
792
793 packed = control->reqseq << L2CAP_CTRL_REQSEQ_SHIFT;
794 packed |= control->final << L2CAP_CTRL_FINAL_SHIFT;
795
796 if (control->sframe) {
797 packed |= control->poll << L2CAP_CTRL_POLL_SHIFT;
798 packed |= control->super << L2CAP_CTRL_SUPER_SHIFT;
799 packed |= L2CAP_CTRL_FRAME_TYPE;
800 } else {
801 packed |= control->sar << L2CAP_CTRL_SAR_SHIFT;
802 packed |= control->txseq << L2CAP_CTRL_TXSEQ_SHIFT;
803 }
804
805 return packed;
806}
807
808static void __unpack_enhanced_control(u16 enh, struct l2cap_ctrl *control)
809{
810 control->reqseq = (enh & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT;
811 control->final = (enh & L2CAP_CTRL_FINAL) >> L2CAP_CTRL_FINAL_SHIFT;
812
813 if (enh & L2CAP_CTRL_FRAME_TYPE) {
814 /* S-Frame */
815 control->sframe = 1;
816 control->poll = (enh & L2CAP_CTRL_POLL) >> L2CAP_CTRL_POLL_SHIFT;
817 control->super = (enh & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT;
818
819 control->sar = 0;
820 control->txseq = 0;
821 } else {
822 /* I-Frame */
823 control->sframe = 0;
824 control->sar = (enh & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT;
825 control->txseq = (enh & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT;
826
827 control->poll = 0;
828 control->super = 0;
829 }
830}
831
832static u32 __pack_extended_control(struct l2cap_ctrl *control)
833{
834 u32 packed;
835
836 packed = control->reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT;
837 packed |= control->final << L2CAP_EXT_CTRL_FINAL_SHIFT;
838
839 if (control->sframe) {
840 packed |= control->poll << L2CAP_EXT_CTRL_POLL_SHIFT;
841 packed |= control->super << L2CAP_EXT_CTRL_SUPER_SHIFT;
842 packed |= L2CAP_EXT_CTRL_FRAME_TYPE;
843 } else {
844 packed |= control->sar << L2CAP_EXT_CTRL_SAR_SHIFT;
845 packed |= control->txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT;
846 }
847
848 return packed;
849}
850
851static void __unpack_extended_control(u32 ext, struct l2cap_ctrl *control)
852{
853 control->reqseq = (ext & L2CAP_EXT_CTRL_REQSEQ) >> L2CAP_EXT_CTRL_REQSEQ_SHIFT;
854 control->final = (ext & L2CAP_EXT_CTRL_FINAL) >> L2CAP_EXT_CTRL_FINAL_SHIFT;
855
856 if (ext & L2CAP_EXT_CTRL_FRAME_TYPE) {
857 /* S-Frame */
858 control->sframe = 1;
859 control->poll = (ext & L2CAP_EXT_CTRL_POLL) >> L2CAP_EXT_CTRL_POLL_SHIFT;
860 control->super = (ext & L2CAP_EXT_CTRL_SUPERVISE) >> L2CAP_EXT_CTRL_SUPER_SHIFT;
861
862 control->sar = 0;
863 control->txseq = 0;
864 } else {
865 /* I-Frame */
866 control->sframe = 0;
867 control->sar = (ext & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT;
868 control->txseq = (ext & L2CAP_EXT_CTRL_TXSEQ) >> L2CAP_EXT_CTRL_TXSEQ_SHIFT;
869
870 control->poll = 0;
871 control->super = 0;
872 }
873}
874
875static inline void __unpack_control(struct l2cap_chan *chan,
876 struct sk_buff *skb)
877{
878 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
879 __unpack_extended_control(get_unaligned_le32(skb->data),
880 &bt_cb(skb)->control);
881 } else {
882 __unpack_enhanced_control(get_unaligned_le16(skb->data),
883 &bt_cb(skb)->control);
884 }
885}
886
887static inline void __pack_control(struct l2cap_chan *chan,
888 struct l2cap_ctrl *control,
889 struct sk_buff *skb)
890{
891 if (test_bit(FLAG_EXT_CTRL, &chan->flags)) {
892 put_unaligned_le32(__pack_extended_control(control),
893 skb->data + L2CAP_HDR_SIZE);
894 } else {
895 put_unaligned_le16(__pack_enhanced_control(control),
896 skb->data + L2CAP_HDR_SIZE);
897 }
898}
899
789static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) 900static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
790{ 901{
791 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); 902 return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
@@ -4359,6 +4470,8 @@ static int l2cap_ertm_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
4359 u16 req_seq; 4470 u16 req_seq;
4360 int len, next_tx_seq_offset, req_seq_offset; 4471 int len, next_tx_seq_offset, req_seq_offset;
4361 4472
4473 __unpack_control(chan, skb);
4474
4362 control = __get_control(chan, skb->data); 4475 control = __get_control(chan, skb->data);
4363 skb_pull(skb, __ctrl_size(chan)); 4476 skb_pull(skb, __ctrl_size(chan));
4364 len = skb->len; 4477 len = skb->len;