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 */
wlanDrvWext_Init(struct net_device * dev)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 */
wlanDrvWext_GetWirelessStats(struct net_device * dev)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
wlanDrvWext_Handler(struct net_device * dev,struct iw_request_info * info,void * iw_req,void * extra)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