cregit-Linux how code gets into the kernel

Release 4.11 net/nfc/nci/core.c

Directory: net/nfc/nci
/*
 *  The NFC Controller Interface is the communication protocol between an
 *  NFC Controller (NFCC) and a Device Host (DH).
 *
 *  Copyright (C) 2011 Texas Instruments, Inc.
 *  Copyright (C) 2014 Marvell International Ltd.
 *
 *  Written by Ilan Elias <ilane@ti.com>
 *
 *  Acknowledgements:
 *  This file is based on hci_core.c, which was written
 *  by Maxim Krasnyansky.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2
 *  as published by the Free Software Foundation
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": %s: " fmt, __func__

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include <linux/export.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/skbuff.h>

#include "../nfc.h"
#include <net/nfc/nci.h>
#include <net/nfc/nci_core.h>
#include <linux/nfc.h>


struct core_conn_create_data {
	
int length;
	
struct nci_core_conn_create_cmd *cmd;
};

static void nci_cmd_work(struct work_struct *work);
static void nci_rx_work(struct work_struct *work);
static void nci_tx_work(struct work_struct *work);


struct nci_conn_info *nci_get_conn_info_by_conn_id(struct nci_dev *ndev, int conn_id) { struct nci_conn_info *conn_info; list_for_each_entry(conn_info, &ndev->conn_info_list, list) { if (conn_info->conn_id == conn_id) return conn_info; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard44100.00%1100.00%
Total44100.00%1100.00%


int nci_get_conn_info_by_dest_type_params(struct nci_dev *ndev, u8 dest_type, struct dest_spec_params *params) { struct nci_conn_info *conn_info; list_for_each_entry(conn_info, &ndev->conn_info_list, list) { if (conn_info->dest_type == dest_type) { if (!params) return conn_info->conn_id; if (conn_info) { if (params->id == conn_info->dest_params->id && params->protocol == conn_info->dest_params->protocol) return conn_info->conn_id; } } } return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard4752.22%150.00%
Robert Dolca4347.78%150.00%
Total90100.00%2100.00%

EXPORT_SYMBOL(nci_get_conn_info_by_dest_type_params); /* ---- NCI requests ---- */
void nci_req_complete(struct nci_dev *ndev, int result) { if (ndev->req_status == NCI_REQ_PEND) { ndev->req_result = result; ndev->req_status = NCI_REQ_DONE; complete(&ndev->req_completion); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias43100.00%1100.00%
Total43100.00%1100.00%

EXPORT_SYMBOL(nci_req_complete);
static void nci_req_cancel(struct nci_dev *ndev, int err) { if (ndev->req_status == NCI_REQ_PEND) { ndev->req_result = err; ndev->req_status = NCI_REQ_CANCELED; complete(&ndev->req_completion); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias44100.00%1100.00%
Total44100.00%1100.00%

/* Execute request and wait for completion. */
static int __nci_request(struct nci_dev *ndev, void (*req)(struct nci_dev *ndev, unsigned long opt), unsigned long opt, __u32 timeout) { int rc = 0; long completion_rc; ndev->req_status = NCI_REQ_PEND; reinit_completion(&ndev->req_completion); req(ndev, opt); completion_rc = wait_for_completion_interruptible_timeout(&ndev->req_completion, timeout); pr_debug("wait_for_completion return %ld\n", completion_rc); if (completion_rc > 0) { switch (ndev->req_status) { case NCI_REQ_DONE: rc = nci_to_errno(ndev->req_result); break; case NCI_REQ_CANCELED: rc = -ndev->req_result; break; default: rc = -ETIMEDOUT; break; } } else { pr_err("wait_for_completion_interruptible_timeout failed %ld\n", completion_rc); rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc)); } ndev->req_status = ndev->req_result = 0; return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias16697.08%125.00%
Joe Perches42.34%250.00%
Axel Lin10.58%125.00%
Total171100.00%4100.00%


inline int nci_request(struct nci_dev *ndev, void (*req)(struct nci_dev *ndev, unsigned long opt), unsigned long opt, __u32 timeout) { int rc; if (!test_bit(NCI_UP, &ndev->flags)) return -ENETDOWN; /* Serialize all requests */ mutex_lock(&ndev->req_lock); rc = __nci_request(ndev, req, opt, timeout); mutex_unlock(&ndev->req_lock); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias87100.00%1100.00%
Total87100.00%1100.00%


static void nci_reset_req(struct nci_dev *ndev, unsigned long opt) { struct nci_core_reset_cmd cmd; cmd.reset_type = NCI_RESET_TYPE_RESET_CONFIG; nci_send_cmd(ndev, NCI_OP_CORE_RESET_CMD, 1, &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias37100.00%2100.00%
Total37100.00%2100.00%


static void nci_init_req(struct nci_dev *ndev, unsigned long opt) { nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias26100.00%1100.00%
Total26100.00%1100.00%


static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) { struct nci_rf_disc_map_cmd cmd; struct disc_map_config *cfg = cmd.mapping_configs; __u8 *num = &cmd.num_mapping_configs; int i; /* set rf mapping configurations */ *num = 0; /* by default mapping is set to NCI_RF_INTERFACE_FRAME */ for (i = 0; i < ndev->num_supported_rf_interfaces; i++) { if (ndev->supported_rf_interfaces[i] == NCI_RF_INTERFACE_ISO_DEP) { cfg[*num].rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | NCI_DISC_MAP_MODE_LISTEN; cfg[*num].rf_interface = NCI_RF_INTERFACE_ISO_DEP; (*num)++; } else if (ndev->supported_rf_interfaces[i] == NCI_RF_INTERFACE_NFC_DEP) { cfg[*num].rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; cfg[*num].mode = NCI_DISC_MAP_MODE_POLL | NCI_DISC_MAP_MODE_LISTEN; cfg[*num].rf_interface = NCI_RF_INTERFACE_NFC_DEP; (*num)++; } if (*num == NCI_MAX_NUM_MAPPING_CONFIGS) break; } nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_MAP_CMD, (1 + ((*num) * sizeof(struct disc_map_config))), &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias202100.00%3100.00%
Total202100.00%3100.00%

struct nci_set_config_param { __u8 id; size_t len; __u8 *val; };
static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt) { struct nci_set_config_param *param = (struct nci_set_config_param *)opt; struct nci_core_set_config_cmd cmd; BUG_ON(param->len > NCI_MAX_PARAM_LEN); cmd.num_params = 1; cmd.param.id = param->id; cmd.param.len = param->len; memcpy(cmd.param.val, param->val, param->len); nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias101100.00%1100.00%
Total101100.00%1100.00%

struct nci_rf_discover_param { __u32 im_protocols; __u32 tm_protocols; };
static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) { struct nci_rf_discover_param *param = (struct nci_rf_discover_param *)opt; struct nci_rf_disc_cmd cmd; cmd.num_disc_configs = 0; if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && (param->im_protocols & NFC_PROTO_JEWEL_MASK || param->im_protocols & NFC_PROTO_MIFARE_MASK || param->im_protocols & NFC_PROTO_ISO14443_MASK || param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_A_PASSIVE_POLL_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; } if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && (param->im_protocols & NFC_PROTO_ISO14443_B_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_B_PASSIVE_POLL_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; } if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && (param->im_protocols & NFC_PROTO_FELICA_MASK || param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_F_PASSIVE_POLL_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; } if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && (param->im_protocols & NFC_PROTO_ISO15693_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_V_PASSIVE_POLL_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; } if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS - 1) && (param->tm_protocols & NFC_PROTO_NFC_DEP_MASK)) { cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_A_PASSIVE_LISTEN_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = NCI_NFC_F_PASSIVE_LISTEN_MODE; cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.num_disc_configs++; } nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD, (1 + (cmd.num_disc_configs * sizeof(struct disc_config))), &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias20654.93%240.00%
Julien Lefrique12032.00%120.00%
Vincent Cuissard4812.80%120.00%
Samuel Ortiz10.27%120.00%
Total375100.00%5100.00%

struct nci_rf_discover_select_param { __u8 rf_discovery_id; __u8 rf_protocol; };
static void nci_rf_discover_select_req(struct nci_dev *ndev, unsigned long opt) { struct nci_rf_discover_select_param *param = (struct nci_rf_discover_select_param *)opt; struct nci_rf_discover_select_cmd cmd; cmd.rf_discovery_id = param->rf_discovery_id; cmd.rf_protocol = param->rf_protocol; switch (cmd.rf_protocol) { case NCI_RF_PROTOCOL_ISO_DEP: cmd.rf_interface = NCI_RF_INTERFACE_ISO_DEP; break; case NCI_RF_PROTOCOL_NFC_DEP: cmd.rf_interface = NCI_RF_INTERFACE_NFC_DEP; break; default: cmd.rf_interface = NCI_RF_INTERFACE_FRAME; break; } nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_SELECT_CMD, sizeof(struct nci_rf_discover_select_cmd), &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias99100.00%1100.00%
Total99100.00%1100.00%


static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) { struct nci_rf_deactivate_cmd cmd; cmd.type = opt; nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, sizeof(struct nci_rf_deactivate_cmd), &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias4097.56%150.00%
Christophe Ricard12.44%150.00%
Total41100.00%2100.00%

struct nci_cmd_param { __u16 opcode; size_t len; __u8 *payload; };
static void nci_generic_req(struct nci_dev *ndev, unsigned long opt) { struct nci_cmd_param *param = (struct nci_cmd_param *)opt; nci_send_cmd(ndev, param->opcode, param->len, param->payload); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard4193.18%150.00%
Robert Dolca36.82%150.00%
Total44100.00%2100.00%


int nci_prop_cmd(struct nci_dev *ndev, __u8 oid, size_t len, __u8 *payload) { struct nci_cmd_param param; param.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY, oid); param.len = len; param.payload = payload; return __nci_request(ndev, nci_generic_req, (unsigned long)&param, msecs_to_jiffies(NCI_CMD_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard6597.01%150.00%
Robert Dolca22.99%150.00%
Total67100.00%2100.00%

EXPORT_SYMBOL(nci_prop_cmd);
int nci_core_cmd(struct nci_dev *ndev, __u16 opcode, size_t len, __u8 *payload) { struct nci_cmd_param param; param.opcode = opcode; param.len = len; param.payload = payload; return __nci_request(ndev, nci_generic_req, (unsigned long)&param, msecs_to_jiffies(NCI_CMD_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca62100.00%1100.00%
Total62100.00%1100.00%

EXPORT_SYMBOL(nci_core_cmd);
int nci_core_reset(struct nci_dev *ndev) { return __nci_request(ndev, nci_reset_req, 0, msecs_to_jiffies(NCI_RESET_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Baldyga25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL(nci_core_reset);
int nci_core_init(struct nci_dev *ndev) { return __nci_request(ndev, nci_init_req, 0, msecs_to_jiffies(NCI_INIT_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Baldyga25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL(nci_core_init); struct nci_loopback_data { u8 conn_id; struct sk_buff *data; };
static void nci_send_data_req(struct nci_dev *ndev, unsigned long opt) { struct nci_loopback_data *data = (struct nci_loopback_data *)opt; nci_send_data(ndev, data->conn_id, data->data); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard40100.00%1100.00%
Total40100.00%1100.00%


static void nci_nfcc_loopback_cb(void *context, struct sk_buff *skb, int err) { struct nci_dev *ndev = (struct nci_dev *)context; struct nci_conn_info *conn_info; conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_conn_id); if (!conn_info) { nci_req_complete(ndev, NCI_STATUS_REJECTED); return; } conn_info->rx_skb = skb; nci_req_complete(ndev, NCI_STATUS_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard74100.00%1100.00%
Total74100.00%1100.00%


int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len, struct sk_buff **resp) { int r; struct nci_loopback_data loopback_data; struct nci_conn_info *conn_info; struct sk_buff *skb; int conn_id = nci_get_conn_info_by_dest_type_params(ndev, NCI_DESTINATION_NFCC_LOOPBACK, NULL); if (conn_id < 0) { r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCC_LOOPBACK, 0, 0, NULL); if (r != NCI_STATUS_OK) return r; conn_id = nci_get_conn_info_by_dest_type_params(ndev, NCI_DESTINATION_NFCC_LOOPBACK, NULL); } conn_info = nci_get_conn_info_by_conn_id(ndev, conn_id); if (!conn_info) return -EPROTO; /* store cb and context to be used on receiving data */ conn_info->data_exchange_cb = nci_nfcc_loopback_cb; conn_info->data_exchange_cb_context = ndev; skb = nci_skb_alloc(ndev, NCI_DATA_HDR_SIZE + data_len, GFP_KERNEL); if (!skb) return -ENOMEM; skb_reserve(skb, NCI_DATA_HDR_SIZE); memcpy(skb_put(skb, data_len), data, data_len); loopback_data.conn_id = conn_id; loopback_data.data = skb; ndev->cur_conn_id = conn_id; r = nci_request(ndev, nci_send_data_req, (unsigned long)&loopback_data, msecs_to_jiffies(NCI_DATA_TIMEOUT)); if (r == NCI_STATUS_OK && resp) *resp = conn_info->rx_skb; return r; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard226100.00%1100.00%
Total226100.00%1100.00%

EXPORT_SYMBOL(nci_nfcc_loopback);
static int nci_open_device(struct nci_dev *ndev) { int rc = 0; mutex_lock(&ndev->req_lock); if (test_bit(NCI_UP, &ndev->flags)) { rc = -EALREADY; goto done; } if (ndev->ops->open(ndev)) { rc = -EIO; goto done; } atomic_set(&ndev->cmd_cnt, 1); set_bit(NCI_INIT, &ndev->flags); if (ndev->ops->init) rc = ndev->ops->init(ndev); if (!rc) { rc = __nci_request(ndev, nci_reset_req, 0, msecs_to_jiffies(NCI_RESET_TIMEOUT)); } if (!rc && ndev->ops->setup) { rc = ndev->ops->setup(ndev); } if (!rc) { rc = __nci_request(ndev, nci_init_req, 0, msecs_to_jiffies(NCI_INIT_TIMEOUT)); } if (!rc && ndev->ops->post_setup) rc = ndev->ops->post_setup(ndev); if (!rc) { rc = __nci_request(ndev, nci_init_complete_req, 0, msecs_to_jiffies(NCI_INIT_TIMEOUT)); } clear_bit(NCI_INIT, &ndev->flags); if (!rc) { set_bit(NCI_UP, &ndev->flags); nci_clear_target_list(ndev); atomic_set(&ndev->state, NCI_IDLE); } else { /* Init failed, cleanup */ skb_queue_purge(&ndev->cmd_q); skb_queue_purge(&ndev->rx_q); skb_queue_purge(&ndev->tx_q); ndev->ops->close(ndev); ndev->flags = 0; } done: mutex_unlock(&ndev->req_lock); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias24777.43%337.50%
Christophe Ricard3310.34%225.00%
Robert Baldyga195.96%112.50%
Amitkumar Karwar175.33%112.50%
Robert Dolca30.94%112.50%
Total319100.00%8100.00%


static int nci_close_device(struct nci_dev *ndev) { nci_req_cancel(ndev, ENODEV); mutex_lock(&ndev->req_lock); if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { del_timer_sync(&ndev->cmd_timer); del_timer_sync(&ndev->data_timer); mutex_unlock(&ndev->req_lock); return 0; } /* Drop RX and TX queues */ skb_queue_purge(&ndev->rx_q); skb_queue_purge(&ndev->tx_q); /* Flush RX and TX wq */ flush_workqueue(ndev->rx_wq); flush_workqueue(ndev->tx_wq); /* Reset device */ skb_queue_purge(&ndev->cmd_q); atomic_set(&ndev->cmd_cnt, 1); set_bit(NCI_INIT, &ndev->flags); __nci_request(ndev, nci_reset_req, 0, msecs_to_jiffies(NCI_RESET_TIMEOUT)); /* After this point our queues are empty * and no works are scheduled. */ ndev->ops->close(ndev); clear_bit(NCI_INIT, &ndev->flags); del_timer_sync(&ndev->cmd_timer); /* Flush cmd wq */ flush_workqueue(ndev->cmd_wq); /* Clear flags */ ndev->flags = 0; mutex_unlock(&ndev->req_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias17990.86%250.00%
Christophe Ricard105.08%125.00%
Amitkumar Karwar84.06%125.00%
Total197100.00%4100.00%

/* NCI command timer function */
static void nci_cmd_timer(unsigned long arg) { struct nci_dev *ndev = (void *) arg; atomic_set(&ndev->cmd_cnt, 1); queue_work(ndev->cmd_wq, &ndev->cmd_work); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias43100.00%1100.00%
Total43100.00%1100.00%

/* NCI data exchange timer function */
static void nci_data_timer(unsigned long arg) { struct nci_dev *ndev = (void *) arg; set_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); queue_work(ndev->rx_wq, &ndev->rx_work); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias43100.00%1100.00%
Total43100.00%1100.00%


static int nci_dev_up(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); return nci_open_device(ndev); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias27100.00%1100.00%
Total27100.00%1100.00%


static int nci_dev_down(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); return nci_close_device(ndev); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias27100.00%1100.00%
Total27100.00%1100.00%


int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val) { struct nci_set_config_param param; if (!val || !len) return 0; param.id = id; param.len = len; param.val = val; return __nci_request(ndev, nci_set_config_req, (unsigned long)&param, msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Amitkumar Karwar73100.00%1100.00%
Total73100.00%1100.00%

EXPORT_SYMBOL(nci_set_config);
static void nci_nfcee_discover_req(struct nci_dev *ndev, unsigned long opt) { struct nci_nfcee_discover_cmd cmd; __u8 action = opt; cmd.discovery_action = action; nci_send_cmd(ndev, NCI_OP_NFCEE_DISCOVER_CMD, 1, &cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard42100.00%1100.00%
Total42100.00%1100.00%


int nci_nfcee_discover(struct nci_dev *ndev, u8 action) { return __nci_request(ndev, nci_nfcee_discover_req, action, msecs_to_jiffies(NCI_CMD_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard2796.43%150.00%
Samuel Ortiz13.57%150.00%
Total28100.00%2100.00%

EXPORT_SYMBOL(nci_nfcee_discover);
static void nci_nfcee_mode_set_req(struct nci_dev *ndev, unsigned long opt) { struct nci_nfcee_mode_set_cmd *cmd = (struct nci_nfcee_mode_set_cmd *)opt; nci_send_cmd(ndev, NCI_OP_NFCEE_MODE_SET_CMD, sizeof(struct nci_nfcee_mode_set_cmd), cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard42100.00%1100.00%
Total42100.00%1100.00%


int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode) { struct nci_nfcee_mode_set_cmd cmd; cmd.nfcee_id = nfcee_id; cmd.nfcee_mode = nfcee_mode; return __nci_request(ndev, nci_nfcee_mode_set_req, (unsigned long)&cmd, msecs_to_jiffies(NCI_CMD_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard5198.08%150.00%
Samuel Ortiz11.92%150.00%
Total52100.00%2100.00%

EXPORT_SYMBOL(nci_nfcee_mode_set);
static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt) { struct core_conn_create_data *data = (struct core_conn_create_data *)opt; nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, data->length, data->cmd); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard42100.00%2100.00%
Total42100.00%2100.00%


int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, u8 number_destination_params, size_t params_len, struct core_conn_create_dest_spec_params *params) { int r; struct nci_core_conn_create_cmd *cmd; struct core_conn_create_data data; data.length = params_len + sizeof(struct nci_core_conn_create_cmd); cmd = kzalloc(data.length, GFP_KERNEL); if (!cmd) return -ENOMEM; cmd->destination_type = destination_type; cmd->number_destination_params = number_destination_params; data.cmd = cmd; if (params) { memcpy(cmd->params, params, params_len); if (params->length > 0) memcpy(&ndev->cur_params, &params->value[DEST_SPEC_PARAMS_ID_INDEX], sizeof(struct dest_spec_params)); else ndev->cur_params.id = 0; } else { ndev->cur_params.id = 0; } ndev->cur_dest_type = destination_type; r = __nci_request(ndev, nci_core_conn_create_req, (unsigned long)&data, msecs_to_jiffies(NCI_CMD_TIMEOUT)); kfree(cmd); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard17492.55%480.00%
Robert Dolca147.45%120.00%
Total188100.00%5100.00%

EXPORT_SYMBOL(nci_core_conn_create);
static void nci_core_conn_close_req(struct nci_dev *ndev, unsigned long opt) { __u8 conn_id = opt; nci_send_cmd(ndev, NCI_OP_CORE_CONN_CLOSE_CMD, 1, &conn_id); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard32100.00%1100.00%
Total32100.00%1100.00%


int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id) { ndev->cur_conn_id = conn_id; return __nci_request(ndev, nci_core_conn_close_req, conn_id, msecs_to_jiffies(NCI_CMD_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard3397.06%266.67%
Samuel Ortiz12.94%133.33%
Total34100.00%3100.00%

EXPORT_SYMBOL(nci_core_conn_close);
static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_set_config_param param; int rc; param.val = nfc_get_local_general_bytes(nfc_dev, &param.len); if ((param.val == NULL) || (param.len == 0)) return 0; if (param.len > NFC_MAX_GT_LEN) return -EINVAL; param.id = NCI_PN_ATR_REQ_GEN_BYTES; rc = nci_request(ndev, nci_set_config_req, (unsigned long)&param, msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); if (rc) return rc; param.id = NCI_LN_ATR_RES_GEN_BYTES; return nci_request(ndev, nci_set_config_req, (unsigned long)&param, msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias9570.37%125.00%
Julien Lefrique3727.41%125.00%
Szymon Janc32.22%250.00%
Total135100.00%4100.00%


static int nci_set_listen_parameters(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; __u8 val; val = NCI_LA_SEL_INFO_NFC_DEP_MASK; rc = nci_set_config(ndev, NCI_LA_SEL_INFO, 1, &val); if (rc) return rc; val = NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK; rc = nci_set_config(ndev, NCI_LF_PROTOCOL_TYPE, 1, &val); if (rc) return rc; val = NCI_LF_CON_BITR_F_212 | NCI_LF_CON_BITR_F_424; return nci_set_config(ndev, NCI_LF_CON_BITR_F, 1, &val); }

Contributors

PersonTokensPropCommitsCommitProp
Julien Lefrique96100.00%1100.00%
Total96100.00%1100.00%


static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, __u32 tm_protocols) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_rf_discover_param param; int rc; if ((atomic_read(&ndev->state) == NCI_DISCOVERY) || (atomic_read(&ndev->state) == NCI_W4_ALL_DISCOVERIES)) { pr_err("unable to start poll, since poll is already active\n"); return -EBUSY; } if (ndev->target_active_prot) { pr_err("there is an active target\n"); return -EBUSY; } if ((atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) || (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) { pr_debug("target active or w4 select, implicitly deactivate\n"); rc = nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); if (rc) return -EBUSY; } if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { rc = nci_set_local_general_bytes(nfc_dev); if (rc) { pr_err("failed to set local general bytes\n"); return rc; } } if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { rc = nci_set_listen_parameters(nfc_dev); if (rc) pr_err("failed to set listen parameters\n"); } param.im_protocols = im_protocols; param.tm_protocols = tm_protocols; rc = nci_request(ndev, nci_rf_discover_req, (unsigned long)&param, msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); if (!rc) ndev->poll_prots = im_protocols; return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias18875.50%541.67%
Julien Lefrique5020.08%325.00%
Samuel Ortiz52.01%18.33%
Joe Perches52.01%216.67%
Christophe Ricard10.40%18.33%
Total249100.00%12100.00%


static void nci_stop_poll(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if ((atomic_read(&ndev->state) != NCI_DISCOVERY) && (atomic_read(&ndev->state) != NCI_W4_ALL_DISCOVERIES)) { pr_err("unable to stop poll, since poll is not active\n"); return; } nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias6695.65%360.00%
Joe Perches22.90%120.00%
Christophe Ricard11.45%120.00%
Total69100.00%5100.00%


static int nci_activate_target(struct nfc_dev *nfc_dev, struct nfc_target *target, __u32 protocol) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_rf_discover_select_param param; struct nfc_target *nci_target = NULL; int i; int rc = 0; pr_debug("target_idx %d, protocol 0x%x\n", target->idx, protocol); if ((atomic_read(&ndev->state) != NCI_W4_HOST_SELECT) && (atomic_read(&ndev->state) != NCI_POLL_ACTIVE)) { pr_err("there is no available target to activate\n"); return -EINVAL; } if (ndev->target_active_prot) { pr_err("there is already an active target\n"); return -EBUSY; } for (i = 0; i < ndev->n_targets; i++) { if (ndev->targets[i].idx == target->idx) { nci_target = &ndev->targets[i]; break; } } if (!nci_target) { pr_err("unable to find the selected target\n"); return -EINVAL; } if (!(nci_target->supported_protocols & (1 << protocol))) { pr_err("target does not support the requested protocol 0x%x\n", protocol); return -EINVAL; } if (atomic_read(&ndev->state) == NCI_W4_HOST_SELECT) { param.rf_discovery_id = nci_target->logical_idx; if (protocol == NFC_PROTO_JEWEL) param.rf_protocol = NCI_RF_PROTOCOL_T1T; else if (protocol == NFC_PROTO_MIFARE) param.rf_protocol = NCI_RF_PROTOCOL_T2T; else if (protocol == NFC_PROTO_FELICA) param.rf_protocol = NCI_RF_PROTOCOL_T3T; else if (protocol == NFC_PROTO_ISO14443 || protocol == NFC_PROTO_ISO14443_B) param.rf_protocol = NCI_RF_PROTOCOL_ISO_DEP; else param.rf_protocol = NCI_RF_PROTOCOL_NFC_DEP; rc = nci_request(ndev, nci_rf_discover_select_req, (unsigned long)&param, msecs_to_jiffies(NCI_RF_DISC_SELECT_TIMEOUT)); } if (!rc) ndev->target_active_prot = protocol; return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias29290.97%330.00%
Eric Lapuyade154.67%110.00%
Joe Perches82.49%330.00%
Samuel Ortiz51.56%220.00%
Dan Carpenter10.31%110.00%
Total321100.00%10100.00%


static void nci_deactivate_target(struct nfc_dev *nfc_dev, struct nfc_target *target, __u8 mode) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); u8 nci_mode = NCI_DEACTIVATE_TYPE_IDLE_MODE; pr_debug("entry\n"); if (!ndev->target_active_prot) { pr_err("unable to deactivate target, no active target\n"); return; } ndev->target_active_prot = 0; switch (mode) { case NFC_TARGET_MODE_SLEEP: nci_mode = NCI_DEACTIVATE_TYPE_SLEEP_MODE; break; } if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) { nci_request(ndev, nci_rf_deactivate_req, nci_mode, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias7270.59%342.86%
Christophe Ricard2322.55%114.29%
Eric Lapuyade43.92%114.29%
Joe Perches32.94%228.57%
Total102100.00%7100.00%


static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, __u8 comm_mode, __u8 *gb, size_t gb_len) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; pr_debug("target_idx %d, comm_mode %d\n", target->idx, comm_mode); rc = nci_activate_target(nfc_dev, target, NFC_PROTO_NFC_DEP); if (rc) return rc; rc = nfc_set_remote_general_bytes(nfc_dev, ndev->remote_gb, ndev->remote_gb_len); if (!rc) rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_PASSIVE, NFC_RF_INITIATOR); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias106100.00%1100.00%
Total106100.00%1100.00%


static int nci_dep_link_down(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; pr_debug("entry\n"); if (nfc_dev->rf_mode == NFC_RF_INITIATOR) { nci_deactivate_target(nfc_dev, NULL, NCI_DEACTIVATE_TYPE_IDLE_MODE); } else { if (atomic_read(&ndev->state) == NCI_LISTEN_ACTIVE || atomic_read(&ndev->state) == NCI_DISCOVERY) { nci_request(ndev, nci_rf_deactivate_req, 0, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); } rc = nfc_tm_deactivated(nfc_dev); if (rc) pr_err("error when signaling tm deactivation\n"); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Julien Lefrique8074.07%133.33%
Ilan Elias2624.07%133.33%
Christophe Ricard21.85%133.33%
Total108100.00%3100.00%


static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; struct nci_conn_info *conn_info; conn_info = ndev->rf_conn_info; if (!conn_info) return -EPROTO; pr_debug("target_idx %d, len %d\n", target->idx, skb->len); if (!ndev->target_active_prot) { pr_err("unable to exchange data, no active target\n"); return -EINVAL; } if (test_and_set_bit(NCI_DATA_EXCHANGE, &ndev->flags)) return -EBUSY; /* store cb and context to be used on receiving data */ conn_info->data_exchange_cb = cb; conn_info->data_exchange_cb_context = cb_context; rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb); if (rc) clear_bit(NCI_DATA_EXCHANGE, &ndev->flags); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias11577.18%330.00%
Christophe Ricard2214.77%220.00%
Eric Lapuyade74.70%110.00%
Joe Perches42.68%330.00%
Samuel Ortiz10.67%110.00%
Total149100.00%10100.00%


static int nci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb); if (rc) pr_err("unable to send data\n"); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Julien Lefrique52100.00%1100.00%
Total52100.00%1100.00%


static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if (ndev->ops->enable_se) return ndev->ops->enable_se(ndev, se_idx); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard3063.83%150.00%
Samuel Ortiz1736.17%150.00%
Total47100.00%2100.00%


static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if (ndev->ops->disable_se) return ndev->ops->disable_se(ndev, se_idx); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard3063.83%150.00%
Samuel Ortiz1736.17%150.00%
Total47100.00%2100.00%


static int nci_discover_se(struct nfc_dev *nfc_dev) { int r; struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if (ndev->ops->discover_se) { r = nci_nfcee_discover(ndev, NCI_NFCEE_DISCOVERY_ACTION_ENABLE); if (r != NCI_STATUS_OK) return -EPROTO; return ndev->ops->discover_se(ndev); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard5278.79%266.67%
Samuel Ortiz1421.21%133.33%
Total66100.00%3100.00%


static int nci_se_io(struct nfc_dev *nfc_dev, u32 se_idx, u8 *apdu, size_t apdu_length, se_io_cb_t cb, void *cb_context) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if (ndev->ops->se_io) return ndev->ops->se_io(ndev, se_idx, apdu, apdu_length, cb, cb_context); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christophe Ricard69100.00%1100.00%
Total69100.00%1100.00%


static int nci_fw_download(struct nfc_dev *nfc_dev, const char *firmware_name) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); if (!ndev->ops->fw_download) return -ENOTSUPP; return ndev->ops->fw_download(ndev, firmware_name); }

Contributors

PersonTokensPropCommitsCommitProp
Clément Perrochaud51100.00%1100.00%
Total51100.00%1100.00%

static struct nfc_ops nci_nfc_ops = { .dev_up = nci_dev_up, .dev_down = nci_dev_down, .start_poll = nci_start_poll, .stop_poll = nci_stop_poll, .dep_link_up = nci_dep_link_up, .dep_link_down = nci_dep_link_down, .activate_target = nci_activate_target, .deactivate_target = nci_deactivate_target, .im_transceive = nci_transceive, .tm_send = nci_tm_send, .enable_se = nci_enable_se, .disable_se = nci_disable_se, .discover_se = nci_discover_se, .se_io = nci_se_io, .fw_download = nci_fw_download, }; /* ---- Interface to NCI drivers ---- */ /** * nci_allocate_device - allocate a new nci device * * @ops: device operations * @supported_protocols: NFC protocols supported by the device */
struct nci_dev *nci_allocate_device(struct nci_ops *ops, __u32 supported_protocols, int tx_headroom, int tx_tailroom) { struct nci_dev *ndev; pr_debug("supported_protocols 0x%x\n", supported_protocols); if (!ops->open || !ops->close || !ops->send) return NULL; if (!supported_protocols) return NULL; ndev = kzalloc(sizeof(struct nci_dev), GFP_KERNEL); if (!ndev) return NULL; ndev->ops = ops; if (ops->n_prop_ops > NCI_MAX_PROPRIETARY_CMD) { pr_err("Too many proprietary commands: %zd\n", ops->n_prop_ops); ops->prop_ops = NULL; ops->n_prop_ops = 0; } ndev->tx_headroom = tx_headroom; ndev->tx_tailroom = tx_tailroom; init_completion(&ndev->req_completion); ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, supported_protocols, tx_headroom + NCI_DATA_HDR_SIZE, tx_tailroom); if (!ndev->nfc_dev) goto free_nci; ndev->hci_dev = nci_hci_allocate(ndev); if (!ndev->hci_dev) goto free_nfc; nfc_set_drvdata(ndev->nfc_dev, ndev); return ndev; free_nfc: kfree(ndev->nfc_dev); free_nci: kfree(ndev); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias13361.29%114.29%
Samuel Ortiz3114.29%114.29%
Christophe Ricard3013.82%114.29%
Dan Carpenter135.99%114.29%
Axel Lin83.69%114.29%
Joe Perches20.92%228.57%
Total217100.00%7100.00%

EXPORT_SYMBOL(nci_allocate_device); /** * nci_free_device - deallocate nci device * * @ndev: The nci device to deallocate */
void nci_free_device(struct nci_dev *ndev) { nfc_free_device(ndev->nfc_dev); kfree(ndev); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias22100.00%1100.00%
Total22100.00%1100.00%

EXPORT_SYMBOL(nci_free_device); /** * nci_register_device - register a nci device in the nfc subsystem * * @dev: The nci device to register */
int nci_register_device(struct nci_dev *ndev) { int rc; struct device *dev = &ndev->nfc_dev->dev; char name[32]; ndev->flags = 0; INIT_WORK(&ndev->cmd_work, nci_cmd_work); snprintf(name, sizeof(name), "%s_nci_cmd_wq", dev_name(dev)); ndev->cmd_wq = create_singlethread_workqueue(name); if (!ndev->cmd_wq) { rc = -ENOMEM; goto exit; } INIT_WORK(&ndev->rx_work, nci_rx_work); snprintf(name, sizeof(name), "%s_nci_rx_wq", dev_name(dev)); ndev->rx_wq = create_singlethread_workqueue(name); if (!ndev->rx_wq) { rc = -ENOMEM; goto destroy_cmd_wq_exit; } INIT_WORK(&ndev->tx_work, nci_tx_work); snprintf(name, sizeof(name), "%s_nci_tx_wq", dev_name(dev)); ndev->tx_wq = create_singlethread_workqueue(name); if (!ndev->tx_wq) { rc = -ENOMEM; goto destroy_rx_wq_exit; } skb_queue_head_init(&ndev->cmd_q); skb_queue_head_init(&ndev->rx_q); skb_queue_head_init(&ndev->tx_q); setup_timer(&ndev->cmd_timer, nci_cmd_timer, (unsigned long) ndev); setup_timer(&ndev->data_timer, nci_data_timer, (unsigned long) ndev); mutex_init(&ndev->req_lock); INIT_LIST_HEAD(&ndev->conn_info_list); rc = nfc_register_device(ndev->nfc_dev); if (rc) goto destroy_rx_wq_exit; goto exit; destroy_rx_wq_exit: destroy_workqueue(ndev->rx_wq); destroy_cmd_wq_exit: destroy_workqueue(ndev->cmd_wq); exit: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias28591.94%250.00%
Vincent Cuissard175.48%125.00%
Christophe Ricard82.58%125.00%
Total310100.00%4100.00%

EXPORT_SYMBOL(nci_register_device); /** * nci_unregister_device - unregister a nci device in the nfc subsystem * * @dev: The nci device to unregister */
void nci_unregister_device(struct nci_dev *ndev) { struct nci_conn_info *conn_info, *n; nci_close_device(ndev); destroy_workqueue(ndev->cmd_wq); destroy_workqueue(ndev->rx_wq); destroy_workqueue(ndev->tx_wq); list_for_each_entry_safe(conn_info, n, &ndev->conn_info_list, list) { list_del(&conn_info->list); /* conn_info is allocated with devm_kzalloc */ } nfc_unregister_device(ndev->nfc_dev); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias4359.72%150.00%
Christophe Ricard2940.28%150.00%
Total72100.00%2100.00%

EXPORT_SYMBOL(nci_unregister_device); /** * nci_recv_frame - receive frame from NCI drivers * * @ndev: The nci device * @skb: The sk_buff to receive */
int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb) { pr_debug("len %d\n", skb->len); if (!ndev || (!test_bit(NCI_UP, &ndev->flags) && !test_bit(NCI_INIT, &ndev->flags))) { kfree_skb(skb); return -ENXIO; } /* Queue frame for rx worker thread */ skb_queue_tail(&ndev->rx_q, skb); queue_work(ndev->rx_wq, &ndev->rx_work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias8392.22%125.00%
Frederic Danis55.56%125.00%
Joe Perches22.22%250.00%
Total90100.00%4100.00%

EXPORT_SYMBOL(nci_recv_frame);
int nci_send_frame(struct nci_dev *ndev, struct sk_buff *skb) { pr_debug("len %d\n", skb->len); if (!ndev) { kfree_skb(skb); return -ENODEV; } /* Get rid of skb owner, prior to sending to the driver. */ skb_orphan(skb); /* Send copy to sniffer */ nfc_send_to_raw_sock(ndev->nfc_dev, skb, RAW_PAYLOAD_NCI, NFC_DIRECTION_TX); return ndev->ops->send(ndev, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias4968.06%120.00%
Hiren Tandel1419.44%120.00%
Frederic Danis79.72%120.00%
Joe Perches22.78%240.00%
Total72100.00%5100.00%

EXPORT_SYMBOL(nci_send_frame); /* Send NCI command */
int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload) { struct nci_ctrl_hdr *hdr; struct sk_buff *skb; pr_debug("opcode 0x%x, plen %d\n", opcode, plen); skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL); if (!skb) { pr_err("no memory for command\n"); return -ENOMEM; } hdr = (struct nci_ctrl_hdr *) skb_put(skb, NCI_CTRL_HDR_SIZE); hdr->gid = nci_opcode_gid(opcode); hdr->oid = nci_opcode_oid(opcode); hdr->plen = plen; nci_mt_set((__u8 *)hdr, NCI_MT_CMD_PKT); nci_pbf_set((__u8 *)hdr, NCI_PBF_LAST); if (plen) memcpy(skb_put(skb, plen), payload, plen); skb_queue_tail(&ndev->cmd_q, skb); queue_work(ndev->cmd_wq, &ndev->cmd_work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias16997.69%125.00%
Joe Perches42.31%375.00%
Total173100.00%4100.00%

EXPORT_SYMBOL(nci_send_cmd); /* Proprietary commands API */
static struct nci_driver_ops *ops_cmd_lookup(struct nci_driver_ops *ops, size_t n_ops, __u16 opcode) { size_t i; struct nci_driver_ops *op; if (!ops || !n_ops) return NULL; for (i = 0; i < n_ops; i++) { op = &ops[i]; if (op->opcode == opcode) return op; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Samuel Ortiz6181.33%133.33%
Robert Dolca1418.67%266.67%
Total75100.00%3100.00%


static int nci_op_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode, struct sk_buff *skb, struct nci_driver_ops *ops, size_t n_ops) { struct nci_driver_ops *op; op = ops_cmd_lookup(ops, n_ops, rsp_opcode); if (!op || !op->rsp) return -ENOTSUPP; return op->rsp(ndev, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Samuel Ortiz4770.15%133.33%
Robert Dolca2029.85%266.67%
Total67100.00%3100.00%


static int nci_op_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode, struct sk_buff *skb, struct nci_driver_ops *ops, size_t n_ops) { struct nci_driver_ops *op; op = ops_cmd_lookup(ops, n_ops, ntf_opcode); if (!op || !op->ntf) return -ENOTSUPP; return op->ntf(ndev, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Samuel Ortiz4770.15%133.33%
Robert Dolca2029.85%266.67%
Total67100.00%3100.00%


int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode, struct sk_buff *skb) { return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->prop_ops, ndev->ops->n_prop_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca40100.00%1100.00%
Total40100.00%1100.00%


int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode, struct sk_buff *skb) { return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->prop_ops, ndev->ops->n_prop_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca40100.00%1100.00%
Total40100.00%1100.00%


int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode, struct sk_buff *skb) { return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->core_ops, ndev->ops->n_core_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca40100.00%1100.00%
Total40100.00%1100.00%


int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode, struct sk_buff *skb) { return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->core_ops, ndev->ops->n_core_ops); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca40100.00%1100.00%
Total40100.00%1100.00%

/* ---- NCI TX Data worker thread ---- */
static void nci_tx_work(struct work_struct *work) { struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work); struct nci_conn_info *conn_info; struct sk_buff *skb; conn_info = nci_get_conn_info_by_conn_id(ndev, ndev->cur_conn_id); if (!conn_info) return; pr_debug("credits_cnt %d\n", atomic_read(&conn_info->credits_cnt)); /* Send queued tx data */ while (atomic_read(&conn_info->credits_cnt)) { skb = skb_dequeue(&ndev->tx_q); if (!skb) return; /* Check if data flow control is used */ if (atomic_read(&conn_info->credits_cnt) != NCI_DATA_FLOW_CONTROL_NOT_USED) atomic_dec(&conn_info->credits_cnt); pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n", nci_pbf(skb->data), nci_conn_id(skb->data), nci_plen(skb->data)); nci_send_frame(ndev, skb); mod_timer(&ndev->data_timer, jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT)); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias13280.49%342.86%
Christophe Ricard2615.85%114.29%
Joe Perches42.44%228.57%
Frederic Danis21.22%114.29%
Total164100.00%7100.00%

/* ----- NCI RX worker thread (data & control) ----- */
static void nci_rx_work(struct work_struct *work) { struct nci_dev *ndev = container_of(work, struct nci_dev, rx_work); struct sk_buff *skb; while ((skb = skb_dequeue(&ndev->rx_q))) { /* Send copy to sniffer */ nfc_send_to_raw_sock(ndev->nfc_dev, skb, RAW_PAYLOAD_NCI, NFC_DIRECTION_RX); /* Process frame */ switch (nci_mt(skb->data)) { case NCI_MT_RSP_PKT: nci_rsp_packet(ndev, skb); break; case NCI_MT_NTF_PKT: nci_ntf_packet(ndev, skb); break; case NCI_MT_DATA_PKT: nci_rx_data_packet(ndev, skb); break; default: pr_err("unknown MT 0x%x\n", nci_mt(skb->data)); kfree_skb(skb); break; } } /* check if a data exchange timout has occurred */ if (test_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags)) { /* complete the data exchange transaction, if exists */ if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) nci_data_exchange_complete(ndev, NULL, ndev->cur_conn_id, -ETIMEDOUT); clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias15788.70%240.00%
Hiren Tandel147.91%120.00%
Christophe Ricard42.26%120.00%
Joe Perches21.13%120.00%
Total177100.00%5100.00%

/* ----- NCI TX CMD worker thread ----- */
static void nci_cmd_work(struct work_struct *work) { struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work); struct sk_buff *skb; pr_debug("cmd_cnt %d\n", atomic_read(&ndev->cmd_cnt)); /* Send queued command */ if (atomic_read(&ndev->cmd_cnt)) { skb = skb_dequeue(&ndev->cmd_q); if (!skb) return; atomic_dec(&ndev->cmd_cnt); pr_debug("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", nci_pbf(skb->data), nci_opcode_gid(nci_opcode(skb->data)), nci_opcode_oid(nci_opcode(skb->data)), nci_plen(skb->data)); nci_send_frame(ndev, skb); mod_timer(&ndev->cmd_timer, jiffies + msecs_to_jiffies(NCI_CMD_TIMEOUT)); } }

Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias13695.77%125.00%
Joe Perches42.82%250.00%
Frederic Danis21.41%125.00%
Total142100.00%4100.00%

MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Ilan Elias396057.07%1215.79%
Christophe Ricard142720.56%2228.95%
Julien Lefrique4526.51%56.58%
Robert Dolca3515.06%67.89%
Samuel Ortiz2763.98%911.84%
Amitkumar Karwar1031.48%33.95%
Robert Baldyga791.14%22.63%
Vincent Cuissard751.08%33.95%
Clément Perrochaud560.81%11.32%
Joe Perches520.75%33.95%
Hiren Tandel280.40%11.32%
Eric Lapuyade260.37%11.32%
Frederic Danis170.24%11.32%
Dan Carpenter140.20%22.63%
Axel Lin90.13%11.32%
Dave Jones80.12%11.32%
Paul Gortmaker30.04%11.32%
Szymon Janc30.04%22.63%
Total6939100.00%76100.00%
Directory: net/nfc/nci
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.