1 /* 2 * WlanDrvWext.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 35 /* 36 * src/wext.c 37 * 38 * Support for Linux Wireless Extensions 39 * 40 */ 41 #include <linux/types.h> 42 #include <linux/socket.h> 43 #include <linux/if.h> 44 #include <linux/wireless.h> 45 #include <net/iw_handler.h> 46 #include "WlanDrvIf.h" 47 #include "CmdHndlr.h" 48 #include "CmdInterpretWext.h" 49 #include "privateCmd.h" 50 #include "DrvMain.h" 51 52 /* Routine prototypes */ 53 54 int wlanDrvWext_Handler (struct net_device *dev, 55 struct iw_request_info *info, 56 void *iw_req, 57 void *extra); 58 59 static struct iw_statistics *wlanDrvWext_GetWirelessStats (struct net_device *dev); 60 61 extern int wlanDrvIf_LoadFiles (TWlanDrvIfObj *drv, TLoaderFilesData *pInitInfo); 62 extern int wlanDrvIf_Start (struct net_device *dev); 63 extern int wlanDrvIf_Stop (struct net_device *dev); 64 65 66 /* callbacks for WEXT commands */ 67 static const iw_handler aWextHandlers[] = { 68 (iw_handler) NULL, /* SIOCSIWCOMMIT */ 69 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWNAME */ 70 (iw_handler) NULL, /* SIOCSIWNWID */ 71 (iw_handler) NULL, /* SIOCGIWNWID */ 72 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWFREQ */ 73 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWFREQ */ 74 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWMODE */ 75 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWMODE */ 76 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWSENS */ 77 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWSENS */ 78 (iw_handler) NULL, /* SIOCSIWRANGE - not used */ 79 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWRANGE */ 80 (iw_handler) NULL, /* SIOCSIWPRIV - not used */ 81 (iw_handler) NULL, /* SIOCGIWPRIV - kernel code */ 82 (iw_handler) NULL, /* SIOCSIWSTATS - not used */ 83 (iw_handler) wlanDrvWext_GetWirelessStats, /* SIOCGIWSTATS - kernel code */ 84 (iw_handler) NULL, /* SIOCSIWSPY */ 85 (iw_handler) NULL, /* SIOCGIWSPY */ 86 (iw_handler) NULL, /* SIOCSIWTHRSPY */ 87 (iw_handler) NULL, /* SIOCGIWTHRSPY */ 88 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWAP */ 89 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWAP */ 90 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWMLME */ 91 (iw_handler) NULL, /* SIOCGIWAPLIST */ 92 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWSCAN */ 93 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWSCAN */ 94 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWESSID */ 95 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWESSID */ 96 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWNICKN */ 97 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWNICKN */ 98 (iw_handler) NULL, /* -- hole -- */ 99 (iw_handler) NULL, /* -- hole -- */ 100 (iw_handler) NULL, /* SIOCSIWRATE */ 101 (iw_handler) NULL, /* SIOCGIWRATE */ 102 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWRTS */ 103 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWRTS */ 104 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWFRAG */ 105 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWFRAG */ 106 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWTXPOW */ 107 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWTXPOW */ 108 (iw_handler) NULL, /* SIOCSIWRETRY */ 109 (iw_handler) NULL, /* SIOCGIWRETRY */ 110 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWENCODE */ 111 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWENCODE */ 112 (iw_handler) NULL, /* SIOCSIWPOWER */ 113 (iw_handler) NULL, /* SIOCGIWPOWER */ 114 (iw_handler) NULL, /* -- hole -- */ 115 (iw_handler) NULL, /* -- hole -- */ 116 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWGENIE */ 117 (iw_handler) NULL, /* SIOCGIWGENIE */ 118 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWAUTH */ 119 (iw_handler) wlanDrvWext_Handler, /* SIOCGIWAUTH */ 120 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWENCODEEXT */ 121 (iw_handler) NULL, /* SIOCGIWENCODEEXT */ 122 (iw_handler) wlanDrvWext_Handler, /* SIOCSIWPMKSA */ 123 }; 124 125 /* callbacks for private commands */ 126 static const iw_handler aPrivateHandlers[] = { 127 (iw_handler) wlanDrvWext_Handler, /* SIOCIWFIRSTPRIV+0 (set) */ 128 (iw_handler) wlanDrvWext_Handler, /* SIOCIWFIRSTPRIV+1 (get) */ 129 }; 130 131 /* Describe the level of WEXT support to kernel */ 132 static struct iw_handler_def tWextIf = { 133 #define N(a) (sizeof (a) / sizeof (a[0])) 134 .standard = (iw_handler *) aWextHandlers, 135 .num_standard = N(aWextHandlers), 136 .private = (iw_handler *) aPrivateHandlers, 137 .num_private = N(aPrivateHandlers), 138 .private_args = NULL, 139 .num_private_args = 0, 140 .get_wireless_stats = wlanDrvWext_GetWirelessStats, 141 #undef N 142 }; 143 144 /* Initialite WEXT support - Register callbacks in kernel */ 145 void wlanDrvWext_Init (struct net_device *dev) 146 { 147 #ifdef HOST_PLATFORM_OMAP3430 148 dev->get_wireless_stats = wlanDrvWext_GetWirelessStats; 149 #endif 150 dev->wireless_handlers = &tWextIf; 151 152 } 153 154 /* Return driver statistics */ 155 static struct iw_statistics *wlanDrvWext_GetWirelessStats(struct net_device *dev) 156 { 157 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 158 159 return (struct iw_statistics *) cmdHndlr_GetStat (drv->tCommon.hCmdHndlr); 160 } 161 162 /* Generic callback for WEXT commands */ 163 164 int wlanDrvWext_Handler (struct net_device *dev, 165 struct iw_request_info *info, 166 void *iw_req, 167 void *extra) 168 { 169 int rc; 170 TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev); 171 ti_private_cmd_t my_command; 172 struct iw_mlme mlme; 173 struct iw_scan_req scanreq; 174 void *copy_to_buf=NULL, *param3=NULL; 175 176 os_memoryZero(drv, &my_command, sizeof(ti_private_cmd_t)); 177 os_memoryZero(drv, &mlme, sizeof(struct iw_mlme)); 178 os_memoryZero(drv, &scanreq, sizeof(struct iw_scan_req)); 179 180 switch (info->cmd) 181 { 182 case SIOCIWFIRSTPRIV: 183 { 184 void *copy_from_buf; 185 186 if (os_memoryCopyFromUser(drv, &my_command, ((union iwreq_data *)iw_req)->data.pointer, sizeof(ti_private_cmd_t))) 187 { 188 os_printf ("wlanDrvWext_Handler() os_memoryCopyFromUser FAILED !!!\n"); 189 return TI_NOK; 190 } 191 if (IS_PARAM_FOR_MODULE(my_command.cmd, DRIVER_MODULE_PARAM)) 192 { 193 /* If it's a driver level command, handle it here and exit */ 194 switch (my_command.cmd) 195 { 196 case DRIVER_INIT_PARAM: 197 return wlanDrvIf_LoadFiles(drv, my_command.in_buffer); 198 199 case DRIVER_START_PARAM: 200 return wlanDrvIf_Start(dev); 201 202 case DRIVER_STOP_PARAM: 203 return wlanDrvIf_Stop(dev); 204 205 case DRIVER_STATUS_PARAM: 206 *(TI_UINT32 *)my_command.out_buffer = 207 (drv->tCommon.eDriverState == DRV_STATE_RUNNING) ? TI_TRUE : TI_FALSE; 208 return TI_OK; 209 } 210 } 211 /* if we are still here handle a normal private command*/ 212 213 if ((my_command.in_buffer) && (my_command.in_buffer_len)) 214 { 215 copy_from_buf = my_command.in_buffer; 216 my_command.in_buffer = os_memoryAlloc(drv, my_command.in_buffer_len); 217 if (os_memoryCopyFromUser(drv, my_command.in_buffer, copy_from_buf, my_command.in_buffer_len)) 218 { 219 os_printf("wlanDrvWext_Handler() os_memoryCopyFromUser 1 FAILED !!!\n"); 220 return TI_NOK; 221 } 222 } 223 if ((my_command.out_buffer) && (my_command.out_buffer_len)) 224 { 225 copy_to_buf = my_command.out_buffer; 226 my_command.out_buffer = os_memoryAlloc(drv, my_command.out_buffer_len); 227 } 228 param3 = &my_command; 229 } 230 break; 231 232 case SIOCSIWMLME: 233 { 234 os_memoryCopyFromUser(drv, &mlme, ((union iwreq_data *)iw_req)->data.pointer, sizeof(struct iw_mlme)); 235 param3 = &mlme; 236 } 237 break; 238 case SIOCSIWSCAN: 239 { 240 if (((union iwreq_data *)iw_req)->data.pointer) { 241 os_memoryCopyFromUser(drv, &scanreq, ((union iwreq_data *)iw_req)->data.pointer, sizeof(struct iw_scan_req)); 242 param3 = &scanreq; 243 } 244 } 245 break; 246 247 case SIOCSIWGENIE: 248 { 249 TI_UINT16 ie_length = ((union iwreq_data *)iw_req)->data.length; 250 TI_UINT8 *ie_content = ((union iwreq_data *)iw_req)->data.pointer; 251 252 if ((ie_length == 0) && (ie_content == NULL)) { 253 /* Do nothing, deleting the IE */ 254 } else if ((ie_content != NULL) && (ie_length <= RSN_MAX_GENERIC_IE_LENGTH) && (ie_length > 0)) { 255 /* One IE cannot be larger than RSN_MAX_GENERIC_IE_LENGTH bytes */ 256 my_command.in_buffer = os_memoryAlloc(drv, ie_length); 257 os_memoryCopyFromUser(drv, my_command.in_buffer, ie_content, ie_length ); 258 param3 = my_command.in_buffer; 259 } else { 260 return TI_NOK; 261 } 262 } 263 break; 264 } 265 /* If the friver is not running, return NOK */ 266 if (drv->tCommon.eDriverState != DRV_STATE_RUNNING) 267 { 268 if (my_command.in_buffer) 269 os_memoryFree(drv, my_command.in_buffer, my_command.in_buffer_len); 270 if (my_command.out_buffer) 271 os_memoryFree(drv,my_command.out_buffer,my_command.out_buffer_len); 272 return TI_NOK; 273 } 274 275 /* Call the Cmd module with the given user paramters */ 276 rc = cmdHndlr_InsertCommand(drv->tCommon.hCmdHndlr, 277 info->cmd, 278 info->flags, 279 iw_req, 280 0, 281 extra, 282 0, 283 param3, 284 NULL); 285 /* Here we are after the command was completed */ 286 if (my_command.in_buffer) 287 { 288 os_memoryFree(drv, my_command.in_buffer, my_command.in_buffer_len); 289 } 290 if (my_command.out_buffer) 291 { 292 if (os_memoryCopyToUser(drv, copy_to_buf, my_command.out_buffer, my_command.out_buffer_len)) 293 { 294 os_printf("wlanDrvWext_Handler() os_memoryCopyToUser FAILED !!!\n"); 295 rc = TI_NOK; 296 } 297 os_memoryFree(drv, my_command.out_buffer, my_command.out_buffer_len); 298 } 299 return rc; 300 } 301