wifi_hal_common.cpp revision af52902e4746aab2bd667ac9bdeb1bbb3e46b539
1a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley/*
2a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Copyright 2016, The Android Open Source Project
3a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley *
4a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Licensed under the Apache License, Version 2.0 (the "License");
5a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * you may not use this file except in compliance with the License.
6a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * You may obtain a copy of the License at
7a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley *
8a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley *     http://www.apache.org/licenses/LICENSE-2.0
9a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley *
10a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * Unless required by applicable law or agreed to in writing, software
11a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * distributed under the License is distributed on an "AS IS" BASIS,
12a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * See the License for the specific language governing permissions and
14a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley * limitations under the License.
15a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley */
16a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
17a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include "hardware_legacy/wifi.h"
18a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
19a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#define LOG_TAG "WifiHalCommon"
20a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
21a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <fcntl.h>
22a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <stdlib.h>
23a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <unistd.h>
24a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
25a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/log.h>
26a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/misc.h>
27a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#include <cutils/properties.h>
28a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
29217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int init_module(void *, unsigned long, const char *);
30217f61b2e8d2beed2fe7fa1124e1d4f52a042ab8Alex Vakulenkoextern "C" int delete_module(const char *, unsigned int);
31a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
32a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_STA
33af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_STA NULL
34a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
35a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_AP
36af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_AP NULL
37a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
38a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_FW_PATH_P2P
39af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_FW_PATH_P2P NULL
40a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
41a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
42a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifndef WIFI_DRIVER_MODULE_ARG
43af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley#define WIFI_DRIVER_MODULE_ARG ""
44a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
45a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
46af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_PROP_NAME[] = "wlan.driver.status";
47a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH
48af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME;
49af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " ";
50af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH;
51af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG;
52af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic const char MODULE_FILE[] = "/proc/modules";
53a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
54a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
55af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int insmod(const char *filename, const char *args) {
56af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  void *module;
57af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  unsigned int size;
58af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int ret;
59a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
60af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  module = load_file(filename, &size);
61af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (!module) return -1;
62a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
63af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  ret = init_module(module, size, args);
64a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
65af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  free(module);
66a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
67af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return ret;
68a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
69a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
70af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileystatic int rmmod(const char *modname) {
71af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int ret = -1;
72af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int maxtry = 10;
73af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley
74af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  while (maxtry-- > 0) {
75af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ret = delete_module(modname, O_NONBLOCK | O_EXCL);
76af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    if (ret < 0 && errno == EAGAIN)
77af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      usleep(500000);
78af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    else
79af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      break;
80af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
81af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley
82af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (ret != 0)
83af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGD("Unable to unload driver module \"%s\": %s\n", modname,
84af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley          strerror(errno));
85af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return ret;
86a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
87a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
88a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
89af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_driver_state(const char *state) {
90af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int len;
91af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int fd;
92af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int ret = 0;
93af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley
94af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (!state) return -1;
95af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
96af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (fd < 0) {
97af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGE("Failed to open driver state control param (%s)", strerror(errno));
98af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return -1;
99af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
100af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  len = strlen(state) + 1;
101af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
102af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGE("Failed to write driver state control param (%s)", strerror(errno));
103af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ret = -1;
104af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
105af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  close(fd);
106af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return ret;
107a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
108a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
109a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
110a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wileyint is_wifi_driver_loaded() {
111af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  char driver_status[PROPERTY_VALUE_MAX];
112a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH
113af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  FILE *proc;
114af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  char line[sizeof(DRIVER_MODULE_TAG) + 10];
115a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
116a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
117af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) ||
118af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      strcmp(driver_status, "ok") != 0) {
119af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return 0; /* driver not loaded */
120af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
121a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH
122af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  /*
123af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley   * If the property says the driver is loaded, check to
124af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley   * make sure that the property setting isn't just left
125af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley   * over from a previous manual shutdown or a runtime
126af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley   * crash.
127af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley   */
128af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
129af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
130a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley    property_set(DRIVER_PROP_NAME, "unloaded");
131a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley    return 0;
132af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
133af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  while ((fgets(line, sizeof(line), proc)) != NULL) {
134af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
135af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      fclose(proc);
136af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      return 1;
137af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    }
138af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
139af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  fclose(proc);
140af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  property_set(DRIVER_PROP_NAME, "unloaded");
141af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return 0;
142a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else
143af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return 1;
144a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
145a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
146a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
147af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_load_driver() {
148a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH
149af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (is_wifi_driver_loaded()) {
150af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return 0;
151af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
152a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
153af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
154a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
155a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#elif defined WIFI_DRIVER_STATE_CTRL_PARAM
156af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (is_wifi_driver_loaded()) {
157af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return 0;
158af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
159a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
160af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;
161a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
162af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  property_set(DRIVER_PROP_NAME, "ok");
163af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return 0;
164a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
165a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
166af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_unload_driver() {
167af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  usleep(200000); /* allow to finish interface down */
168a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_MODULE_PATH
169af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (rmmod(DRIVER_MODULE_NAME) == 0) {
170af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    int count = 20; /* wait at most 10 seconds for completion */
171af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    while (count-- > 0) {
172af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      if (!is_wifi_driver_loaded()) break;
173af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      usleep(500000);
174af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    }
175af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    usleep(500000); /* allow card removal */
176af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    if (count) {
177af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      return 0;
178af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    }
179af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return -1;
180af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  } else
181af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return -1;
182a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#else
183a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
184af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (is_wifi_driver_loaded()) {
185af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) return -1;
186af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
187a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
188af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  property_set(DRIVER_PROP_NAME, "unloaded");
189af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return 0;
190a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley#endif
191a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
192a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
193af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyconst char *wifi_get_fw_path(int fw_type) {
194af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  switch (fw_type) {
195a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley    case WIFI_GET_FW_PATH_STA:
196af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      return WIFI_DRIVER_FW_PATH_STA;
197a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley    case WIFI_GET_FW_PATH_AP:
198af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      return WIFI_DRIVER_FW_PATH_AP;
199a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley    case WIFI_GET_FW_PATH_P2P:
200af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley      return WIFI_DRIVER_FW_PATH_P2P;
201af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
202af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return NULL;
203a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
204a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley
205af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wileyint wifi_change_fw_path(const char *fwpath) {
206af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int len;
207af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int fd;
208af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  int ret = 0;
209af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley
210af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (!fwpath) return ret;
211af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
212af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (fd < 0) {
213af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
214af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    return -1;
215af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
216af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  len = strlen(fwpath) + 1;
217af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
218af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
219af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley    ret = -1;
220af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  }
221af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  close(fd);
222af52902e4746aab2bd667ac9bdeb1bbb3e46b539Christopher Wiley  return ret;
223a591506fbf1445877fc2f97bca1e00b51ccc3a85Christopher Wiley}
224