diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-10-29 14:52:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-10-29 14:52:37 -0400 |
commit | e298c79efcf7b88fded994a03375589d8b726ce7 (patch) | |
tree | ca430a7220b7ee30c1a0aa09b5e2c1511c9d0e4c /net/nfc/llcp/commands.c | |
parent | d1f10302568221c20628200bc8baa426c55f61c0 (diff) | |
parent | 52feb444a90304eb13c03115bb9758101dbb9254 (diff) |
Merge tag 'nfc-next-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-3.0
This is the first NFC pull request for 3.8
With this one we have:
- pn544 p2p support.
- pn544 physical and HCI layers separation. We are getting the pn544 driver
ready to support non i2c physical layers.
- LLCP SNL (Service Name Lookup). This is the NFC p2p service discovery
protocol.
- LLCP datagram sockets (connection less) support.
- IDR library usage for NFC devices indexes assignement.
- NFC netlink extension for setting and getting LLCP link characteristics.
- Various code style fixes and cleanups spread over the pn533, LLCP, HCI and
pn544 code.
Diffstat (limited to 'net/nfc/llcp/commands.c')
-rw-r--r-- | net/nfc/llcp/commands.c | 120 |
1 files changed, 99 insertions, 21 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index c45ccd6c094c..ed2d17312d61 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -261,7 +261,6 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
261 | struct sk_buff *skb; | 261 | struct sk_buff *skb; |
262 | struct nfc_dev *dev; | 262 | struct nfc_dev *dev; |
263 | struct nfc_llcp_local *local; | 263 | struct nfc_llcp_local *local; |
264 | u16 size = 0; | ||
265 | 264 | ||
266 | pr_debug("Sending DISC\n"); | 265 | pr_debug("Sending DISC\n"); |
267 | 266 | ||
@@ -273,17 +272,10 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
273 | if (dev == NULL) | 272 | if (dev == NULL) |
274 | return -ENODEV; | 273 | return -ENODEV; |
275 | 274 | ||
276 | size += LLCP_HEADER_SIZE; | 275 | skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0); |
277 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
278 | |||
279 | skb = alloc_skb(size, GFP_ATOMIC); | ||
280 | if (skb == NULL) | 276 | if (skb == NULL) |
281 | return -ENOMEM; | 277 | return -ENOMEM; |
282 | 278 | ||
283 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
284 | |||
285 | skb = llcp_add_header(skb, sock->dsap, sock->ssap, LLCP_PDU_DISC); | ||
286 | |||
287 | skb_queue_tail(&local->tx_queue, skb); | 279 | skb_queue_tail(&local->tx_queue, skb); |
288 | 280 | ||
289 | return 0; | 281 | return 0; |
@@ -324,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
324 | struct sk_buff *skb; | 316 | struct sk_buff *skb; |
325 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 317 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
326 | u8 *miux_tlv = NULL, miux_tlv_length; | 318 | u8 *miux_tlv = NULL, miux_tlv_length; |
327 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 319 | u8 *rw_tlv = NULL, rw_tlv_length; |
328 | __be16 miux; | ||
329 | int err; | 320 | int err; |
330 | u16 size = 0; | 321 | u16 size = 0; |
331 | 322 | ||
@@ -343,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
343 | size += service_name_tlv_length; | 334 | size += service_name_tlv_length; |
344 | } | 335 | } |
345 | 336 | ||
346 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 337 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
347 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
348 | &miux_tlv_length); | 338 | &miux_tlv_length); |
349 | size += miux_tlv_length; | 339 | size += miux_tlv_length; |
350 | 340 | ||
351 | rw = LLCP_MAX_RW; | 341 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
352 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
353 | size += rw_tlv_length; | 342 | size += rw_tlv_length; |
354 | 343 | ||
355 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | 344 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); |
@@ -386,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
386 | struct nfc_llcp_local *local; | 375 | struct nfc_llcp_local *local; |
387 | struct sk_buff *skb; | 376 | struct sk_buff *skb; |
388 | u8 *miux_tlv = NULL, miux_tlv_length; | 377 | u8 *miux_tlv = NULL, miux_tlv_length; |
389 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 378 | u8 *rw_tlv = NULL, rw_tlv_length; |
390 | __be16 miux; | ||
391 | int err; | 379 | int err; |
392 | u16 size = 0; | 380 | u16 size = 0; |
393 | 381 | ||
@@ -397,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
397 | if (local == NULL) | 385 | if (local == NULL) |
398 | return -ENODEV; | 386 | return -ENODEV; |
399 | 387 | ||
400 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 388 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
401 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
402 | &miux_tlv_length); | 389 | &miux_tlv_length); |
403 | size += miux_tlv_length; | 390 | size += miux_tlv_length; |
404 | 391 | ||
405 | rw = LLCP_MAX_RW; | 392 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
406 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
407 | size += rw_tlv_length; | 393 | size += rw_tlv_length; |
408 | 394 | ||
409 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | 395 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); |
@@ -428,6 +414,52 @@ error_tlv: | |||
428 | return err; | 414 | return err; |
429 | } | 415 | } |
430 | 416 | ||
417 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap) | ||
418 | { | ||
419 | struct sk_buff *skb; | ||
420 | struct nfc_dev *dev; | ||
421 | u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2]; | ||
422 | u16 size = 0; | ||
423 | |||
424 | pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap); | ||
425 | |||
426 | if (local == NULL) | ||
427 | return -ENODEV; | ||
428 | |||
429 | dev = local->dev; | ||
430 | if (dev == NULL) | ||
431 | return -ENODEV; | ||
432 | |||
433 | sdres[0] = tid; | ||
434 | sdres[1] = sap; | ||
435 | sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0, | ||
436 | &sdres_tlv_length); | ||
437 | if (sdres_tlv == NULL) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | size += LLCP_HEADER_SIZE; | ||
441 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
442 | size += sdres_tlv_length; | ||
443 | |||
444 | skb = alloc_skb(size, GFP_KERNEL); | ||
445 | if (skb == NULL) { | ||
446 | kfree(sdres_tlv); | ||
447 | return -ENOMEM; | ||
448 | } | ||
449 | |||
450 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
451 | |||
452 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); | ||
453 | |||
454 | memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length); | ||
455 | |||
456 | skb_queue_tail(&local->tx_queue, skb); | ||
457 | |||
458 | kfree(sdres_tlv); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
431 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | 463 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) |
432 | { | 464 | { |
433 | struct sk_buff *skb; | 465 | struct sk_buff *skb; |
@@ -541,6 +573,52 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
541 | return len; | 573 | return len; |
542 | } | 574 | } |
543 | 575 | ||
576 | int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | ||
577 | struct msghdr *msg, size_t len) | ||
578 | { | ||
579 | struct sk_buff *pdu; | ||
580 | struct nfc_llcp_local *local; | ||
581 | size_t frag_len = 0, remaining_len; | ||
582 | u8 *msg_ptr; | ||
583 | int err; | ||
584 | |||
585 | pr_debug("Send UI frame len %zd\n", len); | ||
586 | |||
587 | local = sock->local; | ||
588 | if (local == NULL) | ||
589 | return -ENODEV; | ||
590 | |||
591 | remaining_len = len; | ||
592 | msg_ptr = (u8 *) msg->msg_iov; | ||
593 | |||
594 | while (remaining_len > 0) { | ||
595 | |||
596 | frag_len = min_t(size_t, sock->miu, remaining_len); | ||
597 | |||
598 | pr_debug("Fragment %zd bytes remaining %zd", | ||
599 | frag_len, remaining_len); | ||
600 | |||
601 | pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, | ||
602 | frag_len + LLCP_HEADER_SIZE, &err); | ||
603 | if (pdu == NULL) { | ||
604 | pr_err("Could not allocate PDU\n"); | ||
605 | continue; | ||
606 | } | ||
607 | |||
608 | pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); | ||
609 | |||
610 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); | ||
611 | |||
612 | /* No need to check for the peer RW for UI frames */ | ||
613 | skb_queue_tail(&local->tx_queue, pdu); | ||
614 | |||
615 | remaining_len -= frag_len; | ||
616 | msg_ptr += frag_len; | ||
617 | } | ||
618 | |||
619 | return len; | ||
620 | } | ||
621 | |||
544 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) | 622 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) |
545 | { | 623 | { |
546 | struct sk_buff *skb; | 624 | struct sk_buff *skb; |