linux/drivers/staging/rtl8188eu/os_dep/rtw_android.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 ******************************************************************************/
  15
  16#include <linux/module.h>
  17#include <linux/netdevice.h>
  18
  19#include <rtw_android.h>
  20#include <osdep_service.h>
  21#include <rtw_debug.h>
  22#include <rtw_ioctl_set.h>
  23
  24static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
  25        "START",
  26        "STOP",
  27        "SCAN-ACTIVE",
  28        "SCAN-PASSIVE",
  29        "RSSI",
  30        "LINKSPEED",
  31        "RXFILTER-START",
  32        "RXFILTER-STOP",
  33        "RXFILTER-ADD",
  34        "RXFILTER-REMOVE",
  35        "BTCOEXSCAN-START",
  36        "BTCOEXSCAN-STOP",
  37        "BTCOEXMODE",
  38        "SETSUSPENDOPT",
  39        "P2P_DEV_ADDR",
  40        "SETFWPATH",
  41        "SETBAND",
  42        "GETBAND",
  43        "COUNTRY",
  44        "P2P_SET_NOA",
  45        "P2P_GET_NOA",
  46        "P2P_SET_PS",
  47        "SET_AP_WPS_P2P_IE",
  48        "MACADDR",
  49        "BLOCK",
  50        "WFD-ENABLE",
  51        "WFD-DISABLE",
  52        "WFD-SET-TCPPORT",
  53        "WFD-SET-MAXTPUT",
  54        "WFD-SET-DEVTYPE",
  55};
  56
  57struct android_wifi_priv_cmd {
  58        const char __user *buf;
  59        int used_len;
  60        int total_len;
  61};
  62
  63/**
  64 * Local (static) functions and variables
  65 */
  66
  67/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
  68 * time (only) in dhd_open, subsequential wifi on will be handled by
  69 * wl_android_wifi_on
  70 */
  71static int g_wifi_on = true;
  72
  73int rtw_android_cmdstr_to_num(char *cmdstr)
  74{
  75        int cmd_num;
  76
  77        for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
  78                if (0 == strncasecmp(cmdstr, android_wifi_cmd_str[cmd_num],
  79                                  strlen(android_wifi_cmd_str[cmd_num])))
  80                        break;
  81        return cmd_num;
  82}
  83
  84static int rtw_android_get_rssi(struct net_device *net, char *command,
  85                                int total_len)
  86{
  87        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
  88        struct  mlme_priv       *pmlmepriv = &(padapter->mlmepriv);
  89        struct  wlan_network    *pcur_network = &pmlmepriv->cur_network;
  90        int bytes_written = 0;
  91
  92        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
  93                bytes_written += snprintf(&command[bytes_written], total_len,
  94                                          "%s rssi %d",
  95                                          pcur_network->network.Ssid.Ssid,
  96                                          padapter->recvpriv.rssi);
  97        }
  98        return bytes_written;
  99}
 100
 101static int rtw_android_get_link_speed(struct net_device *net, char *command,
 102                                      int total_len)
 103{
 104        struct adapter *padapter = (struct adapter *)rtw_netdev_priv(net);
 105        u16 link_speed;
 106
 107        link_speed = rtw_get_cur_max_rate(padapter) / 10;
 108        return snprintf(command, total_len, "LinkSpeed %d",
 109                                 link_speed);
 110}
 111
 112static int rtw_android_get_macaddr(struct net_device *net, char *command,
 113                                   int total_len)
 114{
 115        return snprintf(command, total_len, "Macaddr = %pM",
 116                                 net->dev_addr);
 117}
 118
 119static int android_set_cntry(struct net_device *net, char *command,
 120                             int total_len)
 121{
 122        struct adapter *adapter = (struct adapter *)rtw_netdev_priv(net);
 123        char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
 124        int ret;
 125
 126        ret = rtw_set_country(adapter, country_code);
 127        return (ret == _SUCCESS) ? 0 : -1;
 128}
 129
 130static int android_get_p2p_addr(struct net_device *net, char *command,
 131                                        int total_len)
 132{
 133        /* We use the same address as our HW MAC address */
 134        memcpy(command, net->dev_addr, ETH_ALEN);
 135        return ETH_ALEN;
 136}
 137
 138static int rtw_android_set_block(struct net_device *net, char *command,
 139                                 int total_len)
 140{
 141        return 0;
 142}
 143
 144int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 145{
 146        int ret = 0;
 147        char *command;
 148        int cmd_num;
 149        int bytes_written = 0;
 150        struct android_wifi_priv_cmd priv_cmd;
 151
 152        if (!ifr->ifr_data)
 153                return -EINVAL;
 154        if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(priv_cmd)))
 155                return -EFAULT;
 156        if (priv_cmd.total_len < 1)
 157                return -EINVAL;
 158        command = memdup_user(priv_cmd.buf, priv_cmd.total_len);
 159        if (IS_ERR(command))
 160                return PTR_ERR(command);
 161        command[priv_cmd.total_len - 1] = 0;
 162        DBG_88E("%s: Android private cmd \"%s\" on %s\n",
 163                __func__, command, ifr->ifr_name);
 164        cmd_num = rtw_android_cmdstr_to_num(command);
 165        switch (cmd_num) {
 166        case ANDROID_WIFI_CMD_START:
 167                goto response;
 168        case ANDROID_WIFI_CMD_SETFWPATH:
 169                goto response;
 170        }
 171        if (!g_wifi_on) {
 172                DBG_88E("%s: Ignore private cmd \"%s\" - iface %s is down\n",
 173                        __func__, command, ifr->ifr_name);
 174                ret = 0;
 175                goto free;
 176        }
 177        switch (cmd_num) {
 178        case ANDROID_WIFI_CMD_STOP:
 179                break;
 180        case ANDROID_WIFI_CMD_SCAN_ACTIVE:
 181                break;
 182        case ANDROID_WIFI_CMD_SCAN_PASSIVE:
 183                break;
 184        case ANDROID_WIFI_CMD_RSSI:
 185                bytes_written = rtw_android_get_rssi(net, command,
 186                                                     priv_cmd.total_len);
 187                break;
 188        case ANDROID_WIFI_CMD_LINKSPEED:
 189                bytes_written = rtw_android_get_link_speed(net, command,
 190                                                           priv_cmd.total_len);
 191                break;
 192        case ANDROID_WIFI_CMD_MACADDR:
 193                bytes_written = rtw_android_get_macaddr(net, command,
 194                                                        priv_cmd.total_len);
 195                break;
 196        case ANDROID_WIFI_CMD_BLOCK:
 197                bytes_written = rtw_android_set_block(net, command,
 198                                                      priv_cmd.total_len);
 199                break;
 200        case ANDROID_WIFI_CMD_RXFILTER_START:
 201                break;
 202        case ANDROID_WIFI_CMD_RXFILTER_STOP:
 203                break;
 204        case ANDROID_WIFI_CMD_RXFILTER_ADD:
 205                break;
 206        case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
 207                break;
 208        case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
 209                /* TBD: BTCOEXSCAN-START */
 210                break;
 211        case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
 212                /* TBD: BTCOEXSCAN-STOP */
 213                break;
 214        case ANDROID_WIFI_CMD_BTCOEXMODE:
 215                break;
 216        case ANDROID_WIFI_CMD_SETSUSPENDOPT:
 217                break;
 218        case ANDROID_WIFI_CMD_SETBAND:
 219                break;
 220        case ANDROID_WIFI_CMD_GETBAND:
 221                break;
 222        case ANDROID_WIFI_CMD_COUNTRY:
 223                bytes_written = android_set_cntry(net, command,
 224                                                  priv_cmd.total_len);
 225                break;
 226        case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
 227                bytes_written = android_get_p2p_addr(net, command,
 228                                                     priv_cmd.total_len);
 229                break;
 230        case ANDROID_WIFI_CMD_P2P_SET_NOA:
 231                break;
 232        case ANDROID_WIFI_CMD_P2P_GET_NOA:
 233                break;
 234        case ANDROID_WIFI_CMD_P2P_SET_PS:
 235                break;
 236        default:
 237                DBG_88E("Unknown PRIVATE command %s - ignored\n", command);
 238                snprintf(command, 3, "OK");
 239                bytes_written = strlen("OK");
 240        }
 241
 242response:
 243        if (bytes_written >= 0) {
 244                if ((bytes_written == 0) && (priv_cmd.total_len > 0))
 245                        command[0] = '\0';
 246                if (bytes_written >= priv_cmd.total_len) {
 247                        DBG_88E("%s: bytes_written = %d\n", __func__,
 248                                bytes_written);
 249                        bytes_written = priv_cmd.total_len;
 250                } else {
 251                        bytes_written++;
 252                }
 253                priv_cmd.used_len = bytes_written;
 254                if (copy_to_user((char __user *)priv_cmd.buf, command,
 255                                 bytes_written)) {
 256                        DBG_88E("%s: failed to copy data to user buffer\n",
 257                                __func__);
 258                        ret = -EFAULT;
 259                }
 260        } else {
 261                ret = bytes_written;
 262        }
 263free:
 264        kfree(command);
 265        return ret;
 266}
 267