2 * Copyright (C) 2011 Intel Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #define pr_fmt(fmt) "llcp: %s: " fmt, __func__
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/nfc.h>
27 #include <net/nfc/nfc.h>
32 static u8 llcp_tlv_length
[LLCP_TLV_MAX
] = {
46 static u8
llcp_tlv8(u8
*tlv
, u8 type
)
48 if (tlv
[0] != type
|| tlv
[1] != llcp_tlv_length
[tlv
[0]])
54 static u8
llcp_tlv16(u8
*tlv
, u8 type
)
56 if (tlv
[0] != type
|| tlv
[1] != llcp_tlv_length
[tlv
[0]])
59 return be16_to_cpu(*((__be16
*)(tlv
+ 2)));
63 static u8
llcp_tlv_version(u8
*tlv
)
65 return llcp_tlv8(tlv
, LLCP_TLV_VERSION
);
68 static u16
llcp_tlv_miux(u8
*tlv
)
70 return llcp_tlv16(tlv
, LLCP_TLV_MIUX
) & 0x7f;
73 static u16
llcp_tlv_wks(u8
*tlv
)
75 return llcp_tlv16(tlv
, LLCP_TLV_WKS
);
78 static u16
llcp_tlv_lto(u8
*tlv
)
80 return llcp_tlv8(tlv
, LLCP_TLV_LTO
);
83 static u8
llcp_tlv_opt(u8
*tlv
)
85 return llcp_tlv8(tlv
, LLCP_TLV_OPT
);
88 static u8
llcp_tlv_rw(u8
*tlv
)
90 return llcp_tlv8(tlv
, LLCP_TLV_RW
) & 0xf;
93 u8
*nfc_llcp_build_tlv(u8 type
, u8
*value
, u8 value_length
, u8
*tlv_length
)
97 pr_debug("type %d\n", type
);
99 if (type
>= LLCP_TLV_MAX
)
102 length
= llcp_tlv_length
[type
];
103 if (length
== 0 && value_length
== 0)
106 length
= value_length
;
108 *tlv_length
= 2 + length
;
109 tlv
= kzalloc(2 + length
, GFP_KERNEL
);
115 memcpy(tlv
+ 2, value
, length
);
120 int nfc_llcp_parse_tlv(struct nfc_llcp_local
*local
,
121 u8
*tlv_array
, u16 tlv_array_len
)
123 u8
*tlv
= tlv_array
, type
, length
, offset
= 0;
125 pr_debug("TLV array length %d\n", tlv_array_len
);
130 while (offset
< tlv_array_len
) {
134 pr_debug("type 0x%x length %d\n", type
, length
);
137 case LLCP_TLV_VERSION
:
138 local
->remote_version
= llcp_tlv_version(tlv
);
141 local
->remote_miu
= llcp_tlv_miux(tlv
) + 128;
144 local
->remote_wks
= llcp_tlv_wks(tlv
);
147 local
->remote_lto
= llcp_tlv_lto(tlv
) * 10;
150 local
->remote_opt
= llcp_tlv_opt(tlv
);
153 local
->remote_rw
= llcp_tlv_rw(tlv
);
156 pr_err("Invalid gt tlv value 0x%x\n", type
);
160 offset
+= length
+ 2;
164 pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n",
165 local
->remote_version
, local
->remote_miu
,
166 local
->remote_lto
, local
->remote_opt
,
167 local
->remote_wks
, local
->remote_rw
);
172 static struct sk_buff
*llcp_add_header(struct sk_buff
*pdu
,
173 u8 dsap
, u8 ssap
, u8 ptype
)
177 pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype
, dsap
, ssap
);
179 header
[0] = (u8
)((dsap
<< 2) | (ptype
>> 2));
180 header
[1] = (u8
)((ptype
<< 6) | ssap
);
182 pr_debug("header 0x%x 0x%x\n", header
[0], header
[1]);
184 memcpy(skb_put(pdu
, LLCP_HEADER_SIZE
), header
, LLCP_HEADER_SIZE
);
189 static struct sk_buff
*llcp_add_tlv(struct sk_buff
*pdu
, u8
*tlv
, u8 tlv_length
)
191 /* XXX Add an skb length check */
196 memcpy(skb_put(pdu
, tlv_length
), tlv
, tlv_length
);
201 static struct sk_buff
*llcp_allocate_pdu(struct nfc_llcp_sock
*sock
,
210 skb
= nfc_alloc_send_skb(sock
->dev
, &sock
->sk
, MSG_DONTWAIT
,
211 size
+ LLCP_HEADER_SIZE
, &err
);
213 pr_err("Could not allocate PDU\n");
217 skb
= llcp_add_header(skb
, sock
->dsap
, sock
->ssap
, cmd
);
222 int nfc_llcp_disconnect(struct nfc_llcp_sock
*sock
)
226 struct nfc_llcp_local
*local
;
229 pr_debug("Sending DISC\n");
239 size
+= LLCP_HEADER_SIZE
;
240 size
+= dev
->tx_headroom
+ dev
->tx_tailroom
+ NFC_HEADER_SIZE
;
242 skb
= alloc_skb(size
, GFP_ATOMIC
);
246 skb_reserve(skb
, dev
->tx_headroom
+ NFC_HEADER_SIZE
);
248 skb
= llcp_add_header(skb
, sock
->ssap
, sock
->dsap
, LLCP_PDU_DISC
);
250 skb_queue_tail(&local
->tx_queue
, skb
);
255 int nfc_llcp_send_symm(struct nfc_dev
*dev
)
258 struct nfc_llcp_local
*local
;
261 pr_debug("Sending SYMM\n");
263 local
= nfc_llcp_find_local(dev
);
267 size
+= LLCP_HEADER_SIZE
;
268 size
+= dev
->tx_headroom
+ dev
->tx_tailroom
+ NFC_HEADER_SIZE
;
270 skb
= alloc_skb(size
, GFP_KERNEL
);
274 skb_reserve(skb
, dev
->tx_headroom
+ NFC_HEADER_SIZE
);
276 skb
= llcp_add_header(skb
, 0, 0, LLCP_PDU_SYMM
);
278 return nfc_data_exchange(dev
, local
->target_idx
, skb
,
279 nfc_llcp_recv
, local
);
282 int nfc_llcp_send_connect(struct nfc_llcp_sock
*sock
)
284 struct nfc_llcp_local
*local
;
286 u8
*service_name_tlv
= NULL
, service_name_tlv_length
;
290 pr_debug("Sending CONNECT\n");
296 if (sock
->service_name
!= NULL
) {
297 service_name_tlv
= nfc_llcp_build_tlv(LLCP_TLV_SN
,
299 sock
->service_name_len
,
300 &service_name_tlv_length
);
301 size
+= service_name_tlv_length
;
304 pr_debug("SKB size %d SN length %zu\n", size
, sock
->service_name_len
);
306 skb
= llcp_allocate_pdu(sock
, LLCP_PDU_CONNECT
, size
);
312 if (service_name_tlv
!= NULL
)
313 skb
= llcp_add_tlv(skb
, service_name_tlv
,
314 service_name_tlv_length
);
316 skb_queue_tail(&local
->tx_queue
, skb
);
321 pr_err("error %d\n", err
);
323 kfree(service_name_tlv
);
328 int nfc_llcp_send_cc(struct nfc_llcp_sock
*sock
)
330 struct nfc_llcp_local
*local
;
333 pr_debug("Sending CC\n");
339 skb
= llcp_allocate_pdu(sock
, LLCP_PDU_CC
, 0);
343 skb_queue_tail(&local
->tx_queue
, skb
);
348 int nfc_llcp_send_dm(struct nfc_llcp_local
*local
, u8 ssap
, u8 dsap
, u8 reason
)
352 u16 size
= 1; /* Reason code */
354 pr_debug("Sending DM reason 0x%x\n", reason
);
363 size
+= LLCP_HEADER_SIZE
;
364 size
+= dev
->tx_headroom
+ dev
->tx_tailroom
+ NFC_HEADER_SIZE
;
366 skb
= alloc_skb(size
, GFP_KERNEL
);
370 skb_reserve(skb
, dev
->tx_headroom
+ NFC_HEADER_SIZE
);
372 skb
= llcp_add_header(skb
, ssap
, dsap
, LLCP_PDU_DM
);
374 memcpy(skb_put(skb
, 1), &reason
, 1);
376 skb_queue_head(&local
->tx_queue
, skb
);
381 int nfc_llcp_send_disconnect(struct nfc_llcp_sock
*sock
)
384 struct nfc_llcp_local
*local
;
386 pr_debug("Send DISC\n");
392 skb
= llcp_allocate_pdu(sock
, LLCP_PDU_DISC
, 0);
396 skb_queue_head(&local
->tx_queue
, skb
);