NFC: Set local general bytes in nci_start_poll
authorIlan Elias <ilane@ti.com>
Wed, 15 Aug 2012 08:46:22 +0000 (11:46 +0300)
committerSamuel Ortiz <sameo@linux.intel.com>
Mon, 24 Sep 2012 22:17:23 +0000 (00:17 +0200)
If initiator protocol is NFC-DEP, set the local general bytes
in nci_start_poll.

Signed-off-by: Ilan Elias <ilane@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
include/net/nfc/nci.h
include/net/nfc/nci_core.h
net/nfc/nci/core.c
net/nfc/nci/rsp.c

index 276094b..d260ef3 100644 (file)
@@ -32,6 +32,7 @@
 #define NCI_MAX_NUM_MAPPING_CONFIGS                            10
 #define NCI_MAX_NUM_RF_CONFIGS                                 10
 #define NCI_MAX_NUM_CONN                                       10
+#define NCI_MAX_PARAM_LEN                                      251
 
 /* NCI Status Codes */
 #define NCI_STATUS_OK                                          0x00
 #define NCI_RF_INTERFACE_ISO_DEP                               0x02
 #define NCI_RF_INTERFACE_NFC_DEP                               0x03
 
+/* NCI Configuration Parameter Tags */
+#define NCI_PN_ATR_REQ_GEN_BYTES                               0x29
+
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG                             0x00
 #define NCI_RESET_TYPE_RESET_CONFIG                            0x01
@@ -188,6 +192,18 @@ struct nci_core_reset_cmd {
 
 #define NCI_OP_CORE_INIT_CMD           nci_opcode_pack(NCI_GID_CORE, 0x01)
 
+#define NCI_OP_CORE_SET_CONFIG_CMD     nci_opcode_pack(NCI_GID_CORE, 0x02)
+struct set_config_param {
+       __u8    id;
+       __u8    len;
+       __u8    val[NCI_MAX_PARAM_LEN];
+} __packed;
+
+struct nci_core_set_config_cmd {
+       __u8    num_params;
+       struct  set_config_param param; /* support 1 param per cmd is enough */
+} __packed;
+
 #define NCI_OP_RF_DISCOVER_MAP_CMD     nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 struct disc_map_config {
        __u8    rf_protocol;
@@ -252,6 +268,13 @@ struct nci_core_init_rsp_2 {
        __le32  manufact_specific_info;
 } __packed;
 
+#define NCI_OP_CORE_SET_CONFIG_RSP     nci_opcode_pack(NCI_GID_CORE, 0x02)
+struct nci_core_set_config_rsp {
+       __u8    status;
+       __u8    num_params;
+       __u8    params_id[0];   /* variable size array */
+} __packed;
+
 #define NCI_OP_RF_DISCOVER_MAP_RSP     nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
 
 #define NCI_OP_RF_DISCOVER_RSP         nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
index feba740..f98674d 100644 (file)
@@ -54,6 +54,7 @@ enum nci_state {
 /* NCI timeouts */
 #define NCI_RESET_TIMEOUT                      5000
 #define NCI_INIT_TIMEOUT                       5000
+#define NCI_SET_CONFIG_TIMEOUT                 5000
 #define NCI_RF_DISC_TIMEOUT                    5000
 #define NCI_RF_DISC_SELECT_TIMEOUT             5000
 #define NCI_RF_DEACTIVATE_TIMEOUT              30000
index f81efe1..f017b78 100644 (file)
@@ -176,6 +176,27 @@ static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
                     (1 + ((*num) * sizeof(struct disc_map_config))), &cmd);
 }
 
+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);
+}
+
 static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
 {
        struct nci_rf_disc_cmd cmd;
@@ -388,6 +409,32 @@ static int nci_dev_down(struct nfc_dev *nfc_dev)
        return nci_close_device(ndev);
 }
 
+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;
+       __u8 local_gb[NFC_MAX_GT_LEN];
+       int i, rc = 0;
+
+       param.val = nfc_get_local_general_bytes(nfc_dev, &param.len);
+       if ((param.val == NULL) || (param.len == 0))
+               return rc;
+
+       if (param.len > NCI_MAX_PARAM_LEN)
+               return -EINVAL;
+
+       for (i = 0; i < param.len; i++)
+               local_gb[param.len-1-i] = param.val[i];
+
+       param.id = NCI_PN_ATR_REQ_GEN_BYTES;
+       param.val = local_gb;
+
+       rc = nci_request(ndev, nci_set_config_req, (unsigned long)&param,
+                        msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
+
+       return rc;
+}
+
 static int nci_start_poll(struct nfc_dev *nfc_dev,
                          __u32 im_protocols, __u32 tm_protocols)
 {
@@ -415,6 +462,14 @@ static int nci_start_poll(struct nfc_dev *nfc_dev,
                        return -EBUSY;
        }
 
+       if (im_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;
+               }
+       }
+
        rc = nci_request(ndev, nci_rf_discover_req, im_protocols,
                         msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
 
index 3003c33..dd072f3 100644 (file)
@@ -119,6 +119,16 @@ exit:
        nci_req_complete(ndev, rsp_1->status);
 }
 
+static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
+                                          struct sk_buff *skb)
+{
+       struct nci_core_set_config_rsp *rsp = (void *) skb->data;
+
+       pr_debug("status 0x%x\n", rsp->status);
+
+       nci_req_complete(ndev, rsp->status);
+}
+
 static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev,
                                       struct sk_buff *skb)
 {
@@ -194,6 +204,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
                nci_core_init_rsp_packet(ndev, skb);
                break;
 
+       case NCI_OP_CORE_SET_CONFIG_RSP:
+               nci_core_set_config_rsp_packet(ndev, skb);
+               break;
+
        case NCI_OP_RF_DISCOVER_MAP_RSP:
                nci_rf_disc_map_rsp_packet(ndev, skb);
                break;