162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci   BlueZ - Bluetooth protocol stack for Linux
362306a36Sopenharmony_ci   Copyright (C) 2000-2001 Qualcomm Incorporated
462306a36Sopenharmony_ci   Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
562306a36Sopenharmony_ci   Copyright (C) 2010 Google Inc.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci   This program is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci   it under the terms of the GNU General Public License version 2 as
1162306a36Sopenharmony_ci   published by the Free Software Foundation;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1462306a36Sopenharmony_ci   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1562306a36Sopenharmony_ci   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
1662306a36Sopenharmony_ci   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
1762306a36Sopenharmony_ci   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
1862306a36Sopenharmony_ci   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1962306a36Sopenharmony_ci   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2062306a36Sopenharmony_ci   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
2362306a36Sopenharmony_ci   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
2462306a36Sopenharmony_ci   SOFTWARE IS DISCLAIMED.
2562306a36Sopenharmony_ci*/
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#ifndef __L2CAP_H
2862306a36Sopenharmony_ci#define __L2CAP_H
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <asm/unaligned.h>
3162306a36Sopenharmony_ci#include <linux/atomic.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* L2CAP defaults */
3462306a36Sopenharmony_ci#define L2CAP_DEFAULT_MTU		672
3562306a36Sopenharmony_ci#define L2CAP_DEFAULT_MIN_MTU		48
3662306a36Sopenharmony_ci#define L2CAP_DEFAULT_FLUSH_TO		0xFFFF
3762306a36Sopenharmony_ci#define L2CAP_EFS_DEFAULT_FLUSH_TO	0xFFFFFFFF
3862306a36Sopenharmony_ci#define L2CAP_DEFAULT_TX_WINDOW		63
3962306a36Sopenharmony_ci#define L2CAP_DEFAULT_EXT_WINDOW	0x3FFF
4062306a36Sopenharmony_ci#define L2CAP_DEFAULT_MAX_TX		3
4162306a36Sopenharmony_ci#define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */
4262306a36Sopenharmony_ci#define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */
4362306a36Sopenharmony_ci#define L2CAP_DEFAULT_MAX_PDU_SIZE	1492    /* Sized for AMP packet */
4462306a36Sopenharmony_ci#define L2CAP_DEFAULT_ACK_TO		200
4562306a36Sopenharmony_ci#define L2CAP_DEFAULT_MAX_SDU_SIZE	0xFFFF
4662306a36Sopenharmony_ci#define L2CAP_DEFAULT_SDU_ITIME		0xFFFFFFFF
4762306a36Sopenharmony_ci#define L2CAP_DEFAULT_ACC_LAT		0xFFFFFFFF
4862306a36Sopenharmony_ci#define L2CAP_BREDR_MAX_PAYLOAD		1019    /* 3-DH5 packet */
4962306a36Sopenharmony_ci#define L2CAP_LE_MIN_MTU		23
5062306a36Sopenharmony_ci#define L2CAP_ECRED_CONN_SCID_MAX	5
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define L2CAP_DISC_TIMEOUT		msecs_to_jiffies(100)
5362306a36Sopenharmony_ci#define L2CAP_DISC_REJ_TIMEOUT		msecs_to_jiffies(5000)
5462306a36Sopenharmony_ci#define L2CAP_ENC_TIMEOUT		msecs_to_jiffies(5000)
5562306a36Sopenharmony_ci#define L2CAP_CONN_TIMEOUT		msecs_to_jiffies(40000)
5662306a36Sopenharmony_ci#define L2CAP_INFO_TIMEOUT		msecs_to_jiffies(4000)
5762306a36Sopenharmony_ci#define L2CAP_MOVE_TIMEOUT		msecs_to_jiffies(4000)
5862306a36Sopenharmony_ci#define L2CAP_MOVE_ERTX_TIMEOUT		msecs_to_jiffies(60000)
5962306a36Sopenharmony_ci#define L2CAP_WAIT_ACK_POLL_PERIOD	msecs_to_jiffies(200)
6062306a36Sopenharmony_ci#define L2CAP_WAIT_ACK_TIMEOUT		msecs_to_jiffies(10000)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* L2CAP socket address */
6362306a36Sopenharmony_cistruct sockaddr_l2 {
6462306a36Sopenharmony_ci	sa_family_t	l2_family;
6562306a36Sopenharmony_ci	__le16		l2_psm;
6662306a36Sopenharmony_ci	bdaddr_t	l2_bdaddr;
6762306a36Sopenharmony_ci	__le16		l2_cid;
6862306a36Sopenharmony_ci	__u8		l2_bdaddr_type;
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/* L2CAP socket options */
7262306a36Sopenharmony_ci#define L2CAP_OPTIONS	0x01
7362306a36Sopenharmony_cistruct l2cap_options {
7462306a36Sopenharmony_ci	__u16 omtu;
7562306a36Sopenharmony_ci	__u16 imtu;
7662306a36Sopenharmony_ci	__u16 flush_to;
7762306a36Sopenharmony_ci	__u8  mode;
7862306a36Sopenharmony_ci	__u8  fcs;
7962306a36Sopenharmony_ci	__u8  max_tx;
8062306a36Sopenharmony_ci	__u16 txwin_size;
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci#define L2CAP_CONNINFO	0x02
8462306a36Sopenharmony_cistruct l2cap_conninfo {
8562306a36Sopenharmony_ci	__u16 hci_handle;
8662306a36Sopenharmony_ci	__u8  dev_class[3];
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#define L2CAP_LM	0x03
9062306a36Sopenharmony_ci#define L2CAP_LM_MASTER		0x0001
9162306a36Sopenharmony_ci#define L2CAP_LM_AUTH		0x0002
9262306a36Sopenharmony_ci#define L2CAP_LM_ENCRYPT	0x0004
9362306a36Sopenharmony_ci#define L2CAP_LM_TRUSTED	0x0008
9462306a36Sopenharmony_ci#define L2CAP_LM_RELIABLE	0x0010
9562306a36Sopenharmony_ci#define L2CAP_LM_SECURE		0x0020
9662306a36Sopenharmony_ci#define L2CAP_LM_FIPS		0x0040
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/* L2CAP command codes */
9962306a36Sopenharmony_ci#define L2CAP_COMMAND_REJ	0x01
10062306a36Sopenharmony_ci#define L2CAP_CONN_REQ		0x02
10162306a36Sopenharmony_ci#define L2CAP_CONN_RSP		0x03
10262306a36Sopenharmony_ci#define L2CAP_CONF_REQ		0x04
10362306a36Sopenharmony_ci#define L2CAP_CONF_RSP		0x05
10462306a36Sopenharmony_ci#define L2CAP_DISCONN_REQ	0x06
10562306a36Sopenharmony_ci#define L2CAP_DISCONN_RSP	0x07
10662306a36Sopenharmony_ci#define L2CAP_ECHO_REQ		0x08
10762306a36Sopenharmony_ci#define L2CAP_ECHO_RSP		0x09
10862306a36Sopenharmony_ci#define L2CAP_INFO_REQ		0x0a
10962306a36Sopenharmony_ci#define L2CAP_INFO_RSP		0x0b
11062306a36Sopenharmony_ci#define L2CAP_CONN_PARAM_UPDATE_REQ	0x12
11162306a36Sopenharmony_ci#define L2CAP_CONN_PARAM_UPDATE_RSP	0x13
11262306a36Sopenharmony_ci#define L2CAP_LE_CONN_REQ	0x14
11362306a36Sopenharmony_ci#define L2CAP_LE_CONN_RSP	0x15
11462306a36Sopenharmony_ci#define L2CAP_LE_CREDITS	0x16
11562306a36Sopenharmony_ci#define L2CAP_ECRED_CONN_REQ	0x17
11662306a36Sopenharmony_ci#define L2CAP_ECRED_CONN_RSP	0x18
11762306a36Sopenharmony_ci#define L2CAP_ECRED_RECONF_REQ	0x19
11862306a36Sopenharmony_ci#define L2CAP_ECRED_RECONF_RSP	0x1a
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/* L2CAP extended feature mask */
12162306a36Sopenharmony_ci#define L2CAP_FEAT_FLOWCTL	0x00000001
12262306a36Sopenharmony_ci#define L2CAP_FEAT_RETRANS	0x00000002
12362306a36Sopenharmony_ci#define L2CAP_FEAT_BIDIR_QOS	0x00000004
12462306a36Sopenharmony_ci#define L2CAP_FEAT_ERTM		0x00000008
12562306a36Sopenharmony_ci#define L2CAP_FEAT_STREAMING	0x00000010
12662306a36Sopenharmony_ci#define L2CAP_FEAT_FCS		0x00000020
12762306a36Sopenharmony_ci#define L2CAP_FEAT_EXT_FLOW	0x00000040
12862306a36Sopenharmony_ci#define L2CAP_FEAT_FIXED_CHAN	0x00000080
12962306a36Sopenharmony_ci#define L2CAP_FEAT_EXT_WINDOW	0x00000100
13062306a36Sopenharmony_ci#define L2CAP_FEAT_UCD		0x00000200
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci/* L2CAP checksum option */
13362306a36Sopenharmony_ci#define L2CAP_FCS_NONE		0x00
13462306a36Sopenharmony_ci#define L2CAP_FCS_CRC16		0x01
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/* L2CAP fixed channels */
13762306a36Sopenharmony_ci#define L2CAP_FC_SIG_BREDR	0x02
13862306a36Sopenharmony_ci#define L2CAP_FC_CONNLESS	0x04
13962306a36Sopenharmony_ci#define L2CAP_FC_ATT		0x10
14062306a36Sopenharmony_ci#define L2CAP_FC_SIG_LE		0x20
14162306a36Sopenharmony_ci#define L2CAP_FC_SMP_LE		0x40
14262306a36Sopenharmony_ci#define L2CAP_FC_SMP_BREDR	0x80
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/* L2CAP Control Field bit masks */
14562306a36Sopenharmony_ci#define L2CAP_CTRL_SAR			0xC000
14662306a36Sopenharmony_ci#define L2CAP_CTRL_REQSEQ		0x3F00
14762306a36Sopenharmony_ci#define L2CAP_CTRL_TXSEQ		0x007E
14862306a36Sopenharmony_ci#define L2CAP_CTRL_SUPERVISE		0x000C
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci#define L2CAP_CTRL_RETRANS		0x0080
15162306a36Sopenharmony_ci#define L2CAP_CTRL_FINAL		0x0080
15262306a36Sopenharmony_ci#define L2CAP_CTRL_POLL			0x0010
15362306a36Sopenharmony_ci#define L2CAP_CTRL_FRAME_TYPE		0x0001 /* I- or S-Frame */
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci#define L2CAP_CTRL_TXSEQ_SHIFT		1
15662306a36Sopenharmony_ci#define L2CAP_CTRL_SUPER_SHIFT		2
15762306a36Sopenharmony_ci#define L2CAP_CTRL_POLL_SHIFT		4
15862306a36Sopenharmony_ci#define L2CAP_CTRL_FINAL_SHIFT		7
15962306a36Sopenharmony_ci#define L2CAP_CTRL_REQSEQ_SHIFT		8
16062306a36Sopenharmony_ci#define L2CAP_CTRL_SAR_SHIFT		14
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/* L2CAP Extended Control Field bit mask */
16362306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_TXSEQ		0xFFFC0000
16462306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_SAR		0x00030000
16562306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_SUPERVISE	0x00030000
16662306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_REQSEQ		0x0000FFFC
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_POLL		0x00040000
16962306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_FINAL		0x00000002
17062306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_FRAME_TYPE	0x00000001 /* I- or S-Frame */
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_FINAL_SHIFT	1
17362306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_REQSEQ_SHIFT	2
17462306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_SAR_SHIFT	16
17562306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_SUPER_SHIFT	16
17662306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_POLL_SHIFT	18
17762306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_TXSEQ_SHIFT	18
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/* L2CAP Supervisory Function */
18062306a36Sopenharmony_ci#define L2CAP_SUPER_RR		0x00
18162306a36Sopenharmony_ci#define L2CAP_SUPER_REJ		0x01
18262306a36Sopenharmony_ci#define L2CAP_SUPER_RNR		0x02
18362306a36Sopenharmony_ci#define L2CAP_SUPER_SREJ	0x03
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* L2CAP Segmentation and Reassembly */
18662306a36Sopenharmony_ci#define L2CAP_SAR_UNSEGMENTED	0x00
18762306a36Sopenharmony_ci#define L2CAP_SAR_START		0x01
18862306a36Sopenharmony_ci#define L2CAP_SAR_END		0x02
18962306a36Sopenharmony_ci#define L2CAP_SAR_CONTINUE	0x03
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/* L2CAP Command rej. reasons */
19262306a36Sopenharmony_ci#define L2CAP_REJ_NOT_UNDERSTOOD	0x0000
19362306a36Sopenharmony_ci#define L2CAP_REJ_MTU_EXCEEDED		0x0001
19462306a36Sopenharmony_ci#define L2CAP_REJ_INVALID_CID		0x0002
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/* L2CAP structures */
19762306a36Sopenharmony_cistruct l2cap_hdr {
19862306a36Sopenharmony_ci	__le16     len;
19962306a36Sopenharmony_ci	__le16     cid;
20062306a36Sopenharmony_ci} __packed;
20162306a36Sopenharmony_ci#define L2CAP_LEN_SIZE		2
20262306a36Sopenharmony_ci#define L2CAP_HDR_SIZE		4
20362306a36Sopenharmony_ci#define L2CAP_ENH_HDR_SIZE	6
20462306a36Sopenharmony_ci#define L2CAP_EXT_HDR_SIZE	8
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci#define L2CAP_FCS_SIZE		2
20762306a36Sopenharmony_ci#define L2CAP_SDULEN_SIZE	2
20862306a36Sopenharmony_ci#define L2CAP_PSMLEN_SIZE	2
20962306a36Sopenharmony_ci#define L2CAP_ENH_CTRL_SIZE	2
21062306a36Sopenharmony_ci#define L2CAP_EXT_CTRL_SIZE	4
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistruct l2cap_cmd_hdr {
21362306a36Sopenharmony_ci	__u8       code;
21462306a36Sopenharmony_ci	__u8       ident;
21562306a36Sopenharmony_ci	__le16     len;
21662306a36Sopenharmony_ci} __packed;
21762306a36Sopenharmony_ci#define L2CAP_CMD_HDR_SIZE	4
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistruct l2cap_cmd_rej_unk {
22062306a36Sopenharmony_ci	__le16     reason;
22162306a36Sopenharmony_ci} __packed;
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistruct l2cap_cmd_rej_mtu {
22462306a36Sopenharmony_ci	__le16     reason;
22562306a36Sopenharmony_ci	__le16     max_mtu;
22662306a36Sopenharmony_ci} __packed;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistruct l2cap_cmd_rej_cid {
22962306a36Sopenharmony_ci	__le16     reason;
23062306a36Sopenharmony_ci	__le16     scid;
23162306a36Sopenharmony_ci	__le16     dcid;
23262306a36Sopenharmony_ci} __packed;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistruct l2cap_conn_req {
23562306a36Sopenharmony_ci	__le16     psm;
23662306a36Sopenharmony_ci	__le16     scid;
23762306a36Sopenharmony_ci} __packed;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistruct l2cap_conn_rsp {
24062306a36Sopenharmony_ci	__le16     dcid;
24162306a36Sopenharmony_ci	__le16     scid;
24262306a36Sopenharmony_ci	__le16     result;
24362306a36Sopenharmony_ci	__le16     status;
24462306a36Sopenharmony_ci} __packed;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/* protocol/service multiplexer (PSM) */
24762306a36Sopenharmony_ci#define L2CAP_PSM_SDP		0x0001
24862306a36Sopenharmony_ci#define L2CAP_PSM_RFCOMM	0x0003
24962306a36Sopenharmony_ci#define L2CAP_PSM_3DSP		0x0021
25062306a36Sopenharmony_ci#define L2CAP_PSM_IPSP		0x0023 /* 6LoWPAN */
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci#define L2CAP_PSM_DYN_START	0x1001
25362306a36Sopenharmony_ci#define L2CAP_PSM_DYN_END	0xffff
25462306a36Sopenharmony_ci#define L2CAP_PSM_AUTO_END	0x10ff
25562306a36Sopenharmony_ci#define L2CAP_PSM_LE_DYN_START  0x0080
25662306a36Sopenharmony_ci#define L2CAP_PSM_LE_DYN_END	0x00ff
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/* channel identifier */
25962306a36Sopenharmony_ci#define L2CAP_CID_SIGNALING	0x0001
26062306a36Sopenharmony_ci#define L2CAP_CID_CONN_LESS	0x0002
26162306a36Sopenharmony_ci#define L2CAP_CID_ATT		0x0004
26262306a36Sopenharmony_ci#define L2CAP_CID_LE_SIGNALING	0x0005
26362306a36Sopenharmony_ci#define L2CAP_CID_SMP		0x0006
26462306a36Sopenharmony_ci#define L2CAP_CID_SMP_BREDR	0x0007
26562306a36Sopenharmony_ci#define L2CAP_CID_DYN_START	0x0040
26662306a36Sopenharmony_ci#define L2CAP_CID_DYN_END	0xffff
26762306a36Sopenharmony_ci#define L2CAP_CID_LE_DYN_END	0x007f
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/* connect/create channel results */
27062306a36Sopenharmony_ci#define L2CAP_CR_SUCCESS	0x0000
27162306a36Sopenharmony_ci#define L2CAP_CR_PEND		0x0001
27262306a36Sopenharmony_ci#define L2CAP_CR_BAD_PSM	0x0002
27362306a36Sopenharmony_ci#define L2CAP_CR_SEC_BLOCK	0x0003
27462306a36Sopenharmony_ci#define L2CAP_CR_NO_MEM		0x0004
27562306a36Sopenharmony_ci#define L2CAP_CR_INVALID_SCID	0x0006
27662306a36Sopenharmony_ci#define L2CAP_CR_SCID_IN_USE	0x0007
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci/* credit based connect results */
27962306a36Sopenharmony_ci#define L2CAP_CR_LE_SUCCESS		0x0000
28062306a36Sopenharmony_ci#define L2CAP_CR_LE_BAD_PSM		0x0002
28162306a36Sopenharmony_ci#define L2CAP_CR_LE_NO_MEM		0x0004
28262306a36Sopenharmony_ci#define L2CAP_CR_LE_AUTHENTICATION	0x0005
28362306a36Sopenharmony_ci#define L2CAP_CR_LE_AUTHORIZATION	0x0006
28462306a36Sopenharmony_ci#define L2CAP_CR_LE_BAD_KEY_SIZE	0x0007
28562306a36Sopenharmony_ci#define L2CAP_CR_LE_ENCRYPTION		0x0008
28662306a36Sopenharmony_ci#define L2CAP_CR_LE_INVALID_SCID	0x0009
28762306a36Sopenharmony_ci#define L2CAP_CR_LE_SCID_IN_USE		0X000A
28862306a36Sopenharmony_ci#define L2CAP_CR_LE_UNACCEPT_PARAMS	0X000B
28962306a36Sopenharmony_ci#define L2CAP_CR_LE_INVALID_PARAMS	0X000C
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci/* connect/create channel status */
29262306a36Sopenharmony_ci#define L2CAP_CS_NO_INFO	0x0000
29362306a36Sopenharmony_ci#define L2CAP_CS_AUTHEN_PEND	0x0001
29462306a36Sopenharmony_ci#define L2CAP_CS_AUTHOR_PEND	0x0002
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_cistruct l2cap_conf_req {
29762306a36Sopenharmony_ci	__le16     dcid;
29862306a36Sopenharmony_ci	__le16     flags;
29962306a36Sopenharmony_ci	__u8       data[];
30062306a36Sopenharmony_ci} __packed;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistruct l2cap_conf_rsp {
30362306a36Sopenharmony_ci	__le16     scid;
30462306a36Sopenharmony_ci	__le16     flags;
30562306a36Sopenharmony_ci	__le16     result;
30662306a36Sopenharmony_ci	__u8       data[];
30762306a36Sopenharmony_ci} __packed;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci#define L2CAP_CONF_SUCCESS	0x0000
31062306a36Sopenharmony_ci#define L2CAP_CONF_UNACCEPT	0x0001
31162306a36Sopenharmony_ci#define L2CAP_CONF_REJECT	0x0002
31262306a36Sopenharmony_ci#define L2CAP_CONF_UNKNOWN	0x0003
31362306a36Sopenharmony_ci#define L2CAP_CONF_PENDING	0x0004
31462306a36Sopenharmony_ci#define L2CAP_CONF_EFS_REJECT	0x0005
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci/* configuration req/rsp continuation flag */
31762306a36Sopenharmony_ci#define L2CAP_CONF_FLAG_CONTINUATION	0x0001
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_cistruct l2cap_conf_opt {
32062306a36Sopenharmony_ci	__u8       type;
32162306a36Sopenharmony_ci	__u8       len;
32262306a36Sopenharmony_ci	__u8       val[];
32362306a36Sopenharmony_ci} __packed;
32462306a36Sopenharmony_ci#define L2CAP_CONF_OPT_SIZE	2
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci#define L2CAP_CONF_HINT		0x80
32762306a36Sopenharmony_ci#define L2CAP_CONF_MASK		0x7f
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci#define L2CAP_CONF_MTU		0x01
33062306a36Sopenharmony_ci#define L2CAP_CONF_FLUSH_TO	0x02
33162306a36Sopenharmony_ci#define L2CAP_CONF_QOS		0x03
33262306a36Sopenharmony_ci#define L2CAP_CONF_RFC		0x04
33362306a36Sopenharmony_ci#define L2CAP_CONF_FCS		0x05
33462306a36Sopenharmony_ci#define L2CAP_CONF_EFS		0x06
33562306a36Sopenharmony_ci#define L2CAP_CONF_EWS		0x07
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci#define L2CAP_CONF_MAX_SIZE	22
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_cistruct l2cap_conf_rfc {
34062306a36Sopenharmony_ci	__u8       mode;
34162306a36Sopenharmony_ci	__u8       txwin_size;
34262306a36Sopenharmony_ci	__u8       max_transmit;
34362306a36Sopenharmony_ci	__le16     retrans_timeout;
34462306a36Sopenharmony_ci	__le16     monitor_timeout;
34562306a36Sopenharmony_ci	__le16     max_pdu_size;
34662306a36Sopenharmony_ci} __packed;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci#define L2CAP_MODE_BASIC	0x00
34962306a36Sopenharmony_ci#define L2CAP_MODE_RETRANS	0x01
35062306a36Sopenharmony_ci#define L2CAP_MODE_FLOWCTL	0x02
35162306a36Sopenharmony_ci#define L2CAP_MODE_ERTM		0x03
35262306a36Sopenharmony_ci#define L2CAP_MODE_STREAMING	0x04
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci/* Unlike the above this one doesn't actually map to anything that would
35562306a36Sopenharmony_ci * ever be sent over the air. Therefore, use a value that's unlikely to
35662306a36Sopenharmony_ci * ever be used in the BR/EDR configuration phase.
35762306a36Sopenharmony_ci */
35862306a36Sopenharmony_ci#define L2CAP_MODE_LE_FLOWCTL	0x80
35962306a36Sopenharmony_ci#define L2CAP_MODE_EXT_FLOWCTL	0x81
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistruct l2cap_conf_efs {
36262306a36Sopenharmony_ci	__u8	id;
36362306a36Sopenharmony_ci	__u8	stype;
36462306a36Sopenharmony_ci	__le16	msdu;
36562306a36Sopenharmony_ci	__le32	sdu_itime;
36662306a36Sopenharmony_ci	__le32	acc_lat;
36762306a36Sopenharmony_ci	__le32	flush_to;
36862306a36Sopenharmony_ci} __packed;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci#define L2CAP_SERV_NOTRAFIC	0x00
37162306a36Sopenharmony_ci#define L2CAP_SERV_BESTEFFORT	0x01
37262306a36Sopenharmony_ci#define L2CAP_SERV_GUARANTEED	0x02
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci#define L2CAP_BESTEFFORT_ID	0x01
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_cistruct l2cap_disconn_req {
37762306a36Sopenharmony_ci	__le16     dcid;
37862306a36Sopenharmony_ci	__le16     scid;
37962306a36Sopenharmony_ci} __packed;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistruct l2cap_disconn_rsp {
38262306a36Sopenharmony_ci	__le16     dcid;
38362306a36Sopenharmony_ci	__le16     scid;
38462306a36Sopenharmony_ci} __packed;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_cistruct l2cap_info_req {
38762306a36Sopenharmony_ci	__le16      type;
38862306a36Sopenharmony_ci} __packed;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistruct l2cap_info_rsp {
39162306a36Sopenharmony_ci	__le16      type;
39262306a36Sopenharmony_ci	__le16      result;
39362306a36Sopenharmony_ci	__u8        data[];
39462306a36Sopenharmony_ci} __packed;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci#define L2CAP_MR_SUCCESS	0x0000
39762306a36Sopenharmony_ci#define L2CAP_MR_PEND		0x0001
39862306a36Sopenharmony_ci#define L2CAP_MR_BAD_ID		0x0002
39962306a36Sopenharmony_ci#define L2CAP_MR_SAME_ID	0x0003
40062306a36Sopenharmony_ci#define L2CAP_MR_NOT_SUPP	0x0004
40162306a36Sopenharmony_ci#define L2CAP_MR_COLLISION	0x0005
40262306a36Sopenharmony_ci#define L2CAP_MR_NOT_ALLOWED	0x0006
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistruct l2cap_move_chan_cfm {
40562306a36Sopenharmony_ci	__le16      icid;
40662306a36Sopenharmony_ci	__le16      result;
40762306a36Sopenharmony_ci} __packed;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci#define L2CAP_MC_CONFIRMED	0x0000
41062306a36Sopenharmony_ci#define L2CAP_MC_UNCONFIRMED	0x0001
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cistruct l2cap_move_chan_cfm_rsp {
41362306a36Sopenharmony_ci	__le16      icid;
41462306a36Sopenharmony_ci} __packed;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci/* info type */
41762306a36Sopenharmony_ci#define L2CAP_IT_CL_MTU		0x0001
41862306a36Sopenharmony_ci#define L2CAP_IT_FEAT_MASK	0x0002
41962306a36Sopenharmony_ci#define L2CAP_IT_FIXED_CHAN	0x0003
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci/* info result */
42262306a36Sopenharmony_ci#define L2CAP_IR_SUCCESS	0x0000
42362306a36Sopenharmony_ci#define L2CAP_IR_NOTSUPP	0x0001
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistruct l2cap_conn_param_update_req {
42662306a36Sopenharmony_ci	__le16      min;
42762306a36Sopenharmony_ci	__le16      max;
42862306a36Sopenharmony_ci	__le16      latency;
42962306a36Sopenharmony_ci	__le16      to_multiplier;
43062306a36Sopenharmony_ci} __packed;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistruct l2cap_conn_param_update_rsp {
43362306a36Sopenharmony_ci	__le16      result;
43462306a36Sopenharmony_ci} __packed;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci/* Connection Parameters result */
43762306a36Sopenharmony_ci#define L2CAP_CONN_PARAM_ACCEPTED	0x0000
43862306a36Sopenharmony_ci#define L2CAP_CONN_PARAM_REJECTED	0x0001
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistruct l2cap_le_conn_req {
44162306a36Sopenharmony_ci	__le16     psm;
44262306a36Sopenharmony_ci	__le16     scid;
44362306a36Sopenharmony_ci	__le16     mtu;
44462306a36Sopenharmony_ci	__le16     mps;
44562306a36Sopenharmony_ci	__le16     credits;
44662306a36Sopenharmony_ci} __packed;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_cistruct l2cap_le_conn_rsp {
44962306a36Sopenharmony_ci	__le16     dcid;
45062306a36Sopenharmony_ci	__le16     mtu;
45162306a36Sopenharmony_ci	__le16     mps;
45262306a36Sopenharmony_ci	__le16     credits;
45362306a36Sopenharmony_ci	__le16     result;
45462306a36Sopenharmony_ci} __packed;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cistruct l2cap_le_credits {
45762306a36Sopenharmony_ci	__le16     cid;
45862306a36Sopenharmony_ci	__le16     credits;
45962306a36Sopenharmony_ci} __packed;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci#define L2CAP_ECRED_MIN_MTU		64
46262306a36Sopenharmony_ci#define L2CAP_ECRED_MIN_MPS		64
46362306a36Sopenharmony_ci#define L2CAP_ECRED_MAX_CID		5
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistruct l2cap_ecred_conn_req {
46662306a36Sopenharmony_ci	__le16 psm;
46762306a36Sopenharmony_ci	__le16 mtu;
46862306a36Sopenharmony_ci	__le16 mps;
46962306a36Sopenharmony_ci	__le16 credits;
47062306a36Sopenharmony_ci	__le16 scid[];
47162306a36Sopenharmony_ci} __packed;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistruct l2cap_ecred_conn_rsp {
47462306a36Sopenharmony_ci	__le16 mtu;
47562306a36Sopenharmony_ci	__le16 mps;
47662306a36Sopenharmony_ci	__le16 credits;
47762306a36Sopenharmony_ci	__le16 result;
47862306a36Sopenharmony_ci	__le16 dcid[];
47962306a36Sopenharmony_ci};
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_cistruct l2cap_ecred_reconf_req {
48262306a36Sopenharmony_ci	__le16 mtu;
48362306a36Sopenharmony_ci	__le16 mps;
48462306a36Sopenharmony_ci	__le16 scid[];
48562306a36Sopenharmony_ci} __packed;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci#define L2CAP_RECONF_SUCCESS		0x0000
48862306a36Sopenharmony_ci#define L2CAP_RECONF_INVALID_MTU	0x0001
48962306a36Sopenharmony_ci#define L2CAP_RECONF_INVALID_MPS	0x0002
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_cistruct l2cap_ecred_reconf_rsp {
49262306a36Sopenharmony_ci	__le16 result;
49362306a36Sopenharmony_ci} __packed;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci/* ----- L2CAP channels and connections ----- */
49662306a36Sopenharmony_cistruct l2cap_seq_list {
49762306a36Sopenharmony_ci	__u16	head;
49862306a36Sopenharmony_ci	__u16	tail;
49962306a36Sopenharmony_ci	__u16	mask;
50062306a36Sopenharmony_ci	__u16	*list;
50162306a36Sopenharmony_ci};
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci#define L2CAP_SEQ_LIST_CLEAR	0xFFFF
50462306a36Sopenharmony_ci#define L2CAP_SEQ_LIST_TAIL	0x8000
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_cistruct l2cap_chan {
50762306a36Sopenharmony_ci	struct l2cap_conn	*conn;
50862306a36Sopenharmony_ci	struct kref	kref;
50962306a36Sopenharmony_ci	atomic_t	nesting;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	__u8		state;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	bdaddr_t	dst;
51462306a36Sopenharmony_ci	__u8		dst_type;
51562306a36Sopenharmony_ci	bdaddr_t	src;
51662306a36Sopenharmony_ci	__u8		src_type;
51762306a36Sopenharmony_ci	__le16		psm;
51862306a36Sopenharmony_ci	__le16		sport;
51962306a36Sopenharmony_ci	__u16		dcid;
52062306a36Sopenharmony_ci	__u16		scid;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	__u16		imtu;
52362306a36Sopenharmony_ci	__u16		omtu;
52462306a36Sopenharmony_ci	__u16		flush_to;
52562306a36Sopenharmony_ci	__u8		mode;
52662306a36Sopenharmony_ci	__u8		chan_type;
52762306a36Sopenharmony_ci	__u8		chan_policy;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	__u8		sec_level;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	__u8		ident;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	__u8		conf_req[64];
53462306a36Sopenharmony_ci	__u8		conf_len;
53562306a36Sopenharmony_ci	__u8		num_conf_req;
53662306a36Sopenharmony_ci	__u8		num_conf_rsp;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	__u8		fcs;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	__u16		tx_win;
54162306a36Sopenharmony_ci	__u16		tx_win_max;
54262306a36Sopenharmony_ci	__u16		ack_win;
54362306a36Sopenharmony_ci	__u8		max_tx;
54462306a36Sopenharmony_ci	__u16		retrans_timeout;
54562306a36Sopenharmony_ci	__u16		monitor_timeout;
54662306a36Sopenharmony_ci	__u16		mps;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	__u16		tx_credits;
54962306a36Sopenharmony_ci	__u16		rx_credits;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	__u8		tx_state;
55262306a36Sopenharmony_ci	__u8		rx_state;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	unsigned long	conf_state;
55562306a36Sopenharmony_ci	unsigned long	conn_state;
55662306a36Sopenharmony_ci	unsigned long	flags;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	__u16		next_tx_seq;
55962306a36Sopenharmony_ci	__u16		expected_ack_seq;
56062306a36Sopenharmony_ci	__u16		expected_tx_seq;
56162306a36Sopenharmony_ci	__u16		buffer_seq;
56262306a36Sopenharmony_ci	__u16		srej_save_reqseq;
56362306a36Sopenharmony_ci	__u16		last_acked_seq;
56462306a36Sopenharmony_ci	__u16		frames_sent;
56562306a36Sopenharmony_ci	__u16		unacked_frames;
56662306a36Sopenharmony_ci	__u8		retry_count;
56762306a36Sopenharmony_ci	__u16		sdu_len;
56862306a36Sopenharmony_ci	struct sk_buff	*sdu;
56962306a36Sopenharmony_ci	struct sk_buff	*sdu_last_frag;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	__u16		remote_tx_win;
57262306a36Sopenharmony_ci	__u8		remote_max_tx;
57362306a36Sopenharmony_ci	__u16		remote_mps;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	__u8		local_id;
57662306a36Sopenharmony_ci	__u8		local_stype;
57762306a36Sopenharmony_ci	__u16		local_msdu;
57862306a36Sopenharmony_ci	__u32		local_sdu_itime;
57962306a36Sopenharmony_ci	__u32		local_acc_lat;
58062306a36Sopenharmony_ci	__u32		local_flush_to;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	__u8		remote_id;
58362306a36Sopenharmony_ci	__u8		remote_stype;
58462306a36Sopenharmony_ci	__u16		remote_msdu;
58562306a36Sopenharmony_ci	__u32		remote_sdu_itime;
58662306a36Sopenharmony_ci	__u32		remote_acc_lat;
58762306a36Sopenharmony_ci	__u32		remote_flush_to;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	struct delayed_work	chan_timer;
59062306a36Sopenharmony_ci	struct delayed_work	retrans_timer;
59162306a36Sopenharmony_ci	struct delayed_work	monitor_timer;
59262306a36Sopenharmony_ci	struct delayed_work	ack_timer;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	struct sk_buff		*tx_send_head;
59562306a36Sopenharmony_ci	struct sk_buff_head	tx_q;
59662306a36Sopenharmony_ci	struct sk_buff_head	srej_q;
59762306a36Sopenharmony_ci	struct l2cap_seq_list	srej_list;
59862306a36Sopenharmony_ci	struct l2cap_seq_list	retrans_list;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	struct list_head	list;
60162306a36Sopenharmony_ci	struct list_head	global_l;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	void			*data;
60462306a36Sopenharmony_ci	const struct l2cap_ops	*ops;
60562306a36Sopenharmony_ci	struct mutex		lock;
60662306a36Sopenharmony_ci};
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistruct l2cap_ops {
60962306a36Sopenharmony_ci	char			*name;
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	struct l2cap_chan	*(*new_connection) (struct l2cap_chan *chan);
61262306a36Sopenharmony_ci	int			(*recv) (struct l2cap_chan * chan,
61362306a36Sopenharmony_ci					 struct sk_buff *skb);
61462306a36Sopenharmony_ci	void			(*teardown) (struct l2cap_chan *chan, int err);
61562306a36Sopenharmony_ci	void			(*close) (struct l2cap_chan *chan);
61662306a36Sopenharmony_ci	void			(*state_change) (struct l2cap_chan *chan,
61762306a36Sopenharmony_ci						 int state, int err);
61862306a36Sopenharmony_ci	void			(*ready) (struct l2cap_chan *chan);
61962306a36Sopenharmony_ci	void			(*defer) (struct l2cap_chan *chan);
62062306a36Sopenharmony_ci	void			(*resume) (struct l2cap_chan *chan);
62162306a36Sopenharmony_ci	void			(*suspend) (struct l2cap_chan *chan);
62262306a36Sopenharmony_ci	void			(*set_shutdown) (struct l2cap_chan *chan);
62362306a36Sopenharmony_ci	long			(*get_sndtimeo) (struct l2cap_chan *chan);
62462306a36Sopenharmony_ci	struct pid		*(*get_peer_pid) (struct l2cap_chan *chan);
62562306a36Sopenharmony_ci	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
62662306a36Sopenharmony_ci					       unsigned long hdr_len,
62762306a36Sopenharmony_ci					       unsigned long len, int nb);
62862306a36Sopenharmony_ci	int			(*filter) (struct l2cap_chan * chan,
62962306a36Sopenharmony_ci					   struct sk_buff *skb);
63062306a36Sopenharmony_ci};
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistruct l2cap_conn {
63362306a36Sopenharmony_ci	struct hci_conn		*hcon;
63462306a36Sopenharmony_ci	struct hci_chan		*hchan;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	unsigned int		mtu;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	__u32			feat_mask;
63962306a36Sopenharmony_ci	__u8			remote_fixed_chan;
64062306a36Sopenharmony_ci	__u8			local_fixed_chan;
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	__u8			info_state;
64362306a36Sopenharmony_ci	__u8			info_ident;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	struct delayed_work	info_timer;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	struct sk_buff		*rx_skb;
64862306a36Sopenharmony_ci	__u32			rx_len;
64962306a36Sopenharmony_ci	__u8			tx_ident;
65062306a36Sopenharmony_ci	struct mutex		ident_lock;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	struct sk_buff_head	pending_rx;
65362306a36Sopenharmony_ci	struct work_struct	pending_rx_work;
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci	struct delayed_work	id_addr_timer;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	__u8			disc_reason;
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	struct l2cap_chan	*smp;
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	struct list_head	chan_l;
66262306a36Sopenharmony_ci	struct mutex		chan_lock;
66362306a36Sopenharmony_ci	struct kref		ref;
66462306a36Sopenharmony_ci	struct list_head	users;
66562306a36Sopenharmony_ci};
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_cistruct l2cap_user {
66862306a36Sopenharmony_ci	struct list_head list;
66962306a36Sopenharmony_ci	int (*probe) (struct l2cap_conn *conn, struct l2cap_user *user);
67062306a36Sopenharmony_ci	void (*remove) (struct l2cap_conn *conn, struct l2cap_user *user);
67162306a36Sopenharmony_ci};
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci#define L2CAP_INFO_CL_MTU_REQ_SENT	0x01
67462306a36Sopenharmony_ci#define L2CAP_INFO_FEAT_MASK_REQ_SENT	0x04
67562306a36Sopenharmony_ci#define L2CAP_INFO_FEAT_MASK_REQ_DONE	0x08
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci#define L2CAP_CHAN_RAW			1
67862306a36Sopenharmony_ci#define L2CAP_CHAN_CONN_LESS		2
67962306a36Sopenharmony_ci#define L2CAP_CHAN_CONN_ORIENTED	3
68062306a36Sopenharmony_ci#define L2CAP_CHAN_FIXED		4
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci/* ----- L2CAP socket info ----- */
68362306a36Sopenharmony_ci#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_cistruct l2cap_pinfo {
68662306a36Sopenharmony_ci	struct bt_sock		bt;
68762306a36Sopenharmony_ci	struct l2cap_chan	*chan;
68862306a36Sopenharmony_ci	struct sk_buff		*rx_busy_skb;
68962306a36Sopenharmony_ci};
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_cienum {
69262306a36Sopenharmony_ci	CONF_REQ_SENT,
69362306a36Sopenharmony_ci	CONF_INPUT_DONE,
69462306a36Sopenharmony_ci	CONF_OUTPUT_DONE,
69562306a36Sopenharmony_ci	CONF_MTU_DONE,
69662306a36Sopenharmony_ci	CONF_MODE_DONE,
69762306a36Sopenharmony_ci	CONF_CONNECT_PEND,
69862306a36Sopenharmony_ci	CONF_RECV_NO_FCS,
69962306a36Sopenharmony_ci	CONF_STATE2_DEVICE,
70062306a36Sopenharmony_ci	CONF_EWS_RECV,
70162306a36Sopenharmony_ci	CONF_LOC_CONF_PEND,
70262306a36Sopenharmony_ci	CONF_REM_CONF_PEND,
70362306a36Sopenharmony_ci	CONF_NOT_COMPLETE,
70462306a36Sopenharmony_ci};
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci#define L2CAP_CONF_MAX_CONF_REQ 2
70762306a36Sopenharmony_ci#define L2CAP_CONF_MAX_CONF_RSP 2
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cienum {
71062306a36Sopenharmony_ci	CONN_SREJ_SENT,
71162306a36Sopenharmony_ci	CONN_WAIT_F,
71262306a36Sopenharmony_ci	CONN_SREJ_ACT,
71362306a36Sopenharmony_ci	CONN_SEND_PBIT,
71462306a36Sopenharmony_ci	CONN_REMOTE_BUSY,
71562306a36Sopenharmony_ci	CONN_LOCAL_BUSY,
71662306a36Sopenharmony_ci	CONN_REJ_ACT,
71762306a36Sopenharmony_ci	CONN_SEND_FBIT,
71862306a36Sopenharmony_ci	CONN_RNR_SENT,
71962306a36Sopenharmony_ci};
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci/* Definitions for flags in l2cap_chan */
72262306a36Sopenharmony_cienum {
72362306a36Sopenharmony_ci	FLAG_ROLE_SWITCH,
72462306a36Sopenharmony_ci	FLAG_FORCE_ACTIVE,
72562306a36Sopenharmony_ci	FLAG_FORCE_RELIABLE,
72662306a36Sopenharmony_ci	FLAG_FLUSHABLE,
72762306a36Sopenharmony_ci	FLAG_EXT_CTRL,
72862306a36Sopenharmony_ci	FLAG_EFS_ENABLE,
72962306a36Sopenharmony_ci	FLAG_DEFER_SETUP,
73062306a36Sopenharmony_ci	FLAG_LE_CONN_REQ_SENT,
73162306a36Sopenharmony_ci	FLAG_ECRED_CONN_REQ_SENT,
73262306a36Sopenharmony_ci	FLAG_PENDING_SECURITY,
73362306a36Sopenharmony_ci	FLAG_HOLD_HCI_CONN,
73462306a36Sopenharmony_ci};
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci/* Lock nesting levels for L2CAP channels. We need these because lockdep
73762306a36Sopenharmony_ci * otherwise considers all channels equal and will e.g. complain about a
73862306a36Sopenharmony_ci * connection oriented channel triggering SMP procedures or a listening
73962306a36Sopenharmony_ci * channel creating and locking a child channel.
74062306a36Sopenharmony_ci */
74162306a36Sopenharmony_cienum {
74262306a36Sopenharmony_ci	L2CAP_NESTING_SMP,
74362306a36Sopenharmony_ci	L2CAP_NESTING_NORMAL,
74462306a36Sopenharmony_ci	L2CAP_NESTING_PARENT,
74562306a36Sopenharmony_ci};
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_cienum {
74862306a36Sopenharmony_ci	L2CAP_TX_STATE_XMIT,
74962306a36Sopenharmony_ci	L2CAP_TX_STATE_WAIT_F,
75062306a36Sopenharmony_ci};
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_cienum {
75362306a36Sopenharmony_ci	L2CAP_RX_STATE_RECV,
75462306a36Sopenharmony_ci	L2CAP_RX_STATE_SREJ_SENT,
75562306a36Sopenharmony_ci	L2CAP_RX_STATE_MOVE,
75662306a36Sopenharmony_ci	L2CAP_RX_STATE_WAIT_P,
75762306a36Sopenharmony_ci	L2CAP_RX_STATE_WAIT_F,
75862306a36Sopenharmony_ci};
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_cienum {
76162306a36Sopenharmony_ci	L2CAP_TXSEQ_EXPECTED,
76262306a36Sopenharmony_ci	L2CAP_TXSEQ_EXPECTED_SREJ,
76362306a36Sopenharmony_ci	L2CAP_TXSEQ_UNEXPECTED,
76462306a36Sopenharmony_ci	L2CAP_TXSEQ_UNEXPECTED_SREJ,
76562306a36Sopenharmony_ci	L2CAP_TXSEQ_DUPLICATE,
76662306a36Sopenharmony_ci	L2CAP_TXSEQ_DUPLICATE_SREJ,
76762306a36Sopenharmony_ci	L2CAP_TXSEQ_INVALID,
76862306a36Sopenharmony_ci	L2CAP_TXSEQ_INVALID_IGNORE,
76962306a36Sopenharmony_ci};
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cienum {
77262306a36Sopenharmony_ci	L2CAP_EV_DATA_REQUEST,
77362306a36Sopenharmony_ci	L2CAP_EV_LOCAL_BUSY_DETECTED,
77462306a36Sopenharmony_ci	L2CAP_EV_LOCAL_BUSY_CLEAR,
77562306a36Sopenharmony_ci	L2CAP_EV_RECV_REQSEQ_AND_FBIT,
77662306a36Sopenharmony_ci	L2CAP_EV_RECV_FBIT,
77762306a36Sopenharmony_ci	L2CAP_EV_RETRANS_TO,
77862306a36Sopenharmony_ci	L2CAP_EV_MONITOR_TO,
77962306a36Sopenharmony_ci	L2CAP_EV_EXPLICIT_POLL,
78062306a36Sopenharmony_ci	L2CAP_EV_RECV_IFRAME,
78162306a36Sopenharmony_ci	L2CAP_EV_RECV_RR,
78262306a36Sopenharmony_ci	L2CAP_EV_RECV_REJ,
78362306a36Sopenharmony_ci	L2CAP_EV_RECV_RNR,
78462306a36Sopenharmony_ci	L2CAP_EV_RECV_SREJ,
78562306a36Sopenharmony_ci	L2CAP_EV_RECV_FRAME,
78662306a36Sopenharmony_ci};
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_cienum {
78962306a36Sopenharmony_ci	L2CAP_MOVE_ROLE_NONE,
79062306a36Sopenharmony_ci	L2CAP_MOVE_ROLE_INITIATOR,
79162306a36Sopenharmony_ci	L2CAP_MOVE_ROLE_RESPONDER,
79262306a36Sopenharmony_ci};
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_cienum {
79562306a36Sopenharmony_ci	L2CAP_MOVE_STABLE,
79662306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_REQ,
79762306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_RSP,
79862306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_RSP_SUCCESS,
79962306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_CONFIRM,
80062306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_CONFIRM_RSP,
80162306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_LOGICAL_COMP,
80262306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_LOGICAL_CFM,
80362306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_LOCAL_BUSY,
80462306a36Sopenharmony_ci	L2CAP_MOVE_WAIT_PREPARE,
80562306a36Sopenharmony_ci};
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_civoid l2cap_chan_hold(struct l2cap_chan *c);
80862306a36Sopenharmony_cistruct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c);
80962306a36Sopenharmony_civoid l2cap_chan_put(struct l2cap_chan *c);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic inline void l2cap_chan_lock(struct l2cap_chan *chan)
81262306a36Sopenharmony_ci{
81362306a36Sopenharmony_ci	mutex_lock_nested(&chan->lock, atomic_read(&chan->nesting));
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic inline void l2cap_chan_unlock(struct l2cap_chan *chan)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	mutex_unlock(&chan->lock);
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic inline void l2cap_set_timer(struct l2cap_chan *chan,
82262306a36Sopenharmony_ci				   struct delayed_work *work, long timeout)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	BT_DBG("chan %p state %s timeout %ld", chan,
82562306a36Sopenharmony_ci	       state_to_string(chan->state), timeout);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	/* If delayed work cancelled do not hold(chan)
82862306a36Sopenharmony_ci	   since it is already done with previous set_timer */
82962306a36Sopenharmony_ci	if (!cancel_delayed_work(work))
83062306a36Sopenharmony_ci		l2cap_chan_hold(chan);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	schedule_delayed_work(work, timeout);
83362306a36Sopenharmony_ci}
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_cistatic inline bool l2cap_clear_timer(struct l2cap_chan *chan,
83662306a36Sopenharmony_ci				     struct delayed_work *work)
83762306a36Sopenharmony_ci{
83862306a36Sopenharmony_ci	bool ret;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/* put(chan) if delayed work cancelled otherwise it
84162306a36Sopenharmony_ci	   is done in delayed work function */
84262306a36Sopenharmony_ci	ret = cancel_delayed_work(work);
84362306a36Sopenharmony_ci	if (ret)
84462306a36Sopenharmony_ci		l2cap_chan_put(chan);
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	return ret;
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
85062306a36Sopenharmony_ci#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
85162306a36Sopenharmony_ci#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
85262306a36Sopenharmony_ci#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
85362306a36Sopenharmony_ci#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
85462306a36Sopenharmony_ci		msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
85562306a36Sopenharmony_ci#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_cistatic inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2)
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	if (seq1 >= seq2)
86062306a36Sopenharmony_ci		return seq1 - seq2;
86162306a36Sopenharmony_ci	else
86262306a36Sopenharmony_ci		return chan->tx_win_max + 1 - seq2 + seq1;
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistatic inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
86662306a36Sopenharmony_ci{
86762306a36Sopenharmony_ci	return (seq + 1) % (chan->tx_win_max + 1);
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	return NULL;
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_cistatic inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
87662306a36Sopenharmony_ci{
87762306a36Sopenharmony_ci	return -ENOSYS;
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic inline struct sk_buff *l2cap_chan_no_alloc_skb(struct l2cap_chan *chan,
88162306a36Sopenharmony_ci						      unsigned long hdr_len,
88262306a36Sopenharmony_ci						      unsigned long len, int nb)
88362306a36Sopenharmony_ci{
88462306a36Sopenharmony_ci	return ERR_PTR(-ENOSYS);
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci}
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic inline void l2cap_chan_no_close(struct l2cap_chan *chan)
89262306a36Sopenharmony_ci{
89362306a36Sopenharmony_ci}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_cistatic inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_cistatic inline void l2cap_chan_no_state_change(struct l2cap_chan *chan,
90062306a36Sopenharmony_ci					      int state, int err)
90162306a36Sopenharmony_ci{
90262306a36Sopenharmony_ci}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_cistatic inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci}
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_cistatic inline void l2cap_chan_no_suspend(struct l2cap_chan *chan)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_cistatic inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
91362306a36Sopenharmony_ci{
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_cistatic inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
92162306a36Sopenharmony_ci{
92262306a36Sopenharmony_ci	return 0;
92362306a36Sopenharmony_ci}
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ciextern bool disable_ertm;
92662306a36Sopenharmony_ciextern bool enable_ecred;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ciint l2cap_init_sockets(void);
92962306a36Sopenharmony_civoid l2cap_cleanup_sockets(void);
93062306a36Sopenharmony_cibool l2cap_is_socket(struct socket *sock);
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_civoid __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan);
93362306a36Sopenharmony_civoid __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan);
93462306a36Sopenharmony_civoid __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ciint l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
93762306a36Sopenharmony_ciint l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_cistruct l2cap_chan *l2cap_chan_create(void);
94062306a36Sopenharmony_civoid l2cap_chan_close(struct l2cap_chan *chan, int reason);
94162306a36Sopenharmony_ciint l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
94262306a36Sopenharmony_ci		       bdaddr_t *dst, u8 dst_type);
94362306a36Sopenharmony_ciint l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu);
94462306a36Sopenharmony_ciint l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
94562306a36Sopenharmony_civoid l2cap_chan_busy(struct l2cap_chan *chan, int busy);
94662306a36Sopenharmony_ciint l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
94762306a36Sopenharmony_civoid l2cap_chan_set_defaults(struct l2cap_chan *chan);
94862306a36Sopenharmony_ciint l2cap_ertm_init(struct l2cap_chan *chan);
94962306a36Sopenharmony_civoid l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
95062306a36Sopenharmony_civoid __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
95162306a36Sopenharmony_citypedef void (*l2cap_chan_func_t)(struct l2cap_chan *chan, void *data);
95262306a36Sopenharmony_civoid l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func,
95362306a36Sopenharmony_ci		     void *data);
95462306a36Sopenharmony_civoid l2cap_chan_del(struct l2cap_chan *chan, int err);
95562306a36Sopenharmony_civoid l2cap_send_conn_req(struct l2cap_chan *chan);
95662306a36Sopenharmony_civoid l2cap_move_start(struct l2cap_chan *chan);
95762306a36Sopenharmony_civoid l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
95862306a36Sopenharmony_ci		       u8 status);
95962306a36Sopenharmony_civoid __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_cistruct l2cap_conn *l2cap_conn_get(struct l2cap_conn *conn);
96262306a36Sopenharmony_civoid l2cap_conn_put(struct l2cap_conn *conn);
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ciint l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user);
96562306a36Sopenharmony_civoid l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user);
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci#endif /* __L2CAP_H */
968