162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2011 Intel Corporation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_cienum llcp_state { 762306a36Sopenharmony_ci LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ 862306a36Sopenharmony_ci LLCP_CONNECTING, 962306a36Sopenharmony_ci LLCP_CLOSED, 1062306a36Sopenharmony_ci LLCP_BOUND, 1162306a36Sopenharmony_ci LLCP_LISTEN, 1262306a36Sopenharmony_ci}; 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define LLCP_DEFAULT_LTO 100 1562306a36Sopenharmony_ci#define LLCP_DEFAULT_RW 1 1662306a36Sopenharmony_ci#define LLCP_DEFAULT_MIU 128 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define LLCP_MAX_LTO 0xff 1962306a36Sopenharmony_ci#define LLCP_MAX_RW 15 2062306a36Sopenharmony_ci#define LLCP_MAX_MIUX 0x7ff 2162306a36Sopenharmony_ci#define LLCP_MAX_MIU (LLCP_MAX_MIUX + 128) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define LLCP_WKS_NUM_SAP 16 2462306a36Sopenharmony_ci#define LLCP_SDP_NUM_SAP 16 2562306a36Sopenharmony_ci#define LLCP_LOCAL_NUM_SAP 32 2662306a36Sopenharmony_ci#define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) 2762306a36Sopenharmony_ci#define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) 2862306a36Sopenharmony_ci#define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct nfc_llcp_sock; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct llcp_sock_list { 3362306a36Sopenharmony_ci struct hlist_head head; 3462306a36Sopenharmony_ci rwlock_t lock; 3562306a36Sopenharmony_ci}; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistruct nfc_llcp_sdp_tlv { 3862306a36Sopenharmony_ci u8 *tlv; 3962306a36Sopenharmony_ci u8 tlv_len; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci char *uri; 4262306a36Sopenharmony_ci u8 tid; 4362306a36Sopenharmony_ci u8 sap; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci unsigned long time; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci struct hlist_node node; 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistruct nfc_llcp_local { 5162306a36Sopenharmony_ci struct list_head list; 5262306a36Sopenharmony_ci struct nfc_dev *dev; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci struct kref ref; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci struct mutex sdp_lock; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci struct timer_list link_timer; 5962306a36Sopenharmony_ci struct sk_buff_head tx_queue; 6062306a36Sopenharmony_ci struct work_struct tx_work; 6162306a36Sopenharmony_ci struct work_struct rx_work; 6262306a36Sopenharmony_ci struct sk_buff *rx_pending; 6362306a36Sopenharmony_ci struct work_struct timeout_work; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci u32 target_idx; 6662306a36Sopenharmony_ci u8 rf_mode; 6762306a36Sopenharmony_ci u8 comm_mode; 6862306a36Sopenharmony_ci u8 lto; 6962306a36Sopenharmony_ci u8 rw; 7062306a36Sopenharmony_ci __be16 miux; 7162306a36Sopenharmony_ci unsigned long local_wks; /* Well known services */ 7262306a36Sopenharmony_ci unsigned long local_sdp; /* Local services */ 7362306a36Sopenharmony_ci unsigned long local_sap; /* Local SAPs, not available for discovery */ 7462306a36Sopenharmony_ci atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP]; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* local */ 7762306a36Sopenharmony_ci u8 gb[NFC_MAX_GT_LEN]; 7862306a36Sopenharmony_ci u8 gb_len; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* remote */ 8162306a36Sopenharmony_ci u8 remote_gb[NFC_MAX_GT_LEN]; 8262306a36Sopenharmony_ci u8 remote_gb_len; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci u8 remote_version; 8562306a36Sopenharmony_ci u16 remote_miu; 8662306a36Sopenharmony_ci u16 remote_lto; 8762306a36Sopenharmony_ci u8 remote_opt; 8862306a36Sopenharmony_ci u16 remote_wks; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci struct mutex sdreq_lock; 9162306a36Sopenharmony_ci struct hlist_head pending_sdreqs; 9262306a36Sopenharmony_ci struct timer_list sdreq_timer; 9362306a36Sopenharmony_ci struct work_struct sdreq_timeout_work; 9462306a36Sopenharmony_ci u8 sdreq_next_tid; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* sockets array */ 9762306a36Sopenharmony_ci struct llcp_sock_list sockets; 9862306a36Sopenharmony_ci struct llcp_sock_list connecting_sockets; 9962306a36Sopenharmony_ci struct llcp_sock_list raw_sockets; 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistruct nfc_llcp_sock { 10362306a36Sopenharmony_ci struct sock sk; 10462306a36Sopenharmony_ci struct nfc_dev *dev; 10562306a36Sopenharmony_ci struct nfc_llcp_local *local; 10662306a36Sopenharmony_ci u32 target_idx; 10762306a36Sopenharmony_ci u32 nfc_protocol; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Link parameters */ 11062306a36Sopenharmony_ci u8 ssap; 11162306a36Sopenharmony_ci u8 dsap; 11262306a36Sopenharmony_ci char *service_name; 11362306a36Sopenharmony_ci size_t service_name_len; 11462306a36Sopenharmony_ci u8 rw; 11562306a36Sopenharmony_ci __be16 miux; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* Remote link parameters */ 11962306a36Sopenharmony_ci u8 remote_rw; 12062306a36Sopenharmony_ci u16 remote_miu; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* Link variables */ 12362306a36Sopenharmony_ci u8 send_n; 12462306a36Sopenharmony_ci u8 send_ack_n; 12562306a36Sopenharmony_ci u8 recv_n; 12662306a36Sopenharmony_ci u8 recv_ack_n; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci /* Is the remote peer ready to receive */ 12962306a36Sopenharmony_ci u8 remote_ready; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Reserved source SAP */ 13262306a36Sopenharmony_ci u8 reserved_ssap; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci struct sk_buff_head tx_queue; 13562306a36Sopenharmony_ci struct sk_buff_head tx_pending_queue; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci struct list_head accept_queue; 13862306a36Sopenharmony_ci struct sock *parent; 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistruct nfc_llcp_ui_cb { 14262306a36Sopenharmony_ci __u8 dsap; 14362306a36Sopenharmony_ci __u8 ssap; 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define nfc_llcp_ui_skb_cb(__skb) ((struct nfc_llcp_ui_cb *)&((__skb)->cb[0])) 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci#define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) 14962306a36Sopenharmony_ci#define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#define LLCP_HEADER_SIZE 2 15262306a36Sopenharmony_ci#define LLCP_SEQUENCE_SIZE 1 15362306a36Sopenharmony_ci#define LLCP_AGF_PDU_HEADER_SIZE 2 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/* LLCP versions: 1.1 is 1.0 plus SDP */ 15662306a36Sopenharmony_ci#define LLCP_VERSION_10 0x10 15762306a36Sopenharmony_ci#define LLCP_VERSION_11 0x11 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* LLCP PDU types */ 16062306a36Sopenharmony_ci#define LLCP_PDU_SYMM 0x0 16162306a36Sopenharmony_ci#define LLCP_PDU_PAX 0x1 16262306a36Sopenharmony_ci#define LLCP_PDU_AGF 0x2 16362306a36Sopenharmony_ci#define LLCP_PDU_UI 0x3 16462306a36Sopenharmony_ci#define LLCP_PDU_CONNECT 0x4 16562306a36Sopenharmony_ci#define LLCP_PDU_DISC 0x5 16662306a36Sopenharmony_ci#define LLCP_PDU_CC 0x6 16762306a36Sopenharmony_ci#define LLCP_PDU_DM 0x7 16862306a36Sopenharmony_ci#define LLCP_PDU_FRMR 0x8 16962306a36Sopenharmony_ci#define LLCP_PDU_SNL 0x9 17062306a36Sopenharmony_ci#define LLCP_PDU_I 0xc 17162306a36Sopenharmony_ci#define LLCP_PDU_RR 0xd 17262306a36Sopenharmony_ci#define LLCP_PDU_RNR 0xe 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* Parameters TLV types */ 17562306a36Sopenharmony_ci#define LLCP_TLV_VERSION 0x1 17662306a36Sopenharmony_ci#define LLCP_TLV_MIUX 0x2 17762306a36Sopenharmony_ci#define LLCP_TLV_WKS 0x3 17862306a36Sopenharmony_ci#define LLCP_TLV_LTO 0x4 17962306a36Sopenharmony_ci#define LLCP_TLV_RW 0x5 18062306a36Sopenharmony_ci#define LLCP_TLV_SN 0x6 18162306a36Sopenharmony_ci#define LLCP_TLV_OPT 0x7 18262306a36Sopenharmony_ci#define LLCP_TLV_SDREQ 0x8 18362306a36Sopenharmony_ci#define LLCP_TLV_SDRES 0x9 18462306a36Sopenharmony_ci#define LLCP_TLV_MAX 0xa 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* Well known LLCP SAP */ 18762306a36Sopenharmony_ci#define LLCP_SAP_SDP 0x1 18862306a36Sopenharmony_ci#define LLCP_SAP_IP 0x2 18962306a36Sopenharmony_ci#define LLCP_SAP_OBEX 0x3 19062306a36Sopenharmony_ci#define LLCP_SAP_SNEP 0x4 19162306a36Sopenharmony_ci#define LLCP_SAP_MAX 0xff 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* Disconnection reason code */ 19462306a36Sopenharmony_ci#define LLCP_DM_DISC 0x00 19562306a36Sopenharmony_ci#define LLCP_DM_NOCONN 0x01 19662306a36Sopenharmony_ci#define LLCP_DM_NOBOUND 0x02 19762306a36Sopenharmony_ci#define LLCP_DM_REJ 0x03 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_civoid nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); 20162306a36Sopenharmony_civoid nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); 20262306a36Sopenharmony_civoid nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock); 20362306a36Sopenharmony_cistruct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); 20462306a36Sopenharmony_ciint nfc_llcp_local_put(struct nfc_llcp_local *local); 20562306a36Sopenharmony_ciu8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, 20662306a36Sopenharmony_ci struct nfc_llcp_sock *sock); 20762306a36Sopenharmony_ciu8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 20862306a36Sopenharmony_civoid nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); 20962306a36Sopenharmony_ciint nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); 21062306a36Sopenharmony_civoid nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, 21162306a36Sopenharmony_ci struct sk_buff *skb, u8 direction); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* Sock API */ 21462306a36Sopenharmony_cistruct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp, int kern); 21562306a36Sopenharmony_civoid nfc_llcp_sock_free(struct nfc_llcp_sock *sock); 21662306a36Sopenharmony_civoid nfc_llcp_accept_unlink(struct sock *sk); 21762306a36Sopenharmony_civoid nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); 21862306a36Sopenharmony_cistruct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/* TLV API */ 22162306a36Sopenharmony_ciint nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, 22262306a36Sopenharmony_ci const u8 *tlv_array, u16 tlv_array_len); 22362306a36Sopenharmony_ciint nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, 22462306a36Sopenharmony_ci const u8 *tlv_array, u16 tlv_array_len); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* Commands API */ 22762306a36Sopenharmony_civoid nfc_llcp_recv(void *data, struct sk_buff *skb, int err); 22862306a36Sopenharmony_ciu8 *nfc_llcp_build_tlv(u8 type, const u8 *value, u8 value_length, u8 *tlv_length); 22962306a36Sopenharmony_cistruct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap); 23062306a36Sopenharmony_cistruct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, const char *uri, 23162306a36Sopenharmony_ci size_t uri_len); 23262306a36Sopenharmony_civoid nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); 23362306a36Sopenharmony_civoid nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); 23462306a36Sopenharmony_civoid nfc_llcp_recv(void *data, struct sk_buff *skb, int err); 23562306a36Sopenharmony_ciint nfc_llcp_send_symm(struct nfc_dev *dev); 23662306a36Sopenharmony_ciint nfc_llcp_send_connect(struct nfc_llcp_sock *sock); 23762306a36Sopenharmony_ciint nfc_llcp_send_cc(struct nfc_llcp_sock *sock); 23862306a36Sopenharmony_ciint nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, 23962306a36Sopenharmony_ci struct hlist_head *tlv_list, size_t tlvs_len); 24062306a36Sopenharmony_ciint nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, 24162306a36Sopenharmony_ci struct hlist_head *tlv_list, size_t tlvs_len); 24262306a36Sopenharmony_ciint nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); 24362306a36Sopenharmony_ciint nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); 24462306a36Sopenharmony_ciint nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, 24562306a36Sopenharmony_ci struct msghdr *msg, size_t len); 24662306a36Sopenharmony_ciint nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, 24762306a36Sopenharmony_ci struct msghdr *msg, size_t len); 24862306a36Sopenharmony_ciint nfc_llcp_send_rr(struct nfc_llcp_sock *sock); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci/* Socket API */ 25162306a36Sopenharmony_ciint __init nfc_llcp_sock_init(void); 25262306a36Sopenharmony_civoid nfc_llcp_sock_exit(void); 253