<commit_before>/*
 * I2C Link Layer for ST21NFCB NCI based Driver
 * Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions 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 ": " fmt

#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/st21nfcb.h>

#include <net/nfc/nci.h>
#include <net/nfc/llc.h>
#include <net/nfc/nfc.h>

#include "ndlc.h"

#define DRIVER_DESC "NCI NFC driver for ST21NFCB"

/* ndlc header */
#define ST21NFCB_FRAME_HEADROOM	1
#define ST21NFCB_FRAME_TAILROOM 0

#define ST21NFCB_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
#define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */

#define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c"

static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = {
	{ST21NFCB_NCI_DRIVER_NAME, 0},
	{}
};
MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table);

struct st21nfcb_i2c_phy {
	struct i2c_client *i2c_dev;
	struct llt_ndlc *ndlc;

	unsigned int gpio_irq;
	unsigned int gpio_reset;
	unsigned int irq_polarity;

	int powered;

	/*
	 * < 0 if hardware error occured (e.g. i2c err)
	 * and prevents normal operation.
	 */
	int hard_fault;
};

#define I2C_DUMP_SKB(info, skb)					\
do {								\
	pr_debug("%s:\n", info);				\
	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
		       16, 1, (skb)->data, (skb)->len, 0);	\
} while (0)

static int st21nfcb_nci_i2c_enable(void *phy_id)
{
	struct st21nfcb_i2c_phy *phy = phy_id;

	gpio_set_value(phy->gpio_reset, 0);
	usleep_range(10000, 15000);
	gpio_set_value(phy->gpio_reset, 1);
	phy->powered = 1;
	usleep_range(80000, 85000);

	return 0;
}

static void st21nfcb_nci_i2c_disable(void *phy_id)
{
	struct st21nfcb_i2c_phy *phy = phy_id;

	pr_info("\n");

	phy->powered = 0;
	/* reset chip in order to flush clf */
	gpio_set_value(phy->gpio_reset, 0);
	usleep_range(10000, 15000);
	gpio_set_value(phy->gpio_reset, 1);
}

static void st21nfcb_nci_remove_header(struct sk_buff *skb)
{
	skb_pull(skb, ST21NFCB_FRAME_HEADROOM);
}

/*
 * Writing a frame must not return the number of written bytes.
 * It must return either zero for success, or <0 for error.
 * In addition, it must not alter the skb
 */
static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
{
	int r = -1;
	struct st21nfcb_i2c_phy *phy = phy_id;
	struct i2c_client *client = phy->i2c_dev;

	I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);

	if (phy->hard_fault != 0)
		return phy->hard_fault;

	r = i2c_master_send(client, skb->data, skb->len);
	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_send(client, skb->data, skb->len);
	}

	if (r >= 0) {
		if (r != skb->len)
			r = -EREMOTEIO;
		else
			r = 0;
	}

	st21nfcb_nci_remove_header(skb);

	return r;
}

/*
 * Reads an ndlc frame and returns it in a newly allocated sk_buff.
 * returns:
 * frame size : if received frame is complete (find ST21NFCB_SOF_EOF at
 * end of read)
 * -EAGAIN : if received frame is incomplete (not find ST21NFCB_SOF_EOF
 * at end of read)
 * -EREMOTEIO : i2c read error (fatal)
 * -EBADMSG : frame was incorrect and discarded
 * (value returned from st21nfcb_nci_i2c_repack)
 * -EIO : if no ST21NFCB_SOF_EOF is found after reaching
 * the read length end sequence
 */
static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
				 struct sk_buff **skb)
{
	int r;
	u8 len;
	u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE];
	struct i2c_client *client = phy->i2c_dev;

	r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
	} else if (r != ST21NFCB_NCI_I2C_MIN_SIZE) {
		nfc_err(&client->dev, "cannot read ndlc & nci header\n");
		return -EREMOTEIO;
	}

	len = be16_to_cpu(*(__be16 *) (buf + 2));
	if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
		nfc_err(&client->dev, "invalid frame len\n");
		return -EBADMSG;
	}

	*skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
	if (*skb == NULL)
		return -ENOMEM;

	skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
	skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
	memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE);

	if (!len)
		return 0;

	r = i2c_master_recv(client, buf, len);
	if (r != len) {
		kfree_skb(*skb);
		return -EREMOTEIO;
	}

	skb_put(*skb, len);<commit_msg>NFC: st21nfcb: Fix logic when running into i2c read retry<commit_after>/*
 * I2C Link Layer for ST21NFCB NCI based Driver
 * Copyright (C) 2014  STMicroelectronics SAS. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions 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 ": " fmt

#include <linux/crc-ccitt.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/st21nfcb.h>

#include <net/nfc/nci.h>
#include <net/nfc/llc.h>
#include <net/nfc/nfc.h>

#include "ndlc.h"

#define DRIVER_DESC "NCI NFC driver for ST21NFCB"

/* ndlc header */
#define ST21NFCB_FRAME_HEADROOM	1
#define ST21NFCB_FRAME_TAILROOM 0

#define ST21NFCB_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
#define ST21NFCB_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */

#define ST21NFCB_NCI_I2C_DRIVER_NAME "st21nfcb_nci_i2c"

static struct i2c_device_id st21nfcb_nci_i2c_id_table[] = {
	{ST21NFCB_NCI_DRIVER_NAME, 0},
	{}
};
MODULE_DEVICE_TABLE(i2c, st21nfcb_nci_i2c_id_table);

struct st21nfcb_i2c_phy {
	struct i2c_client *i2c_dev;
	struct llt_ndlc *ndlc;

	unsigned int gpio_irq;
	unsigned int gpio_reset;
	unsigned int irq_polarity;

	int powered;

	/*
	 * < 0 if hardware error occured (e.g. i2c err)
	 * and prevents normal operation.
	 */
	int hard_fault;
};

#define I2C_DUMP_SKB(info, skb)					\
do {								\
	pr_debug("%s:\n", info);				\
	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
		       16, 1, (skb)->data, (skb)->len, 0);	\
} while (0)

static int st21nfcb_nci_i2c_enable(void *phy_id)
{
	struct st21nfcb_i2c_phy *phy = phy_id;

	gpio_set_value(phy->gpio_reset, 0);
	usleep_range(10000, 15000);
	gpio_set_value(phy->gpio_reset, 1);
	phy->powered = 1;
	usleep_range(80000, 85000);

	return 0;
}

static void st21nfcb_nci_i2c_disable(void *phy_id)
{
	struct st21nfcb_i2c_phy *phy = phy_id;

	pr_info("\n");

	phy->powered = 0;
	/* reset chip in order to flush clf */
	gpio_set_value(phy->gpio_reset, 0);
	usleep_range(10000, 15000);
	gpio_set_value(phy->gpio_reset, 1);
}

static void st21nfcb_nci_remove_header(struct sk_buff *skb)
{
	skb_pull(skb, ST21NFCB_FRAME_HEADROOM);
}

/*
 * Writing a frame must not return the number of written bytes.
 * It must return either zero for success, or <0 for error.
 * In addition, it must not alter the skb
 */
static int st21nfcb_nci_i2c_write(void *phy_id, struct sk_buff *skb)
{
	int r = -1;
	struct st21nfcb_i2c_phy *phy = phy_id;
	struct i2c_client *client = phy->i2c_dev;

	I2C_DUMP_SKB("st21nfcb_nci_i2c_write", skb);

	if (phy->hard_fault != 0)
		return phy->hard_fault;

	r = i2c_master_send(client, skb->data, skb->len);
	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_send(client, skb->data, skb->len);
	}

	if (r >= 0) {
		if (r != skb->len)
			r = -EREMOTEIO;
		else
			r = 0;
	}

	st21nfcb_nci_remove_header(skb);

	return r;
}

/*
 * Reads an ndlc frame and returns it in a newly allocated sk_buff.
 * returns:
 * frame size : if received frame is complete (find ST21NFCB_SOF_EOF at
 * end of read)
 * -EAGAIN : if received frame is incomplete (not find ST21NFCB_SOF_EOF
 * at end of read)
 * -EREMOTEIO : i2c read error (fatal)
 * -EBADMSG : frame was incorrect and discarded
 * (value returned from st21nfcb_nci_i2c_repack)
 * -EIO : if no ST21NFCB_SOF_EOF is found after reaching
 * the read length end sequence
 */
static int st21nfcb_nci_i2c_read(struct st21nfcb_i2c_phy *phy,
				 struct sk_buff **skb)
{
	int r;
	u8 len;
	u8 buf[ST21NFCB_NCI_I2C_MAX_SIZE];
	struct i2c_client *client = phy->i2c_dev;

	r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
	if (r == -EREMOTEIO) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_recv(client, buf, ST21NFCB_NCI_I2C_MIN_SIZE);
	}

	if (r != ST21NFCB_NCI_I2C_MIN_SIZE) {
		nfc_err(&client->dev, "cannot read ndlc & nci header\n");
		return -EREMOTEIO;
	}

	len = be16_to_cpu(*(__be16 *) (buf + 2));
	if (len > ST21NFCB_NCI_I2C_MAX_SIZE) {
		nfc_err(&client->dev, "invalid frame len\n");
		return -EBADMSG;
	}

	*skb = alloc_skb(ST21NFCB_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
	if (*skb == NULL)
		return -ENOMEM;

	skb_reserve(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
	skb_put(*skb, ST21NFCB_NCI_I2C_MIN_SIZE);
	memcpy((*skb)->data, buf, ST21NFCB_NCI_I2C_MIN_SIZE);

	if (!len)
		return 0;

	r = i2c_master_recv(client, buf, len);
	if (r != len) {
		kfree_skb(*skb);
		return -EREMOTEIO;
	}

	skb_put(*skb, len);
{'fraction_non_alphanumeric': 0.1195745903995401, 'fraction_numerical': 0.04072051355753569, 'mean_word_length': 4.322794492605813, 'pattern_counts': {'":': 2, '<': 41, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1278540', 'n_tokens_mistral': 4707, 'n_tokens_neox': 4346, 'n_words': 1069}