Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfc: nci: Add nci_nfcc_loopback to the nci core

For test purpose, provide the generic nci loopback function.

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Christophe Ricard and committed by
Samuel Ortiz
1c53855f 9b8d1a4c

+79
+2
include/net/nfc/nci_core.h
··· 306 306 size_t params_len, 307 307 struct core_conn_create_dest_spec_params *params); 308 308 int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id); 309 + int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, 310 + struct sk_buff **resp); 309 311 310 312 struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev); 311 313 int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
+77
net/nfc/nci/core.c
··· 400 400 } 401 401 EXPORT_SYMBOL(nci_core_init); 402 402 403 + struct nci_loopback_data { 404 + u8 conn_id; 405 + struct sk_buff *data; 406 + }; 407 + 408 + static void nci_send_data_req(struct nci_dev *ndev, unsigned long opt) 409 + { 410 + struct nci_loopback_data *data = (struct nci_loopback_data *)opt; 411 + 412 + nci_send_data(ndev, data->conn_id, data->data); 413 + } 414 + 415 + static void nci_nfcc_loopback_cb(void *context, struct sk_buff *skb, int err) 416 + { 417 + struct nci_dev *ndev = (struct nci_dev *)context; 418 + struct nci_conn_info *conn_info; 419 + 420 + conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_conn_id); 421 + if (!conn_info) { 422 + nci_req_complete(ndev, NCI_STATUS_REJECTED); 423 + return; 424 + } 425 + 426 + conn_info->rx_skb = skb; 427 + 428 + nci_req_complete(ndev, NCI_STATUS_OK); 429 + } 430 + 431 + int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, 432 + struct sk_buff **resp) 433 + { 434 + int r; 435 + struct nci_loopback_data loopback_data; 436 + struct nci_conn_info *conn_info; 437 + struct sk_buff *skb; 438 + int conn_id = nci_get_conn_info_by_dest_type_params(ndev, 439 + NCI_DESTINATION_NFCC_LOOPBACK, NULL); 440 + 441 + if (conn_id < 0) { 442 + r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCC_LOOPBACK, 443 + 0, 0, NULL); 444 + if (r != NCI_STATUS_OK) 445 + return r; 446 + 447 + conn_id = nci_get_conn_info_by_dest_type_params(ndev, 448 + NCI_DESTINATION_NFCC_LOOPBACK, 449 + NULL); 450 + } 451 + 452 + conn_info = nci_get_conn_info_by_conn_id(ndev, conn_id); 453 + if (!conn_info) 454 + return -EPROTO; 455 + 456 + /* store cb and context to be used on receiving data */ 457 + conn_info->data_exchange_cb = nci_nfcc_loopback_cb; 458 + conn_info->data_exchange_cb_context = ndev; 459 + 460 + skb = nci_skb_alloc(ndev, NCI_DATA_HDR_SIZE + data_len, GFP_KERNEL); 461 + if (!skb) 462 + return -ENOMEM; 463 + 464 + skb_reserve(skb, NCI_DATA_HDR_SIZE); 465 + memcpy(skb_put(skb, data_len), data, data_len); 466 + 467 + loopback_data.conn_id = conn_id; 468 + loopback_data.data = skb; 469 + 470 + ndev->cur_conn_id = conn_id; 471 + r = nci_request(ndev, nci_send_data_req, (unsigned long)&loopback_data, 472 + msecs_to_jiffies(NCI_DATA_TIMEOUT)); 473 + if (r == NCI_STATUS_OK && resp) 474 + *resp = conn_info->rx_skb; 475 + 476 + return r; 477 + } 478 + EXPORT_SYMBOL(nci_nfcc_loopback); 479 + 403 480 static int nci_open_device(struct nci_dev *ndev) 404 481 { 405 482 int rc = 0;