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