Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * This file define the new driver API for Wireless Extensions
4 : : *
5 : : * Version : 8 16.3.07
6 : : *
7 : : * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
8 : : * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
9 : : */
10 : :
11 : : #ifndef _IW_HANDLER_H
12 : : #define _IW_HANDLER_H
13 : :
14 : : /************************** DOCUMENTATION **************************/
15 : : /*
16 : : * Initial driver API (1996 -> onward) :
17 : : * -----------------------------------
18 : : * The initial API just sends the IOCTL request received from user space
19 : : * to the driver (via the driver ioctl handler). The driver has to
20 : : * handle all the rest...
21 : : *
22 : : * The initial API also defines a specific handler in struct net_device
23 : : * to handle wireless statistics.
24 : : *
25 : : * The initial APIs served us well and has proven a reasonably good design.
26 : : * However, there is a few shortcommings :
27 : : * o No events, everything is a request to the driver.
28 : : * o Large ioctl function in driver with gigantic switch statement
29 : : * (i.e. spaghetti code).
30 : : * o Driver has to mess up with copy_to/from_user, and in many cases
31 : : * does it unproperly. Common mistakes are :
32 : : * * buffer overflows (no checks or off by one checks)
33 : : * * call copy_to/from_user with irq disabled
34 : : * o The user space interface is tied to ioctl because of the use
35 : : * copy_to/from_user.
36 : : *
37 : : * New driver API (2002 -> onward) :
38 : : * -------------------------------
39 : : * The new driver API is just a bunch of standard functions (handlers),
40 : : * each handling a specific Wireless Extension. The driver just export
41 : : * the list of handler it supports, and those will be called apropriately.
42 : : *
43 : : * I tried to keep the main advantage of the previous API (simplicity,
44 : : * efficiency and light weight), and also I provide a good dose of backward
45 : : * compatibility (most structures are the same, driver can use both API
46 : : * simultaneously, ...).
47 : : * Hopefully, I've also addressed the shortcomming of the initial API.
48 : : *
49 : : * The advantage of the new API are :
50 : : * o Handling of Extensions in driver broken in small contained functions
51 : : * o Tighter checks of ioctl before calling the driver
52 : : * o Flexible commit strategy (at least, the start of it)
53 : : * o Backward compatibility (can be mixed with old API)
54 : : * o Driver doesn't have to worry about memory and user-space issues
55 : : * The last point is important for the following reasons :
56 : : * o You are now able to call the new driver API from any API you
57 : : * want (including from within other parts of the kernel).
58 : : * o Common mistakes are avoided (buffer overflow, user space copy
59 : : * with irq disabled and so on).
60 : : *
61 : : * The Drawback of the new API are :
62 : : * o bloat (especially kernel)
63 : : * o need to migrate existing drivers to new API
64 : : * My initial testing shows that the new API adds around 3kB to the kernel
65 : : * and save between 0 and 5kB from a typical driver.
66 : : * Also, as all structures and data types are unchanged, the migration is
67 : : * quite straightforward (but tedious).
68 : : *
69 : : * ---
70 : : *
71 : : * The new driver API is defined below in this file. User space should
72 : : * not be aware of what's happening down there...
73 : : *
74 : : * A new kernel wrapper is in charge of validating the IOCTLs and calling
75 : : * the appropriate driver handler. This is implemented in :
76 : : * # net/core/wireless.c
77 : : *
78 : : * The driver export the list of handlers in :
79 : : * # include/linux/netdevice.h (one place)
80 : : *
81 : : * The new driver API is available for WIRELESS_EXT >= 13.
82 : : * Good luck with migration to the new API ;-)
83 : : */
84 : :
85 : : /* ---------------------- THE IMPLEMENTATION ---------------------- */
86 : : /*
87 : : * Some of the choice I've made are pretty controversials. Defining an
88 : : * API is very much weighting compromises. This goes into some of the
89 : : * details and the thinking behind the implementation.
90 : : *
91 : : * Implementation goals :
92 : : * --------------------
93 : : * The implementation goals were as follow :
94 : : * o Obvious : you should not need a PhD to understand what's happening,
95 : : * the benefit is easier maintenance.
96 : : * o Flexible : it should accommodate a wide variety of driver
97 : : * implementations and be as flexible as the old API.
98 : : * o Lean : it should be efficient memory wise to minimise the impact
99 : : * on kernel footprint.
100 : : * o Transparent to user space : the large number of user space
101 : : * applications that use Wireless Extensions should not need
102 : : * any modifications.
103 : : *
104 : : * Array of functions versus Struct of functions
105 : : * ---------------------------------------------
106 : : * 1) Having an array of functions allow the kernel code to access the
107 : : * handler in a single lookup, which is much more efficient (think hash
108 : : * table here).
109 : : * 2) The only drawback is that driver writer may put their handler in
110 : : * the wrong slot. This is trivial to test (I set the frequency, the
111 : : * bitrate changes). Once the handler is in the proper slot, it will be
112 : : * there forever, because the array is only extended at the end.
113 : : * 3) Backward/forward compatibility : adding new handler just require
114 : : * extending the array, so you can put newer driver in older kernel
115 : : * without having to patch the kernel code (and vice versa).
116 : : *
117 : : * All handler are of the same generic type
118 : : * ----------------------------------------
119 : : * That's a feature !!!
120 : : * 1) Having a generic handler allow to have generic code, which is more
121 : : * efficient. If each of the handler was individually typed I would need
122 : : * to add a big switch in the kernel (== more bloat). This solution is
123 : : * more scalable, adding new Wireless Extensions doesn't add new code.
124 : : * 2) You can use the same handler in different slots of the array. For
125 : : * hardware, it may be more efficient or logical to handle multiple
126 : : * Wireless Extensions with a single function, and the API allow you to
127 : : * do that. (An example would be a single record on the card to control
128 : : * both bitrate and frequency, the handler would read the old record,
129 : : * modify it according to info->cmd and rewrite it).
130 : : *
131 : : * Functions prototype uses union iwreq_data
132 : : * -----------------------------------------
133 : : * Some would have preferred functions defined this way :
134 : : * static int mydriver_ioctl_setrate(struct net_device *dev,
135 : : * long rate, int auto)
136 : : * 1) The kernel code doesn't "validate" the content of iwreq_data, and
137 : : * can't do it (different hardware may have different notion of what a
138 : : * valid frequency is), so we don't pretend that we do it.
139 : : * 2) The above form is not extendable. If I want to add a flag (for
140 : : * example to distinguish setting max rate and basic rate), I would
141 : : * break the prototype. Using iwreq_data is more flexible.
142 : : * 3) Also, the above form is not generic (see above).
143 : : * 4) I don't expect driver developper using the wrong field of the
144 : : * union (Doh !), so static typechecking doesn't add much value.
145 : : * 5) Lastly, you can skip the union by doing :
146 : : * static int mydriver_ioctl_setrate(struct net_device *dev,
147 : : * struct iw_request_info *info,
148 : : * struct iw_param *rrq,
149 : : * char *extra)
150 : : * And then adding the handler in the array like this :
151 : : * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
152 : : *
153 : : * Using functions and not a registry
154 : : * ----------------------------------
155 : : * Another implementation option would have been for every instance to
156 : : * define a registry (a struct containing all the Wireless Extensions)
157 : : * and only have a function to commit the registry to the hardware.
158 : : * 1) This approach can be emulated by the current code, but not
159 : : * vice versa.
160 : : * 2) Some drivers don't keep any configuration in the driver, for them
161 : : * adding such a registry would be a significant bloat.
162 : : * 3) The code to translate from Wireless Extension to native format is
163 : : * needed anyway, so it would not reduce significantely the amount of code.
164 : : * 4) The current approach only selectively translate Wireless Extensions
165 : : * to native format and only selectively set, whereas the registry approach
166 : : * would require to translate all WE and set all parameters for any single
167 : : * change.
168 : : * 5) For many Wireless Extensions, the GET operation return the current
169 : : * dynamic value, not the value that was set.
170 : : *
171 : : * This header is <net/iw_handler.h>
172 : : * ---------------------------------
173 : : * 1) This header is kernel space only and should not be exported to
174 : : * user space. Headers in "include/linux/" are exported, headers in
175 : : * "include/net/" are not.
176 : : *
177 : : * Mixed 32/64 bit issues
178 : : * ----------------------
179 : : * The Wireless Extensions are designed to be 64 bit clean, by using only
180 : : * datatypes with explicit storage size.
181 : : * There are some issues related to kernel and user space using different
182 : : * memory model, and in particular 64bit kernel with 32bit user space.
183 : : * The problem is related to struct iw_point, that contains a pointer
184 : : * that *may* need to be translated.
185 : : * This is quite messy. The new API doesn't solve this problem (it can't),
186 : : * but is a step in the right direction :
187 : : * 1) Meta data about each ioctl is easily available, so we know what type
188 : : * of translation is needed.
189 : : * 2) The move of data between kernel and user space is only done in a single
190 : : * place in the kernel, so adding specific hooks in there is possible.
191 : : * 3) In the long term, it allows to move away from using ioctl as the
192 : : * user space API.
193 : : *
194 : : * So many comments and so few code
195 : : * --------------------------------
196 : : * That's a feature. Comments won't bloat the resulting kernel binary.
197 : : */
198 : :
199 : : /***************************** INCLUDES *****************************/
200 : :
201 : : #include <linux/wireless.h> /* IOCTL user space API */
202 : : #include <linux/if_ether.h>
203 : :
204 : : /***************************** VERSION *****************************/
205 : : /*
206 : : * This constant is used to know which version of the driver API is
207 : : * available. Hopefully, this will be pretty stable and no changes
208 : : * will be needed...
209 : : * I just plan to increment with each new version.
210 : : */
211 : : #define IW_HANDLER_VERSION 8
212 : :
213 : : /*
214 : : * Changes :
215 : : *
216 : : * V2 to V3
217 : : * --------
218 : : * - Move event definition in <linux/wireless.h>
219 : : * - Add Wireless Event support :
220 : : * o wireless_send_event() prototype
221 : : * o iwe_stream_add_event/point() inline functions
222 : : * V3 to V4
223 : : * --------
224 : : * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
225 : : *
226 : : * V4 to V5
227 : : * --------
228 : : * - Add new spy support : struct iw_spy_data & prototypes
229 : : *
230 : : * V5 to V6
231 : : * --------
232 : : * - Change the way we get to spy_data method for added safety
233 : : * - Remove spy #ifdef, they are always on -> cleaner code
234 : : * - Add IW_DESCR_FLAG_NOMAX flag for very large requests
235 : : * - Start migrating get_wireless_stats to struct iw_handler_def
236 : : *
237 : : * V6 to V7
238 : : * --------
239 : : * - Add struct ieee80211_device pointer in struct iw_public_data
240 : : * - Remove (struct iw_point *)->pointer from events and streams
241 : : * - Remove spy_offset from struct iw_handler_def
242 : : * - Add "check" version of event macros for ieee802.11 stack
243 : : *
244 : : * V7 to V8
245 : : * ----------
246 : : * - Prevent leaking of kernel space in stream on 64 bits.
247 : : */
248 : :
249 : : /**************************** CONSTANTS ****************************/
250 : :
251 : : /* Enhanced spy support available */
252 : : #define IW_WIRELESS_SPY
253 : : #define IW_WIRELESS_THRSPY
254 : :
255 : : /* Special error message for the driver to indicate that we
256 : : * should do a commit after return from the iw_handler */
257 : : #define EIWCOMMIT EINPROGRESS
258 : :
259 : : /* Flags available in struct iw_request_info */
260 : : #define IW_REQUEST_FLAG_COMPAT 0x0001 /* Compat ioctl call */
261 : :
262 : : /* Type of headers we know about (basically union iwreq_data) */
263 : : #define IW_HEADER_TYPE_NULL 0 /* Not available */
264 : : #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
265 : : #define IW_HEADER_TYPE_UINT 4 /* __u32 */
266 : : #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
267 : : #define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
268 : : #define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
269 : : #define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
270 : : #define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
271 : :
272 : : /* Handling flags */
273 : : /* Most are not implemented. I just use them as a reminder of some
274 : : * cool features we might need one day ;-) */
275 : : #define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
276 : : /* Wrapper level flags */
277 : : #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
278 : : #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
279 : : #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
280 : : /* SET : Omit payload from generated iwevent */
281 : : #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
282 : : /* Driver level flags */
283 : : #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
284 : :
285 : : /****************************** TYPES ******************************/
286 : :
287 : : /* ----------------------- WIRELESS HANDLER ----------------------- */
288 : : /*
289 : : * A wireless handler is just a standard function, that looks like the
290 : : * ioctl handler.
291 : : * We also define there how a handler list look like... As the Wireless
292 : : * Extension space is quite dense, we use a simple array, which is faster
293 : : * (that's the perfect hash table ;-).
294 : : */
295 : :
296 : : /*
297 : : * Meta data about the request passed to the iw_handler.
298 : : * Most handlers can safely ignore what's in there.
299 : : * The 'cmd' field might come handy if you want to use the same handler
300 : : * for multiple command...
301 : : * This struct is also my long term insurance. I can add new fields here
302 : : * without breaking the prototype of iw_handler...
303 : : */
304 : : struct iw_request_info {
305 : : __u16 cmd; /* Wireless Extension command */
306 : : __u16 flags; /* More to come ;-) */
307 : : };
308 : :
309 : : struct net_device;
310 : :
311 : : /*
312 : : * This is how a function handling a Wireless Extension should look
313 : : * like (both get and set, standard and private).
314 : : */
315 : : typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
316 : : union iwreq_data *wrqu, char *extra);
317 : :
318 : : /*
319 : : * This define all the handler that the driver export.
320 : : * As you need only one per driver type, please use a static const
321 : : * shared by all driver instances... Same for the members...
322 : : * This will be linked from net_device in <linux/netdevice.h>
323 : : */
324 : : struct iw_handler_def {
325 : :
326 : : /* Array of handlers for standard ioctls
327 : : * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST]
328 : : */
329 : : const iw_handler * standard;
330 : : /* Number of handlers defined (more precisely, index of the
331 : : * last defined handler + 1) */
332 : : __u16 num_standard;
333 : :
334 : : #ifdef CONFIG_WEXT_PRIV
335 : : __u16 num_private;
336 : : /* Number of private arg description */
337 : : __u16 num_private_args;
338 : : /* Array of handlers for private ioctls
339 : : * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
340 : : */
341 : : const iw_handler * private;
342 : :
343 : : /* Arguments of private handler. This one is just a list, so you
344 : : * can put it in any order you want and should not leave holes...
345 : : * We will automatically export that to user space... */
346 : : const struct iw_priv_args * private_args;
347 : : #endif
348 : :
349 : : /* New location of get_wireless_stats, to de-bloat struct net_device.
350 : : * The old pointer in struct net_device will be gradually phased
351 : : * out, and drivers are encouraged to use this one... */
352 : : struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
353 : : };
354 : :
355 : : /* ---------------------- IOCTL DESCRIPTION ---------------------- */
356 : : /*
357 : : * One of the main goal of the new interface is to deal entirely with
358 : : * user space/kernel space memory move.
359 : : * For that, we need to know :
360 : : * o if iwreq is a pointer or contain the full data
361 : : * o what is the size of the data to copy
362 : : *
363 : : * For private IOCTLs, we use the same rules as used by iwpriv and
364 : : * defined in struct iw_priv_args.
365 : : *
366 : : * For standard IOCTLs, things are quite different and we need to
367 : : * use the structures below. Actually, this struct is also more
368 : : * efficient, but that's another story...
369 : : */
370 : :
371 : : /*
372 : : * Describe how a standard IOCTL looks like.
373 : : */
374 : : struct iw_ioctl_description {
375 : : __u8 header_type; /* NULL, iw_point or other */
376 : : __u8 token_type; /* Future */
377 : : __u16 token_size; /* Granularity of payload */
378 : : __u16 min_tokens; /* Min acceptable token number */
379 : : __u16 max_tokens; /* Max acceptable token number */
380 : : __u32 flags; /* Special handling of the request */
381 : : };
382 : :
383 : : /* Need to think of short header translation table. Later. */
384 : :
385 : : /* --------------------- ENHANCED SPY SUPPORT --------------------- */
386 : : /*
387 : : * In the old days, the driver was handling spy support all by itself.
388 : : * Now, the driver can delegate this task to Wireless Extensions.
389 : : * It needs to include this struct in its private part and use the
390 : : * standard spy iw_handler.
391 : : */
392 : :
393 : : /*
394 : : * Instance specific spy data, i.e. addresses spied and quality for them.
395 : : */
396 : : struct iw_spy_data {
397 : : /* --- Standard spy support --- */
398 : : int spy_number;
399 : : u_char spy_address[IW_MAX_SPY][ETH_ALEN];
400 : : struct iw_quality spy_stat[IW_MAX_SPY];
401 : : /* --- Enhanced spy support (event) */
402 : : struct iw_quality spy_thr_low; /* Low threshold */
403 : : struct iw_quality spy_thr_high; /* High threshold */
404 : : u_char spy_thr_under[IW_MAX_SPY];
405 : : };
406 : :
407 : : /* --------------------- DEVICE WIRELESS DATA --------------------- */
408 : : /*
409 : : * This is all the wireless data specific to a device instance that
410 : : * is managed by the core of Wireless Extensions or the 802.11 layer.
411 : : * We only keep pointer to those structures, so that a driver is free
412 : : * to share them between instances.
413 : : * This structure should be initialised before registering the device.
414 : : * Access to this data follow the same rules as any other struct net_device
415 : : * data (i.e. valid as long as struct net_device exist, same locking rules).
416 : : */
417 : : /* Forward declaration */
418 : : struct libipw_device;
419 : : /* The struct */
420 : : struct iw_public_data {
421 : : /* Driver enhanced spy support */
422 : : struct iw_spy_data * spy_data;
423 : : /* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */
424 : : struct libipw_device * libipw;
425 : : };
426 : :
427 : : /**************************** PROTOTYPES ****************************/
428 : : /*
429 : : * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
430 : : * Those may be called only within the kernel.
431 : : */
432 : :
433 : : /* First : function strictly used inside the kernel */
434 : :
435 : : /* Handle /proc/net/wireless, called in net/code/dev.c */
436 : : int dev_get_wireless_info(char *buffer, char **start, off_t offset, int length);
437 : :
438 : : /* Second : functions that may be called by driver modules */
439 : :
440 : : /* Send a single event to user space */
441 : : void wireless_send_event(struct net_device *dev, unsigned int cmd,
442 : : union iwreq_data *wrqu, const char *extra);
443 : : #ifdef CONFIG_WEXT_CORE
444 : : /* flush all previous wext events - if work is done from netdev notifiers */
445 : : void wireless_nlevent_flush(void);
446 : : #else
447 : : static inline void wireless_nlevent_flush(void) {}
448 : : #endif
449 : :
450 : : /* We may need a function to send a stream of events to user space.
451 : : * More on that later... */
452 : :
453 : : /* Standard handler for SIOCSIWSPY */
454 : : int iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info,
455 : : union iwreq_data *wrqu, char *extra);
456 : : /* Standard handler for SIOCGIWSPY */
457 : : int iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info,
458 : : union iwreq_data *wrqu, char *extra);
459 : : /* Standard handler for SIOCSIWTHRSPY */
460 : : int iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info,
461 : : union iwreq_data *wrqu, char *extra);
462 : : /* Standard handler for SIOCGIWTHRSPY */
463 : : int iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info,
464 : : union iwreq_data *wrqu, char *extra);
465 : : /* Driver call to update spy records */
466 : : void wireless_spy_update(struct net_device *dev, unsigned char *address,
467 : : struct iw_quality *wstats);
468 : :
469 : : /************************* INLINE FUNTIONS *************************/
470 : : /*
471 : : * Function that are so simple that it's more efficient inlining them
472 : : */
473 : :
474 : 0 : static inline int iwe_stream_lcp_len(struct iw_request_info *info)
475 : : {
476 : : #ifdef CONFIG_COMPAT
477 [ # # # # : 0 : if (info->flags & IW_REQUEST_FLAG_COMPAT)
# # ]
478 : 0 : return IW_EV_COMPAT_LCP_LEN;
479 : : #endif
480 : : return IW_EV_LCP_LEN;
481 : : }
482 : :
483 : 0 : static inline int iwe_stream_point_len(struct iw_request_info *info)
484 : : {
485 : : #ifdef CONFIG_COMPAT
486 [ # # # # ]: 0 : if (info->flags & IW_REQUEST_FLAG_COMPAT)
487 : 0 : return IW_EV_COMPAT_POINT_LEN;
488 : : #endif
489 : : return IW_EV_POINT_LEN;
490 : : }
491 : :
492 : 0 : static inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
493 : : int event_len)
494 : : {
495 : : #ifdef CONFIG_COMPAT
496 [ # # ]: 0 : if (info->flags & IW_REQUEST_FLAG_COMPAT) {
497 : 0 : event_len -= IW_EV_LCP_LEN;
498 : 0 : event_len += IW_EV_COMPAT_LCP_LEN;
499 : : }
500 : : #endif
501 : :
502 [ # # ]: 0 : return event_len;
503 : : }
504 : :
505 : : /*------------------------------------------------------------------*/
506 : : /*
507 : : * Wrapper to add an Wireless Event to a stream of events.
508 : : */
509 : : char *iwe_stream_add_event(struct iw_request_info *info, char *stream,
510 : : char *ends, struct iw_event *iwe, int event_len);
511 : :
512 : : static inline char *
513 : : iwe_stream_add_event_check(struct iw_request_info *info, char *stream,
514 : : char *ends, struct iw_event *iwe, int event_len)
515 : : {
516 : : char *res = iwe_stream_add_event(info, stream, ends, iwe, event_len);
517 : :
518 : : if (res == stream)
519 : : return ERR_PTR(-E2BIG);
520 : : return res;
521 : : }
522 : :
523 : : /*------------------------------------------------------------------*/
524 : : /*
525 : : * Wrapper to add an short Wireless Event containing a pointer to a
526 : : * stream of events.
527 : : */
528 : : char *iwe_stream_add_point(struct iw_request_info *info, char *stream,
529 : : char *ends, struct iw_event *iwe, char *extra);
530 : :
531 : : static inline char *
532 : 0 : iwe_stream_add_point_check(struct iw_request_info *info, char *stream,
533 : : char *ends, struct iw_event *iwe, char *extra)
534 : : {
535 : 0 : char *res = iwe_stream_add_point(info, stream, ends, iwe, extra);
536 : :
537 [ # # # # ]: 0 : if (res == stream)
538 : 0 : return ERR_PTR(-E2BIG);
539 : : return res;
540 : : }
541 : :
542 : : /*------------------------------------------------------------------*/
543 : : /*
544 : : * Wrapper to add a value to a Wireless Event in a stream of events.
545 : : * Be careful, this one is tricky to use properly :
546 : : * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
547 : : */
548 : : char *iwe_stream_add_value(struct iw_request_info *info, char *event,
549 : : char *value, char *ends, struct iw_event *iwe,
550 : : int event_len);
551 : :
552 : : #endif /* _IW_HANDLER_H */
|