sg3-utils: add newer buildable version
[openembedded.git] / recipes / linux / files / iw_handlers.w13-5.diff
1 diff -u -p -r --new-file linux/include/linux-w12/netdevice.h linux/include/linux/netdevice.h
2 --- linux/include/linux-w12/netdevice.h Thu Nov 22 11:47:09 2001
3 +++ linux/include/linux/netdevice.h     Thu Jan 17 12:00:39 2002
4 @@ -278,6 +278,10 @@ struct net_device
5         struct net_device_stats* (*get_stats)(struct net_device *dev);
6         struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
7  
8 +       /* List of functions to handle Wireless Extensions (instead of ioctl).
9 +        * See <net/iw_handler.h> for details. Jean II */
10 +       struct iw_handler_def * wireless_handlers;
11 +
12         /*
13          * This marks the end of the "visible" part of the structure. All
14          * fields hereafter are internal to the system, and may change at
15 diff -u -p -r --new-file linux/include/linux-w12/wireless.h linux/include/linux/wireless.h
16 --- linux/include/linux-w12/wireless.h  Thu Nov 22 11:47:12 2001
17 +++ linux/include/linux/wireless.h      Thu Jan 17 12:04:08 2002
18 @@ -1,9 +1,10 @@
19  /*
20   * This file define a set of standard wireless extensions
21   *
22 - * Version :   12      5.10.01
23 + * Version :   13      6.12.01
24   *
25   * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
26 + * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
27   */
28  
29  #ifndef _LINUX_WIRELESS_H
30 @@ -11,6 +12,8 @@
31  
32  /************************** DOCUMENTATION **************************/
33  /*
34 + * Initial APIs (1996 -> onward) :
35 + * -----------------------------
36   * Basically, the wireless extensions are for now a set of standard ioctl
37   * call + /proc/net/wireless
38   *
39 @@ -27,16 +30,27 @@
40   * We have the list of command plus a structure descibing the
41   * data exchanged...
42   * Note that to add these ioctl, I was obliged to modify :
43 - *     net/core/dev.c (two place + add include)
44 - *     net/ipv4/af_inet.c (one place + add include)
45 + *     # net/core/dev.c (two place + add include)
46 + *     # net/ipv4/af_inet.c (one place + add include)
47   *
48   * /proc/net/wireless is a copy of /proc/net/dev.
49   * We have a structure for data passed from the driver to /proc/net/wireless
50   * Too add this, I've modified :
51 - *     net/core/dev.c (two other places)
52 - *     include/linux/netdevice.h (one place)
53 - *     include/linux/proc_fs.h (one place)
54 + *     # net/core/dev.c (two other places)
55 + *     # include/linux/netdevice.h (one place)
56 + *     # include/linux/proc_fs.h (one place)
57 + *
58 + * New driver API (2001 -> onward) :
59 + * -------------------------------
60 + * This file is only concerned with the user space API and common definitions.
61 + * The new driver API is defined and documented in :
62 + *     # include/net/iw_handler.h
63   *
64 + * Note as well that /proc/net/wireless implementation has now moved in :
65 + *     # include/linux/wireless.c
66 + *
67 + * Other comments :
68 + * --------------
69   * Do not add here things that are redundant with other mechanisms
70   * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
71   * wireless specific.
72 @@ -54,16 +68,14 @@
73  #include <linux/socket.h>              /* for "struct sockaddr" et al  */
74  #include <linux/if.h>                  /* for IFNAMSIZ and co... */
75  
76 -/**************************** CONSTANTS ****************************/
77 -
78 -/* --------------------------- VERSION --------------------------- */
79 +/***************************** VERSION *****************************/
80  /*
81   * This constant is used to know the availability of the wireless
82   * extensions and to know which version of wireless extensions it is
83   * (there is some stuff that will be added in the future...)
84   * I just plan to increment with each new version.
85   */
86 -#define WIRELESS_EXT   12
87 +#define WIRELESS_EXT   13
88  
89  /*
90   * Changes :
91 @@ -123,12 +135,20 @@
92   *     - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
93   *     - Add new statistics (frag, retry, beacon)
94   *     - Add average quality (for user space calibration)
95 + *
96 + * V12 to V13
97 + * ----------
98 + *     - Document creation of new driver API.
99 + *     - Extract union iwreq_data from struct iwreq (for new driver API).
100 + *     - Rename SIOCSIWNAME as SIOCSIWCOMMIT
101   */
102  
103 +/**************************** CONSTANTS ****************************/
104 +
105  /* -------------------------- IOCTL LIST -------------------------- */
106  
107  /* Basic operations */
108 -#define SIOCSIWNAME    0x8B00          /* Unused */
109 +#define SIOCSIWCOMMIT  0x8B00          /* Commit pending changes to driver */
110  #define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
111  #define SIOCSIWNWID    0x8B02          /* set network id (the cell) */
112  #define SIOCGIWNWID    0x8B03          /* get network id */
113 @@ -414,13 +434,49 @@ struct    iw_statistics
114  
115  /* ------------------------ IOCTL REQUEST ------------------------ */
116  /*
117 + * This structure defines the payload of an ioctl, and is used 
118 + * below.
119 + *
120 + * Note that this structure should fit on the memory footprint
121 + * of iwreq (which is the same as ifreq), which mean a max size of
122 + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
123 + * You should check this when increasing the structures defined
124 + * above in this file...
125 + */
126 +union  iwreq_data
127 +{
128 +       /* Config - generic */
129 +       char            name[IFNAMSIZ];
130 +       /* Name : used to verify the presence of  wireless extensions.
131 +        * Name of the protocol/provider... */
132 +
133 +       struct iw_point essid;          /* Extended network name */
134 +       struct iw_param nwid;           /* network id (or domain - the cell) */
135 +       struct iw_freq  freq;           /* frequency or channel :
136 +                                        * 0-1000 = channel
137 +                                        * > 1000 = frequency in Hz */
138 +
139 +       struct iw_param sens;           /* signal level threshold */
140 +       struct iw_param bitrate;        /* default bit rate */
141 +       struct iw_param txpower;        /* default transmit power */
142 +       struct iw_param rts;            /* RTS threshold threshold */
143 +       struct iw_param frag;           /* Fragmentation threshold */
144 +       __u32           mode;           /* Operation mode */
145 +       struct iw_param retry;          /* Retry limits & lifetime */
146 +
147 +       struct iw_point encoding;       /* Encoding stuff : tokens */
148 +       struct iw_param power;          /* PM duration/timeout */
149 +
150 +       struct sockaddr ap_addr;        /* Access point address */
151 +
152 +       struct iw_point data;           /* Other large parameters */
153 +};
154 +
155 +/*
156   * The structure to exchange data for ioctl.
157   * This structure is the same as 'struct ifreq', but (re)defined for
158   * convenience...
159 - *
160 - * Note that it should fit on the same memory footprint !
161 - * You should check this when increasing the above structures (16 octets)
162 - * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
163 + * Do I need to remind you about structure size (32 octets) ?
164   */
165  struct iwreq 
166  {
167 @@ -429,35 +485,8 @@ struct     iwreq 
168                 char    ifrn_name[IFNAMSIZ];    /* if name, e.g. "eth0" */
169         } ifr_ifrn;
170  
171 -       /* Data part */
172 -       union
173 -       {
174 -               /* Config - generic */
175 -               char            name[IFNAMSIZ];
176 -               /* Name : used to verify the presence of  wireless extensions.
177 -                * Name of the protocol/provider... */
178 -
179 -               struct iw_point essid;  /* Extended network name */
180 -               struct iw_param nwid;   /* network id (or domain - the cell) */
181 -               struct iw_freq  freq;   /* frequency or channel :
182 -                                        * 0-1000 = channel
183 -                                        * > 1000 = frequency in Hz */
184 -
185 -               struct iw_param sens;           /* signal level threshold */
186 -               struct iw_param bitrate;        /* default bit rate */
187 -               struct iw_param txpower;        /* default transmit power */
188 -               struct iw_param rts;            /* RTS threshold threshold */
189 -               struct iw_param frag;           /* Fragmentation threshold */
190 -               __u32           mode;           /* Operation mode */
191 -               struct iw_param retry;          /* Retry limits & lifetime */
192 -
193 -               struct iw_point encoding;       /* Encoding stuff : tokens */
194 -               struct iw_param power;          /* PM duration/timeout */
195 -
196 -               struct sockaddr ap_addr;        /* Access point address */
197 -
198 -               struct iw_point data;           /* Other large parameters */
199 -       }       u;
200 +       /* Data part (defined just above) */
201 +       union   iwreq_data      u;
202  };
203  
204  /* -------------------------- IOCTL DATA -------------------------- */
205 diff -u -p -r --new-file linux/include/net-w12/iw_handler.h linux/include/net/iw_handler.h
206 --- linux/include/net-w12/iw_handler.h  Wed Dec 31 16:00:00 1969
207 +++ linux/include/net/iw_handler.h      Thu Jan 17 12:16:46 2002
208 @@ -0,0 +1,374 @@
209 +/*
210 + * This file define the new driver API for Wireless Extensions
211 + *
212 + * Version :   2       6.12.01
213 + *
214 + * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
215 + * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved.
216 + */
217 +
218 +#ifndef _IW_HANDLER_H
219 +#define _IW_HANDLER_H
220 +
221 +/************************** DOCUMENTATION **************************/
222 +/*
223 + * Initial driver API (1996 -> onward) :
224 + * -----------------------------------
225 + * The initial API just sends the IOCTL request received from user space
226 + * to the driver (via the driver ioctl handler). The driver has to
227 + * handle all the rest...
228 + *
229 + * The initial API also defines a specific handler in struct net_device
230 + * to handle wireless statistics.
231 + *
232 + * The initial APIs served us well and has proven a reasonably good design.
233 + * However, there is a few shortcommings :
234 + *     o No events, everything is a request to the driver.
235 + *     o Large ioctl function in driver with gigantic switch statement
236 + *       (i.e. spaghetti code).
237 + *     o Driver has to mess up with copy_to/from_user, and in many cases
238 + *       does it unproperly. Common mistakes are :
239 + *             * buffer overflows (no checks or off by one checks)
240 + *             * call copy_to/from_user with irq disabled
241 + *     o The user space interface is tied to ioctl because of the use
242 + *       copy_to/from_user.
243 + *
244 + * New driver API (2001 -> onward) :
245 + * -------------------------------
246 + * The new driver API is just a bunch of standard functions (handlers),
247 + * each handling a specific Wireless Extension. The driver just export
248 + * the list of handler it supports, and those will be called apropriately.
249 + *
250 + * I tried to keep the main advantage of the previous API (simplicity,
251 + * efficiency and light weight), and also I provide a good dose of backward
252 + * compatibility (most structures are the same, driver can use both API
253 + * simultaneously, ...).
254 + * Hopefully, I've also addressed the shortcomming of the initial API.
255 + *
256 + * The advantage of the new API are :
257 + *     o Handling of Extensions in driver broken in small contained functions
258 + *     o Tighter checks of ioctl before calling the driver
259 + *     o Flexible commit strategy (at least, the start of it)
260 + *     o Backward compatibility (can be mixed with old API)
261 + *     o Driver doesn't have to worry about memory and user-space issues
262 + * The last point is important for the following reasons :
263 + *     o You are now able to call the new driver API from any API you
264 + *             want (including from within other parts of the kernel).
265 + *     o Common mistakes are avoided (buffer overflow, user space copy
266 + *             with irq disabled and so on).
267 + *
268 + * The Drawback of the new API are :
269 + *     o bloat (especially kernel)
270 + *     o need to migrate existing drivers to new API
271 + * My initial testing shows that the new API adds around 3kB to the kernel
272 + * and save between 0 and 5kB from a typical driver.
273 + * Also, as all structures and data types are unchanged, the migration is
274 + * quite straightforward (but tedious).
275 + *
276 + * ---
277 + *
278 + * The new driver API is defined below in this file. User space should
279 + * not be aware of what's happening down there...
280 + *
281 + * A new kernel wrapper is in charge of validating the IOCTLs and calling
282 + * the appropriate driver handler. This is implemented in :
283 + *     # net/core/wireless.c
284 + *
285 + * The driver export the list of handlers in :
286 + *     # include/linux/netdevice.h (one place)
287 + *
288 + * The new driver API is available for WIRELESS_EXT >= 13.
289 + * Good luck with migration to the new API ;-)
290 + */
291 +
292 +/* ---------------------- THE IMPLEMENTATION ---------------------- */
293 +/*
294 + * Some of the choice I've made are pretty controversials. Defining an
295 + * API is very much weighting compromises. This goes into some of the
296 + * details and the thinking behind the implementation.
297 + *
298 + * Implementation goals :
299 + * --------------------
300 + * The implementation goals were as follow :
301 + *     o Obvious : you should not need a PhD to understand what's happening,
302 + *             the benefit is easier maintainance.
303 + *     o Flexible : it should accomodate a wide variety of driver
304 + *             implementations and be as flexible as the old API.
305 + *     o Lean : it should be efficient memory wise to minimise the impact
306 + *             on kernel footprint.
307 + *     o Transparent to user space : the large number of user space
308 + *             applications that use Wireless Extensions should not need
309 + *             any modifications.
310 + *
311 + * Array of functions versus Struct of functions
312 + * ---------------------------------------------
313 + * 1) Having an array of functions allow the kernel code to access the
314 + * handler in a single lookup, which is much more efficient (think hash
315 + * table here).
316 + * 2) The only drawback is that driver writer may put their handler in
317 + * the wrong slot. This is trivial to test (I set the frequency, the
318 + * bitrate changes). Once the handler is in the proper slot, it will be
319 + * there forever, because the array is only extended at the end.
320 + * 3) Backward/forward compatibility : adding new handler just require
321 + * extending the array, so you can put newer driver in older kernel
322 + * without having to patch the kernel code (and vice versa).
323 + *
324 + * All handler are of the same generic type
325 + * ----------------------------------------
326 + * That's a feature !!!
327 + * 1) Having a generic handler allow to have generic code, which is more
328 + * efficient. If each of the handler was individually typed I would need
329 + * to add a big switch in the kernel (== more bloat). This solution is
330 + * more scalable, adding new Wireless Extensions doesn't add new code.
331 + * 2) You can use the same handler in different slots of the array. For
332 + * hardware, it may be more efficient or logical to handle multiple
333 + * Wireless Extensions with a single function, and the API allow you to
334 + * do that. (An example would be a single record on the card to control
335 + * both bitrate and frequency, the handler would read the old record,
336 + * modify it according to info->cmd and rewrite it).
337 + *
338 + * Functions prototype uses union iwreq_data
339 + * -----------------------------------------
340 + * Some would have prefered functions defined this way :
341 + *     static int mydriver_ioctl_setrate(struct net_device *dev, 
342 + *                                       long rate, int auto)
343 + * 1) The kernel code doesn't "validate" the content of iwreq_data, and
344 + * can't do it (different hardware may have different notion of what a
345 + * valid frequency is), so we don't pretend that we do it.
346 + * 2) The above form is not extendable. If I want to add a flag (for
347 + * example to distinguish setting max rate and basic rate), I would
348 + * break the prototype. Using iwreq_data is more flexible.
349 + * 3) Also, the above form is not generic (see above).
350 + * 4) I don't expect driver developper using the wrong field of the
351 + * union (Doh !), so static typechecking doesn't add much value.
352 + * 5) Lastly, you can skip the union by doing :
353 + *     static int mydriver_ioctl_setrate(struct net_device *dev,
354 + *                                       struct iw_request_info *info,
355 + *                                       struct iw_param *rrq,
356 + *                                       char *extra)
357 + * And then adding the handler in the array like this :
358 + *        (iw_handler) mydriver_ioctl_setrate,             // SIOCSIWRATE
359 + *
360 + * Using functions and not a registry
361 + * ----------------------------------
362 + * Another implementation option would have been for every instance to
363 + * define a registry (a struct containing all the Wireless Extensions)
364 + * and only have a function to commit the registry to the hardware.
365 + * 1) This approach can be emulated by the current code, but not
366 + * vice versa.
367 + * 2) Some drivers don't keep any configuration in the driver, for them
368 + * adding such a registry would be a significant bloat.
369 + * 3) The code to translate from Wireless Extension to native format is
370 + * needed anyway, so it would not reduce significantely the amount of code.
371 + * 4) The current approach only selectively translate Wireless Extensions
372 + * to native format and only selectively set, whereas the registry approach
373 + * would require to translate all WE and set all parameters for any single
374 + * change.
375 + * 5) For many Wireless Extensions, the GET operation return the current
376 + * dynamic value, not the value that was set.
377 + *
378 + * This header is <net/iw_handler.h>
379 + * ---------------------------------
380 + * 1) This header is kernel space only and should not be exported to
381 + * user space. Headers in "include/linux/" are exported, headers in
382 + * "include/net/" are not.
383 + *
384 + * Mixed 32/64 bit issues
385 + * ----------------------
386 + * The Wireless Extensions are designed to be 64 bit clean, by using only
387 + * datatypes with explicit storage size.
388 + * There are some issues related to kernel and user space using different
389 + * memory model, and in particular 64bit kernel with 32bit user space.
390 + * The problem is related to struct iw_point, that contains a pointer
391 + * that *may* need to be translated.
392 + * This is quite messy. The new API doesn't solve this problem (it can't),
393 + * but is a step in the right direction :
394 + * 1) Meta data about each ioctl is easily available, so we know what type
395 + * of translation is needed.
396 + * 2) The move of data between kernel and user space is only done in a single
397 + * place in the kernel, so adding specific hooks in there is possible.
398 + * 3) In the long term, it allows to move away from using ioctl as the
399 + * user space API.
400 + *
401 + * So many comments and so few code
402 + * --------------------------------
403 + * That's a feature. Comments won't bloat the resulting kernel binary.
404 + */
405 +
406 +/***************************** INCLUDES *****************************/
407 +
408 +#include <linux/wireless.h>            /* IOCTL user space API */
409 +
410 +/***************************** VERSION *****************************/
411 +/*
412 + * This constant is used to know which version of the driver API is
413 + * available. Hopefully, this will be pretty stable and no changes
414 + * will be needed...
415 + * I just plan to increment with each new version.
416 + */
417 +#define IW_HANDLER_VERSION     2
418 +
419 +/**************************** CONSTANTS ****************************/
420 +
421 +/* Special error message for the driver to indicate that we
422 + * should do a commit after return from the iw_handler */
423 +#define EIWCOMMIT      EINPROGRESS
424 +
425 +/* Flags available in struct iw_request_info */
426 +#define IW_REQUEST_FLAG_NONE   0x0000  /* No flag so far */
427 +
428 +/* Type of headers we know about (basically union iwreq_data) */
429 +#define IW_HEADER_TYPE_NULL    0       /* Not available */
430 +#define IW_HEADER_TYPE_CHAR    2       /* char [IFNAMSIZ] */
431 +#define IW_HEADER_TYPE_UINT    4       /* __u32 */
432 +#define IW_HEADER_TYPE_FREQ    5       /* struct iw_freq */
433 +#define IW_HEADER_TYPE_POINT   6       /* struct iw_point */
434 +#define IW_HEADER_TYPE_PARAM   7       /* struct iw_param */
435 +#define IW_HEADER_TYPE_ADDR    8       /* struct sockaddr */
436 +
437 +/* Handling flags */
438 +/* Most are not implemented. I just use them as a reminder of some
439 + * cool features we might need one day ;-) */
440 +#define IW_DESCR_FLAG_NONE     0x0000  /* Obvious */
441 +/* Wrapper level flags */
442 +#define IW_DESCR_FLAG_DUMP     0x0001  /* Not part of the dump command */
443 +#define IW_DESCR_FLAG_EVENT    0x0002  /* Generate an event on SET */
444 +#define IW_DESCR_FLAG_RESTRICT 0x0004  /* GET request is ROOT only */
445 +/* Driver level flags */
446 +#define IW_DESCR_FLAG_WAIT     0x0100  /* Wait for driver event */
447 +
448 +/****************************** TYPES ******************************/
449 +
450 +/* ----------------------- WIRELESS HANDLER ----------------------- */
451 +/*
452 + * A wireless handler is just a standard function, that looks like the
453 + * ioctl handler.
454 + * We also define there how a handler list look like... As the Wireless
455 + * Extension space is quite dense, we use a simple array, which is faster
456 + * (that's the perfect hash table ;-).
457 + */
458 +
459 +/*
460 + * Meta data about the request passed to the iw_handler.
461 + * Most handlers can safely ignore what's in there.
462 + * The 'cmd' field might come handy if you want to use the same handler
463 + * for multiple command...
464 + * This struct is also my long term insurance. I can add new fields here
465 + * without breaking the prototype of iw_handler...
466 + */
467 +struct iw_request_info
468 +{
469 +       __u16           cmd;            /* Wireless Extension command */
470 +       __u16           flags;          /* More to come ;-) */
471 +};
472 +
473 +/*
474 + * This is how a function handling a Wireless Extension should look
475 + * like (both get and set, standard and private).
476 + */
477 +typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
478 +                         union iwreq_data *wrqu, char *extra);
479 +
480 +/*
481 + * This define all the handler that the driver export.
482 + * As you need only one per driver type, please use a static const
483 + * shared by all driver instances... Same for the members...
484 + * This will be linked from net_device in <linux/netdevice.h>
485 + */
486 +struct iw_handler_def
487 +{
488 +       /* Number of handlers defined (more precisely, index of the
489 +        * last defined handler + 1) */
490 +       __u16                   num_standard;
491 +       __u16                   num_private;
492 +       /* Number of private arg description */
493 +       __u16                   num_private_args;
494 +
495 +       /* Array of handlers for standard ioctls
496 +        * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
497 +        */
498 +       iw_handler *            standard;
499 +
500 +       /* Array of handlers for private ioctls
501 +        * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
502 +        */
503 +       iw_handler *            private;
504 +
505 +       /* Arguments of private handler. This one is just a list, so you
506 +        * can put it in any order you want and should not leave holes...
507 +        * We will automatically export that to user space... */
508 +       struct iw_priv_args *   private_args;
509 +
510 +       /* In the long term, get_wireless_stats will move from
511 +        * 'struct net_device' to here, to minimise bloat. */
512 +};
513 +
514 +/* ----------------------- WIRELESS EVENTS ----------------------- */
515 +/*
516 + * Currently we don't support events, so let's just plan for the
517 + * future...
518 + */
519 +
520 +/*
521 + * A Wireless Event.
522 + */
523 +// How do we define short header ? We don't want a flag on length.
524 +// Probably a flag on event ? Highest bit to zero...
525 +struct iw_event
526 +{
527 +       __u16           length;                 /* Lenght of this stuff */
528 +       __u16           event;                  /* Wireless IOCTL */
529 +       union   iwreq_data      header;         /* IOCTL fixed payload */
530 +       char            extra[0];               /* Optional IOCTL data */
531 +};
532 +
533 +/* ---------------------- IOCTL DESCRIPTION ---------------------- */
534 +/*
535 + * One of the main goal of the new interface is to deal entirely with
536 + * user space/kernel space memory move.
537 + * For that, we need to know :
538 + *     o if iwreq is a pointer or contain the full data
539 + *     o what is the size of the data to copy
540 + *
541 + * For private IOCTLs, we use the same rules as used by iwpriv and
542 + * defined in struct iw_priv_args.
543 + *
544 + * For standard IOCTLs, things are quite different and we need to
545 + * use the stuctures below. Actually, this struct is also more
546 + * efficient, but that's another story...
547 + */
548 +
549 +/*
550 + * Describe how a standard IOCTL looks like.
551 + */
552 +struct iw_ioctl_description
553 +{
554 +       __u8    header_type;            /* NULL, iw_point or other */
555 +       __u8    token_type;             /* Future */
556 +       __u16   token_size;             /* Granularity of payload */
557 +       __u16   min_tokens;             /* Min acceptable token number */
558 +       __u16   max_tokens;             /* Max acceptable token number */
559 +       __u32   flags;                  /* Special handling of the request */
560 +};
561 +
562 +/* Need to think of short header translation table. Later. */
563 +
564 +/**************************** PROTOTYPES ****************************/
565 +/*
566 + * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
567 + * Those may be called only within the kernel.
568 + */
569 +
570 +/* First : function strictly used inside the kernel */
571 +
572 +/* Handle /proc/net/wireless, called in net/code/dev.c */
573 +extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
574 +                                int length);
575 +
576 +/* Handle IOCTLs, called in net/code/dev.c */
577 +extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
578 +
579 +/* Second : functions that may be called by driver modules */
580 +/* None yet */
581 +
582 +#endif /* _LINUX_WIRELESS_H */
583 diff -u -p -r --new-file linux/net/core-w12/Makefile linux/net/core/Makefile
584 --- linux/net/core-w12/Makefile Tue Oct 30 15:08:12 2001
585 +++ linux/net/core/Makefile     Thu Jan 17 11:06:07 2002
586 @@ -26,5 +26,8 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o d
587  obj-$(CONFIG_NETFILTER) += netfilter.o
588  obj-$(CONFIG_NET_DIVERT) += dv.o
589  obj-$(CONFIG_NET_PROFILE) += profile.o
590 +obj-$(CONFIG_NET_RADIO) += wireless.o
591 +# Ugly. I wish all wireless drivers were moved in drivers/net/wireless
592 +obj-$(CONFIG_NET_PCMCIA_RADIO) += wireless.o
593  
594  include $(TOPDIR)/Rules.make
595 diff -u -p -r --new-file linux/net/core-w12/dev.c linux/net/core/dev.c
596 --- linux/net/core-w12/dev.c    Wed Nov  7 14:39:36 2001
597 +++ linux/net/core/dev.c        Thu Jan 17 11:06:07 2002
598 @@ -102,6 +102,7 @@
599  #include <linux/module.h>
600  #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
601  #include <linux/wireless.h>            /* Note : will define WIRELESS_EXT */
602 +#include <net/iw_handler.h>
603  #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
604  #ifdef CONFIG_PLIP
605  extern int plip_init(void);
606 @@ -1796,122 +1797,6 @@ static int dev_proc_stats(char *buffer, 
607  #endif /* CONFIG_PROC_FS */
608  
609  
610 -#ifdef WIRELESS_EXT
611 -#ifdef CONFIG_PROC_FS
612 -
613 -/*
614 - * Print one entry of /proc/net/wireless
615 - * This is a clone of /proc/net/dev (just above)
616 - */
617 -static int sprintf_wireless_stats(char *buffer, struct net_device *dev)
618 -{
619 -       /* Get stats from the driver */
620 -       struct iw_statistics *stats = (dev->get_wireless_stats ?
621 -                                      dev->get_wireless_stats(dev) :
622 -                                      (struct iw_statistics *) NULL);
623 -       int size;
624 -
625 -       if (stats != (struct iw_statistics *) NULL) {
626 -               size = sprintf(buffer,
627 -                              "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d %6d %6d   %6d\n",
628 -                              dev->name,
629 -                              stats->status,
630 -                              stats->qual.qual,
631 -                              stats->qual.updated & 1 ? '.' : ' ',
632 -                              stats->qual.level,
633 -                              stats->qual.updated & 2 ? '.' : ' ',
634 -                              stats->qual.noise,
635 -                              stats->qual.updated & 4 ? '.' : ' ',
636 -                              stats->discard.nwid,
637 -                              stats->discard.code,
638 -                              stats->discard.fragment,
639 -                              stats->discard.retries,
640 -                              stats->discard.misc,
641 -                              stats->miss.beacon);
642 -               stats->qual.updated = 0;
643 -       }
644 -       else
645 -               size = 0;
646 -
647 -       return size;
648 -}
649 -
650 -/*
651 - * Print info for /proc/net/wireless (print all entries)
652 - * This is a clone of /proc/net/dev (just above)
653 - */
654 -static int dev_get_wireless_info(char * buffer, char **start, off_t offset,
655 -                         int length)
656 -{
657 -       int             len = 0;
658 -       off_t           begin = 0;
659 -       off_t           pos = 0;
660 -       int             size;
661 -       
662 -       struct net_device *     dev;
663 -
664 -       size = sprintf(buffer,
665 -                      "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
666 -                      " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
667 -                       );
668 -       
669 -       pos += size;
670 -       len += size;
671 -
672 -       read_lock(&dev_base_lock);
673 -       for (dev = dev_base; dev != NULL; dev = dev->next) {
674 -               size = sprintf_wireless_stats(buffer + len, dev);
675 -               len += size;
676 -               pos = begin + len;
677 -
678 -               if (pos < offset) {
679 -                       len = 0;
680 -                       begin = pos;
681 -               }
682 -               if (pos > offset + length)
683 -                       break;
684 -       }
685 -       read_unlock(&dev_base_lock);
686 -
687 -       *start = buffer + (offset - begin);     /* Start of wanted data */
688 -       len -= (offset - begin);                /* Start slop */
689 -       if (len > length)
690 -               len = length;                   /* Ending slop */
691 -       if (len < 0)
692 -               len = 0;
693 -
694 -       return len;
695 -}
696 -#endif /* CONFIG_PROC_FS */
697 -
698 -/*
699 - *     Allow programatic access to /proc/net/wireless even if /proc
700 - *     doesn't exist... Also more efficient...
701 - */
702 -static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
703 -{
704 -       /* Get stats from the driver */
705 -       struct iw_statistics *stats = (dev->get_wireless_stats ?
706 -                                      dev->get_wireless_stats(dev) :
707 -                                      (struct iw_statistics *) NULL);
708 -
709 -       if (stats != (struct iw_statistics *) NULL) {
710 -               struct iwreq *  wrq = (struct iwreq *)ifr;
711 -
712 -               /* Copy statistics to the user buffer */
713 -               if(copy_to_user(wrq->u.data.pointer, stats,
714 -                               sizeof(struct iw_statistics)))
715 -                       return -EFAULT;
716 -
717 -               /* Check if we need to clear the update flag */
718 -               if(wrq->u.data.flags != 0)
719 -                       stats->qual.updated = 0;
720 -               return(0);
721 -       } else
722 -               return -EOPNOTSUPP;
723 -}
724 -#endif /* WIRELESS_EXT */
725 -
726  /**
727   *     netdev_set_master       -       set up master/slave pair
728   *     @slave: slave device
729 @@ -2209,11 +2094,6 @@ static int dev_ifsioc(struct ifreq *ifr,
730                         notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
731                         return 0;
732  
733 -#ifdef WIRELESS_EXT
734 -               case SIOCGIWSTATS:
735 -                       return dev_iwstats(dev, ifr);
736 -#endif /* WIRELESS_EXT */
737 -
738                 /*
739                  *      Unknown or private ioctl
740                  */
741 @@ -2239,17 +2119,6 @@ static int dev_ifsioc(struct ifreq *ifr,
742                                 return -EOPNOTSUPP;
743                         }
744  
745 -#ifdef WIRELESS_EXT
746 -                       if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
747 -                               if (dev->do_ioctl) {
748 -                                       if (!netif_device_present(dev))
749 -                                               return -ENODEV;
750 -                                       return dev->do_ioctl(dev, ifr, cmd);
751 -                               }
752 -                               return -EOPNOTSUPP;
753 -                       }
754 -#endif /* WIRELESS_EXT */
755 -
756         }
757         return -EINVAL;
758  }
759 @@ -2431,7 +2300,8 @@ int dev_ioctl(unsigned int cmd, void *ar
760                                 }
761                                 dev_load(ifr.ifr_name);
762                                 rtnl_lock();
763 -                               ret = dev_ifsioc(&ifr, cmd);
764 +                               /* Follow me in net/core/wireless.c */
765 +                               ret = wireless_process_ioctl(&ifr, cmd);
766                                 rtnl_unlock();
767                                 if (!ret && IW_IS_GET(cmd) &&
768                                     copy_to_user(arg, &ifr, sizeof(struct ifreq)))
769 @@ -2856,6 +2726,7 @@ int __init net_dev_init(void)
770         proc_net_create("dev", 0, dev_get_info);
771         create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL);
772  #ifdef WIRELESS_EXT
773 +       /* Available in net/core/wireless.c */
774         proc_net_create("wireless", 0, dev_get_wireless_info);
775  #endif /* WIRELESS_EXT */
776  #endif /* CONFIG_PROC_FS */
777 diff -u -p -r --new-file linux/net/core-w12/wireless.c linux/net/core/wireless.c
778 --- linux/net/core-w12/wireless.c       Wed Dec 31 16:00:00 1969
779 +++ linux/net/core/wireless.c   Mon Jan 21 11:13:23 2002
780 @@ -0,0 +1,733 @@
781 +/*
782 + * This file implement the Wireless Extensions APIs.
783 + *
784 + * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
785 + * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
786 + *
787 + * (As all part of the Linux kernel, this file is GPL)
788 + */
789 +
790 +/************************** DOCUMENTATION **************************/
791 +/*
792 + * API definition :
793 + * --------------
794 + * See <linux/wireless.h> for details of the APIs and the rest.
795 + *
796 + * History :
797 + * -------
798 + *
799 + * v1 - 5.12.01 - Jean II
800 + *     o Created this file.
801 + *
802 + * v2 - 13.12.01 - Jean II
803 + *     o Move /proc/net/wireless stuff from net/core/dev.c to here
804 + *     o Make Wireless Extension IOCTLs go through here
805 + *     o Added iw_handler handling ;-)
806 + *     o Added standard ioctl description
807 + *     o Initial dumb commit strategy based on orinoco.c
808 + */
809 +
810 +/***************************** INCLUDES *****************************/
811 +
812 +#include <asm/uaccess.h>               /* copy_to_user() */
813 +#include <linux/config.h>              /* Not needed ??? */
814 +#include <linux/types.h>               /* off_t */
815 +#include <linux/netdevice.h>           /* struct ifreq, dev_get_by_name() */
816 +
817 +#include <linux/wireless.h>            /* Pretty obvious */
818 +#include <net/iw_handler.h>            /* New driver API */
819 +
820 +/**************************** CONSTANTS ****************************/
821 +
822 +/* This will be turned on later on... */
823 +#undef WE_STRICT_WRITE         /* Check write buffer size */
824 +
825 +/* Debuging stuff */
826 +#undef WE_IOCTL_DEBUG          /* Debug IOCTL API */
827 +
828 +/************************* GLOBAL VARIABLES *************************/
829 +/*
830 + * You should not use global variables, because or re-entrancy.
831 + * On our case, it's only const, so it's OK...
832 + */
833 +static const struct iw_ioctl_description       standard_ioctl[] = {
834 +       /* SIOCSIWCOMMIT (internal) */
835 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
836 +       /* SIOCGIWNAME */
837 +       { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
838 +       /* SIOCSIWNWID */
839 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
840 +       /* SIOCGIWNWID */
841 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
842 +       /* SIOCSIWFREQ */
843 +       { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
844 +       /* SIOCGIWFREQ */
845 +       { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
846 +       /* SIOCSIWMODE */
847 +       { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
848 +       /* SIOCGIWMODE */
849 +       { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
850 +       /* SIOCSIWSENS */
851 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
852 +       /* SIOCGIWSENS */
853 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
854 +       /* SIOCSIWRANGE */
855 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
856 +       /* SIOCGIWRANGE */
857 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP},
858 +       /* SIOCSIWPRIV */
859 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
860 +       /* SIOCGIWPRIV (handled directly by us) */
861 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
862 +       /* SIOCSIWSTATS */
863 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
864 +       /* SIOCGIWSTATS (handled directly by us) */
865 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
866 +       /* SIOCSIWSPY */
867 +       { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
868 +       /* SIOCGIWSPY */
869 +       { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
870 +       /* -- hole -- */
871 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
872 +       /* -- hole -- */
873 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
874 +       /* SIOCSIWAP */
875 +       { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
876 +       /* SIOCGIWAP */
877 +       { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
878 +       /* -- hole -- */
879 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
880 +       /* SIOCGIWAPLIST */
881 +       { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
882 +       /* -- hole -- */
883 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
884 +       /* -- hole -- */
885 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
886 +       /* SIOCSIWESSID */
887 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT},
888 +       /* SIOCGIWESSID */
889 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP},
890 +       /* SIOCSIWNICKN */
891 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
892 +       /* SIOCGIWNICKN */
893 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
894 +       /* -- hole -- */
895 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
896 +       /* -- hole -- */
897 +       { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
898 +       /* SIOCSIWRATE */
899 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
900 +       /* SIOCGIWRATE */
901 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
902 +       /* SIOCSIWRTS */
903 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
904 +       /* SIOCGIWRTS */
905 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
906 +       /* SIOCSIWFRAG */
907 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
908 +       /* SIOCGIWFRAG */
909 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
910 +       /* SIOCSIWTXPOW */
911 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
912 +       /* SIOCGIWTXPOW */
913 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
914 +       /* SIOCSIWRETRY */
915 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
916 +       /* SIOCGIWRETRY */
917 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
918 +       /* SIOCSIWENCODE */
919 +       { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
920 +       /* SIOCGIWENCODE */
921 +       { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
922 +       /* SIOCSIWPOWER */
923 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
924 +       /* SIOCGIWPOWER */
925 +       { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
926 +};
927 +
928 +/* Size (in bytes) of the various private data types */
929 +char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
930 +
931 +/************************ COMMON SUBROUTINES ************************/
932 +/*
933 + * Stuff that may be used in various place or doesn't fit in one
934 + * of the section below.
935 + */
936 +
937 +/* ---------------------------------------------------------------- */
938 +/*
939 + * Return the driver handler associated with a specific Wireless Extension.
940 + * Called from various place, so make sure it remains efficient.
941 + */
942 +static inline iw_handler get_handler(struct net_device *dev,
943 +                                    unsigned int cmd)
944 +{
945 +       unsigned int    index;          /* MUST be unsigned */
946 +
947 +       /* Check if we have some wireless handlers defined */
948 +       if(dev->wireless_handlers == NULL)
949 +               return NULL;
950 +
951 +       /* Try as a standard command */
952 +       index = cmd - SIOCIWFIRST;
953 +       if(index < dev->wireless_handlers->num_standard)
954 +               return dev->wireless_handlers->standard[index];
955 +
956 +       /* Try as a private command */
957 +       index = cmd - SIOCIWFIRSTPRIV;
958 +       if(index < dev->wireless_handlers->num_private)
959 +               return dev->wireless_handlers->private[index];
960 +
961 +       /* Not found */
962 +       return NULL;
963 +}
964 +
965 +/* ---------------------------------------------------------------- */
966 +/*
967 + * Get statistics out of the driver
968 + */
969 +static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
970 +{
971 +       return (dev->get_wireless_stats ?
972 +               dev->get_wireless_stats(dev) :
973 +               (struct iw_statistics *) NULL);
974 +       /* In the future, get_wireless_stats may move from 'struct net_device'
975 +        * to 'struct iw_handler_def', to de-bloat struct net_device.
976 +        * Definitely worse a thought... */
977 +}
978 +
979 +/* ---------------------------------------------------------------- */
980 +/*
981 + * Call the commit handler in the driver
982 + * (if exist and if conditions are right)
983 + *
984 + * Note : our current commit strategy is currently pretty dumb,
985 + * but we will be able to improve on that...
986 + * The goal is to try to agreagate as many changes as possible
987 + * before doing the commit. Drivers that will define a commit handler
988 + * are usually those that need a reset after changing parameters, so
989 + * we want to minimise the number of reset.
990 + * A cool idea is to use a timer : at each "set" command, we re-set the
991 + * timer, when the timer eventually fires, we call the driver.
992 + * Hopefully, more on that later.
993 + *
994 + * Also, I'm waiting to see how many people will complain about the
995 + * netif_running(dev) test. I'm open on that one...
996 + * Hopefully, the driver will remember to do a commit in "open()" ;-)
997 + */
998 +static inline int call_commit_handler(struct net_device *      dev)
999 +{
1000 +       if((netif_running(dev)) &&
1001 +          (dev->wireless_handlers->standard[0] != NULL)) {
1002 +               /* Call the commit handler on the driver */
1003 +               return dev->wireless_handlers->standard[0](dev, NULL,
1004 +                                                          NULL, NULL);
1005 +       } else
1006 +               return 0;               /* Command completed successfully */
1007 +}
1008 +
1009 +/* ---------------------------------------------------------------- */
1010 +/*
1011 + * Number of private arguments
1012 + */
1013 +static inline int get_priv_size(__u16  args)
1014 +{
1015 +       int     num = args & IW_PRIV_SIZE_MASK;
1016 +       int     type = (args & IW_PRIV_TYPE_MASK) >> 12;
1017 +
1018 +       return num * priv_type_size[type];
1019 +}
1020 +
1021 +
1022 +/******************** /proc/net/wireless SUPPORT ********************/
1023 +/*
1024 + * The /proc/net/wireless file is a human readable user-space interface
1025 + * exporting various wireless specific statistics from the wireless devices.
1026 + * This is the most popular part of the Wireless Extensions ;-)
1027 + *
1028 + * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
1029 + * The content of the file is basically the content of "struct iw_statistics".
1030 + */
1031 +
1032 +#ifdef CONFIG_PROC_FS
1033 +
1034 +/* ---------------------------------------------------------------- */
1035 +/*
1036 + * Print one entry (line) of /proc/net/wireless
1037 + */
1038 +static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev)
1039 +{
1040 +       /* Get stats from the driver */
1041 +       struct iw_statistics *stats;
1042 +       int size;
1043 +
1044 +       stats = get_wireless_stats(dev);
1045 +       if (stats != (struct iw_statistics *) NULL) {
1046 +               size = sprintf(buffer,
1047 +                              "%6s: %04x  %3d%c  %3d%c  %3d%c  %6d %6d %6d %6d %6d   %6d\n",
1048 +                              dev->name,
1049 +                              stats->status,
1050 +                              stats->qual.qual,
1051 +                              stats->qual.updated & 1 ? '.' : ' ',
1052 +                              stats->qual.level,
1053 +                              stats->qual.updated & 2 ? '.' : ' ',
1054 +                              stats->qual.noise,
1055 +                              stats->qual.updated & 4 ? '.' : ' ',
1056 +                              stats->discard.nwid,
1057 +                              stats->discard.code,
1058 +                              stats->discard.fragment,
1059 +                              stats->discard.retries,
1060 +                              stats->discard.misc,
1061 +                              stats->miss.beacon);
1062 +               stats->qual.updated = 0;
1063 +       }
1064 +       else
1065 +               size = 0;
1066 +
1067 +       return size;
1068 +}
1069 +
1070 +/* ---------------------------------------------------------------- */
1071 +/*
1072 + * Print info for /proc/net/wireless (print all entries)
1073 + */
1074 +int dev_get_wireless_info(char * buffer, char **start, off_t offset,
1075 +                         int length)
1076 +{
1077 +       int             len = 0;
1078 +       off_t           begin = 0;
1079 +       off_t           pos = 0;
1080 +       int             size;
1081 +       
1082 +       struct net_device *     dev;
1083 +
1084 +       size = sprintf(buffer,
1085 +                      "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
1086 +                      " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
1087 +                       );
1088 +       
1089 +       pos += size;
1090 +       len += size;
1091 +
1092 +       read_lock(&dev_base_lock);
1093 +       for (dev = dev_base; dev != NULL; dev = dev->next) {
1094 +               size = sprintf_wireless_stats(buffer + len, dev);
1095 +               len += size;
1096 +               pos = begin + len;
1097 +
1098 +               if (pos < offset) {
1099 +                       len = 0;
1100 +                       begin = pos;
1101 +               }
1102 +               if (pos > offset + length)
1103 +                       break;
1104 +       }
1105 +       read_unlock(&dev_base_lock);
1106 +
1107 +       *start = buffer + (offset - begin);     /* Start of wanted data */
1108 +       len -= (offset - begin);                /* Start slop */
1109 +       if (len > length)
1110 +               len = length;                   /* Ending slop */
1111 +       if (len < 0)
1112 +               len = 0;
1113 +
1114 +       return len;
1115 +}
1116 +#endif /* CONFIG_PROC_FS */
1117 +
1118 +/************************** IOCTL SUPPORT **************************/
1119 +/*
1120 + * The original user space API to configure all those Wireless Extensions
1121 + * is through IOCTLs.
1122 + * In there, we check if we need to call the new driver API (iw_handler)
1123 + * or just call the driver ioctl handler.
1124 + */
1125 +
1126 +/* ---------------------------------------------------------------- */
1127 +/*
1128 + *     Allow programatic access to /proc/net/wireless even if /proc
1129 + *     doesn't exist... Also more efficient...
1130 + */
1131 +static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
1132 +{
1133 +       /* Get stats from the driver */
1134 +       struct iw_statistics *stats;
1135 +
1136 +       stats = get_wireless_stats(dev);
1137 +       if (stats != (struct iw_statistics *) NULL) {
1138 +               struct iwreq *  wrq = (struct iwreq *)ifr;
1139 +
1140 +               /* Copy statistics to the user buffer */
1141 +               if(copy_to_user(wrq->u.data.pointer, stats,
1142 +                               sizeof(struct iw_statistics)))
1143 +                       return -EFAULT;
1144 +
1145 +               /* Check if we need to clear the update flag */
1146 +               if(wrq->u.data.flags != 0)
1147 +                       stats->qual.updated = 0;
1148 +               return 0;
1149 +       } else
1150 +               return -EOPNOTSUPP;
1151 +}
1152 +
1153 +/* ---------------------------------------------------------------- */
1154 +/*
1155 + * Export the driver private handler definition
1156 + * They will be picked up by tools like iwpriv...
1157 + */
1158 +static inline int ioctl_export_private(struct net_device *     dev,
1159 +                                      struct ifreq *           ifr)
1160 +{
1161 +       struct iwreq *                          iwr = (struct iwreq *) ifr;
1162 +
1163 +       /* Check if the driver has something to export */
1164 +       if((dev->wireless_handlers->num_private_args == 0) ||
1165 +          (dev->wireless_handlers->private_args == NULL))
1166 +               return -EOPNOTSUPP;
1167 +
1168 +       /* Check NULL pointer */
1169 +       if(iwr->u.data.pointer == NULL)
1170 +               return -EFAULT;
1171 +#ifdef WE_STRICT_WRITE
1172 +       /* Check if there is enough buffer up there */
1173 +       if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1))
1174 +               return -E2BIG;
1175 +#endif /* WE_STRICT_WRITE */
1176 +
1177 +       /* Set the number of available ioctls. */
1178 +       iwr->u.data.length = dev->wireless_handlers->num_private_args;
1179 +
1180 +       /* Copy structure to the user buffer. */
1181 +       if (copy_to_user(iwr->u.data.pointer,
1182 +                        dev->wireless_handlers->private_args,
1183 +                        sizeof(struct iw_priv_args) * iwr->u.data.length))
1184 +               return -EFAULT;
1185 +
1186 +       return 0;
1187 +}
1188 +
1189 +/* ---------------------------------------------------------------- */
1190 +/*
1191 + * Wrapper to call a standard Wireless Extension handler.
1192 + * We do various checks and also take care of moving data between
1193 + * user space and kernel space.
1194 + */
1195 +static inline int ioctl_standard_call(struct net_device *      dev,
1196 +                                     struct ifreq *            ifr,
1197 +                                     unsigned int              cmd,
1198 +                                     iw_handler                handler)
1199 +{
1200 +       struct iwreq *                          iwr = (struct iwreq *) ifr;
1201 +       const struct iw_ioctl_description *     descr;
1202 +       struct iw_request_info                  info;
1203 +       int                                     ret = -EINVAL;
1204 +
1205 +       /* Get the description of the IOCTL */
1206 +       descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1207 +
1208 +#ifdef WE_IOCTL_DEBUG
1209 +       printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n",
1210 +              ifr->ifr_name, cmd);
1211 +       printk(KERN_DEBUG "Header type : %d, token type : %d, token_size : %d, max_token : %d\n", descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1212 +#endif /* WE_IOCTL_DEBUG */
1213 +
1214 +       /* Prepare the call */
1215 +       info.cmd = cmd;
1216 +       info.flags = 0;
1217 +
1218 +       /* Check if we have a pointer to user space data or not */
1219 +       if(descr->header_type != IW_HEADER_TYPE_POINT) {
1220 +               /* No extra arguments. Trivial to handle */
1221 +               ret = handler(dev, &info, &(iwr->u), NULL);
1222 +       } else {
1223 +               char *  extra;
1224 +               int     err;
1225 +
1226 +               /* Check what user space is giving us */
1227 +               if(IW_IS_SET(cmd)) {
1228 +                       /* Check NULL pointer */
1229 +                       if((iwr->u.data.pointer == NULL) &&
1230 +                          (iwr->u.data.length != 0))
1231 +                               return -EFAULT;
1232 +                       /* Check if number of token fits within bounds */
1233 +                       if(iwr->u.data.length > descr->max_tokens)
1234 +                               return -E2BIG;
1235 +                       if(iwr->u.data.length < descr->min_tokens)
1236 +                               return -EINVAL;
1237 +               } else {
1238 +                       /* Check NULL pointer */
1239 +                       if(iwr->u.data.pointer == NULL)
1240 +                               return -EFAULT;
1241 +#ifdef WE_STRICT_WRITE
1242 +                       /* Check if there is enough buffer up there */
1243 +                       if(iwr->u.data.length < descr->max_tokens)
1244 +                               return -E2BIG;
1245 +#endif /* WE_STRICT_WRITE */
1246 +               }
1247 +
1248 +#ifdef WE_IOCTL_DEBUG
1249 +               printk(KERN_DEBUG "Malloc %d bytes\n",
1250 +                      descr->max_tokens * descr->token_size);
1251 +#endif /* WE_IOCTL_DEBUG */
1252 +
1253 +               /* Always allocate for max space. Easier, and won't last
1254 +                * long... */
1255 +               extra = kmalloc(descr->max_tokens * descr->token_size,
1256 +                               GFP_KERNEL);
1257 +               if (extra == NULL) {
1258 +                       return -ENOMEM;
1259 +               }
1260 +
1261 +               /* If it is a SET, get all the extra data in here */
1262 +               if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
1263 +                       err = copy_from_user(extra, iwr->u.data.pointer,
1264 +                                            iwr->u.data.length *
1265 +                                            descr->token_size);
1266 +                       if (err) {
1267 +                               kfree(extra);
1268 +                               return -EFAULT;
1269 +                       }
1270 +#ifdef WE_IOCTL_DEBUG
1271 +                       printk(KERN_DEBUG "Got %d bytes\n",
1272 +                              iwr->u.data.length * descr->token_size);
1273 +#endif /* WE_IOCTL_DEBUG */
1274 +               }
1275 +
1276 +               /* Call the handler */
1277 +               ret = handler(dev, &info, &(iwr->u), extra);
1278 +
1279 +               /* If we have something to return to the user */
1280 +               if (!ret && IW_IS_GET(cmd)) {
1281 +                       err = copy_to_user(iwr->u.data.pointer, extra,
1282 +                                          iwr->u.data.length *
1283 +                                          descr->token_size);
1284 +                       if (err)
1285 +                               ret =  -EFAULT;                            
1286 +#ifdef WE_IOCTL_DEBUG
1287 +                       printk(KERN_DEBUG "Wrote %d bytes\n",
1288 +                              iwr->u.data.length * descr->token_size);
1289 +#endif /* WE_IOCTL_DEBUG */
1290 +               }
1291 +
1292 +               /* Cleanup - I told you it wasn't that long ;-) */
1293 +               kfree(extra);
1294 +       }
1295 +
1296 +       /* Call commit handler if needed and defined */
1297 +       if(ret == -EIWCOMMIT)
1298 +               ret = call_commit_handler(dev);
1299 +
1300 +       /* Here, we will generate the appropriate event if needed */
1301 +
1302 +       return ret;
1303 +}
1304 +
1305 +/* ---------------------------------------------------------------- */
1306 +/*
1307 + * Wrapper to call a private Wireless Extension handler.
1308 + * We do various checks and also take care of moving data between
1309 + * user space and kernel space.
1310 + * It's not as nice and slimline as the standard wrapper. The cause
1311 + * is struct iw_priv_args, which was not really designed for the
1312 + * job we are going here.
1313 + *
1314 + * IMPORTANT : This function prevent to set and get data on the same
1315 + * IOCTL and enforce the SET/GET convention. Not doing it would be
1316 + * far too hairy...
1317 + * If you need to set and get data at the same time, please don't use
1318 + * a iw_handler but process it in your ioctl handler (i.e. use the
1319 + * old driver API).
1320 + */
1321 +static inline int ioctl_private_call(struct net_device *       dev,
1322 +                                    struct ifreq *             ifr,
1323 +                                    unsigned int               cmd,
1324 +                                    iw_handler         handler)
1325 +{
1326 +       struct iwreq *                  iwr = (struct iwreq *) ifr;
1327 +       struct iw_priv_args *           descr = NULL;
1328 +       struct iw_request_info          info;
1329 +       int                             extra_size = 0;
1330 +       int                             i;
1331 +       int                             ret = -EINVAL;
1332 +
1333 +       /* Get the description of the IOCTL */
1334 +       for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
1335 +               if(cmd == dev->wireless_handlers->private_args[i].cmd) {
1336 +                       descr = &(dev->wireless_handlers->private_args[i]);
1337 +                       break;
1338 +               }
1339 +
1340 +#ifdef WE_IOCTL_DEBUG
1341 +       printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n",
1342 +              ifr->ifr_name, cmd);
1343 +       if(descr) {
1344 +               printk(KERN_DEBUG "Name %s, set %X, get %X\n",
1345 +                      descr->name, descr->set_args, descr->get_args);
1346 +       }
1347 +#endif /* WE_IOCTL_DEBUG */
1348 +
1349 +       /* Compute the size of the set/get arguments */
1350 +       if(descr != NULL) {
1351 +               if(IW_IS_SET(cmd)) {
1352 +                       /* Size of set arguments */
1353 +                       extra_size = get_priv_size(descr->set_args);
1354 +
1355 +                       /* Does it fits in iwr ? */
1356 +                       if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
1357 +                          (extra_size < IFNAMSIZ))
1358 +                               extra_size = 0;
1359 +               } else {
1360 +                       /* Size of set arguments */
1361 +                       extra_size = get_priv_size(descr->get_args);
1362 +
1363 +                       /* Does it fits in iwr ? */
1364 +                       if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
1365 +                          (extra_size < IFNAMSIZ))
1366 +                               extra_size = 0;
1367 +               }
1368 +       }
1369 +
1370 +       /* Prepare the call */
1371 +       info.cmd = cmd;
1372 +       info.flags = 0;
1373 +
1374 +       /* Check if we have a pointer to user space data or not. */
1375 +       if(extra_size == 0) {
1376 +               /* No extra arguments. Trivial to handle */
1377 +               ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
1378 +       } else {
1379 +               char *  extra;
1380 +               int     err;
1381 +
1382 +               /* Check what user space is giving us */
1383 +               if(IW_IS_SET(cmd)) {
1384 +                       /* Check NULL pointer */
1385 +                       if((iwr->u.data.pointer == NULL) &&
1386 +                          (iwr->u.data.length != 0))
1387 +                               return -EFAULT;
1388 +
1389 +                       /* Does it fits within bounds ? */
1390 +                       if(iwr->u.data.length > (descr->set_args &
1391 +                                                IW_PRIV_SIZE_MASK))
1392 +                               return -E2BIG;
1393 +               } else {
1394 +                       /* Check NULL pointer */
1395 +                       if(iwr->u.data.pointer == NULL)
1396 +                               return -EFAULT;
1397 +               }
1398 +
1399 +#ifdef WE_IOCTL_DEBUG
1400 +               printk(KERN_DEBUG "Malloc %d bytes\n", extra_size);
1401 +#endif /* WE_IOCTL_DEBUG */
1402 +
1403 +               /* Always allocate for max space. Easier, and won't last
1404 +                * long... */
1405 +               extra = kmalloc(extra_size, GFP_KERNEL);
1406 +               if (extra == NULL) {
1407 +                       return -ENOMEM;
1408 +               }
1409 +
1410 +               /* If it is a SET, get all the extra data in here */
1411 +               if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
1412 +                       err = copy_from_user(extra, iwr->u.data.pointer,
1413 +                                            extra_size);
1414 +                       if (err) {
1415 +                               kfree(extra);
1416 +                               return -EFAULT;
1417 +                       }
1418 +#ifdef WE_IOCTL_DEBUG
1419 +                       printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length);
1420 +#endif /* WE_IOCTL_DEBUG */
1421 +               }
1422 +
1423 +               /* Call the handler */
1424 +               ret = handler(dev, &info, &(iwr->u), extra);
1425 +
1426 +               /* If we have something to return to the user */
1427 +               if (!ret && IW_IS_GET(cmd)) {
1428 +                       err = copy_to_user(iwr->u.data.pointer, extra,
1429 +                                          extra_size);
1430 +                       if (err)
1431 +                               ret =  -EFAULT;                            
1432 +#ifdef WE_IOCTL_DEBUG
1433 +                       printk(KERN_DEBUG "Wrote %d elem\n",
1434 +                              iwr->u.data.length);
1435 +#endif /* WE_IOCTL_DEBUG */
1436 +               }
1437 +
1438 +               /* Cleanup - I told you it wasn't that long ;-) */
1439 +               kfree(extra);
1440 +       }
1441 +
1442 +
1443 +       /* Call commit handler if needed and defined */
1444 +       if(ret == -EIWCOMMIT)
1445 +               ret = call_commit_handler(dev);
1446 +
1447 +       return ret;
1448 +}
1449 +
1450 +/* ---------------------------------------------------------------- */
1451 +/*
1452 + * Main IOCTl dispatcher. Called from the main networking code
1453 + * (dev_ioctl() in net/core/dev.c).
1454 + * Check the type of IOCTL and call the appropriate wrapper...
1455 + */
1456 +int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1457 +{
1458 +       struct net_device *dev;
1459 +       iw_handler      handler;
1460 +
1461 +       /* Permissions are already checked in dev_ioctl() before calling us.
1462 +        * The copy_to/from_user() of ifr is also dealt with in there */
1463 +
1464 +       /* Make sure the device exist */
1465 +       if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
1466 +               return -ENODEV;
1467 +
1468 +       /* A bunch of special cases, then the generic case...
1469 +        * Note that 'cmd' is already filtered in dev_ioctl() with
1470 +        * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
1471 +       switch(cmd) 
1472 +       {
1473 +               case SIOCGIWSTATS:
1474 +                       /* Get Wireless Stats */
1475 +                       return dev_iwstats(dev, ifr);
1476 +
1477 +               case SIOCGIWPRIV:
1478 +                       /* Check if we have some wireless handlers defined */
1479 +                       if(dev->wireless_handlers != NULL) {
1480 +                               /* We export to user space the definition of
1481 +                                * the private handler ourselves */
1482 +                               return ioctl_export_private(dev, ifr);
1483 +                       }
1484 +                       // ## Fall-through for old API ##
1485 +               default:
1486 +                       /* Generic IOCTL */
1487 +                       /* Basic check */
1488 +                       if (!netif_device_present(dev))
1489 +                               return -ENODEV;
1490 +                       /* New driver API : try to find the handler */
1491 +                       handler = get_handler(dev, cmd);
1492 +                       if(handler != NULL) {
1493 +                               /* Standard and private are not the same */
1494 +                               if(cmd < SIOCIWFIRSTPRIV)
1495 +                                       return ioctl_standard_call(dev,
1496 +                                                                  ifr,
1497 +                                                                  cmd,
1498 +                                                                  handler);
1499 +                               else
1500 +                                       return ioctl_private_call(dev,
1501 +                                                                 ifr,
1502 +                                                                 cmd,
1503 +                                                                 handler);
1504 +                       }
1505 +                       /* Old driver API : call driver ioctl handler */
1506 +                       if (dev->do_ioctl) {
1507 +                               return dev->do_ioctl(dev, ifr, cmd);
1508 +                       }
1509 +                       return -EOPNOTSUPP;
1510 +       }
1511 +       /* Not reached */
1512 +       return -EINVAL;
1513 +}