linux/net/nfc/llcp_commands.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011  Intel Corporation. All rights reserved.
   3 *
   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.
   8 *
   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.
  13 *
  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.
  18 */
  19
  20#define pr_fmt(fmt) "llcp: %s: " fmt, __func__
  21
  22#include <linux/init.h>
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/nfc.h>
  26
  27#include <net/nfc/nfc.h>
  28
  29#include "nfc.h"
  30#include "llcp.h"
  31
  32static u8 llcp_tlv_length[LLCP_TLV_MAX] = {
  33        0,
  34        1, /* VERSION */
  35        2, /* MIUX */
  36        2, /* WKS */
  37        1, /* LTO */
  38        1, /* RW */
  39        0, /* SN */
  40        1, /* OPT */
  41        0, /* SDREQ */
  42        2, /* SDRES */
  43
  44};
  45
  46static u8 llcp_tlv8(u8 *tlv, u8 type)
  47{
  48        if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
  49                return 0;
  50
  51        return tlv[2];
  52}
  53
  54static u16 llcp_tlv16(u8 *tlv, u8 type)
  55{
  56        if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]])
  57                return 0;
  58
  59        return be16_to_cpu(*((__be16 *)(tlv + 2)));
  60}
  61
  62
  63static u8 llcp_tlv_version(u8 *tlv)
  64{
  65        return llcp_tlv8(tlv, LLCP_TLV_VERSION);
  66}
  67
  68static u16 llcp_tlv_miux(u8 *tlv)
  69{
  70        return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff;
  71}
  72
  73static u16 llcp_tlv_wks(u8 *tlv)
  74{
  75        return llcp_tlv16(tlv, LLCP_TLV_WKS);
  76}
  77
  78static u16 llcp_tlv_lto(u8 *tlv)
  79{
  80        return llcp_tlv8(tlv, LLCP_TLV_LTO);
  81}
  82
  83static u8 llcp_tlv_opt(u8 *tlv)
  84{
  85        return llcp_tlv8(tlv, LLCP_TLV_OPT);
  86}
  87
  88static u8 llcp_tlv_rw(u8 *tlv)
  89{
  90        return llcp_tlv8(tlv, LLCP_TLV_RW) & 0xf;
  91}
  92
  93u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length)
  94{
  95        u8 *tlv, length;
  96
  97        pr_debug("type %d\n", type);
  98
  99        if (type >= LLCP_TLV_MAX)
 100                return NULL;
 101
 102        length = llcp_tlv_length[type];
 103        if (length == 0 && value_length == 0)
 104                return NULL;
 105        else if (length == 0)
 106                length = value_length;
 107
 108        *tlv_length = 2 + length;
 109        tlv = kzalloc(2 + length, GFP_KERNEL);
 110        if (tlv == NULL)
 111                return tlv;
 112
 113        tlv[0] = type;
 114        tlv[1] = length;
 115        memcpy(tlv + 2, value, length);
 116
 117        return tlv;
 118}
 119
 120struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdres_tlv(u8 tid, u8 sap)
 121{
 122        struct nfc_llcp_sdp_tlv *sdres;
 123        u8 value[2];
 124
 125        sdres = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
 126        if (sdres == NULL)
 127                return NULL;
 128
 129        value[0] = tid;
 130        value[1] = sap;
 131
 132        sdres->tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, value, 2,
 133                                        &sdres->tlv_len);
 134        if (sdres->tlv == NULL) {
 135                kfree(sdres);
 136                return NULL;
 137        }
 138
 139        sdres->tid = tid;
 140        sdres->sap = sap;
 141
 142        INIT_HLIST_NODE(&sdres->node);
 143
 144        return sdres;
 145}
 146
 147struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
 148                                                  size_t uri_len)
 149{
 150        struct nfc_llcp_sdp_tlv *sdreq;
 151
 152        pr_debug("uri: %s, len: %zu\n", uri, uri_len);
 153
 154        sdreq = kzalloc(sizeof(struct nfc_llcp_sdp_tlv), GFP_KERNEL);
 155        if (sdreq == NULL)
 156                return NULL;
 157
 158        sdreq->tlv_len = uri_len + 3;
 159
 160        if (uri[uri_len - 1] == 0)
 161                sdreq->tlv_len--;
 162
 163        sdreq->tlv = kzalloc(sdreq->tlv_len + 1, GFP_KERNEL);
 164        if (sdreq->tlv == NULL) {
 165                kfree(sdreq);
 166                return NULL;
 167        }
 168
 169        sdreq->tlv[0] = LLCP_TLV_SDREQ;
 170        sdreq->tlv[1] = sdreq->tlv_len - 2;
 171        sdreq->tlv[2] = tid;
 172
 173        sdreq->tid = tid;
 174        sdreq->uri = sdreq->tlv + 3;
 175        memcpy(sdreq->uri, uri, uri_len);
 176
 177        sdreq->time = jiffies;
 178
 179        INIT_HLIST_NODE(&sdreq->node);
 180
 181        return sdreq;
 182}
 183
 184void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp)
 185{
 186        kfree(sdp->tlv);
 187        kfree(sdp);
 188}
 189
 190void nfc_llcp_free_sdp_tlv_list(struct hlist_head *head)
 191{
 192        struct nfc_llcp_sdp_tlv *sdp;
 193        struct hlist_node *n;
 194
 195        hlist_for_each_entry_safe(sdp, n, head, node) {
 196                hlist_del(&sdp->node);
 197
 198                nfc_llcp_free_sdp_tlv(sdp);
 199        }
 200}
 201
 202int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
 203                          u8 *tlv_array, u16 tlv_array_len)
 204{
 205        u8 *tlv = tlv_array, type, length, offset = 0;
 206
 207        pr_debug("TLV array length %d\n", tlv_array_len);
 208
 209        if (local == NULL)
 210                return -ENODEV;
 211
 212        while (offset < tlv_array_len) {
 213                type = tlv[0];
 214                length = tlv[1];
 215
 216                pr_debug("type 0x%x length %d\n", type, length);
 217
 218                switch (type) {
 219                case LLCP_TLV_VERSION:
 220                        local->remote_version = llcp_tlv_version(tlv);
 221                        break;
 222                case LLCP_TLV_MIUX:
 223                        local->remote_miu = llcp_tlv_miux(tlv) + 128;
 224                        break;
 225                case LLCP_TLV_WKS:
 226                        local->remote_wks = llcp_tlv_wks(tlv);
 227                        break;
 228                case LLCP_TLV_LTO:
 229                        local->remote_lto = llcp_tlv_lto(tlv) * 10;
 230                        break;
 231                case LLCP_TLV_OPT:
 232                        local->remote_opt = llcp_tlv_opt(tlv);
 233                        break;
 234                default:
 235                        pr_err("Invalid gt tlv value 0x%x\n", type);
 236                        break;
 237                }
 238
 239                offset += length + 2;
 240                tlv += length + 2;
 241        }
 242
 243        pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n",
 244                 local->remote_version, local->remote_miu,
 245                 local->remote_lto, local->remote_opt,
 246                 local->remote_wks);
 247
 248        return 0;
 249}
 250
 251int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
 252                                  u8 *tlv_array, u16 tlv_array_len)
 253{
 254        u8 *tlv = tlv_array, type, length, offset = 0;
 255
 256        pr_debug("TLV array length %d\n", tlv_array_len);
 257
 258        if (sock == NULL)
 259                return -ENOTCONN;
 260
 261        while (offset < tlv_array_len) {
 262                type = tlv[0];
 263                length = tlv[1];
 264
 265                pr_debug("type 0x%x length %d\n", type, length);
 266
 267                switch (type) {
 268                case LLCP_TLV_MIUX:
 269                        sock->remote_miu = llcp_tlv_miux(tlv) + 128;
 270                        break;
 271                case LLCP_TLV_RW:
 272                        sock->remote_rw = llcp_tlv_rw(tlv);
 273                        break;
 274                case LLCP_TLV_SN:
 275                        break;
 276                default:
 277                        pr_err("Invalid gt tlv value 0x%x\n", type);
 278                        break;
 279                }
 280
 281                offset += length + 2;
 282                tlv += length + 2;
 283        }
 284
 285        pr_debug("sock %p rw %d miu %d\n", sock,
 286                 sock->remote_rw, sock->remote_miu);
 287
 288        return 0;
 289}
 290
 291static struct sk_buff *llcp_add_header(struct sk_buff *pdu,
 292                                       u8 dsap, u8 ssap, u8 ptype)
 293{
 294        u8 header[2];
 295
 296        pr_debug("ptype 0x%x dsap 0x%x ssap 0x%x\n", ptype, dsap, ssap);
 297
 298        header[0] = (u8)((dsap << 2) | (ptype >> 2));
 299        header[1] = (u8)((ptype << 6) | ssap);
 300
 301        pr_debug("header 0x%x 0x%x\n", header[0], header[1]);
 302
 303        memcpy(skb_put(pdu, LLCP_HEADER_SIZE), header, LLCP_HEADER_SIZE);
 304
 305        return pdu;
 306}
 307
 308static struct sk_buff *llcp_add_tlv(struct sk_buff *pdu, u8 *tlv,
 309                                    u8 tlv_length)
 310{
 311        /* XXX Add an skb length check */
 312
 313        if (tlv == NULL)
 314                return NULL;
 315
 316        memcpy(skb_put(pdu, tlv_length), tlv, tlv_length);
 317
 318        return pdu;
 319}
 320
 321static struct sk_buff *llcp_allocate_pdu(struct nfc_llcp_sock *sock,
 322                                         u8 cmd, u16 size)
 323{
 324        struct sk_buff *skb;
 325        int err;
 326
 327        if (sock->ssap == 0)
 328                return NULL;
 329
 330        skb = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
 331                                 size + LLCP_HEADER_SIZE, &err);
 332        if (skb == NULL) {
 333                pr_err("Could not allocate PDU\n");
 334                return NULL;
 335        }
 336
 337        skb = llcp_add_header(skb, sock->dsap, sock->ssap, cmd);
 338
 339        return skb;
 340}
 341
 342int nfc_llcp_disconnect(struct nfc_llcp_sock *sock)
 343{
 344        struct sk_buff *skb;
 345        struct nfc_dev *dev;
 346        struct nfc_llcp_local *local;
 347
 348        pr_debug("Sending DISC\n");
 349
 350        local = sock->local;
 351        if (local == NULL)
 352                return -ENODEV;
 353
 354        dev = sock->dev;
 355        if (dev == NULL)
 356                return -ENODEV;
 357
 358        skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
 359        if (skb == NULL)
 360                return -ENOMEM;
 361
 362        skb_queue_tail(&local->tx_queue, skb);
 363
 364        return 0;
 365}
 366
 367int nfc_llcp_send_symm(struct nfc_dev *dev)
 368{
 369        struct sk_buff *skb;
 370        struct nfc_llcp_local *local;
 371        u16 size = 0;
 372
 373        pr_debug("Sending SYMM\n");
 374
 375        local = nfc_llcp_find_local(dev);
 376        if (local == NULL)
 377                return -ENODEV;
 378
 379        size += LLCP_HEADER_SIZE;
 380        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 381
 382        skb = alloc_skb(size, GFP_KERNEL);
 383        if (skb == NULL)
 384                return -ENOMEM;
 385
 386        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 387
 388        skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
 389
 390        __net_timestamp(skb);
 391
 392        nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX);
 393
 394        return nfc_data_exchange(dev, local->target_idx, skb,
 395                                 nfc_llcp_recv, local);
 396}
 397
 398int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
 399{
 400        struct nfc_llcp_local *local;
 401        struct sk_buff *skb;
 402        u8 *service_name_tlv = NULL, service_name_tlv_length;
 403        u8 *miux_tlv = NULL, miux_tlv_length;
 404        u8 *rw_tlv = NULL, rw_tlv_length, rw;
 405        int err;
 406        u16 size = 0, miux;
 407
 408        pr_debug("Sending CONNECT\n");
 409
 410        local = sock->local;
 411        if (local == NULL)
 412                return -ENODEV;
 413
 414        if (sock->service_name != NULL) {
 415                service_name_tlv = nfc_llcp_build_tlv(LLCP_TLV_SN,
 416                                                      sock->service_name,
 417                                                      sock->service_name_len,
 418                                                      &service_name_tlv_length);
 419                size += service_name_tlv_length;
 420        }
 421
 422        /* If the socket parameters are not set, use the local ones */
 423        miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
 424                local->miux : sock->miux;
 425        rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
 426
 427        miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 428                                      &miux_tlv_length);
 429        size += miux_tlv_length;
 430
 431        rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
 432        size += rw_tlv_length;
 433
 434        pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len);
 435
 436        skb = llcp_allocate_pdu(sock, LLCP_PDU_CONNECT, size);
 437        if (skb == NULL) {
 438                err = -ENOMEM;
 439                goto error_tlv;
 440        }
 441
 442        if (service_name_tlv != NULL)
 443                skb = llcp_add_tlv(skb, service_name_tlv,
 444                                   service_name_tlv_length);
 445
 446        skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
 447        skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 448
 449        skb_queue_tail(&local->tx_queue, skb);
 450
 451        return 0;
 452
 453error_tlv:
 454        pr_err("error %d\n", err);
 455
 456        kfree(service_name_tlv);
 457        kfree(miux_tlv);
 458        kfree(rw_tlv);
 459
 460        return err;
 461}
 462
 463int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
 464{
 465        struct nfc_llcp_local *local;
 466        struct sk_buff *skb;
 467        u8 *miux_tlv = NULL, miux_tlv_length;
 468        u8 *rw_tlv = NULL, rw_tlv_length, rw;
 469        int err;
 470        u16 size = 0, miux;
 471
 472        pr_debug("Sending CC\n");
 473
 474        local = sock->local;
 475        if (local == NULL)
 476                return -ENODEV;
 477
 478        /* If the socket parameters are not set, use the local ones */
 479        miux = be16_to_cpu(sock->miux) > LLCP_MAX_MIUX ?
 480                local->miux : sock->miux;
 481        rw = sock->rw > LLCP_MAX_RW ? local->rw : sock->rw;
 482
 483        miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0,
 484                                      &miux_tlv_length);
 485        size += miux_tlv_length;
 486
 487        rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length);
 488        size += rw_tlv_length;
 489
 490        skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size);
 491        if (skb == NULL) {
 492                err = -ENOMEM;
 493                goto error_tlv;
 494        }
 495
 496        skb = llcp_add_tlv(skb, miux_tlv, miux_tlv_length);
 497        skb = llcp_add_tlv(skb, rw_tlv, rw_tlv_length);
 498
 499        skb_queue_tail(&local->tx_queue, skb);
 500
 501        return 0;
 502
 503error_tlv:
 504        pr_err("error %d\n", err);
 505
 506        kfree(miux_tlv);
 507        kfree(rw_tlv);
 508
 509        return err;
 510}
 511
 512static struct sk_buff *nfc_llcp_allocate_snl(struct nfc_llcp_local *local,
 513                                             size_t tlv_length)
 514{
 515        struct sk_buff *skb;
 516        struct nfc_dev *dev;
 517        u16 size = 0;
 518
 519        if (local == NULL)
 520                return ERR_PTR(-ENODEV);
 521
 522        dev = local->dev;
 523        if (dev == NULL)
 524                return ERR_PTR(-ENODEV);
 525
 526        size += LLCP_HEADER_SIZE;
 527        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 528        size += tlv_length;
 529
 530        skb = alloc_skb(size, GFP_KERNEL);
 531        if (skb == NULL)
 532                return ERR_PTR(-ENOMEM);
 533
 534        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 535
 536        skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL);
 537
 538        return skb;
 539}
 540
 541int nfc_llcp_send_snl_sdres(struct nfc_llcp_local *local,
 542                            struct hlist_head *tlv_list, size_t tlvs_len)
 543{
 544        struct nfc_llcp_sdp_tlv *sdp;
 545        struct hlist_node *n;
 546        struct sk_buff *skb;
 547
 548        skb = nfc_llcp_allocate_snl(local, tlvs_len);
 549        if (IS_ERR(skb))
 550                return PTR_ERR(skb);
 551
 552        hlist_for_each_entry_safe(sdp, n, tlv_list, node) {
 553                memcpy(skb_put(skb, sdp->tlv_len), sdp->tlv, sdp->tlv_len);
 554
 555                hlist_del(&sdp->node);
 556
 557                nfc_llcp_free_sdp_tlv(sdp);
 558        }
 559
 560        skb_queue_tail(&local->tx_queue, skb);
 561
 562        return 0;
 563}
 564
 565int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
 566                            struct hlist_head *tlv_list, size_t tlvs_len)
 567{
 568        struct nfc_llcp_sdp_tlv *sdreq;
 569        struct hlist_node *n;
 570        struct sk_buff *skb;
 571
 572        skb = nfc_llcp_allocate_snl(local, tlvs_len);
 573        if (IS_ERR(skb))
 574                return PTR_ERR(skb);
 575
 576        mutex_lock(&local->sdreq_lock);
 577
 578        if (hlist_empty(&local->pending_sdreqs))
 579                mod_timer(&local->sdreq_timer,
 580                          jiffies + msecs_to_jiffies(3 * local->remote_lto));
 581
 582        hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
 583                pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri);
 584
 585                memcpy(skb_put(skb, sdreq->tlv_len), sdreq->tlv,
 586                       sdreq->tlv_len);
 587
 588                hlist_del(&sdreq->node);
 589
 590                hlist_add_head(&sdreq->node, &local->pending_sdreqs);
 591        }
 592
 593        mutex_unlock(&local->sdreq_lock);
 594
 595        skb_queue_tail(&local->tx_queue, skb);
 596
 597        return 0;
 598}
 599
 600int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason)
 601{
 602        struct sk_buff *skb;
 603        struct nfc_dev *dev;
 604        u16 size = 1; /* Reason code */
 605
 606        pr_debug("Sending DM reason 0x%x\n", reason);
 607
 608        if (local == NULL)
 609                return -ENODEV;
 610
 611        dev = local->dev;
 612        if (dev == NULL)
 613                return -ENODEV;
 614
 615        size += LLCP_HEADER_SIZE;
 616        size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
 617
 618        skb = alloc_skb(size, GFP_KERNEL);
 619        if (skb == NULL)
 620                return -ENOMEM;
 621
 622        skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
 623
 624        skb = llcp_add_header(skb, dsap, ssap, LLCP_PDU_DM);
 625
 626        memcpy(skb_put(skb, 1), &reason, 1);
 627
 628        skb_queue_head(&local->tx_queue, skb);
 629
 630        return 0;
 631}
 632
 633int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock)
 634{
 635        struct sk_buff *skb;
 636        struct nfc_llcp_local *local;
 637
 638        pr_debug("Send DISC\n");
 639
 640        local = sock->local;
 641        if (local == NULL)
 642                return -ENODEV;
 643
 644        skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0);
 645        if (skb == NULL)
 646                return -ENOMEM;
 647
 648        skb_queue_head(&local->tx_queue, skb);
 649
 650        return 0;
 651}
 652
 653int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock,
 654                          struct msghdr *msg, size_t len)
 655{
 656        struct sk_buff *pdu;
 657        struct sock *sk = &sock->sk;
 658        struct nfc_llcp_local *local;
 659        size_t frag_len = 0, remaining_len;
 660        u8 *msg_data, *msg_ptr;
 661        u16 remote_miu;
 662
 663        pr_debug("Send I frame len %zd\n", len);
 664
 665        local = sock->local;
 666        if (local == NULL)
 667                return -ENODEV;
 668
 669        /* Remote is ready but has not acknowledged our frames */
 670        if((sock->remote_ready &&
 671            skb_queue_len(&sock->tx_pending_queue) >= sock->remote_rw &&
 672            skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) {
 673                pr_err("Pending queue is full %d frames\n",
 674                       skb_queue_len(&sock->tx_pending_queue));
 675                return -ENOBUFS;
 676        }
 677
 678        /* Remote is not ready and we've been queueing enough frames */
 679        if ((!sock->remote_ready &&
 680             skb_queue_len(&sock->tx_queue) >= 2 * sock->remote_rw)) {
 681                pr_err("Tx queue is full %d frames\n",
 682                       skb_queue_len(&sock->tx_queue));
 683                return -ENOBUFS;
 684        }
 685
 686        msg_data = kzalloc(len, GFP_KERNEL);
 687        if (msg_data == NULL)
 688                return -ENOMEM;
 689
 690        if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 691                kfree(msg_data);
 692                return -EFAULT;
 693        }
 694
 695        remaining_len = len;
 696        msg_ptr = msg_data;
 697
 698        do {
 699                remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
 700                                local->remote_miu : sock->remote_miu;
 701
 702                frag_len = min_t(size_t, remote_miu, remaining_len);
 703
 704                pr_debug("Fragment %zd bytes remaining %zd",
 705                         frag_len, remaining_len);
 706
 707                pdu = llcp_allocate_pdu(sock, LLCP_PDU_I,
 708                                        frag_len + LLCP_SEQUENCE_SIZE);
 709                if (pdu == NULL)
 710                        return -ENOMEM;
 711
 712                skb_put(pdu, LLCP_SEQUENCE_SIZE);
 713
 714                if (likely(frag_len > 0))
 715                        memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
 716
 717                skb_queue_tail(&sock->tx_queue, pdu);
 718
 719                lock_sock(sk);
 720
 721                nfc_llcp_queue_i_frames(sock);
 722
 723                release_sock(sk);
 724
 725                remaining_len -= frag_len;
 726                msg_ptr += frag_len;
 727        } while (remaining_len > 0);
 728
 729        kfree(msg_data);
 730
 731        return len;
 732}
 733
 734int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap,
 735                           struct msghdr *msg, size_t len)
 736{
 737        struct sk_buff *pdu;
 738        struct nfc_llcp_local *local;
 739        size_t frag_len = 0, remaining_len;
 740        u8 *msg_ptr, *msg_data;
 741        u16 remote_miu;
 742        int err;
 743
 744        pr_debug("Send UI frame len %zd\n", len);
 745
 746        local = sock->local;
 747        if (local == NULL)
 748                return -ENODEV;
 749
 750        msg_data = kzalloc(len, GFP_KERNEL);
 751        if (msg_data == NULL)
 752                return -ENOMEM;
 753
 754        if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
 755                kfree(msg_data);
 756                return -EFAULT;
 757        }
 758
 759        remaining_len = len;
 760        msg_ptr = msg_data;
 761
 762        do {
 763                remote_miu = sock->remote_miu > LLCP_MAX_MIU ?
 764                                local->remote_miu : sock->remote_miu;
 765
 766                frag_len = min_t(size_t, remote_miu, remaining_len);
 767
 768                pr_debug("Fragment %zd bytes remaining %zd",
 769                         frag_len, remaining_len);
 770
 771                pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT,
 772                                         frag_len + LLCP_HEADER_SIZE, &err);
 773                if (pdu == NULL) {
 774                        pr_err("Could not allocate PDU\n");
 775                        continue;
 776                }
 777
 778                pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI);
 779
 780                if (likely(frag_len > 0))
 781                        memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len);
 782
 783                /* No need to check for the peer RW for UI frames */
 784                skb_queue_tail(&local->tx_queue, pdu);
 785
 786                remaining_len -= frag_len;
 787                msg_ptr += frag_len;
 788        } while (remaining_len > 0);
 789
 790        kfree(msg_data);
 791
 792        return len;
 793}
 794
 795int nfc_llcp_send_rr(struct nfc_llcp_sock *sock)
 796{
 797        struct sk_buff *skb;
 798        struct nfc_llcp_local *local;
 799
 800        pr_debug("Send rr nr %d\n", sock->recv_n);
 801
 802        local = sock->local;
 803        if (local == NULL)
 804                return -ENODEV;
 805
 806        skb = llcp_allocate_pdu(sock, LLCP_PDU_RR, LLCP_SEQUENCE_SIZE);
 807        if (skb == NULL)
 808                return -ENOMEM;
 809
 810        skb_put(skb, LLCP_SEQUENCE_SIZE);
 811
 812        skb->data[2] = sock->recv_n;
 813
 814        skb_queue_head(&local->tx_queue, skb);
 815
 816        return 0;
 817}
 818
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.