nfc: st-nci: Move loopback usage from HCI to NCI

NCI provides possible way to run loopback testing has done over HCI.

For us it offers many advantages:
- It simplifies the code: No more need for a vendor_cmds structure
- Loopback over HCI may not be supported in future st-nci firmware

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Christophe Ricard 2016-04-30 09:12:53 +02:00 committed by Samuel Ortiz
parent 1c53855f6b
commit 3aacd7fe55
3 changed files with 14 additions and 66 deletions

View File

@ -113,8 +113,6 @@ static struct nci_hci_gate st_nci_gates[] = {
{NCI_HCI_IDENTITY_MGMT_GATE, NCI_HCI_INVALID_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
{NCI_HCI_LOOPBACK_GATE, NCI_HCI_INVALID_PIPE,
ST_NCI_HOST_CONTROLLER_ID},
/* Secure element pipes are created by secure element host */
{ST_NCI_CONNECTIVITY_GATE, NCI_HCI_DO_NOT_OPEN_PIPE,
@ -385,9 +383,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
case ST_NCI_CONNECTIVITY_GATE:
st_nci_hci_connectivity_event_received(ndev, host, event, skb);
break;
case NCI_HCI_LOOPBACK_GATE:
st_nci_hci_loopback_event_received(ndev, event, skb);
break;
}
}
EXPORT_SYMBOL_GPL(st_nci_hci_event_received);

View File

@ -92,8 +92,7 @@ struct st_nci_se_info {
* white list).
* @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF
* technology. When using this command to anti-collision is done.
* @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF
* connectivity.
* @LOOPBACK: Allow to echo a command and test the Dh to CLF connectivity.
* @HCI_DM_VDC_MEASUREMENT_VALUE: Allow to measure the field applied on the
* CLF antenna. A value between 0 and 0x0f is returned. 0 is maximum.
* @HCI_DM_FWUPD_START: Allow to put CLF into firmware update mode. It is a
@ -115,7 +114,7 @@ enum nfc_vendor_cmds {
HCI_DM_RESET,
HCI_GET_PARAM,
HCI_DM_FIELD_GENERATOR,
HCI_LOOPBACK,
LOOPBACK,
HCI_DM_FWUPD_START,
HCI_DM_FWUPD_END,
HCI_DM_VDC_MEASUREMENT_VALUE,
@ -123,17 +122,11 @@ enum nfc_vendor_cmds {
MANUFACTURER_SPECIFIC,
};
struct st_nci_vendor_info {
struct completion req_completion;
struct sk_buff *rx_skb;
};
struct st_nci_info {
struct llt_ndlc *ndlc;
unsigned long flags;
struct st_nci_se_info se_info;
struct st_nci_vendor_info vendor_info;
};
void st_nci_remove(struct nci_dev *ndev);
@ -155,8 +148,6 @@ void st_nci_hci_event_received(struct nci_dev *ndev, u8 pipe,
void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd,
struct sk_buff *skb);
void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
struct sk_buff *skb);
int st_nci_vendor_cmds_init(struct nci_dev *ndev);
#endif /* __LOCAL_ST_NCI_H_ */

View File

@ -333,62 +333,28 @@ exit:
return r;
}
void st_nci_hci_loopback_event_received(struct nci_dev *ndev, u8 event,
struct sk_buff *skb)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
switch (event) {
case ST_NCI_EVT_POST_DATA:
info->vendor_info.rx_skb = skb;
break;
default:
nfc_err(&ndev->nfc_dev->dev, "Unexpected event on loopback gate\n");
}
complete(&info->vendor_info.req_completion);
}
EXPORT_SYMBOL(st_nci_hci_loopback_event_received);
static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
size_t data_len)
static int st_nci_loopback(struct nfc_dev *dev, void *data,
size_t data_len)
{
int r;
struct sk_buff *msg;
struct sk_buff *msg, *skb;
struct nci_dev *ndev = nfc_get_drvdata(dev);
struct st_nci_info *info = nci_get_drvdata(ndev);
if (data_len <= 0)
return -EPROTO;
reinit_completion(&info->vendor_info.req_completion);
info->vendor_info.rx_skb = NULL;
r = nci_nfcc_loopback(ndev, data, data_len, &skb);
if (r < 0)
return r;
r = nci_hci_send_event(ndev, NCI_HCI_LOOPBACK_GATE,
ST_NCI_EVT_POST_DATA, data, data_len);
if (r != data_len) {
r = -EPROTO;
goto exit;
}
wait_for_completion_interruptible(&info->vendor_info.req_completion);
if (!info->vendor_info.rx_skb ||
info->vendor_info.rx_skb->len != data_len) {
r = -EPROTO;
goto exit;
}
msg = nfc_vendor_cmd_alloc_reply_skb(ndev->nfc_dev,
ST_NCI_VENDOR_OUI,
HCI_LOOPBACK,
info->vendor_info.rx_skb->len);
msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
LOOPBACK, skb->len);
if (!msg) {
r = -ENOMEM;
goto free_skb;
}
if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
info->vendor_info.rx_skb->data)) {
if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
kfree_skb(msg);
r = -ENOBUFS;
goto free_skb;
@ -396,8 +362,7 @@ static int st_nci_hci_loopback(struct nfc_dev *dev, void *data,
r = nfc_vendor_cmd_reply(msg);
free_skb:
kfree_skb(info->vendor_info.rx_skb);
exit:
kfree_skb(skb);
return r;
}
@ -485,8 +450,8 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
},
{
.vendor_id = ST_NCI_VENDOR_OUI,
.subcmd = HCI_LOOPBACK,
.doit = st_nci_hci_loopback,
.subcmd = LOOPBACK,
.doit = st_nci_loopback,
},
{
.vendor_id = ST_NCI_VENDOR_OUI,
@ -507,9 +472,6 @@ static struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
int st_nci_vendor_cmds_init(struct nci_dev *ndev)
{
struct st_nci_info *info = nci_get_drvdata(ndev);
init_completion(&info->vendor_info.req_completion);
return nfc_set_vendor_cmds(ndev->nfc_dev, st_nci_vendor_cmds,
sizeof(st_nci_vendor_cmds));
}