diff options
Diffstat (limited to 'peripheral/wifi/ap6212/wifi_driver_hal_ap6212.cpp')
-rw-r--r-- | peripheral/wifi/ap6212/wifi_driver_hal_ap6212.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/peripheral/wifi/ap6212/wifi_driver_hal_ap6212.cpp b/peripheral/wifi/ap6212/wifi_driver_hal_ap6212.cpp new file mode 100644 index 0000000..39b0bcc --- /dev/null +++ b/peripheral/wifi/ap6212/wifi_driver_hal_ap6212.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <netinet/in.h> +#include <cutils/log.h> +#include <cutils/properties.h> +#include <hardware_brillo/wifi_driver_hal.h> + +#define WIFI_DRIVER_NVRAM_PATH_PARAM \ + "/sys/module/bcmdhd/parameters/nvram_path" +#define WIFI_DRIVER_FW_PATH_PARAM \ + "/sys/module/bcmdhd/parameters/firmware_path" +#define WIFI_DRIVER_FW_PATH "/system/vendor/firmware/" +#define WIFI_DRIVER_NVRAM_PATH \ + WIFI_DRIVER_FW_PATH "nvram_ap6212.txt" +#define WIFI_DRIVER_FW_PATH_STA \ + WIFI_DRIVER_FW_PATH "fw_bcm43438a0.bin" +#define WIFI_DRIVER_FW_PATH_AP \ + WIFI_DRIVER_FW_PATH "fw_bcm43438a0_apsta.bin" +#ifdef WIFI_MODE_P2P +#define WIFI_DRIVER_FW_PATH_P2P \ + WIFI_DRIVER_FW_PATH "fw_bcm43438a0_p2p.bin" +#endif + +const char kStationDeviceName[] = "wlan0"; + +static bool write_file(const char *filename, const char *content) { + int fd = open(filename, O_WRONLY); + if (fd < 0) { + ALOGE("Cannot open %s for writing", filename); + return false; + } + + ssize_t write_count = strlen(content); + ssize_t actual_count = write(fd, content, write_count); + close(fd); + + if (actual_count != write_count) { + ALOGE("Expected to write %d bytes to %s but write returns %d", + write_count, filename, actual_count); + return false; + } + return true; +} + +/* Our HAL needs to set the AP/Station mode prior to actually initializing + * the wifi. We use a dummy function for the initialize. + */ +static wifi_driver_error wifi_driver_initialize_ap6212(void) { + return WIFI_SUCCESS; +} + +static wifi_driver_error wifi_driver_initialize_ap6212_internal(void) { + struct ifreq req; + int rc, socketfd; + + socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (socketfd < 0) { + ALOGE("%s: unable to open control socket\n", __func__); + return WIFI_ERROR_UNKNOWN; + } + + strcpy (req.ifr_name, kStationDeviceName); + rc = ioctl(socketfd, SIOCGIFFLAGS, &req); + if (rc < 0) { + ALOGE("%s: unable to query interface wlan0\n", __func__); + return WIFI_ERROR_UNKNOWN; + } + + req.ifr_flags &= ~(IFF_UP|IFF_RUNNING); + rc = ioctl(socketfd, SIOCSIFFLAGS, &req); + if (rc < 0) { + ALOGE("%s: unable to down interface wlan0\n", __func__); + return WIFI_ERROR_UNKNOWN; + } + + req.ifr_flags |= IFF_UP|IFF_RUNNING; + rc = ioctl(socketfd, SIOCSIFFLAGS, &req); + if (rc < 0) { + ALOGE("%s: unable to up interface wlan0\n", __func__); + return WIFI_ERROR_UNKNOWN; + } + + return WIFI_SUCCESS; +} + +static wifi_driver_error +wifi_driver_set_mode_ap6212( + wifi_driver_mode mode, + char* wifi_device_name, + size_t wifi_device_name_size) { + + const char *firmware_path = nullptr; + + switch (mode) { + case WIFI_MODE_AP: + firmware_path = WIFI_DRIVER_FW_PATH_AP; + break; + + case WIFI_MODE_STATION: + firmware_path = WIFI_DRIVER_FW_PATH_STA; + break; + +#ifdef WIFI_MODE_P2P + case WIFI_MODE_P2P: + firmware_path = WIFI_DRIVER_FW_PATH_P2P; + break; +#endif + + default: + ALOGE("Unkonwn WiFi driver mode %d", mode); + return WIFI_ERROR_INVALID_ARGS; + } + + if (true != write_file(WIFI_DRIVER_NVRAM_PATH_PARAM, WIFI_DRIVER_NVRAM_PATH)) + return WIFI_ERROR_UNKNOWN; + if (true != write_file(WIFI_DRIVER_FW_PATH_PARAM, firmware_path)) + return WIFI_ERROR_UNKNOWN; + + strlcpy(wifi_device_name, kStationDeviceName, wifi_device_name_size); + return wifi_driver_initialize_ap6212_internal(); +} + + +static int +close_ap6212_driver(struct hw_device_t *device) { + wifi_driver_device_t *dev = (wifi_driver_device_t *)device; + if (dev) + free(dev); + return 0; +} + +static int +open_ap6212_driver(const struct hw_module_t* module, const char*, struct hw_device_t** device) { + wifi_driver_device_t* dev = (wifi_driver_device_t *)calloc(1, sizeof(wifi_driver_device_t)); + + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = WIFI_DRIVER_DEVICE_API_VERSION_0_1; + + // We're forced into this cast by the existing API. This pattern is + // common among users of the HAL. + dev->common.module = (hw_module_t *)module; + + dev->common.close = close_ap6212_driver; + dev->wifi_driver_initialize = wifi_driver_initialize_ap6212; + dev->wifi_driver_set_mode = wifi_driver_set_mode_ap6212; + + *device = &dev->common; + + return 0; +} + +static struct hw_module_methods_t ap6212_driver_module_methods = { + .open = open_ap6212_driver, +}; + +hw_module_t HAL_MODULE_INFO_SYM = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = WIFI_DRIVER_HARDWARE_MODULE_ID, + .name = "AP6212 / Kylin module", + .author = "Rockchip", + .methods = &ap6212_driver_module_methods, + .dso = NULL, + .reserved = {0}, +}; |