1/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * 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 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <fcntl.h> 36#include <errno.h> 37#include <hardware/gps.h> 38#include <cutils/properties.h> 39#include "loc_target.h" 40#include "loc_log.h" 41#include <platform_lib_includes.h> 42 43#define APQ8064_ID_1 "109" 44#define APQ8064_ID_2 "153" 45#define MPQ8064_ID_1 "130" 46#define MSM8930_ID_1 "142" 47#define MSM8930_ID_2 "116" 48#define APQ8030_ID_1 "157" 49#define APQ8074_ID_1 "184" 50 51#define LINE_LEN 100 52#define STR_LIQUID "Liquid" 53#define STR_SURF "Surf" 54#define STR_MTP "MTP" 55#define STR_APQ "apq" 56#define STR_APQ_NO_WGR "baseband_apq_nowgr" 57#define STR_AUTO "auto" 58#define IS_STR_END(c) ((c) == '\0' || (c) == '\n' || (c) == '\r') 59#define LENGTH(s) (sizeof(s) - 1) 60#define GPS_CHECK_NO_ERROR 0 61#define GPS_CHECK_NO_GPS_HW 1 62/* When system server is started, it uses 20 seconds as ActivityManager 63 * timeout. After that it sends SIGSTOP signal to process. 64 */ 65#define QCA1530_DETECT_TIMEOUT 15 66#define QCA1530_DETECT_PRESENT "yes" 67#define QCA1530_DETECT_PROGRESS "detect" 68 69static unsigned int gTarget = (unsigned int)-1; 70 71static int read_a_line(const char * file_path, char * line, int line_size) 72{ 73 FILE *fp; 74 int result = 0; 75 76 * line = '\0'; 77 fp = fopen(file_path, "r" ); 78 if( fp == NULL ) { 79 LOC_LOGE("open failed: %s: %s\n", file_path, strerror(errno)); 80 result = -1; 81 } else { 82 int len; 83 fgets(line, line_size, fp); 84 len = strlen(line); 85 len = len < line_size - 1? len : line_size - 1; 86 line[len] = '\0'; 87 LOC_LOGD("cat %s: %s", file_path, line); 88 fclose(fp); 89 } 90 return result; 91} 92 93/*! 94 * \brief Checks if QCA1530 is avalable. 95 * 96 * Function verifies if qca1530 SoC is configured on the device. The test is 97 * based on property value. For 1530 scenario, the value shall be one of the 98 * following: "yes", "no", "detect". All other values are treated equally to 99 * "no". When the value is "detect" the system waits for SoC detection to 100 * finish before returning result. 101 * 102 * \retval true - QCA1530 is available. 103 * \retval false - QCA1530 is not available. 104 */ 105static bool is_qca1530(void) 106{ 107 static const char qca1530_property_name[] = "sys.qca1530"; 108 bool res = false; 109 int ret, i; 110 char buf[PROPERTY_VALUE_MAX]; 111 112 memset(buf, 0, sizeof(buf)); 113 114 for (i = 0; i < QCA1530_DETECT_TIMEOUT; ++i) 115 { 116 ret = platform_lib_abstraction_property_get(qca1530_property_name, buf, NULL); 117 if (ret < 0) 118 { 119 LOC_LOGV( "qca1530: property %s is not accessible, ret=%d", 120 qca1530_property_name, 121 ret); 122 123 break; 124 } 125 126 LOC_LOGV( "qca1530: property %s is set to %s", 127 qca1530_property_name, 128 buf); 129 130 if (!memcmp(buf, QCA1530_DETECT_PRESENT, 131 sizeof(QCA1530_DETECT_PRESENT))) 132 { 133 res = true; 134 break; 135 } 136 if (!memcmp(buf, QCA1530_DETECT_PROGRESS, 137 sizeof(QCA1530_DETECT_PROGRESS))) 138 { 139 LOC_LOGV("qca1530: SoC detection is in progress."); 140 sleep(1); 141 continue; 142 } 143 break; 144 } 145 146 LOC_LOGD("qca1530: detected=%s", res ? "true" : "false"); 147 return res; 148} 149 150/*The character array passed to this function should have length 151 of atleast PROPERTY_VALUE_MAX*/ 152void loc_get_target_baseband(char *baseband, int array_length) 153{ 154 if(baseband && (array_length >= PROPERTY_VALUE_MAX)) { 155 property_get("ro.baseband", baseband, ""); 156 LOC_LOGD("%s:%d]: Baseband: %s\n", __func__, __LINE__, baseband); 157 } 158 else { 159 LOC_LOGE("%s:%d]: NULL parameter or array length less than PROPERTY_VALUE_MAX\n", 160 __func__, __LINE__); 161 } 162} 163 164/*The character array passed to this function should have length 165 of atleast PROPERTY_VALUE_MAX*/ 166void loc_get_platform_name(char *platform_name, int array_length) 167{ 168 if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) { 169 property_get("ro.board.platform", platform_name, ""); 170 LOC_LOGD("%s:%d]: Target name: %s\n", __func__, __LINE__, platform_name); 171 } 172 else { 173 LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n", 174 __func__, __LINE__); 175 } 176} 177 178/*The character array passed to this function should have length 179 of atleast PROPERTY_VALUE_MAX*/ 180void loc_get_auto_platform_name(char *platform_name, int array_length) 181{ 182 if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) { 183 property_get("ro.hardware.type", platform_name, ""); 184 LOC_LOGD("%s:%d]: Autoplatform name: %s\n", __func__, __LINE__, platform_name); 185 } 186 else { 187 LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n", 188 __func__, __LINE__); 189 } 190} 191 192unsigned int loc_get_target(void) 193{ 194 if (gTarget != (unsigned int)-1) 195 return gTarget; 196 197 static const char hw_platform[] = "/sys/devices/soc0/hw_platform"; 198 static const char id[] = "/sys/devices/soc0/soc_id"; 199 static const char hw_platform_dep[] = 200 "/sys/devices/system/soc/soc0/hw_platform"; 201 static const char id_dep[] = "/sys/devices/system/soc/soc0/id"; 202 static const char mdm[] = "/dev/mdm"; // No such file or directory 203 204 char rd_hw_platform[LINE_LEN]; 205 char rd_id[LINE_LEN]; 206 char rd_mdm[LINE_LEN]; 207 char baseband[LINE_LEN]; 208 char rd_auto_platform[LINE_LEN]; 209 210 if (is_qca1530()) { 211 gTarget = TARGET_QCA1530; 212 goto detected; 213 } 214 215 loc_get_target_baseband(baseband, sizeof(baseband)); 216 217 if (!access(hw_platform, F_OK)) { 218 read_a_line(hw_platform, rd_hw_platform, LINE_LEN); 219 } else { 220 read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN); 221 } 222 if (!access(id, F_OK)) { 223 read_a_line(id, rd_id, LINE_LEN); 224 } else { 225 read_a_line(id_dep, rd_id, LINE_LEN); 226 } 227 228 /*check automotive platform*/ 229 loc_get_auto_platform_name(rd_auto_platform, sizeof(rd_auto_platform)); 230 if( !memcmp(rd_auto_platform, STR_AUTO, LENGTH(STR_AUTO)) ) 231 { 232 gTarget = TARGET_AUTO; 233 goto detected; 234 } 235 236 if( !memcmp(baseband, STR_APQ_NO_WGR, LENGTH(STR_APQ_NO_WGR)) ){ 237 238 gTarget = TARGET_NO_GNSS; 239 goto detected; 240 } 241 242 if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) ){ 243 244 if( !memcmp(rd_id, MPQ8064_ID_1, LENGTH(MPQ8064_ID_1)) 245 && IS_STR_END(rd_id[LENGTH(MPQ8064_ID_1)]) ) 246 gTarget = TARGET_NO_GNSS; 247 else 248 gTarget = TARGET_APQ_SA; 249 } 250 else { 251 if( (!memcmp(rd_hw_platform, STR_LIQUID, LENGTH(STR_LIQUID)) 252 && IS_STR_END(rd_hw_platform[LENGTH(STR_LIQUID)])) || 253 (!memcmp(rd_hw_platform, STR_SURF, LENGTH(STR_SURF)) 254 && IS_STR_END(rd_hw_platform[LENGTH(STR_SURF)])) || 255 (!memcmp(rd_hw_platform, STR_MTP, LENGTH(STR_MTP)) 256 && IS_STR_END(rd_hw_platform[LENGTH(STR_MTP)]))) { 257 258 if (!read_a_line( mdm, rd_mdm, LINE_LEN)) 259 gTarget = TARGET_MDM; 260 } 261 else if( (!memcmp(rd_id, MSM8930_ID_1, LENGTH(MSM8930_ID_1)) 262 && IS_STR_END(rd_id[LENGTH(MSM8930_ID_1)])) || 263 (!memcmp(rd_id, MSM8930_ID_2, LENGTH(MSM8930_ID_2)) 264 && IS_STR_END(rd_id[LENGTH(MSM8930_ID_2)])) ) 265 gTarget = TARGET_MSM_NO_SSC; 266 else 267 gTarget = TARGET_UNKNOWN; 268 } 269 270detected: 271 LOC_LOGD("HAL: %s returned %d", __FUNCTION__, gTarget); 272 return gTarget; 273} 274 275/*Reads the property ro.lean to identify if this is a lean target 276 Returns: 277 0 if not a lean and mean target 278 1 if this is a lean and mean target 279*/ 280int loc_identify_lean_target() 281{ 282 int ret = 0; 283 char lean_target[PROPERTY_VALUE_MAX]; 284 property_get("ro.lean", lean_target, ""); 285 LOC_LOGD("%s:%d]: lean target: %s\n", __func__, __LINE__, lean_target); 286 return !(strncmp(lean_target, "true", PROPERTY_VALUE_MAX)); 287} 288