162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file define the new driver API for Wireless Extensions
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Version :	8	16.3.07
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
862306a36Sopenharmony_ci * Copyright (c) 2001-2007 Jean Tourrilhes, All Rights Reserved.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifndef _IW_HANDLER_H
1262306a36Sopenharmony_ci#define _IW_HANDLER_H
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/************************** DOCUMENTATION **************************/
1562306a36Sopenharmony_ci/*
1662306a36Sopenharmony_ci * Initial driver API (1996 -> onward) :
1762306a36Sopenharmony_ci * -----------------------------------
1862306a36Sopenharmony_ci * The initial API just sends the IOCTL request received from user space
1962306a36Sopenharmony_ci * to the driver (via the driver ioctl handler). The driver has to
2062306a36Sopenharmony_ci * handle all the rest...
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * The initial API also defines a specific handler in struct net_device
2362306a36Sopenharmony_ci * to handle wireless statistics.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * The initial APIs served us well and has proven a reasonably good design.
2662306a36Sopenharmony_ci * However, there is a few shortcommings :
2762306a36Sopenharmony_ci *	o No events, everything is a request to the driver.
2862306a36Sopenharmony_ci *	o Large ioctl function in driver with gigantic switch statement
2962306a36Sopenharmony_ci *	  (i.e. spaghetti code).
3062306a36Sopenharmony_ci *	o Driver has to mess up with copy_to/from_user, and in many cases
3162306a36Sopenharmony_ci *	  does it unproperly. Common mistakes are :
3262306a36Sopenharmony_ci *		* buffer overflows (no checks or off by one checks)
3362306a36Sopenharmony_ci *		* call copy_to/from_user with irq disabled
3462306a36Sopenharmony_ci *	o The user space interface is tied to ioctl because of the use
3562306a36Sopenharmony_ci *	  copy_to/from_user.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * New driver API (2002 -> onward) :
3862306a36Sopenharmony_ci * -------------------------------
3962306a36Sopenharmony_ci * The new driver API is just a bunch of standard functions (handlers),
4062306a36Sopenharmony_ci * each handling a specific Wireless Extension. The driver just export
4162306a36Sopenharmony_ci * the list of handler it supports, and those will be called apropriately.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * I tried to keep the main advantage of the previous API (simplicity,
4462306a36Sopenharmony_ci * efficiency and light weight), and also I provide a good dose of backward
4562306a36Sopenharmony_ci * compatibility (most structures are the same, driver can use both API
4662306a36Sopenharmony_ci * simultaneously, ...).
4762306a36Sopenharmony_ci * Hopefully, I've also addressed the shortcomming of the initial API.
4862306a36Sopenharmony_ci *
4962306a36Sopenharmony_ci * The advantage of the new API are :
5062306a36Sopenharmony_ci *	o Handling of Extensions in driver broken in small contained functions
5162306a36Sopenharmony_ci *	o Tighter checks of ioctl before calling the driver
5262306a36Sopenharmony_ci *	o Flexible commit strategy (at least, the start of it)
5362306a36Sopenharmony_ci *	o Backward compatibility (can be mixed with old API)
5462306a36Sopenharmony_ci *	o Driver doesn't have to worry about memory and user-space issues
5562306a36Sopenharmony_ci * The last point is important for the following reasons :
5662306a36Sopenharmony_ci *	o You are now able to call the new driver API from any API you
5762306a36Sopenharmony_ci *		want (including from within other parts of the kernel).
5862306a36Sopenharmony_ci *	o Common mistakes are avoided (buffer overflow, user space copy
5962306a36Sopenharmony_ci *		with irq disabled and so on).
6062306a36Sopenharmony_ci *
6162306a36Sopenharmony_ci * The Drawback of the new API are :
6262306a36Sopenharmony_ci *	o bloat (especially kernel)
6362306a36Sopenharmony_ci *	o need to migrate existing drivers to new API
6462306a36Sopenharmony_ci * My initial testing shows that the new API adds around 3kB to the kernel
6562306a36Sopenharmony_ci * and save between 0 and 5kB from a typical driver.
6662306a36Sopenharmony_ci * Also, as all structures and data types are unchanged, the migration is
6762306a36Sopenharmony_ci * quite straightforward (but tedious).
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * ---
7062306a36Sopenharmony_ci *
7162306a36Sopenharmony_ci * The new driver API is defined below in this file. User space should
7262306a36Sopenharmony_ci * not be aware of what's happening down there...
7362306a36Sopenharmony_ci *
7462306a36Sopenharmony_ci * A new kernel wrapper is in charge of validating the IOCTLs and calling
7562306a36Sopenharmony_ci * the appropriate driver handler. This is implemented in :
7662306a36Sopenharmony_ci *	# net/core/wireless.c
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * The driver export the list of handlers in :
7962306a36Sopenharmony_ci *	# include/linux/netdevice.h (one place)
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * The new driver API is available for WIRELESS_EXT >= 13.
8262306a36Sopenharmony_ci * Good luck with migration to the new API ;-)
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/* ---------------------- THE IMPLEMENTATION ---------------------- */
8662306a36Sopenharmony_ci/*
8762306a36Sopenharmony_ci * Some of the choice I've made are pretty controversials. Defining an
8862306a36Sopenharmony_ci * API is very much weighting compromises. This goes into some of the
8962306a36Sopenharmony_ci * details and the thinking behind the implementation.
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci * Implementation goals :
9262306a36Sopenharmony_ci * --------------------
9362306a36Sopenharmony_ci * The implementation goals were as follow :
9462306a36Sopenharmony_ci *	o Obvious : you should not need a PhD to understand what's happening,
9562306a36Sopenharmony_ci *		the benefit is easier maintenance.
9662306a36Sopenharmony_ci *	o Flexible : it should accommodate a wide variety of driver
9762306a36Sopenharmony_ci *		implementations and be as flexible as the old API.
9862306a36Sopenharmony_ci *	o Lean : it should be efficient memory wise to minimise the impact
9962306a36Sopenharmony_ci *		on kernel footprint.
10062306a36Sopenharmony_ci *	o Transparent to user space : the large number of user space
10162306a36Sopenharmony_ci *		applications that use Wireless Extensions should not need
10262306a36Sopenharmony_ci *		any modifications.
10362306a36Sopenharmony_ci *
10462306a36Sopenharmony_ci * Array of functions versus Struct of functions
10562306a36Sopenharmony_ci * ---------------------------------------------
10662306a36Sopenharmony_ci * 1) Having an array of functions allow the kernel code to access the
10762306a36Sopenharmony_ci * handler in a single lookup, which is much more efficient (think hash
10862306a36Sopenharmony_ci * table here).
10962306a36Sopenharmony_ci * 2) The only drawback is that driver writer may put their handler in
11062306a36Sopenharmony_ci * the wrong slot. This is trivial to test (I set the frequency, the
11162306a36Sopenharmony_ci * bitrate changes). Once the handler is in the proper slot, it will be
11262306a36Sopenharmony_ci * there forever, because the array is only extended at the end.
11362306a36Sopenharmony_ci * 3) Backward/forward compatibility : adding new handler just require
11462306a36Sopenharmony_ci * extending the array, so you can put newer driver in older kernel
11562306a36Sopenharmony_ci * without having to patch the kernel code (and vice versa).
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci * All handler are of the same generic type
11862306a36Sopenharmony_ci * ----------------------------------------
11962306a36Sopenharmony_ci * That's a feature !!!
12062306a36Sopenharmony_ci * 1) Having a generic handler allow to have generic code, which is more
12162306a36Sopenharmony_ci * efficient. If each of the handler was individually typed I would need
12262306a36Sopenharmony_ci * to add a big switch in the kernel (== more bloat). This solution is
12362306a36Sopenharmony_ci * more scalable, adding new Wireless Extensions doesn't add new code.
12462306a36Sopenharmony_ci * 2) You can use the same handler in different slots of the array. For
12562306a36Sopenharmony_ci * hardware, it may be more efficient or logical to handle multiple
12662306a36Sopenharmony_ci * Wireless Extensions with a single function, and the API allow you to
12762306a36Sopenharmony_ci * do that. (An example would be a single record on the card to control
12862306a36Sopenharmony_ci * both bitrate and frequency, the handler would read the old record,
12962306a36Sopenharmony_ci * modify it according to info->cmd and rewrite it).
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * Functions prototype uses union iwreq_data
13262306a36Sopenharmony_ci * -----------------------------------------
13362306a36Sopenharmony_ci * Some would have preferred functions defined this way :
13462306a36Sopenharmony_ci *	static int mydriver_ioctl_setrate(struct net_device *dev,
13562306a36Sopenharmony_ci *					  long rate, int auto)
13662306a36Sopenharmony_ci * 1) The kernel code doesn't "validate" the content of iwreq_data, and
13762306a36Sopenharmony_ci * can't do it (different hardware may have different notion of what a
13862306a36Sopenharmony_ci * valid frequency is), so we don't pretend that we do it.
13962306a36Sopenharmony_ci * 2) The above form is not extendable. If I want to add a flag (for
14062306a36Sopenharmony_ci * example to distinguish setting max rate and basic rate), I would
14162306a36Sopenharmony_ci * break the prototype. Using iwreq_data is more flexible.
14262306a36Sopenharmony_ci * 3) Also, the above form is not generic (see above).
14362306a36Sopenharmony_ci * 4) I don't expect driver developper using the wrong field of the
14462306a36Sopenharmony_ci * union (Doh !), so static typechecking doesn't add much value.
14562306a36Sopenharmony_ci * 5) Lastly, you can skip the union by doing :
14662306a36Sopenharmony_ci *	static int mydriver_ioctl_setrate(struct net_device *dev,
14762306a36Sopenharmony_ci *					  struct iw_request_info *info,
14862306a36Sopenharmony_ci *					  struct iw_param *rrq,
14962306a36Sopenharmony_ci *					  char *extra)
15062306a36Sopenharmony_ci * And then adding the handler in the array like this :
15162306a36Sopenharmony_ci *        (iw_handler) mydriver_ioctl_setrate,             // SIOCSIWRATE
15262306a36Sopenharmony_ci *
15362306a36Sopenharmony_ci * Using functions and not a registry
15462306a36Sopenharmony_ci * ----------------------------------
15562306a36Sopenharmony_ci * Another implementation option would have been for every instance to
15662306a36Sopenharmony_ci * define a registry (a struct containing all the Wireless Extensions)
15762306a36Sopenharmony_ci * and only have a function to commit the registry to the hardware.
15862306a36Sopenharmony_ci * 1) This approach can be emulated by the current code, but not
15962306a36Sopenharmony_ci * vice versa.
16062306a36Sopenharmony_ci * 2) Some drivers don't keep any configuration in the driver, for them
16162306a36Sopenharmony_ci * adding such a registry would be a significant bloat.
16262306a36Sopenharmony_ci * 3) The code to translate from Wireless Extension to native format is
16362306a36Sopenharmony_ci * needed anyway, so it would not reduce significantely the amount of code.
16462306a36Sopenharmony_ci * 4) The current approach only selectively translate Wireless Extensions
16562306a36Sopenharmony_ci * to native format and only selectively set, whereas the registry approach
16662306a36Sopenharmony_ci * would require to translate all WE and set all parameters for any single
16762306a36Sopenharmony_ci * change.
16862306a36Sopenharmony_ci * 5) For many Wireless Extensions, the GET operation return the current
16962306a36Sopenharmony_ci * dynamic value, not the value that was set.
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci * This header is <net/iw_handler.h>
17262306a36Sopenharmony_ci * ---------------------------------
17362306a36Sopenharmony_ci * 1) This header is kernel space only and should not be exported to
17462306a36Sopenharmony_ci * user space. Headers in "include/linux/" are exported, headers in
17562306a36Sopenharmony_ci * "include/net/" are not.
17662306a36Sopenharmony_ci *
17762306a36Sopenharmony_ci * Mixed 32/64 bit issues
17862306a36Sopenharmony_ci * ----------------------
17962306a36Sopenharmony_ci * The Wireless Extensions are designed to be 64 bit clean, by using only
18062306a36Sopenharmony_ci * datatypes with explicit storage size.
18162306a36Sopenharmony_ci * There are some issues related to kernel and user space using different
18262306a36Sopenharmony_ci * memory model, and in particular 64bit kernel with 32bit user space.
18362306a36Sopenharmony_ci * The problem is related to struct iw_point, that contains a pointer
18462306a36Sopenharmony_ci * that *may* need to be translated.
18562306a36Sopenharmony_ci * This is quite messy. The new API doesn't solve this problem (it can't),
18662306a36Sopenharmony_ci * but is a step in the right direction :
18762306a36Sopenharmony_ci * 1) Meta data about each ioctl is easily available, so we know what type
18862306a36Sopenharmony_ci * of translation is needed.
18962306a36Sopenharmony_ci * 2) The move of data between kernel and user space is only done in a single
19062306a36Sopenharmony_ci * place in the kernel, so adding specific hooks in there is possible.
19162306a36Sopenharmony_ci * 3) In the long term, it allows to move away from using ioctl as the
19262306a36Sopenharmony_ci * user space API.
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * So many comments and so few code
19562306a36Sopenharmony_ci * --------------------------------
19662306a36Sopenharmony_ci * That's a feature. Comments won't bloat the resulting kernel binary.
19762306a36Sopenharmony_ci */
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci/***************************** INCLUDES *****************************/
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#include <linux/wireless.h>		/* IOCTL user space API */
20262306a36Sopenharmony_ci#include <linux/if_ether.h>
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/***************************** VERSION *****************************/
20562306a36Sopenharmony_ci/*
20662306a36Sopenharmony_ci * This constant is used to know which version of the driver API is
20762306a36Sopenharmony_ci * available. Hopefully, this will be pretty stable and no changes
20862306a36Sopenharmony_ci * will be needed...
20962306a36Sopenharmony_ci * I just plan to increment with each new version.
21062306a36Sopenharmony_ci */
21162306a36Sopenharmony_ci#define IW_HANDLER_VERSION	8
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/*
21462306a36Sopenharmony_ci * Changes :
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * V2 to V3
21762306a36Sopenharmony_ci * --------
21862306a36Sopenharmony_ci *	- Move event definition in <linux/wireless.h>
21962306a36Sopenharmony_ci *	- Add Wireless Event support :
22062306a36Sopenharmony_ci *		o wireless_send_event() prototype
22162306a36Sopenharmony_ci *		o iwe_stream_add_event/point() inline functions
22262306a36Sopenharmony_ci * V3 to V4
22362306a36Sopenharmony_ci * --------
22462306a36Sopenharmony_ci *	- Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
22562306a36Sopenharmony_ci *
22662306a36Sopenharmony_ci * V4 to V5
22762306a36Sopenharmony_ci * --------
22862306a36Sopenharmony_ci *	- Add new spy support : struct iw_spy_data & prototypes
22962306a36Sopenharmony_ci *
23062306a36Sopenharmony_ci * V5 to V6
23162306a36Sopenharmony_ci * --------
23262306a36Sopenharmony_ci *	- Change the way we get to spy_data method for added safety
23362306a36Sopenharmony_ci *	- Remove spy #ifdef, they are always on -> cleaner code
23462306a36Sopenharmony_ci *	- Add IW_DESCR_FLAG_NOMAX flag for very large requests
23562306a36Sopenharmony_ci *	- Start migrating get_wireless_stats to struct iw_handler_def
23662306a36Sopenharmony_ci *
23762306a36Sopenharmony_ci * V6 to V7
23862306a36Sopenharmony_ci * --------
23962306a36Sopenharmony_ci *	- Add struct ieee80211_device pointer in struct iw_public_data
24062306a36Sopenharmony_ci *	- Remove (struct iw_point *)->pointer from events and streams
24162306a36Sopenharmony_ci *	- Remove spy_offset from struct iw_handler_def
24262306a36Sopenharmony_ci *	- Add "check" version of event macros for ieee802.11 stack
24362306a36Sopenharmony_ci *
24462306a36Sopenharmony_ci * V7 to V8
24562306a36Sopenharmony_ci * ----------
24662306a36Sopenharmony_ci *	- Prevent leaking of kernel space in stream on 64 bits.
24762306a36Sopenharmony_ci */
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci/**************************** CONSTANTS ****************************/
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/* Enhanced spy support available */
25262306a36Sopenharmony_ci#define IW_WIRELESS_SPY
25362306a36Sopenharmony_ci#define IW_WIRELESS_THRSPY
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/* Special error message for the driver to indicate that we
25662306a36Sopenharmony_ci * should do a commit after return from the iw_handler */
25762306a36Sopenharmony_ci#define EIWCOMMIT	EINPROGRESS
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci/* Flags available in struct iw_request_info */
26062306a36Sopenharmony_ci#define IW_REQUEST_FLAG_COMPAT	0x0001	/* Compat ioctl call */
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/* Type of headers we know about (basically union iwreq_data) */
26362306a36Sopenharmony_ci#define IW_HEADER_TYPE_NULL	0	/* Not available */
26462306a36Sopenharmony_ci#define IW_HEADER_TYPE_CHAR	2	/* char [IFNAMSIZ] */
26562306a36Sopenharmony_ci#define IW_HEADER_TYPE_UINT	4	/* __u32 */
26662306a36Sopenharmony_ci#define IW_HEADER_TYPE_FREQ	5	/* struct iw_freq */
26762306a36Sopenharmony_ci#define IW_HEADER_TYPE_ADDR	6	/* struct sockaddr */
26862306a36Sopenharmony_ci#define IW_HEADER_TYPE_POINT	8	/* struct iw_point */
26962306a36Sopenharmony_ci#define IW_HEADER_TYPE_PARAM	9	/* struct iw_param */
27062306a36Sopenharmony_ci#define IW_HEADER_TYPE_QUAL	10	/* struct iw_quality */
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci/* Handling flags */
27362306a36Sopenharmony_ci/* Most are not implemented. I just use them as a reminder of some
27462306a36Sopenharmony_ci * cool features we might need one day ;-) */
27562306a36Sopenharmony_ci#define IW_DESCR_FLAG_NONE	0x0000	/* Obvious */
27662306a36Sopenharmony_ci/* Wrapper level flags */
27762306a36Sopenharmony_ci#define IW_DESCR_FLAG_DUMP	0x0001	/* Not part of the dump command */
27862306a36Sopenharmony_ci#define IW_DESCR_FLAG_EVENT	0x0002	/* Generate an event on SET */
27962306a36Sopenharmony_ci#define IW_DESCR_FLAG_RESTRICT	0x0004	/* GET : request is ROOT only */
28062306a36Sopenharmony_ci				/* SET : Omit payload from generated iwevent */
28162306a36Sopenharmony_ci#define IW_DESCR_FLAG_NOMAX	0x0008	/* GET : no limit on request size */
28262306a36Sopenharmony_ci/* Driver level flags */
28362306a36Sopenharmony_ci#define IW_DESCR_FLAG_WAIT	0x0100	/* Wait for driver event */
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/****************************** TYPES ******************************/
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci/* ----------------------- WIRELESS HANDLER ----------------------- */
28862306a36Sopenharmony_ci/*
28962306a36Sopenharmony_ci * A wireless handler is just a standard function, that looks like the
29062306a36Sopenharmony_ci * ioctl handler.
29162306a36Sopenharmony_ci * We also define there how a handler list look like... As the Wireless
29262306a36Sopenharmony_ci * Extension space is quite dense, we use a simple array, which is faster
29362306a36Sopenharmony_ci * (that's the perfect hash table ;-).
29462306a36Sopenharmony_ci */
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci/*
29762306a36Sopenharmony_ci * Meta data about the request passed to the iw_handler.
29862306a36Sopenharmony_ci * Most handlers can safely ignore what's in there.
29962306a36Sopenharmony_ci * The 'cmd' field might come handy if you want to use the same handler
30062306a36Sopenharmony_ci * for multiple command...
30162306a36Sopenharmony_ci * This struct is also my long term insurance. I can add new fields here
30262306a36Sopenharmony_ci * without breaking the prototype of iw_handler...
30362306a36Sopenharmony_ci */
30462306a36Sopenharmony_cistruct iw_request_info {
30562306a36Sopenharmony_ci	__u16		cmd;		/* Wireless Extension command */
30662306a36Sopenharmony_ci	__u16		flags;		/* More to come ;-) */
30762306a36Sopenharmony_ci};
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistruct net_device;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci/*
31262306a36Sopenharmony_ci * This is how a function handling a Wireless Extension should look
31362306a36Sopenharmony_ci * like (both get and set, standard and private).
31462306a36Sopenharmony_ci */
31562306a36Sopenharmony_citypedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
31662306a36Sopenharmony_ci			  union iwreq_data *wrqu, char *extra);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci/*
31962306a36Sopenharmony_ci * This define all the handler that the driver export.
32062306a36Sopenharmony_ci * As you need only one per driver type, please use a static const
32162306a36Sopenharmony_ci * shared by all driver instances... Same for the members...
32262306a36Sopenharmony_ci * This will be linked from net_device in <linux/netdevice.h>
32362306a36Sopenharmony_ci */
32462306a36Sopenharmony_cistruct iw_handler_def {
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/* Array of handlers for standard ioctls
32762306a36Sopenharmony_ci	 * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST]
32862306a36Sopenharmony_ci	 */
32962306a36Sopenharmony_ci	const iw_handler *	standard;
33062306a36Sopenharmony_ci	/* Number of handlers defined (more precisely, index of the
33162306a36Sopenharmony_ci	 * last defined handler + 1) */
33262306a36Sopenharmony_ci	__u16			num_standard;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci#ifdef CONFIG_WEXT_PRIV
33562306a36Sopenharmony_ci	__u16			num_private;
33662306a36Sopenharmony_ci	/* Number of private arg description */
33762306a36Sopenharmony_ci	__u16			num_private_args;
33862306a36Sopenharmony_ci	/* Array of handlers for private ioctls
33962306a36Sopenharmony_ci	 * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
34062306a36Sopenharmony_ci	 */
34162306a36Sopenharmony_ci	const iw_handler *	private;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	/* Arguments of private handler. This one is just a list, so you
34462306a36Sopenharmony_ci	 * can put it in any order you want and should not leave holes...
34562306a36Sopenharmony_ci	 * We will automatically export that to user space... */
34662306a36Sopenharmony_ci	const struct iw_priv_args *	private_args;
34762306a36Sopenharmony_ci#endif
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* New location of get_wireless_stats, to de-bloat struct net_device.
35062306a36Sopenharmony_ci	 * The old pointer in struct net_device will be gradually phased
35162306a36Sopenharmony_ci	 * out, and drivers are encouraged to use this one... */
35262306a36Sopenharmony_ci	struct iw_statistics*	(*get_wireless_stats)(struct net_device *dev);
35362306a36Sopenharmony_ci};
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci/* ---------------------- IOCTL DESCRIPTION ---------------------- */
35662306a36Sopenharmony_ci/*
35762306a36Sopenharmony_ci * One of the main goal of the new interface is to deal entirely with
35862306a36Sopenharmony_ci * user space/kernel space memory move.
35962306a36Sopenharmony_ci * For that, we need to know :
36062306a36Sopenharmony_ci *	o if iwreq is a pointer or contain the full data
36162306a36Sopenharmony_ci *	o what is the size of the data to copy
36262306a36Sopenharmony_ci *
36362306a36Sopenharmony_ci * For private IOCTLs, we use the same rules as used by iwpriv and
36462306a36Sopenharmony_ci * defined in struct iw_priv_args.
36562306a36Sopenharmony_ci *
36662306a36Sopenharmony_ci * For standard IOCTLs, things are quite different and we need to
36762306a36Sopenharmony_ci * use the structures below. Actually, this struct is also more
36862306a36Sopenharmony_ci * efficient, but that's another story...
36962306a36Sopenharmony_ci */
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci/*
37262306a36Sopenharmony_ci * Describe how a standard IOCTL looks like.
37362306a36Sopenharmony_ci */
37462306a36Sopenharmony_cistruct iw_ioctl_description {
37562306a36Sopenharmony_ci	__u8	header_type;		/* NULL, iw_point or other */
37662306a36Sopenharmony_ci	__u8	token_type;		/* Future */
37762306a36Sopenharmony_ci	__u16	token_size;		/* Granularity of payload */
37862306a36Sopenharmony_ci	__u16	min_tokens;		/* Min acceptable token number */
37962306a36Sopenharmony_ci	__u16	max_tokens;		/* Max acceptable token number */
38062306a36Sopenharmony_ci	__u32	flags;			/* Special handling of the request */
38162306a36Sopenharmony_ci};
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/* Need to think of short header translation table. Later. */
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci/* --------------------- ENHANCED SPY SUPPORT --------------------- */
38662306a36Sopenharmony_ci/*
38762306a36Sopenharmony_ci * In the old days, the driver was handling spy support all by itself.
38862306a36Sopenharmony_ci * Now, the driver can delegate this task to Wireless Extensions.
38962306a36Sopenharmony_ci * It needs to include this struct in its private part and use the
39062306a36Sopenharmony_ci * standard spy iw_handler.
39162306a36Sopenharmony_ci */
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci/*
39462306a36Sopenharmony_ci * Instance specific spy data, i.e. addresses spied and quality for them.
39562306a36Sopenharmony_ci */
39662306a36Sopenharmony_cistruct iw_spy_data {
39762306a36Sopenharmony_ci	/* --- Standard spy support --- */
39862306a36Sopenharmony_ci	int			spy_number;
39962306a36Sopenharmony_ci	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
40062306a36Sopenharmony_ci	struct iw_quality	spy_stat[IW_MAX_SPY];
40162306a36Sopenharmony_ci	/* --- Enhanced spy support (event) */
40262306a36Sopenharmony_ci	struct iw_quality	spy_thr_low;	/* Low threshold */
40362306a36Sopenharmony_ci	struct iw_quality	spy_thr_high;	/* High threshold */
40462306a36Sopenharmony_ci	u_char			spy_thr_under[IW_MAX_SPY];
40562306a36Sopenharmony_ci};
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci/* --------------------- DEVICE WIRELESS DATA --------------------- */
40862306a36Sopenharmony_ci/*
40962306a36Sopenharmony_ci * This is all the wireless data specific to a device instance that
41062306a36Sopenharmony_ci * is managed by the core of Wireless Extensions or the 802.11 layer.
41162306a36Sopenharmony_ci * We only keep pointer to those structures, so that a driver is free
41262306a36Sopenharmony_ci * to share them between instances.
41362306a36Sopenharmony_ci * This structure should be initialised before registering the device.
41462306a36Sopenharmony_ci * Access to this data follow the same rules as any other struct net_device
41562306a36Sopenharmony_ci * data (i.e. valid as long as struct net_device exist, same locking rules).
41662306a36Sopenharmony_ci */
41762306a36Sopenharmony_ci/* Forward declaration */
41862306a36Sopenharmony_cistruct libipw_device;
41962306a36Sopenharmony_ci/* The struct */
42062306a36Sopenharmony_cistruct iw_public_data {
42162306a36Sopenharmony_ci	/* Driver enhanced spy support */
42262306a36Sopenharmony_ci	struct iw_spy_data *		spy_data;
42362306a36Sopenharmony_ci	/* Legacy structure managed by the ipw2x00-specific IEEE 802.11 layer */
42462306a36Sopenharmony_ci	struct libipw_device *		libipw;
42562306a36Sopenharmony_ci};
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci/**************************** PROTOTYPES ****************************/
42862306a36Sopenharmony_ci/*
42962306a36Sopenharmony_ci * Functions part of the Wireless Extensions (defined in net/wireless/wext-core.c).
43062306a36Sopenharmony_ci * Those may be called by driver modules.
43162306a36Sopenharmony_ci */
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci/* Send a single event to user space */
43462306a36Sopenharmony_civoid wireless_send_event(struct net_device *dev, unsigned int cmd,
43562306a36Sopenharmony_ci			 union iwreq_data *wrqu, const char *extra);
43662306a36Sopenharmony_ci#ifdef CONFIG_WEXT_CORE
43762306a36Sopenharmony_ci/* flush all previous wext events - if work is done from netdev notifiers */
43862306a36Sopenharmony_civoid wireless_nlevent_flush(void);
43962306a36Sopenharmony_ci#else
44062306a36Sopenharmony_cistatic inline void wireless_nlevent_flush(void) {}
44162306a36Sopenharmony_ci#endif
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/* We may need a function to send a stream of events to user space.
44462306a36Sopenharmony_ci * More on that later... */
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci/* Standard handler for SIOCSIWSPY */
44762306a36Sopenharmony_ciint iw_handler_set_spy(struct net_device *dev, struct iw_request_info *info,
44862306a36Sopenharmony_ci		       union iwreq_data *wrqu, char *extra);
44962306a36Sopenharmony_ci/* Standard handler for SIOCGIWSPY */
45062306a36Sopenharmony_ciint iw_handler_get_spy(struct net_device *dev, struct iw_request_info *info,
45162306a36Sopenharmony_ci		       union iwreq_data *wrqu, char *extra);
45262306a36Sopenharmony_ci/* Standard handler for SIOCSIWTHRSPY */
45362306a36Sopenharmony_ciint iw_handler_set_thrspy(struct net_device *dev, struct iw_request_info *info,
45462306a36Sopenharmony_ci			  union iwreq_data *wrqu, char *extra);
45562306a36Sopenharmony_ci/* Standard handler for SIOCGIWTHRSPY */
45662306a36Sopenharmony_ciint iw_handler_get_thrspy(struct net_device *dev, struct iw_request_info *info,
45762306a36Sopenharmony_ci			  union iwreq_data *wrqu, char *extra);
45862306a36Sopenharmony_ci/* Driver call to update spy records */
45962306a36Sopenharmony_civoid wireless_spy_update(struct net_device *dev, unsigned char *address,
46062306a36Sopenharmony_ci			 struct iw_quality *wstats);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci/************************* INLINE FUNTIONS *************************/
46362306a36Sopenharmony_ci/*
46462306a36Sopenharmony_ci * Function that are so simple that it's more efficient inlining them
46562306a36Sopenharmony_ci */
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic inline int iwe_stream_lcp_len(struct iw_request_info *info)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
47062306a36Sopenharmony_ci	if (info->flags & IW_REQUEST_FLAG_COMPAT)
47162306a36Sopenharmony_ci		return IW_EV_COMPAT_LCP_LEN;
47262306a36Sopenharmony_ci#endif
47362306a36Sopenharmony_ci	return IW_EV_LCP_LEN;
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic inline int iwe_stream_point_len(struct iw_request_info *info)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
47962306a36Sopenharmony_ci	if (info->flags & IW_REQUEST_FLAG_COMPAT)
48062306a36Sopenharmony_ci		return IW_EV_COMPAT_POINT_LEN;
48162306a36Sopenharmony_ci#endif
48262306a36Sopenharmony_ci	return IW_EV_POINT_LEN;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic inline int iwe_stream_event_len_adjust(struct iw_request_info *info,
48662306a36Sopenharmony_ci					      int event_len)
48762306a36Sopenharmony_ci{
48862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT
48962306a36Sopenharmony_ci	if (info->flags & IW_REQUEST_FLAG_COMPAT) {
49062306a36Sopenharmony_ci		event_len -= IW_EV_LCP_LEN;
49162306a36Sopenharmony_ci		event_len += IW_EV_COMPAT_LCP_LEN;
49262306a36Sopenharmony_ci	}
49362306a36Sopenharmony_ci#endif
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	return event_len;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci/*------------------------------------------------------------------*/
49962306a36Sopenharmony_ci/*
50062306a36Sopenharmony_ci * Wrapper to add an Wireless Event to a stream of events.
50162306a36Sopenharmony_ci */
50262306a36Sopenharmony_cichar *iwe_stream_add_event(struct iw_request_info *info, char *stream,
50362306a36Sopenharmony_ci			   char *ends, struct iw_event *iwe, int event_len);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_cistatic inline char *
50662306a36Sopenharmony_ciiwe_stream_add_event_check(struct iw_request_info *info, char *stream,
50762306a36Sopenharmony_ci			   char *ends, struct iw_event *iwe, int event_len)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	char *res = iwe_stream_add_event(info, stream, ends, iwe, event_len);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	if (res == stream)
51262306a36Sopenharmony_ci		return ERR_PTR(-E2BIG);
51362306a36Sopenharmony_ci	return res;
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci/*------------------------------------------------------------------*/
51762306a36Sopenharmony_ci/*
51862306a36Sopenharmony_ci * Wrapper to add an short Wireless Event containing a pointer to a
51962306a36Sopenharmony_ci * stream of events.
52062306a36Sopenharmony_ci */
52162306a36Sopenharmony_cichar *iwe_stream_add_point(struct iw_request_info *info, char *stream,
52262306a36Sopenharmony_ci			   char *ends, struct iw_event *iwe, char *extra);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_cistatic inline char *
52562306a36Sopenharmony_ciiwe_stream_add_point_check(struct iw_request_info *info, char *stream,
52662306a36Sopenharmony_ci			   char *ends, struct iw_event *iwe, char *extra)
52762306a36Sopenharmony_ci{
52862306a36Sopenharmony_ci	char *res = iwe_stream_add_point(info, stream, ends, iwe, extra);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	if (res == stream)
53162306a36Sopenharmony_ci		return ERR_PTR(-E2BIG);
53262306a36Sopenharmony_ci	return res;
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci/*------------------------------------------------------------------*/
53662306a36Sopenharmony_ci/*
53762306a36Sopenharmony_ci * Wrapper to add a value to a Wireless Event in a stream of events.
53862306a36Sopenharmony_ci * Be careful, this one is tricky to use properly :
53962306a36Sopenharmony_ci * At the first run, you need to have (value = event + IW_EV_LCP_LEN).
54062306a36Sopenharmony_ci */
54162306a36Sopenharmony_cichar *iwe_stream_add_value(struct iw_request_info *info, char *event,
54262306a36Sopenharmony_ci			   char *value, char *ends, struct iw_event *iwe,
54362306a36Sopenharmony_ci			   int event_len);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci#endif	/* _IW_HANDLER_H */
546