diff options
Diffstat (limited to 'include/net/bluetooth/l2cap.h')
-rw-r--r-- | include/net/bluetooth/l2cap.h | 93 |
1 files changed, 79 insertions, 14 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 9b242c6bf55b..1c7d1cd5e679 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -44,6 +44,7 @@ | |||
44 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF | 44 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF |
45 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF | 45 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF |
46 | #define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF | 46 | #define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF |
47 | #define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */ | ||
47 | 48 | ||
48 | #define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100) | 49 | #define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100) |
49 | #define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000) | 50 | #define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000) |
@@ -57,6 +58,7 @@ struct sockaddr_l2 { | |||
57 | __le16 l2_psm; | 58 | __le16 l2_psm; |
58 | bdaddr_t l2_bdaddr; | 59 | bdaddr_t l2_bdaddr; |
59 | __le16 l2_cid; | 60 | __le16 l2_cid; |
61 | __u8 l2_bdaddr_type; | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | /* L2CAP socket options */ | 64 | /* L2CAP socket options */ |
@@ -139,6 +141,8 @@ struct l2cap_conninfo { | |||
139 | 141 | ||
140 | #define L2CAP_CTRL_TXSEQ_SHIFT 1 | 142 | #define L2CAP_CTRL_TXSEQ_SHIFT 1 |
141 | #define L2CAP_CTRL_SUPER_SHIFT 2 | 143 | #define L2CAP_CTRL_SUPER_SHIFT 2 |
144 | #define L2CAP_CTRL_POLL_SHIFT 4 | ||
145 | #define L2CAP_CTRL_FINAL_SHIFT 7 | ||
142 | #define L2CAP_CTRL_REQSEQ_SHIFT 8 | 146 | #define L2CAP_CTRL_REQSEQ_SHIFT 8 |
143 | #define L2CAP_CTRL_SAR_SHIFT 14 | 147 | #define L2CAP_CTRL_SAR_SHIFT 14 |
144 | 148 | ||
@@ -152,9 +156,11 @@ struct l2cap_conninfo { | |||
152 | #define L2CAP_EXT_CTRL_FINAL 0x00000002 | 156 | #define L2CAP_EXT_CTRL_FINAL 0x00000002 |
153 | #define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */ | 157 | #define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */ |
154 | 158 | ||
159 | #define L2CAP_EXT_CTRL_FINAL_SHIFT 1 | ||
155 | #define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2 | 160 | #define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2 |
156 | #define L2CAP_EXT_CTRL_SAR_SHIFT 16 | 161 | #define L2CAP_EXT_CTRL_SAR_SHIFT 16 |
157 | #define L2CAP_EXT_CTRL_SUPER_SHIFT 16 | 162 | #define L2CAP_EXT_CTRL_SUPER_SHIFT 16 |
163 | #define L2CAP_EXT_CTRL_POLL_SHIFT 18 | ||
158 | #define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18 | 164 | #define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18 |
159 | 165 | ||
160 | /* L2CAP Supervisory Function */ | 166 | /* L2CAP Supervisory Function */ |
@@ -186,6 +192,8 @@ struct l2cap_hdr { | |||
186 | #define L2CAP_FCS_SIZE 2 | 192 | #define L2CAP_FCS_SIZE 2 |
187 | #define L2CAP_SDULEN_SIZE 2 | 193 | #define L2CAP_SDULEN_SIZE 2 |
188 | #define L2CAP_PSMLEN_SIZE 2 | 194 | #define L2CAP_PSMLEN_SIZE 2 |
195 | #define L2CAP_ENH_CTRL_SIZE 2 | ||
196 | #define L2CAP_EXT_CTRL_SIZE 4 | ||
189 | 197 | ||
190 | struct l2cap_cmd_hdr { | 198 | struct l2cap_cmd_hdr { |
191 | __u8 code; | 199 | __u8 code; |
@@ -401,6 +409,16 @@ struct l2cap_conn_param_update_rsp { | |||
401 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 | 409 | #define L2CAP_CONN_PARAM_REJECTED 0x0001 |
402 | 410 | ||
403 | /* ----- L2CAP channels and connections ----- */ | 411 | /* ----- L2CAP channels and connections ----- */ |
412 | struct l2cap_seq_list { | ||
413 | __u16 head; | ||
414 | __u16 tail; | ||
415 | __u16 mask; | ||
416 | __u16 *list; | ||
417 | }; | ||
418 | |||
419 | #define L2CAP_SEQ_LIST_CLEAR 0xFFFF | ||
420 | #define L2CAP_SEQ_LIST_TAIL 0x8000 | ||
421 | |||
404 | struct srej_list { | 422 | struct srej_list { |
405 | __u16 tx_seq; | 423 | __u16 tx_seq; |
406 | struct list_head list; | 424 | struct list_head list; |
@@ -446,6 +464,9 @@ struct l2cap_chan { | |||
446 | __u16 monitor_timeout; | 464 | __u16 monitor_timeout; |
447 | __u16 mps; | 465 | __u16 mps; |
448 | 466 | ||
467 | __u8 tx_state; | ||
468 | __u8 rx_state; | ||
469 | |||
449 | unsigned long conf_state; | 470 | unsigned long conf_state; |
450 | unsigned long conn_state; | 471 | unsigned long conn_state; |
451 | unsigned long flags; | 472 | unsigned long flags; |
@@ -456,9 +477,11 @@ struct l2cap_chan { | |||
456 | __u16 buffer_seq; | 477 | __u16 buffer_seq; |
457 | __u16 buffer_seq_srej; | 478 | __u16 buffer_seq_srej; |
458 | __u16 srej_save_reqseq; | 479 | __u16 srej_save_reqseq; |
480 | __u16 last_acked_seq; | ||
459 | __u16 frames_sent; | 481 | __u16 frames_sent; |
460 | __u16 unacked_frames; | 482 | __u16 unacked_frames; |
461 | __u8 retry_count; | 483 | __u8 retry_count; |
484 | __u16 srej_queue_next; | ||
462 | __u8 num_acked; | 485 | __u8 num_acked; |
463 | __u16 sdu_len; | 486 | __u16 sdu_len; |
464 | struct sk_buff *sdu; | 487 | struct sk_buff *sdu; |
@@ -490,6 +513,8 @@ struct l2cap_chan { | |||
490 | struct sk_buff *tx_send_head; | 513 | struct sk_buff *tx_send_head; |
491 | struct sk_buff_head tx_q; | 514 | struct sk_buff_head tx_q; |
492 | struct sk_buff_head srej_q; | 515 | struct sk_buff_head srej_q; |
516 | struct l2cap_seq_list srej_list; | ||
517 | struct l2cap_seq_list retrans_list; | ||
493 | struct list_head srej_l; | 518 | struct list_head srej_l; |
494 | 519 | ||
495 | struct list_head list; | 520 | struct list_head list; |
@@ -508,8 +533,7 @@ struct l2cap_ops { | |||
508 | void (*close) (void *data); | 533 | void (*close) (void *data); |
509 | void (*state_change) (void *data, int state); | 534 | void (*state_change) (void *data, int state); |
510 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 535 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
511 | unsigned long len, int nb, int *err); | 536 | unsigned long len, int nb); |
512 | |||
513 | }; | 537 | }; |
514 | 538 | ||
515 | struct l2cap_conn { | 539 | struct l2cap_conn { |
@@ -600,6 +624,44 @@ enum { | |||
600 | FLAG_EFS_ENABLE, | 624 | FLAG_EFS_ENABLE, |
601 | }; | 625 | }; |
602 | 626 | ||
627 | enum { | ||
628 | L2CAP_TX_STATE_XMIT, | ||
629 | L2CAP_TX_STATE_WAIT_F, | ||
630 | }; | ||
631 | |||
632 | enum { | ||
633 | L2CAP_RX_STATE_RECV, | ||
634 | L2CAP_RX_STATE_SREJ_SENT, | ||
635 | }; | ||
636 | |||
637 | enum { | ||
638 | L2CAP_TXSEQ_EXPECTED, | ||
639 | L2CAP_TXSEQ_EXPECTED_SREJ, | ||
640 | L2CAP_TXSEQ_UNEXPECTED, | ||
641 | L2CAP_TXSEQ_UNEXPECTED_SREJ, | ||
642 | L2CAP_TXSEQ_DUPLICATE, | ||
643 | L2CAP_TXSEQ_DUPLICATE_SREJ, | ||
644 | L2CAP_TXSEQ_INVALID, | ||
645 | L2CAP_TXSEQ_INVALID_IGNORE, | ||
646 | }; | ||
647 | |||
648 | enum { | ||
649 | L2CAP_EV_DATA_REQUEST, | ||
650 | L2CAP_EV_LOCAL_BUSY_DETECTED, | ||
651 | L2CAP_EV_LOCAL_BUSY_CLEAR, | ||
652 | L2CAP_EV_RECV_REQSEQ_AND_FBIT, | ||
653 | L2CAP_EV_RECV_FBIT, | ||
654 | L2CAP_EV_RETRANS_TO, | ||
655 | L2CAP_EV_MONITOR_TO, | ||
656 | L2CAP_EV_EXPLICIT_POLL, | ||
657 | L2CAP_EV_RECV_IFRAME, | ||
658 | L2CAP_EV_RECV_RR, | ||
659 | L2CAP_EV_RECV_REJ, | ||
660 | L2CAP_EV_RECV_RNR, | ||
661 | L2CAP_EV_RECV_SREJ, | ||
662 | L2CAP_EV_RECV_FRAME, | ||
663 | }; | ||
664 | |||
603 | static inline void l2cap_chan_hold(struct l2cap_chan *c) | 665 | static inline void l2cap_chan_hold(struct l2cap_chan *c) |
604 | { | 666 | { |
605 | atomic_inc(&c->refcnt); | 667 | atomic_inc(&c->refcnt); |
@@ -622,21 +684,26 @@ static inline void l2cap_chan_unlock(struct l2cap_chan *chan) | |||
622 | } | 684 | } |
623 | 685 | ||
624 | static inline void l2cap_set_timer(struct l2cap_chan *chan, | 686 | static inline void l2cap_set_timer(struct l2cap_chan *chan, |
625 | struct delayed_work *work, long timeout) | 687 | struct delayed_work *work, long timeout) |
626 | { | 688 | { |
627 | BT_DBG("chan %p state %s timeout %ld", chan, | 689 | BT_DBG("chan %p state %s timeout %ld", chan, |
628 | state_to_string(chan->state), timeout); | 690 | state_to_string(chan->state), timeout); |
629 | 691 | ||
692 | /* If delayed work cancelled do not hold(chan) | ||
693 | since it is already done with previous set_timer */ | ||
630 | if (!cancel_delayed_work(work)) | 694 | if (!cancel_delayed_work(work)) |
631 | l2cap_chan_hold(chan); | 695 | l2cap_chan_hold(chan); |
696 | |||
632 | schedule_delayed_work(work, timeout); | 697 | schedule_delayed_work(work, timeout); |
633 | } | 698 | } |
634 | 699 | ||
635 | static inline bool l2cap_clear_timer(struct l2cap_chan *chan, | 700 | static inline bool l2cap_clear_timer(struct l2cap_chan *chan, |
636 | struct delayed_work *work) | 701 | struct delayed_work *work) |
637 | { | 702 | { |
638 | bool ret; | 703 | bool ret; |
639 | 704 | ||
705 | /* put(chan) if delayed work cancelled otherwise it | ||
706 | is done in delayed work function */ | ||
640 | ret = cancel_delayed_work(work); | 707 | ret = cancel_delayed_work(work); |
641 | if (ret) | 708 | if (ret) |
642 | l2cap_chan_put(chan); | 709 | l2cap_chan_put(chan); |
@@ -658,13 +725,10 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan, | |||
658 | 725 | ||
659 | static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) | 726 | static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) |
660 | { | 727 | { |
661 | int offset; | 728 | if (seq1 >= seq2) |
662 | 729 | return seq1 - seq2; | |
663 | offset = (seq1 - seq2) % (chan->tx_win_max + 1); | 730 | else |
664 | if (offset < 0) | 731 | return chan->tx_win_max + 1 - seq2 + seq1; |
665 | offset += (chan->tx_win_max + 1); | ||
666 | |||
667 | return offset; | ||
668 | } | 732 | } |
669 | 733 | ||
670 | static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq) | 734 | static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq) |
@@ -852,14 +916,15 @@ int __l2cap_wait_ack(struct sock *sk); | |||
852 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); | 916 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); |
853 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); | 917 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); |
854 | 918 | ||
855 | struct l2cap_chan *l2cap_chan_create(struct sock *sk); | 919 | struct l2cap_chan *l2cap_chan_create(void); |
856 | void l2cap_chan_close(struct l2cap_chan *chan, int reason); | 920 | void l2cap_chan_close(struct l2cap_chan *chan, int reason); |
857 | void l2cap_chan_destroy(struct l2cap_chan *chan); | 921 | void l2cap_chan_destroy(struct l2cap_chan *chan); |
858 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | 922 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, |
859 | bdaddr_t *dst); | 923 | bdaddr_t *dst, u8 dst_type); |
860 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 924 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
861 | u32 priority); | 925 | u32 priority); |
862 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); | 926 | void l2cap_chan_busy(struct l2cap_chan *chan, int busy); |
863 | int l2cap_chan_check_security(struct l2cap_chan *chan); | 927 | int l2cap_chan_check_security(struct l2cap_chan *chan); |
928 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); | ||
864 | 929 | ||
865 | #endif /* __L2CAP_H */ | 930 | #endif /* __L2CAP_H */ |