11ccea77eSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 230cc4587SSamuel Ortiz /* 330cc4587SSamuel Ortiz * Copyright (C) 2011 Intel Corporation. All rights reserved. 430cc4587SSamuel Ortiz */ 530cc4587SSamuel Ortiz 630cc4587SSamuel Ortiz enum llcp_state { 730cc4587SSamuel Ortiz LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ 8b4011239SSamuel Ortiz LLCP_CONNECTING, 930cc4587SSamuel Ortiz LLCP_CLOSED, 1030cc4587SSamuel Ortiz LLCP_BOUND, 1130cc4587SSamuel Ortiz LLCP_LISTEN, 1230cc4587SSamuel Ortiz }; 1330cc4587SSamuel Ortiz 1430cc4587SSamuel Ortiz #define LLCP_DEFAULT_LTO 100 1530cc4587SSamuel Ortiz #define LLCP_DEFAULT_RW 1 1630cc4587SSamuel Ortiz #define LLCP_DEFAULT_MIU 128 1730cc4587SSamuel Ortiz 1830cc4587SSamuel Ortiz #define LLCP_MAX_LTO 0xff 1930cc4587SSamuel Ortiz #define LLCP_MAX_RW 15 2030cc4587SSamuel Ortiz #define LLCP_MAX_MIUX 0x7ff 2130cc4587SSamuel Ortiz #define LLCP_MAX_MIU (LLCP_MAX_MIUX + 128) 2230cc4587SSamuel Ortiz 2330cc4587SSamuel Ortiz #define LLCP_WKS_NUM_SAP 16 2430cc4587SSamuel Ortiz #define LLCP_SDP_NUM_SAP 16 2530cc4587SSamuel Ortiz #define LLCP_LOCAL_NUM_SAP 32 2630cc4587SSamuel Ortiz #define LLCP_LOCAL_SAP_OFFSET (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP) 2730cc4587SSamuel Ortiz #define LLCP_MAX_SAP (LLCP_WKS_NUM_SAP + LLCP_SDP_NUM_SAP + LLCP_LOCAL_NUM_SAP) 2830cc4587SSamuel Ortiz #define LLCP_SDP_UNBOUND (LLCP_MAX_SAP + 1) 2930cc4587SSamuel Ortiz 3030cc4587SSamuel Ortiz struct nfc_llcp_sock; 3130cc4587SSamuel Ortiz 3230cc4587SSamuel Ortiz struct llcp_sock_list { 3330cc4587SSamuel Ortiz struct hlist_head head; 3430cc4587SSamuel Ortiz rwlock_t lock; 3530cc4587SSamuel Ortiz }; 3630cc4587SSamuel Ortiz 3730cc4587SSamuel Ortiz struct nfc_llcp_sdp_tlv { 3830cc4587SSamuel Ortiz u8 *tlv; 3930cc4587SSamuel Ortiz u8 tlv_len; 4030cc4587SSamuel Ortiz 4130cc4587SSamuel Ortiz char *uri; 4230cc4587SSamuel Ortiz u8 tid; 4330cc4587SSamuel Ortiz u8 sap; 4430cc4587SSamuel Ortiz 4530cc4587SSamuel Ortiz unsigned long time; 4630cc4587SSamuel Ortiz 4730cc4587SSamuel Ortiz struct hlist_node node; 4830cc4587SSamuel Ortiz }; 4930cc4587SSamuel Ortiz 5030cc4587SSamuel Ortiz struct nfc_llcp_local { 5130cc4587SSamuel Ortiz struct list_head list; 5230cc4587SSamuel Ortiz struct nfc_dev *dev; 5330cc4587SSamuel Ortiz 5430cc4587SSamuel Ortiz struct kref ref; 5530cc4587SSamuel Ortiz 5630cc4587SSamuel Ortiz struct mutex sdp_lock; 5730cc4587SSamuel Ortiz 5830cc4587SSamuel Ortiz struct timer_list link_timer; 5930cc4587SSamuel Ortiz struct sk_buff_head tx_queue; 6030cc4587SSamuel Ortiz struct work_struct tx_work; 6130cc4587SSamuel Ortiz struct work_struct rx_work; 6230cc4587SSamuel Ortiz struct sk_buff *rx_pending; 6330cc4587SSamuel Ortiz struct work_struct timeout_work; 6430cc4587SSamuel Ortiz 6530cc4587SSamuel Ortiz u32 target_idx; 6630cc4587SSamuel Ortiz u8 rf_mode; 6730cc4587SSamuel Ortiz u8 comm_mode; 6830cc4587SSamuel Ortiz u8 lto; 6930cc4587SSamuel Ortiz u8 rw; 7030cc4587SSamuel Ortiz __be16 miux; 7130cc4587SSamuel Ortiz unsigned long local_wks; /* Well known services */ 7230cc4587SSamuel Ortiz unsigned long local_sdp; /* Local services */ 7330cc4587SSamuel Ortiz unsigned long local_sap; /* Local SAPs, not available for discovery */ 7430cc4587SSamuel Ortiz atomic_t local_sdp_cnt[LLCP_SDP_NUM_SAP]; 7530cc4587SSamuel Ortiz 7630cc4587SSamuel Ortiz /* local */ 7730cc4587SSamuel Ortiz u8 gb[NFC_MAX_GT_LEN]; 7830cc4587SSamuel Ortiz u8 gb_len; 7930cc4587SSamuel Ortiz 8030cc4587SSamuel Ortiz /* remote */ 8130cc4587SSamuel Ortiz u8 remote_gb[NFC_MAX_GT_LEN]; 8230cc4587SSamuel Ortiz u8 remote_gb_len; 8330cc4587SSamuel Ortiz 8430cc4587SSamuel Ortiz u8 remote_version; 8530cc4587SSamuel Ortiz u16 remote_miu; 8630cc4587SSamuel Ortiz u16 remote_lto; 8730cc4587SSamuel Ortiz u8 remote_opt; 8830cc4587SSamuel Ortiz u16 remote_wks; 8930cc4587SSamuel Ortiz 9030cc4587SSamuel Ortiz struct mutex sdreq_lock; 9130cc4587SSamuel Ortiz struct hlist_head pending_sdreqs; 9230cc4587SSamuel Ortiz struct timer_list sdreq_timer; 9330cc4587SSamuel Ortiz struct work_struct sdreq_timeout_work; 9430cc4587SSamuel Ortiz u8 sdreq_next_tid; 9530cc4587SSamuel Ortiz 9630cc4587SSamuel Ortiz /* sockets array */ 9730cc4587SSamuel Ortiz struct llcp_sock_list sockets; 9830cc4587SSamuel Ortiz struct llcp_sock_list connecting_sockets; 9930cc4587SSamuel Ortiz struct llcp_sock_list raw_sockets; 10030cc4587SSamuel Ortiz }; 10130cc4587SSamuel Ortiz 10230cc4587SSamuel Ortiz struct nfc_llcp_sock { 10330cc4587SSamuel Ortiz struct sock sk; 10430cc4587SSamuel Ortiz struct nfc_dev *dev; 10530cc4587SSamuel Ortiz struct nfc_llcp_local *local; 10630cc4587SSamuel Ortiz u32 target_idx; 10730cc4587SSamuel Ortiz u32 nfc_protocol; 10830cc4587SSamuel Ortiz 10930cc4587SSamuel Ortiz /* Link parameters */ 11030cc4587SSamuel Ortiz u8 ssap; 11130cc4587SSamuel Ortiz u8 dsap; 11230cc4587SSamuel Ortiz char *service_name; 11330cc4587SSamuel Ortiz size_t service_name_len; 11430cc4587SSamuel Ortiz u8 rw; 11530cc4587SSamuel Ortiz __be16 miux; 11630cc4587SSamuel Ortiz 11730cc4587SSamuel Ortiz 11830cc4587SSamuel Ortiz /* Remote link parameters */ 11930cc4587SSamuel Ortiz u8 remote_rw; 12030cc4587SSamuel Ortiz u16 remote_miu; 12130cc4587SSamuel Ortiz 12230cc4587SSamuel Ortiz /* Link variables */ 12330cc4587SSamuel Ortiz u8 send_n; 12430cc4587SSamuel Ortiz u8 send_ack_n; 12530cc4587SSamuel Ortiz u8 recv_n; 12630cc4587SSamuel Ortiz u8 recv_ack_n; 12730cc4587SSamuel Ortiz 12830cc4587SSamuel Ortiz /* Is the remote peer ready to receive */ 12930cc4587SSamuel Ortiz u8 remote_ready; 13030cc4587SSamuel Ortiz 13130cc4587SSamuel Ortiz /* Reserved source SAP */ 13230cc4587SSamuel Ortiz u8 reserved_ssap; 13330cc4587SSamuel Ortiz 13430cc4587SSamuel Ortiz struct sk_buff_head tx_queue; 13530cc4587SSamuel Ortiz struct sk_buff_head tx_pending_queue; 13630cc4587SSamuel Ortiz 13730cc4587SSamuel Ortiz struct list_head accept_queue; 13830cc4587SSamuel Ortiz struct sock *parent; 13930cc4587SSamuel Ortiz }; 14030cc4587SSamuel Ortiz 14130cc4587SSamuel Ortiz struct nfc_llcp_ui_cb { 14230cc4587SSamuel Ortiz __u8 dsap; 14330cc4587SSamuel Ortiz __u8 ssap; 14430cc4587SSamuel Ortiz }; 14530cc4587SSamuel Ortiz 14630cc4587SSamuel Ortiz #define nfc_llcp_ui_skb_cb(__skb) ((struct nfc_llcp_ui_cb *)&((__skb)->cb[0])) 14730cc4587SSamuel Ortiz 14830cc4587SSamuel Ortiz #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) 14930cc4587SSamuel Ortiz #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) 15030cc4587SSamuel Ortiz 15130cc4587SSamuel Ortiz #define LLCP_HEADER_SIZE 2 15230cc4587SSamuel Ortiz #define LLCP_SEQUENCE_SIZE 1 15330cc4587SSamuel Ortiz #define LLCP_AGF_PDU_HEADER_SIZE 2 15430cc4587SSamuel Ortiz 15530cc4587SSamuel Ortiz /* LLCP versions: 1.1 is 1.0 plus SDP */ 15630cc4587SSamuel Ortiz #define LLCP_VERSION_10 0x10 15730cc4587SSamuel Ortiz #define LLCP_VERSION_11 0x11 15830cc4587SSamuel Ortiz 15930cc4587SSamuel Ortiz /* LLCP PDU types */ 16030cc4587SSamuel Ortiz #define LLCP_PDU_SYMM 0x0 16130cc4587SSamuel Ortiz #define LLCP_PDU_PAX 0x1 16230cc4587SSamuel Ortiz #define LLCP_PDU_AGF 0x2 16330cc4587SSamuel Ortiz #define LLCP_PDU_UI 0x3 16430cc4587SSamuel Ortiz #define LLCP_PDU_CONNECT 0x4 16530cc4587SSamuel Ortiz #define LLCP_PDU_DISC 0x5 16630cc4587SSamuel Ortiz #define LLCP_PDU_CC 0x6 16730cc4587SSamuel Ortiz #define LLCP_PDU_DM 0x7 16830cc4587SSamuel Ortiz #define LLCP_PDU_FRMR 0x8 16930cc4587SSamuel Ortiz #define LLCP_PDU_SNL 0x9 17030cc4587SSamuel Ortiz #define LLCP_PDU_I 0xc 17130cc4587SSamuel Ortiz #define LLCP_PDU_RR 0xd 17230cc4587SSamuel Ortiz #define LLCP_PDU_RNR 0xe 17330cc4587SSamuel Ortiz 17430cc4587SSamuel Ortiz /* Parameters TLV types */ 17530cc4587SSamuel Ortiz #define LLCP_TLV_VERSION 0x1 17630cc4587SSamuel Ortiz #define LLCP_TLV_MIUX 0x2 17730cc4587SSamuel Ortiz #define LLCP_TLV_WKS 0x3 17830cc4587SSamuel Ortiz #define LLCP_TLV_LTO 0x4 17930cc4587SSamuel Ortiz #define LLCP_TLV_RW 0x5 18030cc4587SSamuel Ortiz #define LLCP_TLV_SN 0x6 18130cc4587SSamuel Ortiz #define LLCP_TLV_OPT 0x7 18230cc4587SSamuel Ortiz #define LLCP_TLV_SDREQ 0x8 18330cc4587SSamuel Ortiz #define LLCP_TLV_SDRES 0x9 18430cc4587SSamuel Ortiz #define LLCP_TLV_MAX 0xa 18530cc4587SSamuel Ortiz 18630cc4587SSamuel Ortiz /* Well known LLCP SAP */ 18730cc4587SSamuel Ortiz #define LLCP_SAP_SDP 0x1 18830cc4587SSamuel Ortiz #define LLCP_SAP_IP 0x2 18930cc4587SSamuel Ortiz #define LLCP_SAP_OBEX 0x3 19030cc4587SSamuel Ortiz #define LLCP_SAP_SNEP 0x4 19130cc4587SSamuel Ortiz #define LLCP_SAP_MAX 0xff 19230cc4587SSamuel Ortiz 19330cc4587SSamuel Ortiz /* Disconnection reason code */ 19430cc4587SSamuel Ortiz #define LLCP_DM_DISC 0x00 19530cc4587SSamuel Ortiz #define LLCP_DM_NOCONN 0x01 19630cc4587SSamuel Ortiz #define LLCP_DM_NOBOUND 0x02 19730cc4587SSamuel Ortiz #define LLCP_DM_REJ 0x03 19830cc4587SSamuel Ortiz 19930cc4587SSamuel Ortiz 20030cc4587SSamuel Ortiz void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); 20130cc4587SSamuel Ortiz void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); 20230cc4587SSamuel Ortiz void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock); 20330cc4587SSamuel Ortiz struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); 20430cc4587SSamuel Ortiz int nfc_llcp_local_put(struct nfc_llcp_local *local); 20530cc4587SSamuel Ortiz u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, 20630cc4587SSamuel Ortiz struct nfc_llcp_sock *sock); 20730cc4587SSamuel Ortiz u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 20830cc4587SSamuel Ortiz void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); 20930cc4587SSamuel Ortiz int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); 21030cc4587SSamuel Ortiz void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, 21130cc4587SSamuel Ortiz struct sk_buff *skb, u8 direction); 21230cc4587SSamuel Ortiz 21330cc4587SSamuel Ortiz /* Sock API */ 21411aa9c28SEric W. Biederman struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp, int kern); 21530cc4587SSamuel Ortiz void nfc_llcp_sock_free(struct nfc_llcp_sock *sock); 21630cc4587SSamuel Ortiz void nfc_llcp_accept_unlink(struct sock *sk); 21730cc4587SSamuel Ortiz void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); 21830cc4587SSamuel Ortiz struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); 21930cc4587SSamuel Ortiz 22030cc4587SSamuel Ortiz /* TLV API */ 22130cc4587SSamuel Ortiz int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, 222*3df40eb3SKrzysztof Kozlowski const u8 *tlv_array, u16 tlv_array_len); 22330cc4587SSamuel Ortiz int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, 224*3df40eb3SKrzysztof Kozlowski const u8 *tlv_array, u16 tlv_array_len); 22530cc4587SSamuel Ortiz 22630cc4587SSamuel Ortiz /* Commands API */ 22730cc4587SSamuel Ortiz void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); 228*3df40eb3SKrzysztof Kozlowski u8 *nfc_llcp_build_tlv(u8 type, const u8 *value, u8 value_length, u8 *tlv_length); 22930cc4587SSamuel Ortiz struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap); 230*3df40eb3SKrzysztof Kozlowski struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, const char *uri, 23130cc4587SSamuel Ortiz size_t uri_len); 23230cc4587SSamuel Ortiz void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); 23330cc4587SSamuel Ortiz void nfc_llcp_free_sdp_tlv_list(struct hlist_head *sdp_head); 23430cc4587SSamuel Ortiz void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); 23530cc4587SSamuel Ortiz int nfc_llcp_send_symm(struct nfc_dev *dev); 23630cc4587SSamuel Ortiz int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); 23730cc4587SSamuel Ortiz int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); 23830cc4587SSamuel Ortiz int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local, 23930cc4587SSamuel Ortiz struct hlist_head *tlv_list, size_t tlvs_len); 24030cc4587SSamuel Ortiz int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local, 24130cc4587SSamuel Ortiz struct hlist_head *tlv_list, size_t tlvs_len); 24230cc4587SSamuel Ortiz int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); 24330cc4587SSamuel Ortiz int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); 24430cc4587SSamuel Ortiz int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, 24530cc4587SSamuel Ortiz struct msghdr *msg, size_t len); 24630cc4587SSamuel Ortiz int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, 24730cc4587SSamuel Ortiz struct msghdr *msg, size_t len); 24830cc4587SSamuel Ortiz int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); 24930cc4587SSamuel Ortiz 25030cc4587SSamuel Ortiz /* Socket API */ 25130cc4587SSamuel Ortiz int __init nfc_llcp_sock_init(void); 25230cc4587SSamuel Ortiz void nfc_llcp_sock_exit(void); 253