1 /*--------------------------------------------------------------------------
2 Copyright (c) 2013, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of The Linux Foundation nor
12 the names of its contributors may be used to endorse or promote
13 products derived from this software without specific prior written
14 permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28
29 #ifdef WCNSS_QMI
30 #define LOG_TAG "wcnss_qmi"
31 #include <cutils/log.h>
32 #include "wcnss_qmi_client.h"
33 #include "qmi.h"
34 #include "qmi_client.h"
35 #include "device_management_service_v01.h"
36 #include <cutils/properties.h>
37
38 #define SUCCESS 0
39 #define FAILED -1
40
41 #define WLAN_ADDR_SIZE 6
42 #define DMS_QMI_TIMEOUT (2000)
43
44 static qmi_client_type dms_qmi_client;
45 static int qmi_handle;
46 static int dms_init_done = FAILED;
47
48 /* Android system property for fetching the modem type */
49 #define QMI_UIM_PROPERTY_BASEBAND "ro.baseband"
50
51 /* Android system property values for various modem types */
52 #define QMI_UIM_PROP_BASEBAND_VALUE_SVLTE_1 "svlte1"
53 #define QMI_UIM_PROP_BASEBAND_VALUE_SVLTE_2A "svlte2a"
54 #define QMI_UIM_PROP_BASEBAND_VALUE_CSFB "csfb"
55 #define QMI_UIM_PROP_BASEBAND_VALUE_SGLTE "sglte"
56 #define QMI_UIM_PROP_BASEBAND_VALUE_SGLTE2 "sglte2"
57 #define QMI_UIM_PROP_BASEBAND_VALUE_MSM "msm"
58 #define QMI_UIM_PROP_BASEBAND_VALUE_APQ "apq"
59 #define QMI_UIM_PROP_BASEBAND_VALUE_MDMUSB "mdm"
60 #define QMI_UIM_PROP_BASEBAND_VALUE_DSDA "dsda"
61 #define QMI_UIM_PROP_BASEBAND_VALUE_DSDA_2 "dsda2"
62
dms_find_modem_port(char * prop_value_ptr)63 static char *dms_find_modem_port( char *prop_value_ptr)
64 {
65 char *qmi_modem_port_ptr = QMI_PORT_RMNET_0;
66
67 /* Sanity check */
68 if (prop_value_ptr == NULL) {
69 ALOGE("%s", "NULL prop_value_ptr, using default port",
70 __func__);
71 return qmi_modem_port_ptr;
72 }
73
74 ALOGE("%s: Baseband property value read: %s", __func__,
75 prop_value_ptr);
76
77 /* Map the port based on the read property */
78 if ((strcmp(prop_value_ptr,
79 QMI_UIM_PROP_BASEBAND_VALUE_SVLTE_1) == 0) ||
80 (strcmp(prop_value_ptr,
81 QMI_UIM_PROP_BASEBAND_VALUE_SVLTE_2A) == 0) ||
82 (strcmp(prop_value_ptr,
83 QMI_UIM_PROP_BASEBAND_VALUE_CSFB) == 0)) {
84 qmi_modem_port_ptr = QMI_PORT_RMNET_SDIO_0;
85 } else if ((strcmp(prop_value_ptr,
86 QMI_UIM_PROP_BASEBAND_VALUE_MDMUSB) == 0) ||
87 (strcmp(prop_value_ptr,
88 QMI_UIM_PROP_BASEBAND_VALUE_SGLTE2) == 0)) {
89 qmi_modem_port_ptr = QMI_PORT_RMNET_USB_0;
90 } else if ((strcmp(prop_value_ptr,
91 QMI_UIM_PROP_BASEBAND_VALUE_MSM) == 0) ||
92 (strcmp(prop_value_ptr,
93 QMI_UIM_PROP_BASEBAND_VALUE_APQ) == 0) ||
94 (strcmp(prop_value_ptr,
95 QMI_UIM_PROP_BASEBAND_VALUE_SGLTE) == 0)) {
96 qmi_modem_port_ptr = QMI_PORT_RMNET_0;
97 } else if (strcmp(prop_value_ptr,
98 QMI_UIM_PROP_BASEBAND_VALUE_DSDA) == 0) {
99 /* If it is a DSDA configuration, use the existing API */
100 qmi_modem_port_ptr = (char *)QMI_PLATFORM_INTERNAL_USE_PORT_ID;
101 } else if (strcmp(prop_value_ptr,
102 QMI_UIM_PROP_BASEBAND_VALUE_DSDA_2) == 0) {
103 /* If it is a DSDA2 configuration, use the existing API */
104 qmi_modem_port_ptr = (char *)QMI_PLATFORM_INTERNAL_USE_PORT_ID;
105 } else {
106 ALOGE("%s: Property value does not match,using default port:%s",
107 __func__, qmi_modem_port_ptr);
108 }
109
110 ALOGE("%s: QMI port found for modem: %s", __func__, qmi_modem_port_ptr);
111
112 return qmi_modem_port_ptr;
113 }
114
wcnss_init_qmi()115 int wcnss_init_qmi()
116 {
117 qmi_client_error_type qmi_client_err;
118 qmi_idl_service_object_type dms_service;
119 char prop_value[PROPERTY_VALUE_MAX];
120 char *qmi_modem_port = NULL;
121
122 ALOGE("%s: Initialize wcnss QMI Interface", __func__);
123
124 qmi_handle = qmi_init(NULL, NULL);
125 if (qmi_handle < 0) {
126 ALOGE("%s: Error while initializing qmi", __func__);
127 return FAILED;
128 }
129
130 dms_service = dms_get_service_object_v01();
131 if (dms_service == NULL) {
132 ALOGE("%s: Not able to get the service handle", __func__);
133 goto exit;
134 }
135
136 /* Find out the modem type */
137 memset(prop_value, 0x00, sizeof(prop_value));
138 property_get(QMI_UIM_PROPERTY_BASEBAND, prop_value, "");
139
140 /* Map to a respective QMI port */
141 qmi_modem_port = dms_find_modem_port(prop_value);
142 if (qmi_modem_port == NULL) {
143 ALOGE("%s: qmi_modem_port is NULL", __func__);
144 goto exit;
145 }
146
147 qmi_client_err = qmi_client_init((const char *)qmi_modem_port,
148 dms_service, NULL, dms_service, &dms_qmi_client);
149
150 if ((qmi_client_err == QMI_PORT_NOT_OPEN_ERR) &&
151 (strcmp(qmi_modem_port, QMI_PORT_RMNET_0) == 0)){
152 ALOGE("%s: Retrying with port RMNET_1: %d",
153 __func__, qmi_client_err);
154 qmi_modem_port = QMI_PORT_RMNET_1;
155 qmi_client_err = qmi_client_init((const char *)qmi_modem_port,
156 dms_service, NULL, dms_service, &dms_qmi_client);
157 }
158
159 if (qmi_client_err != QMI_NO_ERR){
160 ALOGE("%s: Error while Initializing QMI Client: %d",
161 __func__, qmi_client_err);
162 goto exit;
163 }
164
165 dms_init_done = SUCCESS;
166 return SUCCESS;
167
168 exit:
169 qmi_handle = qmi_release(qmi_handle);
170 if ( qmi_handle < 0 ) {
171 ALOGE("%s: Error while releasing qmi %d",
172 __func__, qmi_handle);
173 }
174 return FAILED;
175 }
176
wcnss_qmi_get_wlan_address(unsigned char * pBdAddr)177 int wcnss_qmi_get_wlan_address(unsigned char *pBdAddr)
178 {
179 qmi_client_error_type qmi_client_err;
180 dms_get_mac_address_req_msg_v01 addr_req;
181 dms_get_mac_address_resp_msg_v01 addr_resp;
182
183 if ((dms_init_done == FAILED) || (pBdAddr == NULL)) {
184 ALOGE("%s: DMS init fail or pBdAddr is NULL", __func__);
185 return FAILED;
186 }
187
188 /* clear the request content */
189 memset(&addr_req, 0, sizeof(addr_req));
190
191 /*Request to get the WLAN MAC address */
192 addr_req.device = DMS_DEVICE_MAC_WLAN_V01;
193
194 qmi_client_err = qmi_client_send_msg_sync(dms_qmi_client,
195 QMI_DMS_GET_MAC_ADDRESS_REQ_V01, &addr_req, sizeof(addr_req),
196 &addr_resp, sizeof(addr_resp), DMS_QMI_TIMEOUT);
197
198 if (qmi_client_err != QMI_NO_ERR){
199 ALOGE("%s: Failed to get Rsp from Modem Error:%d",
200 __func__, qmi_client_err);
201 return FAILED;
202 }
203
204 ALOGE("%s: Mac Address_valid: %d Mac Address Len: %d",
205 __func__, addr_resp.mac_address_valid,
206 addr_resp.mac_address_len);
207
208 if (addr_resp.mac_address_valid &&
209 (addr_resp.mac_address_len == WLAN_ADDR_SIZE)) {
210 memcpy(pBdAddr, addr_resp.mac_address,
211 addr_resp.mac_address_len);
212 ALOGE("%s: Succesfully Read WLAN MAC Address", __func__);
213 return SUCCESS;
214 } else {
215 ALOGE("%s: Failed to Read WLAN MAC Address", __func__);
216 return FAILED;
217 }
218 }
219
wcnss_qmi_deinit()220 void wcnss_qmi_deinit()
221 {
222 qmi_client_error_type qmi_client_err;
223
224 ALOGE("%s: Deinitialize wcnss QMI Interface", __func__);
225
226 if (dms_init_done == FAILED) {
227 ALOGE("%s: DMS Service was not Initialized", __func__);
228 return;
229 }
230
231 qmi_client_err = qmi_client_release(dms_qmi_client);
232
233 if (qmi_client_err != QMI_NO_ERR){
234 ALOGE("%s: Error while releasing qmi_client: %d",
235 __func__, qmi_client_err);
236 }
237
238 qmi_handle = qmi_release(qmi_handle);
239 if (qmi_handle < 0) {
240 ALOGE("%s: Error while releasing qmi %d",
241 __func__, qmi_handle);
242 }
243
244 dms_init_done = FAILED;
245 }
246 #endif
247