aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-10-04 19:21:47 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-10-26 12:26:47 -0400
commit19cfe5843e86cc95542d9d875c9386e197956d75 (patch)
treed62047673a68ba9c4dceb1751f08f5ec42e94f03 /net/nfc
parentc43bb03d5a7df53684cfb2a1fed5ea20014c7056 (diff)
NFC: Initial SNL support
SNL (Service Name Lookup) allows for LLCP peers to map service names with SAPs. This is mandatory for connection less support as peers need to get the right SAPs without sending the CONNECT frame. Here we only support the Rx part of SNL. The Tx one will be implemented when supporting connection less LLCP sockets. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/llcp/llcp.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 71cc8af097a4..786cf745e87b 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -1043,6 +1043,66 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb)
1043 return; 1043 return;
1044} 1044}
1045 1045
1046static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
1047 struct sk_buff *skb)
1048{
1049 struct nfc_llcp_sock *llcp_sock;
1050 u8 dsap, ssap, *tlv, type, length, tid, sap;
1051 u16 tlv_len, offset;
1052 char *service_name;
1053 size_t service_name_len;
1054
1055 dsap = nfc_llcp_dsap(skb);
1056 ssap = nfc_llcp_ssap(skb);
1057
1058 pr_debug("%d %d\n", dsap, ssap);
1059
1060 if (dsap != LLCP_SAP_SDP || ssap != LLCP_SAP_SDP) {
1061 pr_err("Wrong SNL SAP\n");
1062 return;
1063 }
1064
1065 tlv = &skb->data[LLCP_HEADER_SIZE];
1066 tlv_len = skb->len - LLCP_HEADER_SIZE;
1067 offset = 0;
1068
1069 while(offset < tlv_len) {
1070 type = tlv[0];
1071 length = tlv[1];
1072
1073 switch (type) {
1074 case LLCP_TLV_SDREQ:
1075 tid = tlv[2];
1076 service_name = (char *) &tlv[3];
1077 service_name_len = length - 1;
1078
1079 pr_debug("Looking for %s\n", service_name);
1080
1081 if (service_name_len == strlen("urn:nfc:sn:sdp") &&
1082 !strncmp(service_name, "urn:nfc:sn:sdp",
1083 service_name_len)) {
1084 sap = 1;
1085 } else {
1086 llcp_sock =
1087 nfc_llcp_sock_from_sn(local,
1088 service_name,
1089 service_name_len);
1090 sap = llcp_sock ? llcp_sock->ssap : 0;
1091 }
1092
1093 nfc_llcp_send_snl(local, tid, sap);
1094 break;
1095
1096 default:
1097 pr_err("Invalid SNL tlv value 0x%x\n", type);
1098 break;
1099 }
1100
1101 offset += length + 2;
1102 tlv += length + 2;
1103 }
1104}
1105
1046static void nfc_llcp_rx_work(struct work_struct *work) 1106static void nfc_llcp_rx_work(struct work_struct *work)
1047{ 1107{
1048 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 1108 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -1093,6 +1153,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1093 nfc_llcp_recv_dm(local, skb); 1153 nfc_llcp_recv_dm(local, skb);
1094 break; 1154 break;
1095 1155
1156 case LLCP_PDU_SNL:
1157 pr_debug("SNL\n");
1158 nfc_llcp_recv_snl(local, skb);
1159 break;
1160
1096 case LLCP_PDU_I: 1161 case LLCP_PDU_I:
1097 case LLCP_PDU_RR: 1162 case LLCP_PDU_RR:
1098 case LLCP_PDU_RNR: 1163 case LLCP_PDU_RNR: