1 /******************************************************************************
2  *
3  *  Copyright (C) 2010-2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains functions that NCI vendor specific interface with the
22  *  NFCC. On the receive side, it routes events to the appropriate handler
23  *  (callback). On the transmit side, it manages the command transmission.
24  *
25  ******************************************************************************/
26 #include <string.h>
27 
28 #include <android-base/stringprintf.h>
29 #include <base/logging.h>
30 
31 #include "nfc_target.h"
32 
33 #include "gki.h"
34 #include "nfc_int.h"
35 
36 using android::base::StringPrintf;
37 
38 /****************************************************************************
39 ** Declarations
40 ****************************************************************************/
41 
42 /*******************************************************************************
43 **
44 ** Function         NFC_RegVSCback
45 **
46 ** Description      This function is called to register or de-register a
47 **                  callback function to receive Proprietary NCI response and
48 **                  notification events. The maximum number of callback
49 **                  functions allowed is NFC_NUM_VS_CBACKS
50 **
51 ** Returns          tNFC_STATUS
52 **
53 *******************************************************************************/
NFC_RegVSCback(bool is_register,tNFC_VS_CBACK * p_cback)54 tNFC_STATUS NFC_RegVSCback(bool is_register, tNFC_VS_CBACK* p_cback) {
55   tNFC_STATUS status = NFC_STATUS_FAILED;
56   int i;
57 
58   if (is_register) {
59     for (i = 0; i < NFC_NUM_VS_CBACKS; i++) {
60       /* find an empty spot to hold the callback function */
61       if (nfc_cb.p_vs_cb[i] == NULL) {
62         nfc_cb.p_vs_cb[i] = p_cback;
63         status = NFC_STATUS_OK;
64         break;
65       }
66     }
67   } else {
68     for (i = 0; i < NFC_NUM_VS_CBACKS; i++) {
69       /* find the callback to de-register */
70       if (nfc_cb.p_vs_cb[i] == p_cback) {
71         nfc_cb.p_vs_cb[i] = NULL;
72         status = NFC_STATUS_OK;
73         break;
74       }
75     }
76   }
77   return status;
78 }
79 
80 /*******************************************************************************
81 **
82 ** Function         NFC_SendRawVsCommand
83 **
84 ** Description      This function is called to send the raw vendor specific
85 **                  command to NFCC. The response from NFCC is reported to the
86 **                  given tNFC_VS_CBACK.
87 **
88 ** Parameters       p_data - The command buffer
89 **
90 ** Returns          tNFC_STATUS
91 **
92 *******************************************************************************/
NFC_SendRawVsCommand(NFC_HDR * p_data,tNFC_VS_CBACK * p_cback)93 tNFC_STATUS NFC_SendRawVsCommand(NFC_HDR* p_data, tNFC_VS_CBACK* p_cback) {
94   /* Validate parameters */
95   if (p_data == NULL || (p_data->len > NCI_MAX_VSC_SIZE)) {
96     LOG(ERROR) << StringPrintf("buffer offset must be >= %d",
97                                NCI_VSC_MSG_HDR_SIZE);
98     if (p_data) GKI_freebuf(p_data);
99     return NFC_STATUS_INVALID_PARAM;
100   }
101 
102   p_data->event = BT_EVT_TO_NFC_NCI;
103   p_data->layer_specific = NFC_WAIT_RSP_RAW_VS;
104   /* save the callback function in the BT_HDR, to receive the response */
105   ((tNFC_NCI_VS_MSG*)p_data)->p_cback = p_cback;
106 
107   nfc_ncif_check_cmd_queue(p_data);
108   return NFC_STATUS_OK;
109 }
110 
111 /*******************************************************************************
112 **
113 ** Function         NFC_SendVsCommand
114 **
115 ** Description      This function is called to send the given vendor specific
116 **                  command to NFCC. The response from NFCC is reported to the
117 **                  given tNFC_VS_CBACK as (oid).
118 **
119 ** Parameters       oid - The opcode of the VS command.
120 **                  p_data - The parameters for the VS command
121 **
122 ** Returns          tNFC_STATUS
123 **
124 *******************************************************************************/
NFC_SendVsCommand(uint8_t oid,NFC_HDR * p_data,tNFC_VS_CBACK * p_cback)125 tNFC_STATUS NFC_SendVsCommand(uint8_t oid, NFC_HDR* p_data,
126                               tNFC_VS_CBACK* p_cback) {
127   tNFC_STATUS status = NFC_STATUS_OK;
128   uint8_t* pp;
129 
130   /* Allow VSC with 0-length payload */
131   if (p_data == NULL) {
132     p_data = NCI_GET_CMD_BUF(0);
133     if (p_data) {
134       p_data->offset = NCI_VSC_MSG_HDR_SIZE;
135       p_data->len = 0;
136     }
137   }
138 
139   /* Validate parameters */
140   if ((p_data == NULL) || (p_data->offset < NCI_VSC_MSG_HDR_SIZE) ||
141       (p_data->len > NCI_MAX_VSC_SIZE)) {
142     LOG(ERROR) << StringPrintf("buffer offset must be >= %d",
143                                NCI_VSC_MSG_HDR_SIZE);
144     if (p_data) GKI_freebuf(p_data);
145     return NFC_STATUS_INVALID_PARAM;
146   }
147 
148   p_data->event = BT_EVT_TO_NFC_NCI;
149   p_data->layer_specific = NFC_WAIT_RSP_VSC;
150   /* save the callback function in the NFC_HDR, to receive the response */
151   ((tNFC_NCI_VS_MSG*)p_data)->p_cback = p_cback;
152 
153   p_data->offset -= NCI_MSG_HDR_SIZE;
154   pp = (uint8_t*)(p_data + 1) + p_data->offset;
155   NCI_MSG_BLD_HDR0(pp, NCI_MT_CMD, NCI_GID_PROP);
156   NCI_MSG_BLD_HDR1(pp, oid);
157   *pp = (uint8_t)p_data->len;
158   p_data->len += NCI_MSG_HDR_SIZE;
159   nfc_ncif_check_cmd_queue(p_data);
160   return status;
161 }
162