Commit 04bb7ecf authored by John W. Linville's avatar John W. Linville

Merge tag 'nfc-next-3.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next

Samuel Ortiz <sameo@linux.intel.com> says:

"NFC: 3.19 pull request

This is the NFC pull request for 3.19.

With this one we get:

- NFC digital improvements for DEP support: Chaining, NACK and ATN
  support added.

- NCI improvements: Support for p2p target, SE IO operand addition,
  SE operands extensions to support proprietary implementations, and
  a few fixes.

- NFC HCI improvements: OPEN_PIPE and NOTIFY_ALL_CLEARED support,
  and SE IO operand addition.

- A bunch of minor improvements and fixes for STMicro st21nfcb and
  st21nfca"
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents ea375117 e479ce47
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/pn544.h> #include <linux/platform_data/pn544.h>
#include <asm/unaligned.h>
#include <net/nfc/hci.h> #include <net/nfc/hci.h>
#include <net/nfc/llc.h> #include <net/nfc/llc.h>
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/nfc.h> #include <linux/nfc.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/st21nfca.h> #include <linux/platform_data/st21nfca.h>
#include <asm/unaligned.h>
#include <net/nfc/hci.h> #include <net/nfc/hci.h>
#include <net/nfc/llc.h> #include <net/nfc/llc.h>
...@@ -72,7 +72,6 @@ struct st21nfca_i2c_phy { ...@@ -72,7 +72,6 @@ struct st21nfca_i2c_phy {
struct nfc_hci_dev *hdev; struct nfc_hci_dev *hdev;
unsigned int gpio_ena; unsigned int gpio_ena;
unsigned int gpio_irq;
unsigned int irq_polarity; unsigned int irq_polarity;
struct sk_buff *pending_skb; struct sk_buff *pending_skb;
...@@ -531,20 +530,12 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client) ...@@ -531,20 +530,12 @@ static int st21nfca_hci_i2c_of_request_resources(struct i2c_client *client)
"clf_enable"); "clf_enable");
if (r) { if (r) {
nfc_err(&client->dev, "Failed to request enable pin\n"); nfc_err(&client->dev, "Failed to request enable pin\n");
return -ENODEV; return r;
} }
phy->gpio_ena = gpio; phy->gpio_ena = gpio;
/* IRQ */ phy->irq_polarity = irq_get_trigger_type(client->irq);
r = irq_of_parse_and_map(pp, 0);
if (r < 0) {
nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
return r;
}
phy->irq_polarity = irq_get_trigger_type(r);
client->irq = r;
return 0; return 0;
} }
...@@ -560,7 +551,6 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client) ...@@ -560,7 +551,6 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
struct st21nfca_nfc_platform_data *pdata; struct st21nfca_nfc_platform_data *pdata;
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
int r; int r;
int irq;
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
if (pdata == NULL) { if (pdata == NULL) {
...@@ -569,35 +559,17 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client) ...@@ -569,35 +559,17 @@ static int st21nfca_hci_i2c_request_resources(struct i2c_client *client)
} }
/* store for later use */ /* store for later use */
phy->gpio_irq = pdata->gpio_irq;
phy->gpio_ena = pdata->gpio_ena; phy->gpio_ena = pdata->gpio_ena;
phy->irq_polarity = pdata->irq_polarity; phy->irq_polarity = pdata->irq_polarity;
r = devm_gpio_request_one(&client->dev, phy->gpio_irq, GPIOF_IN,
"wake_up");
if (r) {
pr_err("%s : gpio_request failed\n", __FILE__);
return -ENODEV;
}
if (phy->gpio_ena > 0) { if (phy->gpio_ena > 0) {
r = devm_gpio_request_one(&client->dev, phy->gpio_ena, r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
GPIOF_OUT_INIT_HIGH, "clf_enable"); GPIOF_OUT_INIT_HIGH, "clf_enable");
if (r) { if (r) {
pr_err("%s : ena gpio_request failed\n", __FILE__); pr_err("%s : ena gpio_request failed\n", __FILE__);
return -ENODEV; return r;
}
} }
/* IRQ */
irq = gpio_to_irq(phy->gpio_irq);
if (irq < 0) {
nfc_err(&client->dev,
"Unable to get irq number for GPIO %d error %d\n",
phy->gpio_irq, r);
return -ENODEV;
} }
client->irq = irq;
return 0; return 0;
} }
...@@ -656,7 +628,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, ...@@ -656,7 +628,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
r = st21nfca_hci_platform_init(phy); r = st21nfca_hci_platform_init(phy);
if (r < 0) { if (r < 0) {
nfc_err(&client->dev, "Unable to reboot st21nfca\n"); nfc_err(&client->dev, "Unable to reboot st21nfca\n");
return -ENODEV; return r;
} }
r = devm_request_threaded_irq(&client->dev, client->irq, NULL, r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
...@@ -687,10 +659,13 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client) ...@@ -687,10 +659,13 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client)
return 0; return 0;
} }
#ifdef CONFIG_OF
static const struct of_device_id of_st21nfca_i2c_match[] = { static const struct of_device_id of_st21nfca_i2c_match[] = {
{ .compatible = "st,st21nfca_i2c", }, { .compatible = "st,st21nfca_i2c", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
#endif
static struct i2c_driver st21nfca_hci_i2c_driver = { static struct i2c_driver st21nfca_hci_i2c_driver = {
.driver = { .driver = {
......
...@@ -77,10 +77,6 @@ ...@@ -77,10 +77,6 @@
((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN)) ((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/ #define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/
#define ST21NFCA_EVT_FIELD_ON 0x11
#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
#define ST21NFCA_EVT_FIELD_OFF 0x14
static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES); static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
...@@ -841,31 +837,11 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev, ...@@ -841,31 +837,11 @@ static int st21nfca_hci_check_presence(struct nfc_hci_dev *hdev,
static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
u8 event, struct sk_buff *skb) u8 event, struct sk_buff *skb)
{ {
int r; pr_debug("hci event: %d gate: %x\n", event, gate);
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
pr_debug("hci event: %d\n", event); switch (gate) {
case ST21NFCA_RF_CARD_F_GATE:
switch (event) { return st21nfca_dep_event_received(hdev, event, skb);
case ST21NFCA_EVT_CARD_ACTIVATED:
if (gate == ST21NFCA_RF_CARD_F_GATE)
info->dep_info.curr_nfc_dep_pni = 0;
break;
case ST21NFCA_EVT_CARD_DEACTIVATED:
break;
case ST21NFCA_EVT_FIELD_ON:
break;
case ST21NFCA_EVT_FIELD_OFF:
break;
case ST21NFCA_EVT_SEND_DATA:
if (gate == ST21NFCA_RF_CARD_F_GATE) {
r = st21nfca_tm_event_send_data(hdev, skb, gate);
if (r < 0)
return r;
return 0;
}
info->dep_info.curr_nfc_dep_pni = 0;
return 1;
default: default:
return 1; return 1;
} }
......
...@@ -85,6 +85,4 @@ struct st21nfca_hci_info { ...@@ -85,6 +85,4 @@ struct st21nfca_hci_info {
#define ST21NFCA_RF_CARD_F_GATE 0x24 #define ST21NFCA_RF_CARD_F_GATE 0x24
#define ST21NFCA_EVT_SEND_DATA 0x10
#endif /* __LOCAL_ST21NFCA_H_ */ #endif /* __LOCAL_ST21NFCA_H_ */
...@@ -49,6 +49,12 @@ ...@@ -49,6 +49,12 @@
#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30 #define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
#define ST21NFCA_GB_BIT 0x02 #define ST21NFCA_GB_BIT 0x02
#define ST21NFCA_EVT_SEND_DATA 0x10
#define ST21NFCA_EVT_FIELD_ON 0x11
#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
#define ST21NFCA_EVT_FIELD_OFF 0x14
#define ST21NFCA_EVT_CARD_F_BITRATE 0x16 #define ST21NFCA_EVT_CARD_F_BITRATE 0x16
#define ST21NFCA_EVT_READER_F_BITRATE 0x13 #define ST21NFCA_EVT_READER_F_BITRATE 0x13
#define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38) #define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
...@@ -372,8 +378,8 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev, ...@@ -372,8 +378,8 @@ static int st21nfca_tm_recv_dep_req(struct nfc_hci_dev *hdev,
return r; return r;
} }
int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb, static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
u8 gate) struct sk_buff *skb)
{ {
u8 cmd0, cmd1; u8 cmd0, cmd1;
int r; int r;
...@@ -400,7 +406,42 @@ int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb, ...@@ -400,7 +406,42 @@ int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
} }
return r; return r;
} }
EXPORT_SYMBOL(st21nfca_tm_event_send_data);
/*
* Returns:
* <= 0: driver handled the event, skb consumed
* 1: driver does not handle the event, please do standard processing
*/
int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
u8 event, struct sk_buff *skb)
{
int r = 0;
struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
pr_debug("dep event: %d\n", event);
switch (event) {
case ST21NFCA_EVT_CARD_ACTIVATED:
info->dep_info.curr_nfc_dep_pni = 0;
break;
case ST21NFCA_EVT_CARD_DEACTIVATED:
break;
case ST21NFCA_EVT_FIELD_ON:
break;
case ST21NFCA_EVT_FIELD_OFF:
break;
case ST21NFCA_EVT_SEND_DATA:
r = st21nfca_tm_event_send_data(hdev, skb);
if (r < 0)
return r;
return 0;
default:
return 1;
}
kfree_skb(skb);
return r;
}
EXPORT_SYMBOL(st21nfca_dep_event_received);
static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi, static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
u8 bri, u8 lri) u8 bri, u8 lri)
......
...@@ -32,8 +32,8 @@ struct st21nfca_dep_info { ...@@ -32,8 +32,8 @@ struct st21nfca_dep_info {
u8 lri; u8 lri;
} __packed; } __packed;
int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb, int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
u8 gate); u8 event, struct sk_buff *skb);
int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb); int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len); int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
......
...@@ -50,7 +50,6 @@ struct st21nfcb_i2c_phy { ...@@ -50,7 +50,6 @@ struct st21nfcb_i2c_phy {
struct i2c_client *i2c_dev; struct i2c_client *i2c_dev;
struct llt_ndlc *ndlc; struct llt_ndlc *ndlc;
unsigned int gpio_irq;
unsigned int gpio_reset; unsigned int gpio_reset;
unsigned int irq_polarity; unsigned int irq_polarity;
...@@ -81,8 +80,6 @@ static void st21nfcb_nci_i2c_disable(void *phy_id) ...@@ -81,8 +80,6 @@ static void st21nfcb_nci_i2c_disable(void *phy_id)
{ {
struct st21nfcb_i2c_phy *phy = phy_id; struct st21nfcb_i2c_phy *phy = phy_id;
pr_info("\n");
phy->powered = 0; phy->powered = 0;
/* reset chip in order to flush clf */ /* reset chip in order to flush clf */
gpio_set_value(phy->gpio_reset, 0); gpio_set_value(phy->gpio_reset, 0);
...@@ -258,19 +255,11 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client) ...@@ -258,19 +255,11 @@ static int st21nfcb_nci_i2c_of_request_resources(struct i2c_client *client)
GPIOF_OUT_INIT_HIGH, "clf_reset"); GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) { if (r) {
nfc_err(&client->dev, "Failed to request reset pin\n"); nfc_err(&client->dev, "Failed to request reset pin\n");
return -ENODEV;
}
phy->gpio_reset = gpio;
/* IRQ */
r = irq_of_parse_and_map(pp, 0);
if (r < 0) {
nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
return r; return r;
} }
phy->gpio_reset = gpio;
phy->irq_polarity = irq_get_trigger_type(r); phy->irq_polarity = irq_get_trigger_type(client->irq);
client->irq = r;
return 0; return 0;
} }
...@@ -286,7 +275,6 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client) ...@@ -286,7 +275,6 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
struct st21nfcb_nfc_platform_data *pdata; struct st21nfcb_nfc_platform_data *pdata;
struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client); struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
int r; int r;
int irq;
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
if (pdata == NULL) { if (pdata == NULL) {
...@@ -295,33 +283,15 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client) ...@@ -295,33 +283,15 @@ static int st21nfcb_nci_i2c_request_resources(struct i2c_client *client)
} }
/* store for later use */ /* store for later use */
phy->gpio_irq = pdata->gpio_irq;
phy->gpio_reset = pdata->gpio_reset; phy->gpio_reset = pdata->gpio_reset;
phy->irq_polarity = pdata->irq_polarity; phy->irq_polarity = pdata->irq_polarity;
r = devm_gpio_request_one(&client->dev, phy->gpio_irq,
GPIOF_IN, "clf_irq");
if (r) {
pr_err("%s : gpio_request failed\n", __FILE__);
return -ENODEV;
}
r = devm_gpio_request_one(&client->dev, r = devm_gpio_request_one(&client->dev,
phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset"); phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) { if (r) {
pr_err("%s : reset gpio_request failed\n", __FILE__); pr_err("%s : reset gpio_request failed\n", __FILE__);
return -ENODEV; return r;
}
/* IRQ */
irq = gpio_to_irq(phy->gpio_irq);
if (irq < 0) {
nfc_err(&client->dev,
"Unable to get irq number for GPIO %d error %d\n",
phy->gpio_irq, r);
return -ENODEV;
} }
client->irq = irq;
return 0; return 0;
} }
...@@ -401,10 +371,13 @@ static int st21nfcb_nci_i2c_remove(struct i2c_client *client) ...@@ -401,10 +371,13 @@ static int st21nfcb_nci_i2c_remove(struct i2c_client *client)
return 0; return 0;
} }
#ifdef CONFIG_OF
static const struct of_device_id of_st21nfcb_i2c_match[] = { static const struct of_device_id of_st21nfcb_i2c_match[] = {
{ .compatible = "st,st21nfcb_i2c", }, { .compatible = "st,st21nfcb_i2c", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, of_st21nfcb_i2c_match);
#endif
static struct i2c_driver st21nfcb_nci_i2c_driver = { static struct i2c_driver st21nfcb_nci_i2c_driver = {
.driver = { .driver = {
......
...@@ -266,7 +266,7 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev, ...@@ -266,7 +266,7 @@ int ndlc_probe(void *phy_id, struct nfc_phy_ops *phy_ops, struct device *dev,
*ndlc_id = ndlc; *ndlc_id = ndlc;
/* start timers */ /* initialize timers */
init_timer(&ndlc->t1_timer); init_timer(&ndlc->t1_timer);
ndlc->t1_timer.data = (unsigned long)ndlc; ndlc->t1_timer.data = (unsigned long)ndlc;
ndlc->t1_timer.function = ndlc_t1_timeout; ndlc->t1_timer.function = ndlc_t1_timeout;
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci" #define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
struct st21nfca_nfc_platform_data { struct st21nfca_nfc_platform_data {
unsigned int gpio_irq;
unsigned int gpio_ena; unsigned int gpio_ena;
unsigned int irq_polarity; unsigned int irq_polarity;
}; };
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci" #define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci"
struct st21nfcb_nfc_platform_data { struct st21nfcb_nfc_platform_data {
unsigned int gpio_irq;
unsigned int gpio_reset; unsigned int gpio_reset;
unsigned int irq_polarity; unsigned int irq_polarity;
}; };
......
...@@ -225,6 +225,19 @@ struct nfc_digital_dev { ...@@ -225,6 +225,19 @@ struct nfc_digital_dev {
u8 curr_protocol; u8 curr_protocol;
u8 curr_rf_tech; u8 curr_rf_tech;
u8 curr_nfc_dep_pni; u8 curr_nfc_dep_pni;
u8 did;
u8 local_payload_max;
u8 remote_payload_max;
struct sk_buff *chaining_skb;
struct digital_data_exch *data_exch;
int atn_count;
int nack_count;
struct sk_buff *saved_skb;
unsigned int saved_skb_len;
u16 target_fsc; u16 target_fsc;
......
...@@ -57,10 +57,14 @@ struct nfc_hci_ops { ...@@ -57,10 +57,14 @@ struct nfc_hci_ops {
int (*discover_se)(struct nfc_hci_dev *dev); int (*discover_se)(struct nfc_hci_dev *dev);
int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx); int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx); int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx);
int (*se_io)(struct nfc_hci_dev *dev, u32 se_idx,
u8 *apdu, size_t apdu_length,
se_io_cb_t cb, void *cb_context);
}; };
/* Pipes */ /* Pipes */
#define NFC_HCI_INVALID_PIPE 0x80 #define NFC_HCI_INVALID_PIPE 0x80
#define NFC_HCI_DO_NOT_CREATE_PIPE 0x81
#define NFC_HCI_LINK_MGMT_PIPE 0x00 #define NFC_HCI_LINK_MGMT_PIPE 0x00
#define NFC_HCI_ADMIN_PIPE 0x01 #define NFC_HCI_ADMIN_PIPE 0x01
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#ifndef __NCI_H #ifndef __NCI_H
#define __NCI_H #define __NCI_H
#include <net/nfc/nfc.h>
/* NCI constants */ /* NCI constants */
#define NCI_MAX_NUM_MAPPING_CONFIGS 10 #define NCI_MAX_NUM_MAPPING_CONFIGS 10
#define NCI_MAX_NUM_RF_CONFIGS 10 #define NCI_MAX_NUM_RF_CONFIGS 10
...@@ -73,6 +75,8 @@ ...@@ -73,6 +75,8 @@
#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83 #define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85 #define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
#define NCI_RF_TECH_MODE_LISTEN_MASK 0x80
/* NCI RF Technologies */ /* NCI RF Technologies */
#define NCI_NFC_RF_TECHNOLOGY_A 0x00 #define NCI_NFC_RF_TECHNOLOGY_A 0x00
#define NCI_NFC_RF_TECHNOLOGY_B 0x01 #define NCI_NFC_RF_TECHNOLOGY_B 0x01
...@@ -106,6 +110,17 @@ ...@@ -106,6 +110,17 @@
/* NCI Configuration Parameter Tags */ /* NCI Configuration Parameter Tags */
#define NCI_PN_ATR_REQ_GEN_BYTES 0x29 #define NCI_PN_ATR_REQ_GEN_BYTES 0x29
#define NCI_LN_ATR_RES_GEN_BYTES 0x61
#define NCI_LA_SEL_INFO 0x32
#define NCI_LF_PROTOCOL_TYPE 0x50
#define NCI_LF_CON_BITR_F 0x54
/* NCI Configuration Parameters masks */
#define NCI_LA_SEL_INFO_ISO_DEP_MASK 0x20
#define NCI_LA_SEL_INFO_NFC_DEP_MASK 0x40
#define NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK 0x02
#define NCI_LF_CON_BITR_F_212 0x02
#define NCI_LF_CON_BITR_F_424 0x04
/* NCI Reset types */ /* NCI Reset types */
#define NCI_RESET_TYPE_KEEP_CONFIG 0x00 #define NCI_RESET_TYPE_KEEP_CONFIG 0x00
...@@ -314,26 +329,31 @@ struct nci_core_intf_error_ntf { ...@@ -314,26 +329,31 @@ struct nci_core_intf_error_ntf {
struct rf_tech_specific_params_nfca_poll { struct rf_tech_specific_params_nfca_poll {
__u16 sens_res; __u16 sens_res;
__u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */ __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
__u8 nfcid1[10]; __u8 nfcid1[NFC_NFCID1_MAXSIZE];
__u8 sel_res_len; /* 0 or 1 Bytes */ __u8 sel_res_len; /* 0 or 1 Bytes */
__u8 sel_res; __u8 sel_res;
} __packed; } __packed;
struct rf_tech_specific_params_nfcb_poll { struct rf_tech_specific_params_nfcb_poll {
__u8 sensb_res_len; __u8 sensb_res_len;
__u8 sensb_res[12]; /* 11 or 12 Bytes */ __u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; /* 11 or 12 Bytes */
} __packed; } __packed;
struct rf_tech_specific_params_nfcf_poll { struct rf_tech_specific_params_nfcf_poll {
__u8 bit_rate; __u8 bit_rate;
__u8 sensf_res_len; __u8 sensf_res_len;
__u8 sensf_res[18]; /* 16 or 18 Bytes */ __u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; /* 16 or 18 Bytes */
} __packed; } __packed;
struct rf_tech_specific_params_nfcv_poll { struct rf_tech_specific_params_nfcv_poll {
__u8 res_flags; __u8 res_flags;
__u8 dsfid; __u8 dsfid;
__u8 uid[8]; /* 8 Bytes */ __u8 uid[NFC_ISO15693_UID_MAXSIZE]; /* 8 Bytes */
} __packed;
struct rf_tech_specific_params_nfcf_listen {
__u8 local_nfcid2_len;
__u8 local_nfcid2[NFC_NFCID2_MAXSIZE]; /* 0 or 8 Bytes */
} __packed; } __packed;
struct nci_rf_discover_ntf { struct nci_rf_discover_ntf {
...@@ -365,7 +385,12 @@ struct activation_params_nfcb_poll_iso_dep { ...@@ -365,7 +385,12 @@ struct activation_params_nfcb_poll_iso_dep {
struct activation_params_poll_nfc_dep { struct activation_params_poll_nfc_dep {
__u8 atr_res_len; __u8 atr_res_len;
__u8 atr_res[63]; __u8 atr_res[NFC_ATR_RES_MAXSIZE - 2]; /* ATR_RES from byte 3 */
};
struct activation_params_listen_nfc_dep {
__u8 atr_req_len;
__u8 atr_req[NFC_ATR_REQ_MAXSIZE - 2]; /* ATR_REQ from byte 3 */
}; };
struct nci_rf_intf_activated_ntf { struct nci_rf_intf_activated_ntf {
...@@ -382,6 +407,7 @@ struct nci_rf_intf_activated_ntf { ...@@ -382,6 +407,7 @@ struct nci_rf_intf_activated_ntf {
struct rf_tech_specific_params_nfcb_poll nfcb_poll; struct rf_tech_specific_params_nfcb_poll nfcb_poll;
struct rf_tech_specific_params_nfcf_poll nfcf_poll; struct rf_tech_specific_params_nfcf_poll nfcf_poll;
struct rf_tech_specific_params_nfcv_poll nfcv_poll; struct rf_tech_specific_params_nfcv_poll nfcv_poll;
struct rf_tech_specific_params_nfcf_listen nfcf_listen;
} rf_tech_specific_params; } rf_tech_specific_params;
__u8 data_exch_rf_tech_and_mode; __u8 data_exch_rf_tech_and_mode;
...@@ -393,6 +419,7 @@ struct nci_rf_intf_activated_ntf { ...@@ -393,6 +419,7 @@ struct nci_rf_intf_activated_ntf {
struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep; struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep; struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
struct activation_params_poll_nfc_dep poll_nfc_dep; struct activation_params_poll_nfc_dep poll_nfc_dep;
struct activation_params_listen_nfc_dep listen_nfc_dep;
} activation_params; } activation_params;
} __packed; } __packed;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* *
* Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2013 Intel Corporation. All rights reserved. * Copyright (C) 2013 Intel Corporation. All rights reserved.
* Copyright (C) 2014 Marvell International Ltd.
* *
* Written by Ilan Elias <ilane@ti.com> * Written by Ilan Elias <ilane@ti.com>
* *
...@@ -49,6 +50,8 @@ enum nci_state { ...@@ -49,6 +50,8 @@ enum nci_state {
NCI_W4_ALL_DISCOVERIES, NCI_W4_ALL_DISCOVERIES,
NCI_W4_HOST_SELECT, NCI_W4_HOST_SELECT,
NCI_POLL_ACTIVE, NCI_POLL_ACTIVE,
NCI_LISTEN_ACTIVE,
NCI_LISTEN_SLEEP,
}; };
/* NCI timeouts */ /* NCI timeouts */
...@@ -69,6 +72,12 @@ struct nci_ops { ...@@ -69,6 +72,12 @@ struct nci_ops {
int (*send)(struct nci_dev *ndev, struct sk_buff *skb); int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
int (*setup)(struct nci_dev *ndev); int (*setup)(struct nci_dev *ndev);
__u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol); __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
int (*discover_se)(struct nci_dev *ndev);
int (*disable_se)(struct nci_dev *ndev, u32 se_idx);
int (*enable_se)(struct nci_dev *ndev, u32 se_idx);
int (*se_io)(struct nci_dev *ndev, u32 se_idx,
u8 *apdu, size_t apdu_length,
se_io_cb_t cb, void *cb_context);
}; };
#define NCI_MAX_SUPPORTED_RF_INTERFACES 4 #define NCI_MAX_SUPPORTED_RF_INTERFACES 4
......
/* /*
* Copyright (C) 2011 Instituto Nokia de Tecnologia * Copyright (C) 2011 Instituto Nokia de Tecnologia
* Copyright (C) 2014 Marvell International Ltd.
* *
* Authors: * Authors:
* Lauro Ramos Venancio <lauro.venancio@openbossa.org> * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
...@@ -87,6 +88,7 @@ struct nfc_ops { ...@@ -87,6 +88,7 @@ struct nfc_ops {
#define NFC_TARGET_IDX_ANY -1 #define NFC_TARGET_IDX_ANY -1
#define NFC_MAX_GT_LEN 48 #define NFC_MAX_GT_LEN 48
#define NFC_ATR_RES_GT_OFFSET 15 #define NFC_ATR_RES_GT_OFFSET 15
#define NFC_ATR_REQ_GT_OFFSET 14
/** /**
* struct nfc_target - NFC target descriptiom * struct nfc_target - NFC target descriptiom
......
...@@ -116,6 +116,7 @@ enum nfc_commands { ...@@ -116,6 +116,7 @@ enum nfc_commands {
NFC_EVENT_SE_TRANSACTION, NFC_EVENT_SE_TRANSACTION,
NFC_CMD_GET_SE, NFC_CMD_GET_SE,
NFC_CMD_SE_IO, NFC_CMD_SE_IO,
NFC_CMD_ACTIVATE_TARGET,
/* private: internal use only */ /* private: internal use only */
__NFC_CMD_AFTER_LAST __NFC_CMD_AFTER_LAST
}; };
...@@ -202,6 +203,10 @@ enum nfc_sdp_attr { ...@@ -202,6 +203,10 @@ enum nfc_sdp_attr {
#define NFC_NFCID3_MAXSIZE 10 #define NFC_NFCID3_MAXSIZE 10
#define NFC_SENSB_RES_MAXSIZE 12 #define NFC_SENSB_RES_MAXSIZE 12
#define NFC_SENSF_RES_MAXSIZE 18 #define NFC_SENSF_RES_MAXSIZE 18
#define NFC_ATR_REQ_MAXSIZE 64
#define NFC_ATR_RES_MAXSIZE 64
#define NFC_ATR_REQ_GB_MAXSIZE 48
#define NFC_ATR_RES_GB_MAXSIZE 47
#define NFC_GB_MAXSIZE 48 #define NFC_GB_MAXSIZE 48
#define NFC_FIRMWARE_NAME_MAXSIZE 32 #define NFC_FIRMWARE_NAME_MAXSIZE 32
#define NFC_ISO15693_UID_MAXSIZE 8 #define NFC_ISO15693_UID_MAXSIZE 8
......
This diff is collapsed.
...@@ -345,6 +345,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, ...@@ -345,6 +345,9 @@ int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate,
pr_debug("\n"); pr_debug("\n");
if (hdev->gate2pipe[dest_gate] == NFC_HCI_DO_NOT_CREATE_PIPE)
return 0;
if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE) if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
return -EADDRINUSE; return -EADDRINUSE;
......
...@@ -167,6 +167,48 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, ...@@ -167,6 +167,48 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
struct sk_buff *skb) struct sk_buff *skb)
{ {
int r = 0;
u8 gate = nfc_hci_pipe2gate(hdev, pipe);
u8 local_gate, new_pipe;
u8 gate_opened = 0x00;
pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
switch (cmd) {
case NFC_HCI_ADM_NOTIFY_PIPE_CREATED:
if (skb->len != 5) {
r = -EPROTO;
break;
}
local_gate = skb->data[3];
new_pipe = skb->data[4];
nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
/* save the new created pipe and bind with local gate,
* the description for skb->data[3] is destination gate id
* but since we received this cmd from host controller, we
* are the destination and it is our local gate
*/
hdev->gate2pipe[local_gate] = new_pipe;
break;
case NFC_HCI_ANY_OPEN_PIPE:
/* if the pipe is already created, we allow remote host to
* open it
*/
if (gate != 0xff)
nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK,
&gate_opened, 1);
break;
case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
break;
default:
pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate);
r = -EINVAL;
break;
}
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -717,6 +759,19 @@ static int hci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) ...@@ -717,6 +759,19 @@ static int hci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx)
return 0; return 0;
} }
static int hci_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 nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
if (hdev->ops->se_io)
return hdev->ops->se_io(hdev, se_idx, apdu,
apdu_length, cb, cb_context);
return 0;
}
static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err) static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
{ {
mutex_lock(&hdev->msg_tx_mutex); mutex_lock(&hdev->msg_tx_mutex);
...@@ -830,6 +885,7 @@ static struct nfc_ops hci_nfc_ops = { ...@@ -830,6 +885,7 @@ static struct nfc_ops hci_nfc_ops = {
.discover_se = hci_discover_se, .discover_se = hci_discover_se,
.enable_se = hci_enable_se, .enable_se = hci_enable_se,
.disable_se = hci_disable_se, .disable_se = hci_disable_se,
.se_io = hci_se_io,
}; };
struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
......
...@@ -401,7 +401,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) ...@@ -401,7 +401,8 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
u8 *miux_tlv = NULL, miux_tlv_length; u8 *miux_tlv = NULL, miux_tlv_length;
u8 *rw_tlv = NULL, rw_tlv_length, rw; u8 *rw_tlv = NULL, rw_tlv_length, rw;
int err; int err;
u16 size = 0, miux; u16 size = 0;
__be16 miux;
pr_debug("Sending CONNECT\n"); pr_debug("Sending CONNECT\n");
...@@ -465,7 +466,8 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) ...@@ -465,7 +466,8 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock)
u8 *miux_tlv = NULL, miux_tlv_length; u8 *miux_tlv = NULL, miux_tlv_length;
u8 *rw_tlv = NULL, rw_tlv_length, rw; u8 *rw_tlv = NULL, rw_tlv_length, rw;
int err; int err;
u16 size = 0, miux; u16 size = 0;
__be16 miux;
pr_debug("Sending CC\n"); pr_debug("Sending CC\n");
......
/* /*
* Copyright (C) 2011 Intel Corporation. All rights reserved. * Copyright (C) 2011 Intel Corporation. All rights reserved.
* Copyright (C) 2014 Marvell International Ltd.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -1511,8 +1512,10 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) ...@@ -1511,8 +1512,10 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
struct nfc_llcp_local *local; struct nfc_llcp_local *local;
local = nfc_llcp_find_local(dev); local = nfc_llcp_find_local(dev);
if (local == NULL) if (local == NULL) {
kfree_skb(skb);
return -ENODEV; return -ENODEV;
}
__nfc_llcp_recv(local, skb); __nfc_llcp_recv(local, skb);
......
...@@ -524,12 +524,12 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -524,12 +524,12 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr,
static inline unsigned int llcp_accept_poll(struct sock *parent) static inline unsigned int llcp_accept_poll(struct sock *parent)
{ {
struct nfc_llcp_sock *llcp_sock, *n, *parent_sock; struct nfc_llcp_sock *llcp_sock, *parent_sock;
struct sock *sk; struct sock *sk;
parent_sock = nfc_llcp_sock(parent); parent_sock = nfc_llcp_sock(parent);
list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue, list_for_each_entry(llcp_sock, &parent_sock->accept_queue,
accept_queue) { accept_queue) {
sk = &llcp_sock->sk; sk = &llcp_sock->sk;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* NFC Controller (NFCC) and a Device Host (DH). * NFC Controller (NFCC) and a Device Host (DH).
* *
* Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2014 Marvell International Ltd.
* *
* Written by Ilan Elias <ilane@ti.com> * Written by Ilan Elias <ilane@ti.com>
* *
...@@ -196,18 +197,24 @@ static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt) ...@@ -196,18 +197,24 @@ static void nci_set_config_req(struct nci_dev *ndev, unsigned long opt)
nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd); nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd);
} }
struct nci_rf_discover_param {
__u32 im_protocols;
__u32 tm_protocols;
};
static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) 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; struct nci_rf_disc_cmd cmd;
__u32 protocols = opt;
cmd.num_disc_configs = 0; cmd.num_disc_configs = 0;
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
(protocols & NFC_PROTO_JEWEL_MASK || (param->im_protocols & NFC_PROTO_JEWEL_MASK ||
protocols & NFC_PROTO_MIFARE_MASK || param->im_protocols & NFC_PROTO_MIFARE_MASK ||
protocols & NFC_PROTO_ISO14443_MASK || param->im_protocols & NFC_PROTO_ISO14443_MASK ||
protocols & NFC_PROTO_NFC_DEP_MASK)) { param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_A_PASSIVE_POLL_MODE; NCI_NFC_A_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
...@@ -215,7 +222,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) ...@@ -215,7 +222,7 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
} }
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
(protocols & NFC_PROTO_ISO14443_B_MASK)) { (param->im_protocols & NFC_PROTO_ISO14443_B_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_B_PASSIVE_POLL_MODE; NCI_NFC_B_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
...@@ -223,8 +230,8 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) ...@@ -223,8 +230,8 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
} }
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
(protocols & NFC_PROTO_FELICA_MASK || (param->im_protocols & NFC_PROTO_FELICA_MASK ||
protocols & NFC_PROTO_NFC_DEP_MASK)) { param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_F_PASSIVE_POLL_MODE; NCI_NFC_F_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
...@@ -232,13 +239,25 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) ...@@ -232,13 +239,25 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
} }
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
(protocols & NFC_PROTO_ISO15693_MASK)) { (param->im_protocols & NFC_PROTO_ISO15693_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_V_PASSIVE_POLL_MODE; NCI_NFC_V_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1; cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
cmd.num_disc_configs++; 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, nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
(1 + (cmd.num_disc_configs * sizeof(struct disc_config))), (1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
&cmd); &cmd);
...@@ -280,7 +299,7 @@ static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt) ...@@ -280,7 +299,7 @@ static void nci_rf_deactivate_req(struct nci_dev *ndev, unsigned long opt)
{ {
struct nci_rf_deactivate_cmd cmd; struct nci_rf_deactivate_cmd cmd;
cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE; cmd.type = opt;
nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD, nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
sizeof(struct nci_rf_deactivate_cmd), &cmd); sizeof(struct nci_rf_deactivate_cmd), &cmd);
...@@ -441,6 +460,7 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) ...@@ -441,6 +460,7 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
{ {
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_set_config_param param; struct nci_set_config_param param;
int rc;
param.val = nfc_get_local_general_bytes(nfc_dev, &param.len); param.val = nfc_get_local_general_bytes(nfc_dev, &param.len);
if ((param.val == NULL) || (param.len == 0)) if ((param.val == NULL) || (param.len == 0))
...@@ -451,14 +471,45 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) ...@@ -451,14 +471,45 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev)
param.id = NCI_PN_ATR_REQ_GEN_BYTES; 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, return nci_request(ndev, nci_set_config_req, (unsigned long)&param,
msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
} }
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);
}
static int nci_start_poll(struct nfc_dev *nfc_dev, static int nci_start_poll(struct nfc_dev *nfc_dev,
__u32 im_protocols, __u32 tm_protocols) __u32 im_protocols, __u32 tm_protocols)
{ {
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_rf_discover_param param;
int rc; int rc;
if ((atomic_read(&ndev->state) == NCI_DISCOVERY) || if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
...@@ -476,13 +527,14 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, ...@@ -476,13 +527,14 @@ static int nci_start_poll(struct nfc_dev *nfc_dev,
(atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) { (atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
pr_debug("target active or w4 select, implicitly deactivate\n"); pr_debug("target active or w4 select, implicitly deactivate\n");
rc = nci_request(ndev, nci_rf_deactivate_req, 0, rc = nci_request(ndev, nci_rf_deactivate_req,
NCI_DEACTIVATE_TYPE_IDLE_MODE,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
if (rc) if (rc)
return -EBUSY; return -EBUSY;
} }
if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
rc = nci_set_local_general_bytes(nfc_dev); rc = nci_set_local_general_bytes(nfc_dev);
if (rc) { if (rc) {
pr_err("failed to set local general bytes\n"); pr_err("failed to set local general bytes\n");
...@@ -490,7 +542,15 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, ...@@ -490,7 +542,15 @@ static int nci_start_poll(struct nfc_dev *nfc_dev,
} }
} }
rc = nci_request(ndev, nci_rf_discover_req, im_protocols, 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)); msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
if (!rc) if (!rc)
...@@ -509,7 +569,7 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev) ...@@ -509,7 +569,7 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev)
return; return;
} }
nci_request(ndev, nci_rf_deactivate_req, 0, nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
} }
...@@ -594,7 +654,8 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, ...@@ -594,7 +654,8 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev,
ndev->target_active_prot = 0; ndev->target_active_prot = 0;
if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) { if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
nci_request(ndev, nci_rf_deactivate_req, 0, nci_request(ndev, nci_rf_deactivate_req,
NCI_DEACTIVATE_TYPE_SLEEP_MODE,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
} }
} }
...@@ -622,9 +683,24 @@ static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, ...@@ -622,9 +683,24 @@ static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
static int nci_dep_link_down(struct nfc_dev *nfc_dev) 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"); pr_debug("entry\n");
if (nfc_dev->rf_mode == NFC_RF_INITIATOR) {
nci_deactivate_target(nfc_dev, NULL); nci_deactivate_target(nfc_dev, NULL);
} 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; return 0;
} }
...@@ -658,18 +734,58 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, ...@@ -658,18 +734,58 @@ static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
return rc; return rc;
} }
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;
}
static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx) 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; return 0;
} }
static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx) 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; return 0;
} }
static int nci_discover_se(struct nfc_dev *nfc_dev) static int nci_discover_se(struct nfc_dev *nfc_dev)
{ {
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
if (ndev->ops->discover_se)
return ndev->ops->discover_se(ndev);
return 0;
}
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; return 0;
} }
...@@ -683,9 +799,11 @@ static struct nfc_ops nci_nfc_ops = { ...@@ -683,9 +799,11 @@ static struct nfc_ops nci_nfc_ops = {
.activate_target = nci_activate_target, .activate_target = nci_activate_target,
.deactivate_target = nci_deactivate_target, .deactivate_target = nci_deactivate_target,
.im_transceive = nci_transceive, .im_transceive = nci_transceive,
.tm_send = nci_tm_send,
.enable_se = nci_enable_se, .enable_se = nci_enable_se,
.disable_se = nci_disable_se, .disable_se = nci_disable_se,
.discover_se = nci_discover_se, .discover_se = nci_discover_se,
.se_io = nci_se_io,
}; };
/* ---- Interface to NCI drivers ---- */ /* ---- Interface to NCI drivers ---- */
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* NFC Controller (NFCC) and a Device Host (DH). * NFC Controller (NFCC) and a Device Host (DH).
* *
* Copyright (C) 2011 Texas Instruments, Inc. * Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2014 Marvell International Ltd.
* *
* Written by Ilan Elias <ilane@ti.com> * Written by Ilan Elias <ilane@ti.com>
* *
...@@ -184,11 +185,16 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb) ...@@ -184,11 +185,16 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb)
static void nci_add_rx_data_frag(struct nci_dev *ndev, static void nci_add_rx_data_frag(struct nci_dev *ndev,
struct sk_buff *skb, struct sk_buff *skb,
__u8 pbf) __u8 pbf, __u8 status)
{ {
int reassembly_len; int reassembly_len;
int err = 0; int err = 0;
if (status) {
err = status;
goto exit;
}
if (ndev->rx_data_reassembly) { if (ndev->rx_data_reassembly) {
reassembly_len = ndev->rx_data_reassembly->len; reassembly_len = ndev->rx_data_reassembly->len;
...@@ -223,13 +229,24 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev, ...@@ -223,13 +229,24 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev,
} }
exit: exit:
if (ndev->nfc_dev->rf_mode == NFC_RF_INITIATOR) {
nci_data_exchange_complete(ndev, skb, err); nci_data_exchange_complete(ndev, skb, err);
} else if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) {
/* Data received in Target mode, forward to nfc core */
err = nfc_tm_data_received(ndev->nfc_dev, skb);
if (err)
pr_err("unable to handle received data\n");
} else {
pr_err("rf mode unknown\n");
kfree_skb(skb);
}
} }
/* Rx Data packet */ /* Rx Data packet */
void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
{ {
__u8 pbf = nci_pbf(skb->data); __u8 pbf = nci_pbf(skb->data);
__u8 status = 0;
pr_debug("len %d\n", skb->len); pr_debug("len %d\n", skb->len);
...@@ -247,8 +264,9 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) ...@@ -247,8 +264,9 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
ndev->target_active_prot == NFC_PROTO_ISO15693) { ndev->target_active_prot == NFC_PROTO_ISO15693) {
/* frame I/F => remove the status byte */ /* frame I/F => remove the status byte */
pr_debug("frame I/F => remove the status byte\n"); pr_debug("frame I/F => remove the status byte\n");
status = skb->data[skb->len - 1];
skb_trim(skb, (skb->len - 1)); skb_trim(skb, (skb->len - 1));
} }
nci_add_rx_data_frag(ndev, skb, pbf); nci_add_rx_data_frag(ndev, skb, pbf, nci_to_errno(status));
} }
...@@ -103,7 +103,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, ...@@ -103,7 +103,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev,
struct rf_tech_specific_params_nfca_poll *nfca_poll, struct rf_tech_specific_params_nfca_poll *nfca_poll,
__u8 *data) __u8 *data)
{ {
nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data));
data += 2; data += 2;
nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
...@@ -167,7 +167,19 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev, ...@@ -167,7 +167,19 @@ static __u8 *nci_extract_rf_params_nfcv_passive_poll(struct nci_dev *ndev,
return data; return data;
} }
__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol) static __u8 *nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev,
struct rf_tech_specific_params_nfcf_listen *nfcf_listen,
__u8 *data)
{
nfcf_listen->local_nfcid2_len = min_t(__u8, *data++,
NFC_NFCID2_MAXSIZE);
memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len);
data += nfcf_listen->local_nfcid2_len;
return data;
}
static __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
{ {
if (ndev->ops->get_rfprotocol) if (ndev->ops->get_rfprotocol)
return ndev->ops->get_rfprotocol(ndev, rf_protocol); return ndev->ops->get_rfprotocol(ndev, rf_protocol);
...@@ -401,17 +413,29 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev, ...@@ -401,17 +413,29 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
struct nci_rf_intf_activated_ntf *ntf, __u8 *data) struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
{ {
struct activation_params_poll_nfc_dep *poll; struct activation_params_poll_nfc_dep *poll;
struct activation_params_listen_nfc_dep *listen;
switch (ntf->activation_rf_tech_and_mode) { switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE: case NCI_NFC_A_PASSIVE_POLL_MODE:
case NCI_NFC_F_PASSIVE_POLL_MODE: case NCI_NFC_F_PASSIVE_POLL_MODE:
poll = &ntf->activation_params.poll_nfc_dep; poll = &ntf->activation_params.poll_nfc_dep;
poll->atr_res_len = min_t(__u8, *data++, 63); poll->atr_res_len = min_t(__u8, *data++,
NFC_ATR_RES_MAXSIZE - 2);
pr_debug("atr_res_len %d\n", poll->atr_res_len); pr_debug("atr_res_len %d\n", poll->atr_res_len);
if (poll->atr_res_len > 0) if (poll->atr_res_len > 0)
memcpy(poll->atr_res, data, poll->atr_res_len); memcpy(poll->atr_res, data, poll->atr_res_len);
break; break;
case NCI_NFC_A_PASSIVE_LISTEN_MODE:
case NCI_NFC_F_PASSIVE_LISTEN_MODE:
listen = &ntf->activation_params.listen_nfc_dep;
listen->atr_req_len = min_t(__u8, *data++,
NFC_ATR_REQ_MAXSIZE - 2);
pr_debug("atr_req_len %d\n", listen->atr_req_len);
if (listen->atr_req_len > 0)
memcpy(listen->atr_req, data, listen->atr_req_len);
break;
default: default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf->activation_rf_tech_and_mode); ntf->activation_rf_tech_and_mode);
...@@ -444,6 +468,48 @@ static void nci_target_auto_activated(struct nci_dev *ndev, ...@@ -444,6 +468,48 @@ static void nci_target_auto_activated(struct nci_dev *ndev,
nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets); nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets);
} }
static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev,
struct nci_rf_intf_activated_ntf *ntf)
{
ndev->remote_gb_len = 0;
if (ntf->activation_params_len <= 0)
return NCI_STATUS_OK;
switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE:
case NCI_NFC_F_PASSIVE_POLL_MODE:
ndev->remote_gb_len = min_t(__u8,
(ntf->activation_params.poll_nfc_dep.atr_res_len
- NFC_ATR_RES_GT_OFFSET),
NFC_ATR_RES_GB_MAXSIZE);
memcpy(ndev->remote_gb,
(ntf->activation_params.poll_nfc_dep.atr_res
+ NFC_ATR_RES_GT_OFFSET),
ndev->remote_gb_len);
break;
case NCI_NFC_A_PASSIVE_LISTEN_MODE:
case NCI_NFC_F_PASSIVE_LISTEN_MODE:
ndev->remote_gb_len = min_t(__u8,
(ntf->activation_params.listen_nfc_dep.atr_req_len
- NFC_ATR_REQ_GT_OFFSET),
NFC_ATR_REQ_GB_MAXSIZE);
memcpy(ndev->remote_gb,
(ntf->activation_params.listen_nfc_dep.atr_req
+ NFC_ATR_REQ_GT_OFFSET),
ndev->remote_gb_len);
break;
default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf->activation_rf_tech_and_mode);
return NCI_STATUS_RF_PROTOCOL_ERROR;
}
return NCI_STATUS_OK;
}
static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -493,6 +559,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, ...@@ -493,6 +559,16 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
&(ntf.rf_tech_specific_params.nfcv_poll), data); &(ntf.rf_tech_specific_params.nfcv_poll), data);
break; break;
case NCI_NFC_A_PASSIVE_LISTEN_MODE:
/* no RF technology specific parameters */
break;
case NCI_NFC_F_PASSIVE_LISTEN_MODE:
data = nci_extract_rf_params_nfcf_passive_listen(ndev,
&(ntf.rf_tech_specific_params.nfcf_listen),
data);
break;
default: default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf.activation_rf_tech_and_mode); ntf.activation_rf_tech_and_mode);
...@@ -546,33 +622,40 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, ...@@ -546,33 +622,40 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
/* store general bytes to be reported later in dep_link_up */ /* store general bytes to be reported later in dep_link_up */
if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) { if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
ndev->remote_gb_len = 0; err = nci_store_general_bytes_nfc_dep(ndev, &ntf);
if (err != NCI_STATUS_OK)
if (ntf.activation_params_len > 0) { pr_err("unable to store general bytes\n");
/* ATR_RES general bytes at offset 15 */
ndev->remote_gb_len = min_t(__u8,
(ntf.activation_params
.poll_nfc_dep.atr_res_len
- NFC_ATR_RES_GT_OFFSET),
NFC_MAX_GT_LEN);
memcpy(ndev->remote_gb,
(ntf.activation_params.poll_nfc_dep
.atr_res + NFC_ATR_RES_GT_OFFSET),
ndev->remote_gb_len);
}
} }
} }
if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) {
/* Poll mode */
if (atomic_read(&ndev->state) == NCI_DISCOVERY) { if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
/* A single target was found and activated automatically */ /* A single target was found and activated
* automatically */
atomic_set(&ndev->state, NCI_POLL_ACTIVE); atomic_set(&ndev->state, NCI_POLL_ACTIVE);
if (err == NCI_STATUS_OK) if (err == NCI_STATUS_OK)
nci_target_auto_activated(ndev, &ntf); nci_target_auto_activated(ndev, &ntf);
} else { /* ndev->state == NCI_W4_HOST_SELECT */ } else { /* ndev->state == NCI_W4_HOST_SELECT */
/* A selected target was activated, so complete the request */ /* A selected target was activated, so complete the
* request */
atomic_set(&ndev->state, NCI_POLL_ACTIVE); atomic_set(&ndev->state, NCI_POLL_ACTIVE);
nci_req_complete(ndev, err); nci_req_complete(ndev, err);
} }
} else {
/* Listen mode */
atomic_set(&ndev->state, NCI_LISTEN_ACTIVE);
if (err == NCI_STATUS_OK &&
ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) {
err = nfc_tm_activated(ndev->nfc_dev,
NFC_PROTO_NFC_DEP_MASK,
NFC_COMM_PASSIVE,
ndev->remote_gb,
ndev->remote_gb_len);
if (err != NCI_STATUS_OK)
pr_err("error when signaling tm activation\n");
}
}
} }
static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
...@@ -595,8 +678,21 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, ...@@ -595,8 +678,21 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev,
if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags)) if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
nci_data_exchange_complete(ndev, NULL, -EIO); nci_data_exchange_complete(ndev, NULL, -EIO);
switch (ntf->type) {
case NCI_DEACTIVATE_TYPE_IDLE_MODE:
nci_clear_target_list(ndev); nci_clear_target_list(ndev);
atomic_set(&ndev->state, NCI_IDLE); atomic_set(&ndev->state, NCI_IDLE);
break;
case NCI_DEACTIVATE_TYPE_SLEEP_MODE:
case NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE:
atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
break;
case NCI_DEACTIVATE_TYPE_DISCOVERY:
nci_clear_target_list(ndev);
atomic_set(&ndev->state, NCI_DISCOVERY);
break;
}
nci_req_complete(ndev, NCI_STATUS_OK); nci_req_complete(ndev, NCI_STATUS_OK);
} }
......
...@@ -810,6 +810,31 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) ...@@ -810,6 +810,31 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
return rc; return rc;
} }
static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
{
struct nfc_dev *dev;
u32 device_idx, target_idx, protocol;
int rc;
if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
return -EINVAL;
device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
dev = nfc_get_device(device_idx);
if (!dev)
return -ENODEV;
target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
nfc_deactivate_target(dev, target_idx);
rc = nfc_activate_target(dev, target_idx, protocol);
nfc_put_device(dev);
return 0;
}
static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info) static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
{ {
struct nfc_dev *dev; struct nfc_dev *dev;
...@@ -1285,6 +1310,51 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb) ...@@ -1285,6 +1310,51 @@ static int nfc_genl_dump_ses_done(struct netlink_callback *cb)
return 0; return 0;
} }
static int nfc_se_io(struct nfc_dev *dev, u32 se_idx,
u8 *apdu, size_t apdu_length,
se_io_cb_t cb, void *cb_context)
{
struct nfc_se *se;
int rc;
pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
device_lock(&dev->dev);
if (!device_is_registered(&dev->dev)) {
rc = -ENODEV;
goto error;
}
if (!dev->dev_up) {
rc = -ENODEV;
goto error;
}
if (!dev->ops->se_io) {
rc = -EOPNOTSUPP;
goto error;
}
se = nfc_find_se(dev, se_idx);
if (!se) {
rc = -EINVAL;
goto error;
}
if (se->state != NFC_SE_ENABLED) {
rc = -ENODEV;
goto error;
}
rc = dev->ops->se_io(dev, se_idx, apdu,
apdu_length, cb, cb_context);
error:
device_unlock(&dev->dev);
return rc;
}
struct se_io_ctx { struct se_io_ctx {
u32 dev_idx; u32 dev_idx;
u32 se_idx; u32 se_idx;
...@@ -1367,7 +1437,7 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) ...@@ -1367,7 +1437,7 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info)
ctx->dev_idx = dev_idx; ctx->dev_idx = dev_idx;
ctx->se_idx = se_idx; ctx->se_idx = se_idx;
return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
} }
static const struct genl_ops nfc_genl_ops[] = { static const struct genl_ops nfc_genl_ops[] = {
...@@ -1455,6 +1525,11 @@ static const struct genl_ops nfc_genl_ops[] = { ...@@ -1455,6 +1525,11 @@ static const struct genl_ops nfc_genl_ops[] = {
.doit = nfc_genl_se_io, .doit = nfc_genl_se_io,
.policy = nfc_genl_policy, .policy = nfc_genl_policy,
}, },
{
.cmd = NFC_CMD_ACTIVATE_TARGET,
.doit = nfc_genl_activate_target,
.policy = nfc_genl_policy,
},
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment