diff options
author | Andrea Adami <andrea.adami@gmail.com> | 2010-10-03 18:56:43 +0200 |
---|---|---|
committer | Andrea Adami <andrea.adami@gmail.com> | 2010-10-03 20:58:32 +0200 |
commit | 65e34b9c63d661a52abcbf952bcc1c7c78a0c8da (patch) | |
tree | 4e1435d5a59b6fea839a2a58a2a751a8328b08b1 /recipes/linux/files | |
parent | 86822c3ae68dad2d25f4429221e76eb92dc0cdfe (diff) | |
download | openembedded-65e34b9c63d661a52abcbf952bcc1c7c78a0c8da.tar.gz |
kernels-2.4-embedix: move unsupported recipes to obsolete
Diffstat (limited to 'recipes/linux/files')
-rw-r--r-- | recipes/linux/files/ir240_sys_max_tx-2.diff | 110 | ||||
-rw-r--r-- | recipes/linux/files/ir241_qos_param-2.diff | 164 | ||||
-rw-r--r-- | recipes/linux/files/iw240_we15-6.diff | 399 | ||||
-rw-r--r-- | recipes/linux/files/iw249_we16-6.diff | 670 | ||||
-rw-r--r-- | recipes/linux/files/iw_handlers.w13-5.diff | 1513 | ||||
-rw-r--r-- | recipes/linux/files/iw_handlers.w14-5.diff | 838 | ||||
-rw-r--r-- | recipes/linux/files/linux-2.4.18-list_move.patch | 32 |
7 files changed, 0 insertions, 3726 deletions
diff --git a/recipes/linux/files/ir240_sys_max_tx-2.diff b/recipes/linux/files/ir240_sys_max_tx-2.diff deleted file mode 100644 index 5f1307d7dc..0000000000 --- a/recipes/linux/files/ir240_sys_max_tx-2.diff +++ /dev/null @@ -1,110 +0,0 @@ ---- linux/net/irda/irsysctl.c.orig 2003-05-13 11:20:16.000000000 +0200 -+++ linux/net/irda/irsysctl.c 2005-01-22 18:39:40.496001712 +0100 -@@ -40,7 +40,8 @@ - - enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS, - DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME, -- MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME, SPECIFIC_DEV }; -+ MAX_TX_DATA_SIZE, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME, -+ SPECIFIC_DEV }; - - extern int sysctl_discovery; - extern int sysctl_discovery_slots; -@@ -51,6 +52,7 @@ - extern char sysctl_devname[]; - extern int sysctl_max_baud_rate; - extern int sysctl_min_tx_turn_time; -+extern int sysctl_max_tx_data_size; - extern int sysctl_max_noreply_time; - extern int sysctl_warn_noreply_time; - extern int sysctl_lap_keepalive_time; -@@ -71,6 +73,8 @@ - static int min_max_baud_rate = 2400; - static int max_min_tx_turn_time = 10000; /* See qos.c - IrLAP spec */ - static int min_min_tx_turn_time = 0; -+static int max_max_tx_data_size = 2048; /* See qos.c - IrLAP spec */ -+static int min_max_tx_data_size = 64; - static int max_max_noreply_time = 40; /* See qos.c - IrLAP spec */ - static int min_max_noreply_time = 3; - static int max_warn_noreply_time = 3; /* 3s == standard */ -@@ -128,6 +132,9 @@ - { MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, - NULL, &min_min_tx_turn_time, &max_min_tx_turn_time }, -+ { MAX_TX_DATA_SIZE, "max_tx_data_size", &sysctl_max_tx_data_size, -+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, -+ NULL, &min_max_tx_data_size, &max_max_tx_data_size }, - { MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, - NULL, &min_max_noreply_time, &max_max_noreply_time }, ---- linux/net/irda/qos.c.orig 2003-05-13 11:20:16.000000000 +0200 -+++ linux/net/irda/qos.c 2005-01-22 18:36:46.759413688 +0100 -@@ -60,10 +60,26 @@ - * Nonzero values (usec) are used as lower limit to the per-connection - * mtt value which was announced by the other end during negotiation. - * Might be helpful if the peer device provides too short mtt. -- * Default is 10 which means using the unmodified value given by the peer -- * except if it's 0 (0 is likely a bug in the other stack). -+ * Default is 10us which means using the unmodified value given by the -+ * peer except if it's 0 (0 is likely a bug in the other stack). - */ - unsigned sysctl_min_tx_turn_time = 10; -+/* -+ * Maximum data size to be used in transmission in payload of LAP frame. -+ * There is a bit of confusion in the IrDA spec : -+ * The LAP spec defines the payload of a LAP frame (I field) to be -+ * 2048 bytes max (IrLAP 1.1, chapt 6.6.5, p40). -+ * On the other hand, the PHY mention frames of 2048 bytes max (IrPHY -+ * 1.2, chapt 5.3.2.1, p41). But, this number includes the LAP header -+ * (2 bytes), and CRC (32 bits at 4 Mb/s). So, for the I field (LAP -+ * payload), that's only 2042 bytes. Oups ! -+ * I've had trouble trouble transmitting 2048 bytes frames with USB -+ * dongles and nsc-ircc at 4 Mb/s, so adjust to 2042... I don't know -+ * if this bug applies only for 2048 bytes frames or all negociated -+ * frame sizes, but all hardware seem to support "2048 bytes" frames. -+ * You can use the sysctl to play with this value anyway. -+ * Jean II */ -+unsigned sysctl_max_tx_data_size = 2042; - - /* - * Specific device list limits some negotiation parameters at the connection -@@ -398,10 +414,10 @@ - while ((qos->data_size.value > line_capacity) && (index > 0)) { - qos->data_size.value = data_sizes[index--]; - IRDA_DEBUG(2, __FUNCTION__ -- "(), redusing data size to %d\n", -+ "(), reducing data size to %d\n", - qos->data_size.value); - } --#else /* Use method descibed in section 6.6.11 of IrLAP */ -+#else /* Use method described in section 6.6.11 of IrLAP */ - while (irlap_requested_line_capacity(qos) > line_capacity) { - ASSERT(index != 0, return;); - -@@ -409,18 +425,24 @@ - if (qos->window_size.value > 1) { - qos->window_size.value--; - IRDA_DEBUG(2, __FUNCTION__ -- "(), redusing window size to %d\n", -+ "(), reducing window size to %d\n", - qos->window_size.value); - } else if (index > 1) { - qos->data_size.value = data_sizes[index--]; - IRDA_DEBUG(2, __FUNCTION__ -- "(), redusing data size to %d\n", -+ "(), reducing data size to %d\n", - qos->data_size.value); - } else { - WARNING(__FUNCTION__ "(), nothing more we can do!\n"); - } - } - #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ -+ /* -+ * Fix tx data size according to user limits - Jean II -+ */ -+ if (qos->data_size.value > sysctl_max_tx_data_size) -+ /* Allow non discrete adjustement to avoid loosing capacity */ -+ qos->data_size.value = sysctl_max_tx_data_size; - } - - /* diff --git a/recipes/linux/files/ir241_qos_param-2.diff b/recipes/linux/files/ir241_qos_param-2.diff deleted file mode 100644 index dfe77c52b0..0000000000 --- a/recipes/linux/files/ir241_qos_param-2.diff +++ /dev/null @@ -1,164 +0,0 @@ ---- linux/net/irda/qos.c.orig 2005-01-22 19:19:56.013787192 +0100 -+++ linux/net/irda/qos.c 2005-01-22 19:21:13.493008560 +0100 -@@ -73,13 +73,18 @@ - * 1.2, chapt 5.3.2.1, p41). But, this number includes the LAP header - * (2 bytes), and CRC (32 bits at 4 Mb/s). So, for the I field (LAP - * payload), that's only 2042 bytes. Oups ! -- * I've had trouble trouble transmitting 2048 bytes frames with USB -- * dongles and nsc-ircc at 4 Mb/s, so adjust to 2042... I don't know -- * if this bug applies only for 2048 bytes frames or all negociated -- * frame sizes, but all hardware seem to support "2048 bytes" frames. -- * You can use the sysctl to play with this value anyway. -+ * My nsc-ircc hardware has troubles receiving 2048 bytes frames at 4 Mb/s, -+ * so adjust to 2042... I don't know if this bug applies only for 2048 -+ * bytes frames or all negociated frame sizes, but you can use the sysctl -+ * to play with this value anyway. - * Jean II */ - unsigned sysctl_max_tx_data_size = 2042; -+/* -+ * Maximum transmit window, i.e. number of LAP frames between turn-around. -+ * This allow to override what the peer told us. Some peers are buggy and -+ * don't always support what they tell us. -+ * Jean II */ -+unsigned sysctl_max_tx_window = 7; - - /* - * Specific device list limits some negotiation parameters at the connection -@@ -227,7 +232,19 @@ - { - __u16 msb = 0x8000; - int index = 15; /* Current MSB */ -- -+ -+ /* Check for buggy peers. -+ * Note : there is a small probability that it could be us, but I -+ * would expect driver authors to catch that pretty early and be -+ * able to check precisely what's going on. If a end user sees this, -+ * it's very likely the peer. - Jean II */ -+ if (word == 0) { -+ WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n", -+ __FUNCTION__); -+ /* The only safe choice (we don't know the array size) */ -+ word = 0x1; -+ } -+ - while (msb) { - if (word & msb) - break; /* Found it! */ -@@ -378,10 +395,14 @@ - - /* - * Make sure the mintt is sensible. -+ * Main culprit : Ericsson T39. - Jean II - */ - if (sysctl_min_tx_turn_time > qos->min_turn_time.value) { - int i; - -+ WARNING("%s(), Detected buggy peer, adjust mtt to %dus!\n", -+ __FUNCTION__, sysctl_min_tx_turn_time); -+ - /* We don't really need bits, but easier this way */ - i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times, - 8, &qos->min_turn_time.bits); -@@ -443,6 +464,11 @@ - if (qos->data_size.value > sysctl_max_tx_data_size) - /* Allow non discrete adjustement to avoid loosing capacity */ - qos->data_size.value = sysctl_max_tx_data_size; -+ /* -+ * Override Tx window if user request it. - Jean II -+ */ -+ if (qos->window_size.value > sysctl_max_tx_window) -+ qos->window_size.value = sysctl_max_tx_window; - } - - /* ---- linux/net/irda/irsysctl.c.orig 2005-01-22 19:19:56.006788256 +0100 -+++ linux/net/irda/irsysctl.c 2005-01-22 19:24:31.273941288 +0100 -@@ -40,8 +40,8 @@ - - enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS, - DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME, -- MAX_TX_DATA_SIZE, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME, -- SPECIFIC_DEV }; -+ MAX_TX_DATA_SIZE, MAX_TX_WINDOW, MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, -+ LAP_KEEPALIVE_TIME, SPECIFIC_DEV }; - - extern int sysctl_discovery; - extern int sysctl_discovery_slots; -@@ -53,6 +53,7 @@ - extern int sysctl_max_baud_rate; - extern int sysctl_min_tx_turn_time; - extern int sysctl_max_tx_data_size; -+extern int sysctl_max_tx_window; - extern int sysctl_max_noreply_time; - extern int sysctl_warn_noreply_time; - extern int sysctl_lap_keepalive_time; -@@ -75,6 +76,8 @@ - static int min_min_tx_turn_time = 0; - static int max_max_tx_data_size = 2048; /* See qos.c - IrLAP spec */ - static int min_max_tx_data_size = 64; -+static int max_max_tx_window = 7; /* See qos.c - IrLAP spec */ -+static int min_max_tx_window = 1; - static int max_max_noreply_time = 40; /* See qos.c - IrLAP spec */ - static int min_max_noreply_time = 3; - static int max_warn_noreply_time = 3; /* 3s == standard */ -@@ -135,6 +138,9 @@ - { MAX_TX_DATA_SIZE, "max_tx_data_size", &sysctl_max_tx_data_size, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, - NULL, &min_max_tx_data_size, &max_max_tx_data_size }, -+ { MAX_TX_WINDOW, "max_tx_window", &sysctl_max_tx_window, -+ sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, -+ NULL, &min_max_tx_window, &max_max_tx_window }, - { MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time, - sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, - NULL, &min_max_noreply_time, &max_max_noreply_time }, ---- linux/net/irda/parameters.c.orig 2003-05-13 11:20:16.000000000 +0200 -+++ linux/net/irda/parameters.c 2005-01-22 19:21:13.527003392 +0100 -@@ -204,11 +204,13 @@ - { - irda_param_t p; - int n = 0; -+ int extract_len; /* Real lenght we extract */ - int err; - - p.pi = pi; /* In case handler needs to know */ - p.pl = buf[1]; /* Extract lenght of value */ - p.pv.i = 0; /* Clear value */ -+ extract_len = p.pl; /* Default : extract all */ - - /* Check if buffer is long enough for parsing */ - if (len < (2+p.pl)) { -@@ -220,18 +222,30 @@ - /* - * Check that the integer length is what we expect it to be. If the - * handler want a 16 bits integer then a 32 bits is not good enough -+ * PV_INTEGER means that the handler is flexible. - */ - if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) { - ERROR(__FUNCTION__ "(), invalid parameter length! " - "Expected %d bytes, but value had %d bytes!\n", - type & PV_MASK, p.pl); - -- /* Skip parameter */ -- return p.pl+2; -+ /* Most parameters are bit/byte fields or little endian, -+ * so it's ok to only extract a subset of it (the subset -+ * that the handler expect). This is necessary, as some -+ * broken implementations seems to add extra undefined bits. -+ * If the parameter is shorter than we expect or is big -+ * endian, we can't play those tricks. Jean II */ -+ if((p.pl < (type & PV_MASK)) || (type & PV_BIG_ENDIAN)) { -+ /* Skip parameter */ -+ return p.pl+2; -+ } else { -+ /* Extract subset of it, fallthrough */ -+ extract_len = type & PV_MASK; -+ } - } - - -- switch (p.pl) { -+ switch (extract_len) { - case 1: - n += irda_param_unpack(buf+2, "b", &p.pv.i); - break; diff --git a/recipes/linux/files/iw240_we15-6.diff b/recipes/linux/files/iw240_we15-6.diff deleted file mode 100644 index 2ebfd8ec12..0000000000 --- a/recipes/linux/files/iw240_we15-6.diff +++ /dev/null @@ -1,399 +0,0 @@ -diff -u -p linux/include/linux/wireless.14.h linux/include/linux/wireless.h ---- linux/include/linux/wireless.14.h Mon Dec 2 18:51:00 2002 -+++ linux/include/linux/wireless.h Mon Dec 2 18:53:35 2002 -@@ -1,7 +1,7 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 14 25.1.02 -+ * Version : 15 12.7.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. -@@ -80,7 +80,7 @@ - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 14 -+#define WIRELESS_EXT 15 - - /* - * Changes : -@@ -153,17 +153,32 @@ - * - Define additional specific event numbers - * - Add "addr" and "param" fields in union iwreq_data - * - AP scanning stuff (SIOCSIWSCAN and friends) -+ * -+ * V14 to V15 -+ * ---------- -+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg -+ * - Make struct iw_freq signed (both m & e), add explicit padding -+ * - Add IWEVCUSTOM for driver specific event/scanning token -+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses -+ * - Add IW_TXPOW_RANGE for range of Tx Powers -+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points -+ * - Add IW_MODE_MONITOR for passive monitor - */ - - /**************************** CONSTANTS ****************************/ - - /* -------------------------- IOCTL LIST -------------------------- */ - --/* Basic operations */ -+/* Wireless Identification */ - #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ - #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ --#define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ --#define SIOCGIWNWID 0x8B03 /* get network id */ -+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. -+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... -+ * Don't put the name of your driver there, it's useless. */ -+ -+/* Basic operations */ -+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ -+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ - #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ - #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ - #define SIOCSIWMODE 0x8B06 /* set operation mode */ -@@ -178,16 +193,18 @@ - #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ - #define SIOCSIWSTATS 0x8B0E /* Unused */ - #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ -+/* SIOCGIWSTATS is strictly used between user space and the kernel, and -+ * is never passed to the driver (i.e. the driver will never see it). */ - --/* Mobile IP support */ -+/* Mobile IP support (statistics per MAC address) */ - #define SIOCSIWSPY 0x8B10 /* set spy addresses */ - #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ - - /* Access Point manipulation */ - #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ - #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ --#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ --#define SIOCSIWSCAN 0x8B18 /* trigger scanning */ -+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ -+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ - #define SIOCGIWSCAN 0x8B19 /* get scanning results */ - - /* 802.11 specific support */ -@@ -197,9 +214,7 @@ - #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ - /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit - * within the 'iwreq' structure, so we need to use the 'data' member to -- * point to a string in user space, like it is done for RANGE... -- * The "flags" member indicate if the ESSID is active or not (promiscuous). -- */ -+ * point to a string in user space, like it is done for RANGE... */ - - /* Other parameters useful in 802.11 and some other devices */ - #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ -@@ -257,7 +272,10 @@ - /* Most events use the same identifier as ioctl requests */ - - #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ --#define IWEVQUAL 0x8C01 /* Quality part of statistics */ -+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ -+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ -+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ -+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ - - #define IWEVFIRST 0x8C00 - -@@ -273,7 +291,8 @@ - #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ - #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ - #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ --#define IW_PRIV_TYPE_FLOAT 0x5000 -+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ -+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ - - #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ - -@@ -297,13 +316,16 @@ - - /* Maximum tx powers in the range struct */ - #define IW_MAX_TXPOWER 8 -+/* Note : if you more than 8 TXPowers, just set the max and min or -+ * a few of them in the struct iw_range. */ - - /* Maximum of address that you may set with SPY */ --#define IW_MAX_SPY 8 -+#define IW_MAX_SPY 8 /* set */ -+#define IW_MAX_GET_SPY 64 /* get */ - - /* Maximum of address that you may get in the - list of access points in range */ --#define IW_MAX_AP 8 -+#define IW_MAX_AP 64 - - /* Maximum size of the ESSID and NICKN strings */ - #define IW_ESSID_MAX_SIZE 32 -@@ -315,6 +337,7 @@ - #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ - #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ - #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ -+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ - - /* Maximum number of size of encoding token available - * they are listed in the range structure */ -@@ -350,8 +373,10 @@ - #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - - /* Transmit Power flags available */ -+#define IW_TXPOW_TYPE 0x00FF /* Type of value */ - #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ - #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ -+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ - - /* Retry limits and lifetime flags available */ - #define IW_RETRY_ON 0x0000 /* No details... */ -@@ -376,6 +401,9 @@ - /* Maximum size of returned data */ - #define IW_SCAN_MAX_DATA 4096 /* In bytes */ - -+/* Max number of char in custom event - use multiple of them if needed */ -+#define IW_CUSTOM_MAX 256 /* In bytes */ -+ - /****************************** TYPES ******************************/ - - /* --------------------------- SUBTYPES --------------------------- */ -@@ -411,9 +439,10 @@ struct iw_point - */ - struct iw_freq - { -- __u32 m; /* Mantissa */ -- __u16 e; /* Exponent */ -+ __s32 m; /* Mantissa */ -+ __s16 e; /* Exponent */ - __u8 i; /* List index (when in range struct) */ -+ __u8 pad; /* Unused - just for alignement */ - }; - - /* -diff -u -p linux/include/net/iw_handler.14.h linux/include/net/iw_handler.h ---- linux/include/net/iw_handler.14.h Mon Dec 2 18:51:17 2002 -+++ linux/include/net/iw_handler.h Mon Dec 2 18:54:51 2002 -@@ -1,7 +1,7 @@ - /* - * This file define the new driver API for Wireless Extensions - * -- * Version : 3 17.1.02 -+ * Version : 4 21.6.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. -@@ -206,7 +206,7 @@ - * will be needed... - * I just plan to increment with each new version. - */ --#define IW_HANDLER_VERSION 3 -+#define IW_HANDLER_VERSION 4 - - /* - * Changes : -@@ -217,6 +217,9 @@ - * - Add Wireless Event support : - * o wireless_send_event() prototype - * o iwe_stream_add_event/point() inline functions -+ * V3 to V4 -+ * -------- -+ * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes - */ - - /**************************** CONSTANTS ****************************/ -@@ -233,10 +236,10 @@ - #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */ - #define IW_HEADER_TYPE_UINT 4 /* __u32 */ - #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */ --#define IW_HEADER_TYPE_POINT 6 /* struct iw_point */ --#define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */ --#define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */ --#define IW_HEADER_TYPE_QUAL 9 /* struct iw_quality */ -+#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */ -+#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */ -+#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */ -+#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */ - - /* Handling flags */ - /* Most are not implemented. I just use them as a reminder of some -diff -u -p linux/net/core/wireless.14.c linux/net/core/wireless.c ---- linux/net/core/wireless.14.c Mon Dec 2 18:51:35 2002 -+++ linux/net/core/wireless.c Mon Dec 2 18:53:10 2002 -@@ -33,8 +33,16 @@ - * o Propagate events as rtnetlink IFLA_WIRELESS option - * o Generate event on selected SET requests - * -- * v4 - 18.04.01 - Jean II -+ * v4 - 18.04.02 - Jean II - * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 -+ * -+ * v5 - 21.06.02 - Jean II -+ * o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup) -+ * o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes -+ * o Add IWEVCUSTOM for driver specific event/scanning token -+ * o Turn on WE_STRICT_WRITE by default + kernel warning -+ * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) -+ * o Fix off-by-one in test (extra_size <= IFNAMSIZ) - */ - - /***************************** INCLUDES *****************************/ -@@ -50,8 +58,9 @@ - - /**************************** CONSTANTS ****************************/ - --/* This will be turned on later on... */ --#undef WE_STRICT_WRITE /* Check write buffer size */ -+/* Enough lenience, let's make sure things are proper... */ -+#define WE_STRICT_WRITE /* Check write buffer size */ -+/* I'll probably drop both the define and kernel message in the next version */ - - /* Debuging stuff */ - #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ -@@ -106,7 +115,7 @@ static const struct iw_ioctl_description - /* SIOCSIWSPY */ - { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0}, - /* SIOCGIWSPY */ -- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0}, -+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0}, - /* -- hole -- */ - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* -- hole -- */ -@@ -176,25 +185,41 @@ static const struct iw_ioctl_description - { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, - /* IWEVQUAL */ - { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0}, -+ /* IWEVCUSTOM */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_CUSTOM_MAX, 0}, -+ /* IWEVREGISTERED */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, -+ /* IWEVEXPIRED */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, - }; - static const int standard_event_num = (sizeof(standard_event) / - sizeof(struct iw_ioctl_description)); - - /* Size (in bytes) of the various private data types */ --static const char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+static const char priv_type_size[] = { -+ 0, /* IW_PRIV_TYPE_NONE */ -+ 1, /* IW_PRIV_TYPE_BYTE */ -+ 1, /* IW_PRIV_TYPE_CHAR */ -+ 0, /* Not defined */ -+ sizeof(__u32), /* IW_PRIV_TYPE_INT */ -+ sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ -+ sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ -+ 0, /* Not defined */ -+}; - - /* Size (in bytes) of various events */ - static const int event_type_size[] = { -- IW_EV_LCP_LEN, -+ IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ -+ 0, -+ IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */ - 0, -- IW_EV_CHAR_LEN, -+ IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */ -+ IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */ -+ IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */ - 0, -- IW_EV_UINT_LEN, -- IW_EV_FREQ_LEN, - IW_EV_POINT_LEN, /* Without variable payload */ -- IW_EV_PARAM_LEN, -- IW_EV_ADDR_LEN, -- IW_EV_QUAL_LEN, -+ IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */ -+ IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ - }; - - /************************ COMMON SUBROUTINES ************************/ -@@ -440,8 +465,10 @@ static inline int ioctl_export_private(s - return -EFAULT; - #ifdef WE_STRICT_WRITE - /* Check if there is enough buffer up there */ -- if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1)) -+ if(iwr->u.data.length < dev->wireless_handlers->num_private_args) { -+ printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args); - return -E2BIG; -+ } - #endif /* WE_STRICT_WRITE */ - - /* Set the number of available ioctls. */ -@@ -471,6 +498,7 @@ static inline int ioctl_standard_call(st - const struct iw_ioctl_description * descr; - struct iw_request_info info; - int ret = -EINVAL; -+ int user_size = 0; - - /* Get the description of the IOCTL */ - if((cmd - SIOCIWFIRST) >= standard_ioctl_num) -@@ -518,11 +546,8 @@ static inline int ioctl_standard_call(st - /* Check NULL pointer */ - if(iwr->u.data.pointer == NULL) - return -EFAULT; --#ifdef WE_STRICT_WRITE -- /* Check if there is enough buffer up there */ -- if(iwr->u.data.length < descr->max_tokens) -- return -E2BIG; --#endif /* WE_STRICT_WRITE */ -+ /* Save user space buffer size for checking */ -+ user_size = iwr->u.data.length; - } - - #ifdef WE_IOCTL_DEBUG -@@ -559,6 +584,15 @@ static inline int ioctl_standard_call(st - - /* If we have something to return to the user */ - if (!ret && IW_IS_GET(cmd)) { -+#ifdef WE_STRICT_WRITE -+ /* Check if there is enough buffer up there */ -+ if(user_size < iwr->u.data.length) { -+ printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length); -+ kfree(extra); -+ return -E2BIG; -+ } -+#endif /* WE_STRICT_WRITE */ -+ - err = copy_to_user(iwr->u.data.pointer, extra, - iwr->u.data.length * - descr->token_size); -@@ -646,12 +680,18 @@ static inline int ioctl_private_call(str - /* Compute the size of the set/get arguments */ - if(descr != NULL) { - if(IW_IS_SET(cmd)) { -+ int offset = 0; /* For sub-ioctls */ -+ /* Check for sub-ioctl handler */ -+ if(descr->name[0] == '\0') -+ /* Reserve one int for sub-ioctl index */ -+ offset = sizeof(__u32); -+ - /* Size of set arguments */ - extra_size = get_priv_size(descr->set_args); - - /* Does it fits in iwr ? */ - if((descr->set_args & IW_PRIV_SIZE_FIXED) && -- (extra_size < IFNAMSIZ)) -+ ((extra_size + offset) <= IFNAMSIZ)) - extra_size = 0; - } else { - /* Size of set arguments */ -@@ -659,7 +699,7 @@ static inline int ioctl_private_call(str - - /* Does it fits in iwr ? */ - if((descr->get_args & IW_PRIV_SIZE_FIXED) && -- (extra_size < IFNAMSIZ)) -+ (extra_size <= IFNAMSIZ)) - extra_size = 0; - } - } -@@ -925,7 +965,7 @@ void wireless_send_event(struct net_devi - * The best the driver could do is to log an error message. - * We will do it ourselves instead... - */ -- printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n", -+ printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n", - dev->name, cmd); - return; - } diff --git a/recipes/linux/files/iw249_we16-6.diff b/recipes/linux/files/iw249_we16-6.diff deleted file mode 100644 index 0a5aaab954..0000000000 --- a/recipes/linux/files/iw249_we16-6.diff +++ /dev/null @@ -1,670 +0,0 @@ -diff -u -p linux/include/linux/wireless.15.h linux/include/linux/wireless.h ---- linux/include/linux/wireless.15.h 2004-11-05 14:59:33.000000000 -0800 -+++ linux/include/linux/wireless.h 2004-11-05 15:00:42.000000000 -0800 -@@ -1,7 +1,7 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 15 12.7.02 -+ * Version : 16 2.4.03 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. -@@ -69,6 +69,8 @@ - - /***************************** INCLUDES *****************************/ - -+/* To minimise problems in user space, I might remove those headers -+ * at some point. Jean II */ - #include <linux/types.h> /* for "caddr_t" et al */ - #include <linux/socket.h> /* for "struct sockaddr" et al */ - #include <linux/if.h> /* for IFNAMSIZ and co... */ -@@ -80,7 +82,7 @@ - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 15 -+#define WIRELESS_EXT 16 - - /* - * Changes : -@@ -163,6 +165,16 @@ - * - Add IW_TXPOW_RANGE for range of Tx Powers - * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points - * - Add IW_MODE_MONITOR for passive monitor -+ * -+ * V15 to V16 -+ * ---------- -+ * - Increase the number of bitrates in iw_range to 32 (for 802.11g) -+ * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) -+ * - Reshuffle struct iw_range for increases, add filler -+ * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses -+ * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support -+ * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" -+ * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index - */ - - /**************************** CONSTANTS ****************************/ -@@ -196,9 +208,11 @@ - /* SIOCGIWSTATS is strictly used between user space and the kernel, and - * is never passed to the driver (i.e. the driver will never see it). */ - --/* Mobile IP support (statistics per MAC address) */ -+/* Spy support (statistics per MAC address - used for Mobile IP support) */ - #define SIOCSIWSPY 0x8B10 /* set spy addresses */ - #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ -+#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ -+#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ - - /* Access Point manipulation */ - #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ -@@ -294,7 +308,7 @@ - #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ - #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ - --#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */ -+#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ - - #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ - -@@ -306,13 +320,13 @@ - /* ----------------------- OTHER CONSTANTS ----------------------- */ - - /* Maximum frequencies in the range struct */ --#define IW_MAX_FREQUENCIES 16 -+#define IW_MAX_FREQUENCIES 32 - /* Note : if you have something like 80 frequencies, - * don't increase this constant and don't fill the frequency list. - * The user will be able to set by channel anyway... */ - - /* Maximum bit rates in the range struct */ --#define IW_MAX_BITRATES 8 -+#define IW_MAX_BITRATES 32 - - /* Maximum tx powers in the range struct */ - #define IW_MAX_TXPOWER 8 -@@ -320,8 +334,7 @@ - * a few of them in the struct iw_range. */ - - /* Maximum of address that you may set with SPY */ --#define IW_MAX_SPY 8 /* set */ --#define IW_MAX_GET_SPY 64 /* get */ -+#define IW_MAX_SPY 8 - - /* Maximum of address that you may get in the - list of access points in range */ -@@ -354,7 +367,8 @@ - #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ - #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ - #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ --#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -+#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -+#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ - - /* Power management flags available (along with the value, if any) */ - #define IW_POWER_ON 0x0000 /* No details... */ -@@ -482,6 +496,17 @@ struct iw_missed - __u32 beacon; /* Missed beacons/superframe */ - }; - -+/* -+ * Quality range (for spy threshold) -+ */ -+struct iw_thrspy -+{ -+ struct sockaddr addr; /* Source address (hw/mac) */ -+ struct iw_quality qual; /* Quality of the link */ -+ struct iw_quality low; /* Low threshold */ -+ struct iw_quality high; /* High threshold */ -+}; -+ - /* ------------------------ WIRELESS STATS ------------------------ */ - /* - * Wireless statistics (used for /proc/net/wireless) -@@ -534,7 +559,7 @@ union iwreq_data - struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ -- struct sockaddr addr; /* Destination address (hw) */ -+ struct sockaddr addr; /* Destination address (hw/mac) */ - - struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ -@@ -582,17 +607,31 @@ struct iw_range - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - -- /* Frequency */ -- __u16 num_channels; /* Number of channels [0; num - 1] */ -- __u8 num_frequency; /* Number of entry in the list */ -- struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ -- /* Note : this frequency list doesn't need to fit channel numbers */ -+ /* Old Frequency (backward compat - moved lower ) */ -+ __u16 old_num_channels; -+ __u8 old_num_frequency; -+ /* Filler to keep "version" at the same offset */ -+ __s32 old_freq[6]; - - /* signal level threshold range */ - __s32 sensitivity; - - /* Quality of link & SNR stuff */ -+ /* Quality range (link, level, noise) -+ * If the quality is absolute, it will be in the range [0 ; max_qual], -+ * if the quality is dBm, it will be in the range [max_qual ; 0]. -+ * Don't forget that we use 8 bit arithmetics... */ - struct iw_quality max_qual; /* Quality of the link */ -+ /* This should contain the average/typical values of the quality -+ * indicator. This should be the threshold between a "good" and -+ * a "bad" link (example : monitor going from green to orange). -+ * Currently, user space apps like quality monitors don't have any -+ * way to calibrate the measurement. With this, they can split -+ * the range between 0 and max_qual in different quality level -+ * (using a geometric subdivision centered on the average). -+ * I expect that people doing the user space apps will feedback -+ * us on which value we need to put in each driver... */ -+ struct iw_quality avg_qual; /* Quality of the link */ - - /* Rates */ - __u8 num_bitrates; /* Number of entries in the list */ -@@ -619,6 +658,8 @@ struct iw_range - __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ - __u8 num_encoding_sizes; /* Number of entry in the list */ - __u8 max_encoding_tokens; /* Max number of tokens */ -+ /* For drivers that need a "login/passwd" form */ -+ __u8 encoding_login_index; /* token index for login token */ - - /* Transmit power */ - __u16 txpower_capa; /* What options are supported */ -@@ -638,18 +679,12 @@ struct iw_range - __s32 min_r_time; /* Minimal retry lifetime */ - __s32 max_r_time; /* Maximal retry lifetime */ - -- /* Average quality of link & SNR */ -- struct iw_quality avg_qual; /* Quality of the link */ -- /* This should contain the average/typical values of the quality -- * indicator. This should be the threshold between a "good" and -- * a "bad" link (example : monitor going from green to orange). -- * Currently, user space apps like quality monitors don't have any -- * way to calibrate the measurement. With this, they can split -- * the range between 0 and max_qual in different quality level -- * (using a geometric subdivision centered on the average). -- * I expect that people doing the user space apps will feedback -- * us on which value we need to put in each driver... -- */ -+ /* Frequency */ -+ __u16 num_channels; /* Number of channels [0; num - 1] */ -+ __u8 num_frequency; /* Number of entry in the list */ -+ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ -+ /* Note : this frequency list doesn't need to fit channel numbers, -+ * because each entry contain its channel index */ - }; - - /* -diff -u -p linux/include/net/iw_handler.15.h linux/include/net/iw_handler.h ---- linux/include/net/iw_handler.15.h 2004-11-05 14:59:47.000000000 -0800 -+++ linux/include/net/iw_handler.h 2004-11-05 15:00:42.000000000 -0800 -@@ -1,7 +1,7 @@ - /* - * This file define the new driver API for Wireless Extensions - * -- * Version : 4 21.6.02 -+ * Version : 5 4.12.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> - * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. -@@ -206,7 +206,7 @@ - * will be needed... - * I just plan to increment with each new version. - */ --#define IW_HANDLER_VERSION 4 -+#define IW_HANDLER_VERSION 5 - - /* - * Changes : -@@ -220,10 +220,18 @@ - * V3 to V4 - * -------- - * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes -+ * -+ * V4 to V5 -+ * -------- -+ * - Add new spy support : struct iw_spy_data & prototypes - */ - - /**************************** CONSTANTS ****************************/ - -+/* Enable enhanced spy support. Disable to reduce footprint */ -+#define IW_WIRELESS_SPY -+#define IW_WIRELESS_THRSPY -+ - /* Special error message for the driver to indicate that we - * should do a commit after return from the iw_handler */ - #define EIWCOMMIT EINPROGRESS -@@ -315,6 +323,9 @@ struct iw_handler_def - * We will automatically export that to user space... */ - struct iw_priv_args * private_args; - -+ /* Driver enhanced spy support */ -+ long spy_offset; /* Spy data offset */ -+ - /* In the long term, get_wireless_stats will move from - * 'struct net_device' to here, to minimise bloat. */ - }; -@@ -350,6 +361,33 @@ struct iw_ioctl_description - - /* Need to think of short header translation table. Later. */ - -+/* --------------------- ENHANCED SPY SUPPORT --------------------- */ -+/* -+ * In the old days, the driver was handling spy support all by itself. -+ * Now, the driver can delegate this task to Wireless Extensions. -+ * It needs to include this struct in its private part and use the -+ * standard spy iw_handler. -+ */ -+ -+/* -+ * Instance specific spy data, i.e. addresses spied and quality for them. -+ */ -+struct iw_spy_data -+{ -+#ifdef IW_WIRELESS_SPY -+ /* --- Standard spy support --- */ -+ int spy_number; -+ u_char spy_address[IW_MAX_SPY][ETH_ALEN]; -+ struct iw_quality spy_stat[IW_MAX_SPY]; -+#ifdef IW_WIRELESS_THRSPY -+ /* --- Enhanced spy support (event) */ -+ struct iw_quality spy_thr_low; /* Low threshold */ -+ struct iw_quality spy_thr_high; /* High threshold */ -+ u_char spy_thr_under[IW_MAX_SPY]; -+#endif /* IW_WIRELESS_THRSPY */ -+#endif /* IW_WIRELESS_SPY */ -+}; -+ - /**************************** PROTOTYPES ****************************/ - /* - * Functions part of the Wireless Extensions (defined in net/core/wireless.c). -@@ -376,6 +414,31 @@ extern void wireless_send_event(struct n - /* We may need a function to send a stream of events to user space. - * More on that later... */ - -+/* Standard handler for SIOCSIWSPY */ -+extern int iw_handler_set_spy(struct net_device * dev, -+ struct iw_request_info * info, -+ union iwreq_data * wrqu, -+ char * extra); -+/* Standard handler for SIOCGIWSPY */ -+extern int iw_handler_get_spy(struct net_device * dev, -+ struct iw_request_info * info, -+ union iwreq_data * wrqu, -+ char * extra); -+/* Standard handler for SIOCSIWTHRSPY */ -+extern int iw_handler_set_thrspy(struct net_device * dev, -+ struct iw_request_info *info, -+ union iwreq_data * wrqu, -+ char * extra); -+/* Standard handler for SIOCGIWTHRSPY */ -+extern int iw_handler_get_thrspy(struct net_device * dev, -+ struct iw_request_info *info, -+ union iwreq_data * wrqu, -+ char * extra); -+/* Driver call to update spy records */ -+extern void wireless_spy_update(struct net_device * dev, -+ unsigned char * address, -+ struct iw_quality * wstats); -+ - /************************* INLINE FUNTIONS *************************/ - /* - * Function that are so simple that it's more efficient inlining them -diff -u -p linux/net/core/wireless.15.c linux/net/core/wireless.c ---- linux/net/core/wireless.15.c 2004-11-05 15:00:11.000000000 -0800 -+++ linux/net/core/wireless.c 2004-11-05 15:00:42.000000000 -0800 -@@ -2,7 +2,7 @@ - * This file implement the Wireless Extensions APIs. - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved. - * - * (As all part of the Linux kernel, this file is GPL) - */ -@@ -43,6 +43,11 @@ - * o Turn on WE_STRICT_WRITE by default + kernel warning - * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) - * o Fix off-by-one in test (extra_size <= IFNAMSIZ) -+ * -+ * v6 - 9.01.03 - Jean II -+ * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() -+ * o Add enhanced spy support : iw_handler_set_thrspy() and event. -+ * o Add WIRELESS_EXT version display in /proc/net/wireless - */ - - /***************************** INCLUDES *****************************/ -@@ -52,6 +57,7 @@ - #include <linux/types.h> /* off_t */ - #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ - #include <linux/rtnetlink.h> /* rtnetlink stuff */ -+#include <linux/if_arp.h> /* ARPHRD_ETHER */ - - #include <linux/wireless.h> /* Pretty obvious */ - #include <net/iw_handler.h> /* New driver API */ -@@ -65,6 +71,7 @@ - /* Debuging stuff */ - #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ - #undef WE_EVENT_DEBUG /* Debug Event dispatcher */ -+#undef WE_SPY_DEBUG /* Debug enhanced spy support */ - - /* Options */ - #define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ -@@ -72,7 +79,7 @@ - - /************************* GLOBAL VARIABLES *************************/ - /* -- * You should not use global variables, because or re-entrancy. -+ * You should not use global variables, because of re-entrancy. - * On our case, it's only const, so it's OK... - */ - /* -@@ -115,11 +122,11 @@ static const struct iw_ioctl_description - /* SIOCSIWSPY */ - { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0}, - /* SIOCGIWSPY */ -- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0}, -+ /* SIOCSIWTHRSPY */ -+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0}, -+ /* SIOCGIWTHRSPY */ -+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0}, - /* SIOCSIWAP */ - { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, - /* SIOCGIWAP */ -@@ -377,9 +384,9 @@ int dev_get_wireless_info(char * buffer, - struct net_device * dev; - - size = sprintf(buffer, -- "Inter-| sta-| Quality | Discarded packets | Missed\n" -- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n" -- ); -+ "Inter-| sta-| Quality | Discarded packets | Missed | WE\n" -+ " face | tus | link level noise | nwid crypt frag retry misc | beacon | %d\n", -+ WIRELESS_EXT); - - pos += size; - len += size; -@@ -1024,3 +1031,252 @@ void wireless_send_event(struct net_devi - - return; /* Always success, I guess ;-) */ - } -+ -+/********************** ENHANCED IWSPY SUPPORT **********************/ -+/* -+ * In the old days, the driver was handling spy support all by itself. -+ * Now, the driver can delegate this task to Wireless Extensions. -+ * It needs to use those standard spy iw_handler in struct iw_handler_def, -+ * push data to us via XXX and include struct iw_spy_data in its -+ * private part. -+ * One of the main advantage of centralising spy support here is that -+ * it becomes much easier to improve and extend it without having to touch -+ * the drivers. One example is the addition of the Spy-Threshold events. -+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h -+ */ -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Standard Wireless Handler : set Spy List -+ */ -+int iw_handler_set_spy(struct net_device * dev, -+ struct iw_request_info * info, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+#ifdef IW_WIRELESS_SPY -+ struct iw_spy_data * spydata = (dev->priv + -+ dev->wireless_handlers->spy_offset); -+ struct sockaddr * address = (struct sockaddr *) extra; -+ -+ /* Disable spy collection while we copy the addresses. -+ * As we don't disable interrupts, we need to do this to avoid races. -+ * As we are the only writer, this is good enough. */ -+ spydata->spy_number = 0; -+ -+ /* Are there are addresses to copy? */ -+ if(wrqu->data.length > 0) { -+ int i; -+ -+ /* Copy addresses */ -+ for(i = 0; i < wrqu->data.length; i++) -+ memcpy(spydata->spy_address[i], address[i].sa_data, -+ ETH_ALEN); -+ /* Reset stats */ -+ memset(spydata->spy_stat, 0, -+ sizeof(struct iw_quality) * IW_MAX_SPY); -+ -+#ifdef WE_SPY_DEBUG -+ printk(KERN_DEBUG "iw_handler_set_spy() : offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length); -+ for (i = 0; i < wrqu->data.length; i++) -+ printk(KERN_DEBUG -+ "%02X:%02X:%02X:%02X:%02X:%02X \n", -+ spydata->spy_address[i][0], -+ spydata->spy_address[i][1], -+ spydata->spy_address[i][2], -+ spydata->spy_address[i][3], -+ spydata->spy_address[i][4], -+ spydata->spy_address[i][5]); -+#endif /* WE_SPY_DEBUG */ -+ } -+ /* Enable addresses */ -+ spydata->spy_number = wrqu->data.length; -+ -+ return 0; -+#else /* IW_WIRELESS_SPY */ -+ return -EOPNOTSUPP; -+#endif /* IW_WIRELESS_SPY */ -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Standard Wireless Handler : get Spy List -+ */ -+int iw_handler_get_spy(struct net_device * dev, -+ struct iw_request_info * info, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+#ifdef IW_WIRELESS_SPY -+ struct iw_spy_data * spydata = (dev->priv + -+ dev->wireless_handlers->spy_offset); -+ struct sockaddr * address = (struct sockaddr *) extra; -+ int i; -+ -+ wrqu->data.length = spydata->spy_number; -+ -+ /* Copy addresses. */ -+ for(i = 0; i < spydata->spy_number; i++) { -+ memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN); -+ address[i].sa_family = AF_UNIX; -+ } -+ /* Copy stats to the user buffer (just after). */ -+ if(spydata->spy_number > 0) -+ memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number), -+ spydata->spy_stat, -+ sizeof(struct iw_quality) * spydata->spy_number); -+ /* Reset updated flags. */ -+ for(i = 0; i < spydata->spy_number; i++) -+ spydata->spy_stat[i].updated = 0; -+ return 0; -+#else /* IW_WIRELESS_SPY */ -+ return -EOPNOTSUPP; -+#endif /* IW_WIRELESS_SPY */ -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Standard Wireless Handler : set spy threshold -+ */ -+int iw_handler_set_thrspy(struct net_device * dev, -+ struct iw_request_info *info, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+#ifdef IW_WIRELESS_THRSPY -+ struct iw_spy_data * spydata = (dev->priv + -+ dev->wireless_handlers->spy_offset); -+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra; -+ -+ /* Just do it */ -+ memcpy(&(spydata->spy_thr_low), &(threshold->low), -+ 2 * sizeof(struct iw_quality)); -+ -+ /* Clear flag */ -+ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); -+ -+#ifdef WE_SPY_DEBUG -+ printk(KERN_DEBUG "iw_handler_set_thrspy() : low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level); -+#endif /* WE_SPY_DEBUG */ -+ -+ return 0; -+#else /* IW_WIRELESS_THRSPY */ -+ return -EOPNOTSUPP; -+#endif /* IW_WIRELESS_THRSPY */ -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Standard Wireless Handler : get spy threshold -+ */ -+int iw_handler_get_thrspy(struct net_device * dev, -+ struct iw_request_info *info, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+#ifdef IW_WIRELESS_THRSPY -+ struct iw_spy_data * spydata = (dev->priv + -+ dev->wireless_handlers->spy_offset); -+ struct iw_thrspy * threshold = (struct iw_thrspy *) extra; -+ -+ /* Just do it */ -+ memcpy(&(threshold->low), &(spydata->spy_thr_low), -+ 2 * sizeof(struct iw_quality)); -+ -+ return 0; -+#else /* IW_WIRELESS_THRSPY */ -+ return -EOPNOTSUPP; -+#endif /* IW_WIRELESS_THRSPY */ -+} -+ -+#ifdef IW_WIRELESS_THRSPY -+/*------------------------------------------------------------------*/ -+/* -+ * Prepare and send a Spy Threshold event -+ */ -+static void iw_send_thrspy_event(struct net_device * dev, -+ struct iw_spy_data * spydata, -+ unsigned char * address, -+ struct iw_quality * wstats) -+{ -+ union iwreq_data wrqu; -+ struct iw_thrspy threshold; -+ -+ /* Init */ -+ wrqu.data.length = 1; -+ wrqu.data.flags = 0; -+ /* Copy address */ -+ memcpy(threshold.addr.sa_data, address, ETH_ALEN); -+ threshold.addr.sa_family = ARPHRD_ETHER; -+ /* Copy stats */ -+ memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); -+ /* Copy also thresholds */ -+ memcpy(&(threshold.low), &(spydata->spy_thr_low), -+ 2 * sizeof(struct iw_quality)); -+ -+#ifdef WE_SPY_DEBUG -+ printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n", -+ threshold.addr.sa_data[0], -+ threshold.addr.sa_data[1], -+ threshold.addr.sa_data[2], -+ threshold.addr.sa_data[3], -+ threshold.addr.sa_data[4], -+ threshold.addr.sa_data[5], threshold.qual.level); -+#endif /* WE_SPY_DEBUG */ -+ -+ /* Send event to user space */ -+ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); -+} -+#endif /* IW_WIRELESS_THRSPY */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Call for the driver to update the spy data. -+ * For now, the spy data is a simple array. As the size of the array is -+ * small, this is good enough. If we wanted to support larger number of -+ * spy addresses, we should use something more efficient... -+ */ -+void wireless_spy_update(struct net_device * dev, -+ unsigned char * address, -+ struct iw_quality * wstats) -+{ -+#ifdef IW_WIRELESS_SPY -+ struct iw_spy_data * spydata = (dev->priv + -+ dev->wireless_handlers->spy_offset); -+ int i; -+ int match = -1; -+ -+#ifdef WE_SPY_DEBUG -+ printk(KERN_DEBUG "wireless_spy_update() : offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]); -+#endif /* WE_SPY_DEBUG */ -+ -+ /* Update all records that match */ -+ for(i = 0; i < spydata->spy_number; i++) -+ if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) { -+ memcpy(&(spydata->spy_stat[i]), wstats, -+ sizeof(struct iw_quality)); -+ match = i; -+ } -+#ifdef IW_WIRELESS_THRSPY -+ /* Generate an event if we cross the spy threshold. -+ * To avoid event storms, we have a simple hysteresis : we generate -+ * event only when we go under the low threshold or above the -+ * high threshold. */ -+ if(match >= 0) { -+ if(spydata->spy_thr_under[match]) { -+ if(wstats->level > spydata->spy_thr_high.level) { -+ spydata->spy_thr_under[match] = 0; -+ iw_send_thrspy_event(dev, spydata, -+ address, wstats); -+ } -+ } else { -+ if(wstats->level < spydata->spy_thr_low.level) { -+ spydata->spy_thr_under[match] = 1; -+ iw_send_thrspy_event(dev, spydata, -+ address, wstats); -+ } -+ } -+ } -+#endif /* IW_WIRELESS_THRSPY */ -+#endif /* IW_WIRELESS_SPY */ -+} -diff -u -p linux/net/netsyms.15.c linux/net/netsyms.c ---- linux/net/netsyms.15.c 2004-11-05 15:00:25.000000000 -0800 -+++ linux/net/netsyms.c 2004-11-05 15:01:38.000000000 -0800 -@@ -589,9 +589,13 @@ EXPORT_SYMBOL(net_call_rx_atomic); - EXPORT_SYMBOL(softnet_data); - - #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) --/* Don't include the whole header mess for a single function */ --extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra); -+#include <net/iw_handler.h> - EXPORT_SYMBOL(wireless_send_event); -+EXPORT_SYMBOL(iw_handler_set_spy); -+EXPORT_SYMBOL(iw_handler_get_spy); -+EXPORT_SYMBOL(iw_handler_set_thrspy); -+EXPORT_SYMBOL(iw_handler_get_thrspy); -+EXPORT_SYMBOL(wireless_spy_update); - #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ - - #endif /* CONFIG_NET */ diff --git a/recipes/linux/files/iw_handlers.w13-5.diff b/recipes/linux/files/iw_handlers.w13-5.diff deleted file mode 100644 index a27a7654a9..0000000000 --- a/recipes/linux/files/iw_handlers.w13-5.diff +++ /dev/null @@ -1,1513 +0,0 @@ -diff -u -p -r --new-file linux/include/linux-w12/netdevice.h linux/include/linux/netdevice.h ---- linux/include/linux-w12/netdevice.h Thu Nov 22 11:47:09 2001 -+++ linux/include/linux/netdevice.h Thu Jan 17 12:00:39 2002 -@@ -278,6 +278,10 @@ struct net_device - struct net_device_stats* (*get_stats)(struct net_device *dev); - struct iw_statistics* (*get_wireless_stats)(struct net_device *dev); - -+ /* List of functions to handle Wireless Extensions (instead of ioctl). -+ * See <net/iw_handler.h> for details. Jean II */ -+ struct iw_handler_def * wireless_handlers; -+ - /* - * This marks the end of the "visible" part of the structure. All - * fields hereafter are internal to the system, and may change at -diff -u -p -r --new-file linux/include/linux-w12/wireless.h linux/include/linux/wireless.h ---- linux/include/linux-w12/wireless.h Thu Nov 22 11:47:12 2001 -+++ linux/include/linux/wireless.h Thu Jan 17 12:04:08 2002 -@@ -1,9 +1,10 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 12 5.10.01 -+ * Version : 13 6.12.01 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -+ * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _LINUX_WIRELESS_H -@@ -11,6 +12,8 @@ - - /************************** DOCUMENTATION **************************/ - /* -+ * Initial APIs (1996 -> onward) : -+ * ----------------------------- - * Basically, the wireless extensions are for now a set of standard ioctl - * call + /proc/net/wireless - * -@@ -27,16 +30,27 @@ - * We have the list of command plus a structure descibing the - * data exchanged... - * Note that to add these ioctl, I was obliged to modify : -- * net/core/dev.c (two place + add include) -- * net/ipv4/af_inet.c (one place + add include) -+ * # net/core/dev.c (two place + add include) -+ * # net/ipv4/af_inet.c (one place + add include) - * - * /proc/net/wireless is a copy of /proc/net/dev. - * We have a structure for data passed from the driver to /proc/net/wireless - * Too add this, I've modified : -- * net/core/dev.c (two other places) -- * include/linux/netdevice.h (one place) -- * include/linux/proc_fs.h (one place) -+ * # net/core/dev.c (two other places) -+ * # include/linux/netdevice.h (one place) -+ * # include/linux/proc_fs.h (one place) -+ * -+ * New driver API (2001 -> onward) : -+ * ------------------------------- -+ * This file is only concerned with the user space API and common definitions. -+ * The new driver API is defined and documented in : -+ * # include/net/iw_handler.h - * -+ * Note as well that /proc/net/wireless implementation has now moved in : -+ * # include/linux/wireless.c -+ * -+ * Other comments : -+ * -------------- - * Do not add here things that are redundant with other mechanisms - * (drivers init, ifconfig, /proc/net/dev, ...) and with are not - * wireless specific. -@@ -54,16 +68,14 @@ - #include <linux/socket.h> /* for "struct sockaddr" et al */ - #include <linux/if.h> /* for IFNAMSIZ and co... */ - --/**************************** CONSTANTS ****************************/ -- --/* --------------------------- VERSION --------------------------- */ -+/***************************** VERSION *****************************/ - /* - * This constant is used to know the availability of the wireless - * extensions and to know which version of wireless extensions it is - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 12 -+#define WIRELESS_EXT 13 - - /* - * Changes : -@@ -123,12 +135,20 @@ - * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space - * - Add new statistics (frag, retry, beacon) - * - Add average quality (for user space calibration) -+ * -+ * V12 to V13 -+ * ---------- -+ * - Document creation of new driver API. -+ * - Extract union iwreq_data from struct iwreq (for new driver API). -+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT - */ - -+/**************************** CONSTANTS ****************************/ -+ - /* -------------------------- IOCTL LIST -------------------------- */ - - /* Basic operations */ --#define SIOCSIWNAME 0x8B00 /* Unused */ -+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ - #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ - #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ - #define SIOCGIWNWID 0x8B03 /* get network id */ -@@ -414,13 +434,49 @@ struct iw_statistics - - /* ------------------------ IOCTL REQUEST ------------------------ */ - /* -+ * This structure defines the payload of an ioctl, and is used -+ * below. -+ * -+ * Note that this structure should fit on the memory footprint -+ * of iwreq (which is the same as ifreq), which mean a max size of -+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... -+ * You should check this when increasing the structures defined -+ * above in this file... -+ */ -+union iwreq_data -+{ -+ /* Config - generic */ -+ char name[IFNAMSIZ]; -+ /* Name : used to verify the presence of wireless extensions. -+ * Name of the protocol/provider... */ -+ -+ struct iw_point essid; /* Extended network name */ -+ struct iw_param nwid; /* network id (or domain - the cell) */ -+ struct iw_freq freq; /* frequency or channel : -+ * 0-1000 = channel -+ * > 1000 = frequency in Hz */ -+ -+ struct iw_param sens; /* signal level threshold */ -+ struct iw_param bitrate; /* default bit rate */ -+ struct iw_param txpower; /* default transmit power */ -+ struct iw_param rts; /* RTS threshold threshold */ -+ struct iw_param frag; /* Fragmentation threshold */ -+ __u32 mode; /* Operation mode */ -+ struct iw_param retry; /* Retry limits & lifetime */ -+ -+ struct iw_point encoding; /* Encoding stuff : tokens */ -+ struct iw_param power; /* PM duration/timeout */ -+ -+ struct sockaddr ap_addr; /* Access point address */ -+ -+ struct iw_point data; /* Other large parameters */ -+}; -+ -+/* - * The structure to exchange data for ioctl. - * This structure is the same as 'struct ifreq', but (re)defined for - * convenience... -- * -- * Note that it should fit on the same memory footprint ! -- * You should check this when increasing the above structures (16 octets) -- * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... -+ * Do I need to remind you about structure size (32 octets) ? - */ - struct iwreq - { -@@ -429,35 +485,8 @@ struct iwreq - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ - } ifr_ifrn; - -- /* Data part */ -- union -- { -- /* Config - generic */ -- char name[IFNAMSIZ]; -- /* Name : used to verify the presence of wireless extensions. -- * Name of the protocol/provider... */ -- -- struct iw_point essid; /* Extended network name */ -- struct iw_param nwid; /* network id (or domain - the cell) */ -- struct iw_freq freq; /* frequency or channel : -- * 0-1000 = channel -- * > 1000 = frequency in Hz */ -- -- struct iw_param sens; /* signal level threshold */ -- struct iw_param bitrate; /* default bit rate */ -- struct iw_param txpower; /* default transmit power */ -- struct iw_param rts; /* RTS threshold threshold */ -- struct iw_param frag; /* Fragmentation threshold */ -- __u32 mode; /* Operation mode */ -- struct iw_param retry; /* Retry limits & lifetime */ -- -- struct iw_point encoding; /* Encoding stuff : tokens */ -- struct iw_param power; /* PM duration/timeout */ -- -- struct sockaddr ap_addr; /* Access point address */ -- -- struct iw_point data; /* Other large parameters */ -- } u; -+ /* Data part (defined just above) */ -+ union iwreq_data u; - }; - - /* -------------------------- IOCTL DATA -------------------------- */ -diff -u -p -r --new-file linux/include/net-w12/iw_handler.h linux/include/net/iw_handler.h ---- linux/include/net-w12/iw_handler.h Wed Dec 31 16:00:00 1969 -+++ linux/include/net/iw_handler.h Thu Jan 17 12:16:46 2002 -@@ -0,0 +1,374 @@ -+/* -+ * This file define the new driver API for Wireless Extensions -+ * -+ * Version : 2 6.12.01 -+ * -+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -+ * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved. -+ */ -+ -+#ifndef _IW_HANDLER_H -+#define _IW_HANDLER_H -+ -+/************************** DOCUMENTATION **************************/ -+/* -+ * Initial driver API (1996 -> onward) : -+ * ----------------------------------- -+ * The initial API just sends the IOCTL request received from user space -+ * to the driver (via the driver ioctl handler). The driver has to -+ * handle all the rest... -+ * -+ * The initial API also defines a specific handler in struct net_device -+ * to handle wireless statistics. -+ * -+ * The initial APIs served us well and has proven a reasonably good design. -+ * However, there is a few shortcommings : -+ * o No events, everything is a request to the driver. -+ * o Large ioctl function in driver with gigantic switch statement -+ * (i.e. spaghetti code). -+ * o Driver has to mess up with copy_to/from_user, and in many cases -+ * does it unproperly. Common mistakes are : -+ * * buffer overflows (no checks or off by one checks) -+ * * call copy_to/from_user with irq disabled -+ * o The user space interface is tied to ioctl because of the use -+ * copy_to/from_user. -+ * -+ * New driver API (2001 -> onward) : -+ * ------------------------------- -+ * The new driver API is just a bunch of standard functions (handlers), -+ * each handling a specific Wireless Extension. The driver just export -+ * the list of handler it supports, and those will be called apropriately. -+ * -+ * I tried to keep the main advantage of the previous API (simplicity, -+ * efficiency and light weight), and also I provide a good dose of backward -+ * compatibility (most structures are the same, driver can use both API -+ * simultaneously, ...). -+ * Hopefully, I've also addressed the shortcomming of the initial API. -+ * -+ * The advantage of the new API are : -+ * o Handling of Extensions in driver broken in small contained functions -+ * o Tighter checks of ioctl before calling the driver -+ * o Flexible commit strategy (at least, the start of it) -+ * o Backward compatibility (can be mixed with old API) -+ * o Driver doesn't have to worry about memory and user-space issues -+ * The last point is important for the following reasons : -+ * o You are now able to call the new driver API from any API you -+ * want (including from within other parts of the kernel). -+ * o Common mistakes are avoided (buffer overflow, user space copy -+ * with irq disabled and so on). -+ * -+ * The Drawback of the new API are : -+ * o bloat (especially kernel) -+ * o need to migrate existing drivers to new API -+ * My initial testing shows that the new API adds around 3kB to the kernel -+ * and save between 0 and 5kB from a typical driver. -+ * Also, as all structures and data types are unchanged, the migration is -+ * quite straightforward (but tedious). -+ * -+ * --- -+ * -+ * The new driver API is defined below in this file. User space should -+ * not be aware of what's happening down there... -+ * -+ * A new kernel wrapper is in charge of validating the IOCTLs and calling -+ * the appropriate driver handler. This is implemented in : -+ * # net/core/wireless.c -+ * -+ * The driver export the list of handlers in : -+ * # include/linux/netdevice.h (one place) -+ * -+ * The new driver API is available for WIRELESS_EXT >= 13. -+ * Good luck with migration to the new API ;-) -+ */ -+ -+/* ---------------------- THE IMPLEMENTATION ---------------------- */ -+/* -+ * Some of the choice I've made are pretty controversials. Defining an -+ * API is very much weighting compromises. This goes into some of the -+ * details and the thinking behind the implementation. -+ * -+ * Implementation goals : -+ * -------------------- -+ * The implementation goals were as follow : -+ * o Obvious : you should not need a PhD to understand what's happening, -+ * the benefit is easier maintainance. -+ * o Flexible : it should accomodate a wide variety of driver -+ * implementations and be as flexible as the old API. -+ * o Lean : it should be efficient memory wise to minimise the impact -+ * on kernel footprint. -+ * o Transparent to user space : the large number of user space -+ * applications that use Wireless Extensions should not need -+ * any modifications. -+ * -+ * Array of functions versus Struct of functions -+ * --------------------------------------------- -+ * 1) Having an array of functions allow the kernel code to access the -+ * handler in a single lookup, which is much more efficient (think hash -+ * table here). -+ * 2) The only drawback is that driver writer may put their handler in -+ * the wrong slot. This is trivial to test (I set the frequency, the -+ * bitrate changes). Once the handler is in the proper slot, it will be -+ * there forever, because the array is only extended at the end. -+ * 3) Backward/forward compatibility : adding new handler just require -+ * extending the array, so you can put newer driver in older kernel -+ * without having to patch the kernel code (and vice versa). -+ * -+ * All handler are of the same generic type -+ * ---------------------------------------- -+ * That's a feature !!! -+ * 1) Having a generic handler allow to have generic code, which is more -+ * efficient. If each of the handler was individually typed I would need -+ * to add a big switch in the kernel (== more bloat). This solution is -+ * more scalable, adding new Wireless Extensions doesn't add new code. -+ * 2) You can use the same handler in different slots of the array. For -+ * hardware, it may be more efficient or logical to handle multiple -+ * Wireless Extensions with a single function, and the API allow you to -+ * do that. (An example would be a single record on the card to control -+ * both bitrate and frequency, the handler would read the old record, -+ * modify it according to info->cmd and rewrite it). -+ * -+ * Functions prototype uses union iwreq_data -+ * ----------------------------------------- -+ * Some would have prefered functions defined this way : -+ * static int mydriver_ioctl_setrate(struct net_device *dev, -+ * long rate, int auto) -+ * 1) The kernel code doesn't "validate" the content of iwreq_data, and -+ * can't do it (different hardware may have different notion of what a -+ * valid frequency is), so we don't pretend that we do it. -+ * 2) The above form is not extendable. If I want to add a flag (for -+ * example to distinguish setting max rate and basic rate), I would -+ * break the prototype. Using iwreq_data is more flexible. -+ * 3) Also, the above form is not generic (see above). -+ * 4) I don't expect driver developper using the wrong field of the -+ * union (Doh !), so static typechecking doesn't add much value. -+ * 5) Lastly, you can skip the union by doing : -+ * static int mydriver_ioctl_setrate(struct net_device *dev, -+ * struct iw_request_info *info, -+ * struct iw_param *rrq, -+ * char *extra) -+ * And then adding the handler in the array like this : -+ * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE -+ * -+ * Using functions and not a registry -+ * ---------------------------------- -+ * Another implementation option would have been for every instance to -+ * define a registry (a struct containing all the Wireless Extensions) -+ * and only have a function to commit the registry to the hardware. -+ * 1) This approach can be emulated by the current code, but not -+ * vice versa. -+ * 2) Some drivers don't keep any configuration in the driver, for them -+ * adding such a registry would be a significant bloat. -+ * 3) The code to translate from Wireless Extension to native format is -+ * needed anyway, so it would not reduce significantely the amount of code. -+ * 4) The current approach only selectively translate Wireless Extensions -+ * to native format and only selectively set, whereas the registry approach -+ * would require to translate all WE and set all parameters for any single -+ * change. -+ * 5) For many Wireless Extensions, the GET operation return the current -+ * dynamic value, not the value that was set. -+ * -+ * This header is <net/iw_handler.h> -+ * --------------------------------- -+ * 1) This header is kernel space only and should not be exported to -+ * user space. Headers in "include/linux/" are exported, headers in -+ * "include/net/" are not. -+ * -+ * Mixed 32/64 bit issues -+ * ---------------------- -+ * The Wireless Extensions are designed to be 64 bit clean, by using only -+ * datatypes with explicit storage size. -+ * There are some issues related to kernel and user space using different -+ * memory model, and in particular 64bit kernel with 32bit user space. -+ * The problem is related to struct iw_point, that contains a pointer -+ * that *may* need to be translated. -+ * This is quite messy. The new API doesn't solve this problem (it can't), -+ * but is a step in the right direction : -+ * 1) Meta data about each ioctl is easily available, so we know what type -+ * of translation is needed. -+ * 2) The move of data between kernel and user space is only done in a single -+ * place in the kernel, so adding specific hooks in there is possible. -+ * 3) In the long term, it allows to move away from using ioctl as the -+ * user space API. -+ * -+ * So many comments and so few code -+ * -------------------------------- -+ * That's a feature. Comments won't bloat the resulting kernel binary. -+ */ -+ -+/***************************** INCLUDES *****************************/ -+ -+#include <linux/wireless.h> /* IOCTL user space API */ -+ -+/***************************** VERSION *****************************/ -+/* -+ * This constant is used to know which version of the driver API is -+ * available. Hopefully, this will be pretty stable and no changes -+ * will be needed... -+ * I just plan to increment with each new version. -+ */ -+#define IW_HANDLER_VERSION 2 -+ -+/**************************** CONSTANTS ****************************/ -+ -+/* Special error message for the driver to indicate that we -+ * should do a commit after return from the iw_handler */ -+#define EIWCOMMIT EINPROGRESS -+ -+/* Flags available in struct iw_request_info */ -+#define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */ -+ -+/* Type of headers we know about (basically union iwreq_data) */ -+#define IW_HEADER_TYPE_NULL 0 /* Not available */ -+#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */ -+#define IW_HEADER_TYPE_UINT 4 /* __u32 */ -+#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */ -+#define IW_HEADER_TYPE_POINT 6 /* struct iw_point */ -+#define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */ -+#define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */ -+ -+/* Handling flags */ -+/* Most are not implemented. I just use them as a reminder of some -+ * cool features we might need one day ;-) */ -+#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */ -+/* Wrapper level flags */ -+#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */ -+#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ -+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */ -+/* Driver level flags */ -+#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ -+ -+/****************************** TYPES ******************************/ -+ -+/* ----------------------- WIRELESS HANDLER ----------------------- */ -+/* -+ * A wireless handler is just a standard function, that looks like the -+ * ioctl handler. -+ * We also define there how a handler list look like... As the Wireless -+ * Extension space is quite dense, we use a simple array, which is faster -+ * (that's the perfect hash table ;-). -+ */ -+ -+/* -+ * Meta data about the request passed to the iw_handler. -+ * Most handlers can safely ignore what's in there. -+ * The 'cmd' field might come handy if you want to use the same handler -+ * for multiple command... -+ * This struct is also my long term insurance. I can add new fields here -+ * without breaking the prototype of iw_handler... -+ */ -+struct iw_request_info -+{ -+ __u16 cmd; /* Wireless Extension command */ -+ __u16 flags; /* More to come ;-) */ -+}; -+ -+/* -+ * This is how a function handling a Wireless Extension should look -+ * like (both get and set, standard and private). -+ */ -+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, -+ union iwreq_data *wrqu, char *extra); -+ -+/* -+ * This define all the handler that the driver export. -+ * As you need only one per driver type, please use a static const -+ * shared by all driver instances... Same for the members... -+ * This will be linked from net_device in <linux/netdevice.h> -+ */ -+struct iw_handler_def -+{ -+ /* Number of handlers defined (more precisely, index of the -+ * last defined handler + 1) */ -+ __u16 num_standard; -+ __u16 num_private; -+ /* Number of private arg description */ -+ __u16 num_private_args; -+ -+ /* Array of handlers for standard ioctls -+ * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME] -+ */ -+ iw_handler * standard; -+ -+ /* Array of handlers for private ioctls -+ * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] -+ */ -+ iw_handler * private; -+ -+ /* Arguments of private handler. This one is just a list, so you -+ * can put it in any order you want and should not leave holes... -+ * We will automatically export that to user space... */ -+ struct iw_priv_args * private_args; -+ -+ /* In the long term, get_wireless_stats will move from -+ * 'struct net_device' to here, to minimise bloat. */ -+}; -+ -+/* ----------------------- WIRELESS EVENTS ----------------------- */ -+/* -+ * Currently we don't support events, so let's just plan for the -+ * future... -+ */ -+ -+/* -+ * A Wireless Event. -+ */ -+// How do we define short header ? We don't want a flag on length. -+// Probably a flag on event ? Highest bit to zero... -+struct iw_event -+{ -+ __u16 length; /* Lenght of this stuff */ -+ __u16 event; /* Wireless IOCTL */ -+ union iwreq_data header; /* IOCTL fixed payload */ -+ char extra[0]; /* Optional IOCTL data */ -+}; -+ -+/* ---------------------- IOCTL DESCRIPTION ---------------------- */ -+/* -+ * One of the main goal of the new interface is to deal entirely with -+ * user space/kernel space memory move. -+ * For that, we need to know : -+ * o if iwreq is a pointer or contain the full data -+ * o what is the size of the data to copy -+ * -+ * For private IOCTLs, we use the same rules as used by iwpriv and -+ * defined in struct iw_priv_args. -+ * -+ * For standard IOCTLs, things are quite different and we need to -+ * use the stuctures below. Actually, this struct is also more -+ * efficient, but that's another story... -+ */ -+ -+/* -+ * Describe how a standard IOCTL looks like. -+ */ -+struct iw_ioctl_description -+{ -+ __u8 header_type; /* NULL, iw_point or other */ -+ __u8 token_type; /* Future */ -+ __u16 token_size; /* Granularity of payload */ -+ __u16 min_tokens; /* Min acceptable token number */ -+ __u16 max_tokens; /* Max acceptable token number */ -+ __u32 flags; /* Special handling of the request */ -+}; -+ -+/* Need to think of short header translation table. Later. */ -+ -+/**************************** PROTOTYPES ****************************/ -+/* -+ * Functions part of the Wireless Extensions (defined in net/core/wireless.c). -+ * Those may be called only within the kernel. -+ */ -+ -+/* First : function strictly used inside the kernel */ -+ -+/* Handle /proc/net/wireless, called in net/code/dev.c */ -+extern int dev_get_wireless_info(char * buffer, char **start, off_t offset, -+ int length); -+ -+/* Handle IOCTLs, called in net/code/dev.c */ -+extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); -+ -+/* Second : functions that may be called by driver modules */ -+/* None yet */ -+ -+#endif /* _LINUX_WIRELESS_H */ -diff -u -p -r --new-file linux/net/core-w12/Makefile linux/net/core/Makefile ---- linux/net/core-w12/Makefile Tue Oct 30 15:08:12 2001 -+++ linux/net/core/Makefile Thu Jan 17 11:06:07 2002 -@@ -26,5 +26,8 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o d - obj-$(CONFIG_NETFILTER) += netfilter.o - obj-$(CONFIG_NET_DIVERT) += dv.o - obj-$(CONFIG_NET_PROFILE) += profile.o -+obj-$(CONFIG_NET_RADIO) += wireless.o -+# Ugly. I wish all wireless drivers were moved in drivers/net/wireless -+obj-$(CONFIG_NET_PCMCIA_RADIO) += wireless.o - - include $(TOPDIR)/Rules.make -diff -u -p -r --new-file linux/net/core-w12/dev.c linux/net/core/dev.c ---- linux/net/core-w12/dev.c Wed Nov 7 14:39:36 2001 -+++ linux/net/core/dev.c Thu Jan 17 11:06:07 2002 -@@ -102,6 +102,7 @@ - #include <linux/module.h> - #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) - #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ -+#include <net/iw_handler.h> - #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ - #ifdef CONFIG_PLIP - extern int plip_init(void); -@@ -1796,122 +1797,6 @@ static int dev_proc_stats(char *buffer, - #endif /* CONFIG_PROC_FS */ - - --#ifdef WIRELESS_EXT --#ifdef CONFIG_PROC_FS -- --/* -- * Print one entry of /proc/net/wireless -- * This is a clone of /proc/net/dev (just above) -- */ --static int sprintf_wireless_stats(char *buffer, struct net_device *dev) --{ -- /* Get stats from the driver */ -- struct iw_statistics *stats = (dev->get_wireless_stats ? -- dev->get_wireless_stats(dev) : -- (struct iw_statistics *) NULL); -- int size; -- -- if (stats != (struct iw_statistics *) NULL) { -- size = sprintf(buffer, -- "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n", -- dev->name, -- stats->status, -- stats->qual.qual, -- stats->qual.updated & 1 ? '.' : ' ', -- stats->qual.level, -- stats->qual.updated & 2 ? '.' : ' ', -- stats->qual.noise, -- stats->qual.updated & 4 ? '.' : ' ', -- stats->discard.nwid, -- stats->discard.code, -- stats->discard.fragment, -- stats->discard.retries, -- stats->discard.misc, -- stats->miss.beacon); -- stats->qual.updated = 0; -- } -- else -- size = 0; -- -- return size; --} -- --/* -- * Print info for /proc/net/wireless (print all entries) -- * This is a clone of /proc/net/dev (just above) -- */ --static int dev_get_wireless_info(char * buffer, char **start, off_t offset, -- int length) --{ -- int len = 0; -- off_t begin = 0; -- off_t pos = 0; -- int size; -- -- struct net_device * dev; -- -- size = sprintf(buffer, -- "Inter-| sta-| Quality | Discarded packets | Missed\n" -- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n" -- ); -- -- pos += size; -- len += size; -- -- read_lock(&dev_base_lock); -- for (dev = dev_base; dev != NULL; dev = dev->next) { -- size = sprintf_wireless_stats(buffer + len, dev); -- len += size; -- pos = begin + len; -- -- if (pos < offset) { -- len = 0; -- begin = pos; -- } -- if (pos > offset + length) -- break; -- } -- read_unlock(&dev_base_lock); -- -- *start = buffer + (offset - begin); /* Start of wanted data */ -- len -= (offset - begin); /* Start slop */ -- if (len > length) -- len = length; /* Ending slop */ -- if (len < 0) -- len = 0; -- -- return len; --} --#endif /* CONFIG_PROC_FS */ -- --/* -- * Allow programatic access to /proc/net/wireless even if /proc -- * doesn't exist... Also more efficient... -- */ --static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr) --{ -- /* Get stats from the driver */ -- struct iw_statistics *stats = (dev->get_wireless_stats ? -- dev->get_wireless_stats(dev) : -- (struct iw_statistics *) NULL); -- -- if (stats != (struct iw_statistics *) NULL) { -- struct iwreq * wrq = (struct iwreq *)ifr; -- -- /* Copy statistics to the user buffer */ -- if(copy_to_user(wrq->u.data.pointer, stats, -- sizeof(struct iw_statistics))) -- return -EFAULT; -- -- /* Check if we need to clear the update flag */ -- if(wrq->u.data.flags != 0) -- stats->qual.updated = 0; -- return(0); -- } else -- return -EOPNOTSUPP; --} --#endif /* WIRELESS_EXT */ -- - /** - * netdev_set_master - set up master/slave pair - * @slave: slave device -@@ -2209,11 +2094,6 @@ static int dev_ifsioc(struct ifreq *ifr, - notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); - return 0; - --#ifdef WIRELESS_EXT -- case SIOCGIWSTATS: -- return dev_iwstats(dev, ifr); --#endif /* WIRELESS_EXT */ -- - /* - * Unknown or private ioctl - */ -@@ -2239,17 +2119,6 @@ static int dev_ifsioc(struct ifreq *ifr, - return -EOPNOTSUPP; - } - --#ifdef WIRELESS_EXT -- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { -- if (dev->do_ioctl) { -- if (!netif_device_present(dev)) -- return -ENODEV; -- return dev->do_ioctl(dev, ifr, cmd); -- } -- return -EOPNOTSUPP; -- } --#endif /* WIRELESS_EXT */ -- - } - return -EINVAL; - } -@@ -2431,7 +2300,8 @@ int dev_ioctl(unsigned int cmd, void *ar - } - dev_load(ifr.ifr_name); - rtnl_lock(); -- ret = dev_ifsioc(&ifr, cmd); -+ /* Follow me in net/core/wireless.c */ -+ ret = wireless_process_ioctl(&ifr, cmd); - rtnl_unlock(); - if (!ret && IW_IS_GET(cmd) && - copy_to_user(arg, &ifr, sizeof(struct ifreq))) -@@ -2856,6 +2726,7 @@ int __init net_dev_init(void) - proc_net_create("dev", 0, dev_get_info); - create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL); - #ifdef WIRELESS_EXT -+ /* Available in net/core/wireless.c */ - proc_net_create("wireless", 0, dev_get_wireless_info); - #endif /* WIRELESS_EXT */ - #endif /* CONFIG_PROC_FS */ -diff -u -p -r --new-file linux/net/core-w12/wireless.c linux/net/core/wireless.c ---- linux/net/core-w12/wireless.c Wed Dec 31 16:00:00 1969 -+++ linux/net/core/wireless.c Mon Jan 21 11:13:23 2002 -@@ -0,0 +1,733 @@ -+/* -+ * This file implement the Wireless Extensions APIs. -+ * -+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -+ * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. -+ * -+ * (As all part of the Linux kernel, this file is GPL) -+ */ -+ -+/************************** DOCUMENTATION **************************/ -+/* -+ * API definition : -+ * -------------- -+ * See <linux/wireless.h> for details of the APIs and the rest. -+ * -+ * History : -+ * ------- -+ * -+ * v1 - 5.12.01 - Jean II -+ * o Created this file. -+ * -+ * v2 - 13.12.01 - Jean II -+ * o Move /proc/net/wireless stuff from net/core/dev.c to here -+ * o Make Wireless Extension IOCTLs go through here -+ * o Added iw_handler handling ;-) -+ * o Added standard ioctl description -+ * o Initial dumb commit strategy based on orinoco.c -+ */ -+ -+/***************************** INCLUDES *****************************/ -+ -+#include <asm/uaccess.h> /* copy_to_user() */ -+#include <linux/config.h> /* Not needed ??? */ -+#include <linux/types.h> /* off_t */ -+#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ -+ -+#include <linux/wireless.h> /* Pretty obvious */ -+#include <net/iw_handler.h> /* New driver API */ -+ -+/**************************** CONSTANTS ****************************/ -+ -+/* This will be turned on later on... */ -+#undef WE_STRICT_WRITE /* Check write buffer size */ -+ -+/* Debuging stuff */ -+#undef WE_IOCTL_DEBUG /* Debug IOCTL API */ -+ -+/************************* GLOBAL VARIABLES *************************/ -+/* -+ * You should not use global variables, because or re-entrancy. -+ * On our case, it's only const, so it's OK... -+ */ -+static const struct iw_ioctl_description standard_ioctl[] = { -+ /* SIOCSIWCOMMIT (internal) */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCGIWNAME */ -+ { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWNWID */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT}, -+ /* SIOCGIWNWID */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWFREQ */ -+ { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT}, -+ /* SIOCGIWFREQ */ -+ { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWMODE */ -+ { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT}, -+ /* SIOCGIWMODE */ -+ { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWSENS */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWSENS */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWRANGE */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCGIWRANGE */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWPRIV */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCGIWPRIV (handled directly by us) */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWSTATS */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCGIWSTATS (handled directly by us) */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWSPY */ -+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0}, -+ /* SIOCGIWSPY */ -+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWAP */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, -+ /* SIOCGIWAP */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCGIWAPLIST */ -+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWESSID */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT}, -+ /* SIOCGIWESSID */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP}, -+ /* SIOCSIWNICKN */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ /* SIOCGIWNICKN */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* -- hole -- */ -+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWRATE */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWRATE */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWRTS */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWRTS */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWFRAG */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWFRAG */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWTXPOW */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWTXPOW */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWRETRY */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWRETRY */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCSIWENCODE */ -+ { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT}, -+ /* SIOCGIWENCODE */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT}, -+ /* SIOCSIWPOWER */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWPOWER */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+}; -+ -+/* Size (in bytes) of the various private data types */ -+char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+ -+/************************ COMMON SUBROUTINES ************************/ -+/* -+ * Stuff that may be used in various place or doesn't fit in one -+ * of the section below. -+ */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Return the driver handler associated with a specific Wireless Extension. -+ * Called from various place, so make sure it remains efficient. -+ */ -+static inline iw_handler get_handler(struct net_device *dev, -+ unsigned int cmd) -+{ -+ unsigned int index; /* MUST be unsigned */ -+ -+ /* Check if we have some wireless handlers defined */ -+ if(dev->wireless_handlers == NULL) -+ return NULL; -+ -+ /* Try as a standard command */ -+ index = cmd - SIOCIWFIRST; -+ if(index < dev->wireless_handlers->num_standard) -+ return dev->wireless_handlers->standard[index]; -+ -+ /* Try as a private command */ -+ index = cmd - SIOCIWFIRSTPRIV; -+ if(index < dev->wireless_handlers->num_private) -+ return dev->wireless_handlers->private[index]; -+ -+ /* Not found */ -+ return NULL; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Get statistics out of the driver -+ */ -+static inline struct iw_statistics *get_wireless_stats(struct net_device *dev) -+{ -+ return (dev->get_wireless_stats ? -+ dev->get_wireless_stats(dev) : -+ (struct iw_statistics *) NULL); -+ /* In the future, get_wireless_stats may move from 'struct net_device' -+ * to 'struct iw_handler_def', to de-bloat struct net_device. -+ * Definitely worse a thought... */ -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Call the commit handler in the driver -+ * (if exist and if conditions are right) -+ * -+ * Note : our current commit strategy is currently pretty dumb, -+ * but we will be able to improve on that... -+ * The goal is to try to agreagate as many changes as possible -+ * before doing the commit. Drivers that will define a commit handler -+ * are usually those that need a reset after changing parameters, so -+ * we want to minimise the number of reset. -+ * A cool idea is to use a timer : at each "set" command, we re-set the -+ * timer, when the timer eventually fires, we call the driver. -+ * Hopefully, more on that later. -+ * -+ * Also, I'm waiting to see how many people will complain about the -+ * netif_running(dev) test. I'm open on that one... -+ * Hopefully, the driver will remember to do a commit in "open()" ;-) -+ */ -+static inline int call_commit_handler(struct net_device * dev) -+{ -+ if((netif_running(dev)) && -+ (dev->wireless_handlers->standard[0] != NULL)) { -+ /* Call the commit handler on the driver */ -+ return dev->wireless_handlers->standard[0](dev, NULL, -+ NULL, NULL); -+ } else -+ return 0; /* Command completed successfully */ -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Number of private arguments -+ */ -+static inline int get_priv_size(__u16 args) -+{ -+ int num = args & IW_PRIV_SIZE_MASK; -+ int type = (args & IW_PRIV_TYPE_MASK) >> 12; -+ -+ return num * priv_type_size[type]; -+} -+ -+ -+/******************** /proc/net/wireless SUPPORT ********************/ -+/* -+ * The /proc/net/wireless file is a human readable user-space interface -+ * exporting various wireless specific statistics from the wireless devices. -+ * This is the most popular part of the Wireless Extensions ;-) -+ * -+ * This interface is a pure clone of /proc/net/dev (in net/core/dev.c). -+ * The content of the file is basically the content of "struct iw_statistics". -+ */ -+ -+#ifdef CONFIG_PROC_FS -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Print one entry (line) of /proc/net/wireless -+ */ -+static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev) -+{ -+ /* Get stats from the driver */ -+ struct iw_statistics *stats; -+ int size; -+ -+ stats = get_wireless_stats(dev); -+ if (stats != (struct iw_statistics *) NULL) { -+ size = sprintf(buffer, -+ "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n", -+ dev->name, -+ stats->status, -+ stats->qual.qual, -+ stats->qual.updated & 1 ? '.' : ' ', -+ stats->qual.level, -+ stats->qual.updated & 2 ? '.' : ' ', -+ stats->qual.noise, -+ stats->qual.updated & 4 ? '.' : ' ', -+ stats->discard.nwid, -+ stats->discard.code, -+ stats->discard.fragment, -+ stats->discard.retries, -+ stats->discard.misc, -+ stats->miss.beacon); -+ stats->qual.updated = 0; -+ } -+ else -+ size = 0; -+ -+ return size; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Print info for /proc/net/wireless (print all entries) -+ */ -+int dev_get_wireless_info(char * buffer, char **start, off_t offset, -+ int length) -+{ -+ int len = 0; -+ off_t begin = 0; -+ off_t pos = 0; -+ int size; -+ -+ struct net_device * dev; -+ -+ size = sprintf(buffer, -+ "Inter-| sta-| Quality | Discarded packets | Missed\n" -+ " face | tus | link level noise | nwid crypt frag retry misc | beacon\n" -+ ); -+ -+ pos += size; -+ len += size; -+ -+ read_lock(&dev_base_lock); -+ for (dev = dev_base; dev != NULL; dev = dev->next) { -+ size = sprintf_wireless_stats(buffer + len, dev); -+ len += size; -+ pos = begin + len; -+ -+ if (pos < offset) { -+ len = 0; -+ begin = pos; -+ } -+ if (pos > offset + length) -+ break; -+ } -+ read_unlock(&dev_base_lock); -+ -+ *start = buffer + (offset - begin); /* Start of wanted data */ -+ len -= (offset - begin); /* Start slop */ -+ if (len > length) -+ len = length; /* Ending slop */ -+ if (len < 0) -+ len = 0; -+ -+ return len; -+} -+#endif /* CONFIG_PROC_FS */ -+ -+/************************** IOCTL SUPPORT **************************/ -+/* -+ * The original user space API to configure all those Wireless Extensions -+ * is through IOCTLs. -+ * In there, we check if we need to call the new driver API (iw_handler) -+ * or just call the driver ioctl handler. -+ */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Allow programatic access to /proc/net/wireless even if /proc -+ * doesn't exist... Also more efficient... -+ */ -+static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr) -+{ -+ /* Get stats from the driver */ -+ struct iw_statistics *stats; -+ -+ stats = get_wireless_stats(dev); -+ if (stats != (struct iw_statistics *) NULL) { -+ struct iwreq * wrq = (struct iwreq *)ifr; -+ -+ /* Copy statistics to the user buffer */ -+ if(copy_to_user(wrq->u.data.pointer, stats, -+ sizeof(struct iw_statistics))) -+ return -EFAULT; -+ -+ /* Check if we need to clear the update flag */ -+ if(wrq->u.data.flags != 0) -+ stats->qual.updated = 0; -+ return 0; -+ } else -+ return -EOPNOTSUPP; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Export the driver private handler definition -+ * They will be picked up by tools like iwpriv... -+ */ -+static inline int ioctl_export_private(struct net_device * dev, -+ struct ifreq * ifr) -+{ -+ struct iwreq * iwr = (struct iwreq *) ifr; -+ -+ /* Check if the driver has something to export */ -+ if((dev->wireless_handlers->num_private_args == 0) || -+ (dev->wireless_handlers->private_args == NULL)) -+ return -EOPNOTSUPP; -+ -+ /* Check NULL pointer */ -+ if(iwr->u.data.pointer == NULL) -+ return -EFAULT; -+#ifdef WE_STRICT_WRITE -+ /* Check if there is enough buffer up there */ -+ if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1)) -+ return -E2BIG; -+#endif /* WE_STRICT_WRITE */ -+ -+ /* Set the number of available ioctls. */ -+ iwr->u.data.length = dev->wireless_handlers->num_private_args; -+ -+ /* Copy structure to the user buffer. */ -+ if (copy_to_user(iwr->u.data.pointer, -+ dev->wireless_handlers->private_args, -+ sizeof(struct iw_priv_args) * iwr->u.data.length)) -+ return -EFAULT; -+ -+ return 0; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Wrapper to call a standard Wireless Extension handler. -+ * We do various checks and also take care of moving data between -+ * user space and kernel space. -+ */ -+static inline int ioctl_standard_call(struct net_device * dev, -+ struct ifreq * ifr, -+ unsigned int cmd, -+ iw_handler handler) -+{ -+ struct iwreq * iwr = (struct iwreq *) ifr; -+ const struct iw_ioctl_description * descr; -+ struct iw_request_info info; -+ int ret = -EINVAL; -+ -+ /* Get the description of the IOCTL */ -+ descr = &(standard_ioctl[cmd - SIOCIWFIRST]); -+ -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n", -+ ifr->ifr_name, cmd); -+ 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); -+#endif /* WE_IOCTL_DEBUG */ -+ -+ /* Prepare the call */ -+ info.cmd = cmd; -+ info.flags = 0; -+ -+ /* Check if we have a pointer to user space data or not */ -+ if(descr->header_type != IW_HEADER_TYPE_POINT) { -+ /* No extra arguments. Trivial to handle */ -+ ret = handler(dev, &info, &(iwr->u), NULL); -+ } else { -+ char * extra; -+ int err; -+ -+ /* Check what user space is giving us */ -+ if(IW_IS_SET(cmd)) { -+ /* Check NULL pointer */ -+ if((iwr->u.data.pointer == NULL) && -+ (iwr->u.data.length != 0)) -+ return -EFAULT; -+ /* Check if number of token fits within bounds */ -+ if(iwr->u.data.length > descr->max_tokens) -+ return -E2BIG; -+ if(iwr->u.data.length < descr->min_tokens) -+ return -EINVAL; -+ } else { -+ /* Check NULL pointer */ -+ if(iwr->u.data.pointer == NULL) -+ return -EFAULT; -+#ifdef WE_STRICT_WRITE -+ /* Check if there is enough buffer up there */ -+ if(iwr->u.data.length < descr->max_tokens) -+ return -E2BIG; -+#endif /* WE_STRICT_WRITE */ -+ } -+ -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Malloc %d bytes\n", -+ descr->max_tokens * descr->token_size); -+#endif /* WE_IOCTL_DEBUG */ -+ -+ /* Always allocate for max space. Easier, and won't last -+ * long... */ -+ extra = kmalloc(descr->max_tokens * descr->token_size, -+ GFP_KERNEL); -+ if (extra == NULL) { -+ return -ENOMEM; -+ } -+ -+ /* If it is a SET, get all the extra data in here */ -+ if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { -+ err = copy_from_user(extra, iwr->u.data.pointer, -+ iwr->u.data.length * -+ descr->token_size); -+ if (err) { -+ kfree(extra); -+ return -EFAULT; -+ } -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Got %d bytes\n", -+ iwr->u.data.length * descr->token_size); -+#endif /* WE_IOCTL_DEBUG */ -+ } -+ -+ /* Call the handler */ -+ ret = handler(dev, &info, &(iwr->u), extra); -+ -+ /* If we have something to return to the user */ -+ if (!ret && IW_IS_GET(cmd)) { -+ err = copy_to_user(iwr->u.data.pointer, extra, -+ iwr->u.data.length * -+ descr->token_size); -+ if (err) -+ ret = -EFAULT; -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Wrote %d bytes\n", -+ iwr->u.data.length * descr->token_size); -+#endif /* WE_IOCTL_DEBUG */ -+ } -+ -+ /* Cleanup - I told you it wasn't that long ;-) */ -+ kfree(extra); -+ } -+ -+ /* Call commit handler if needed and defined */ -+ if(ret == -EIWCOMMIT) -+ ret = call_commit_handler(dev); -+ -+ /* Here, we will generate the appropriate event if needed */ -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Wrapper to call a private Wireless Extension handler. -+ * We do various checks and also take care of moving data between -+ * user space and kernel space. -+ * It's not as nice and slimline as the standard wrapper. The cause -+ * is struct iw_priv_args, which was not really designed for the -+ * job we are going here. -+ * -+ * IMPORTANT : This function prevent to set and get data on the same -+ * IOCTL and enforce the SET/GET convention. Not doing it would be -+ * far too hairy... -+ * If you need to set and get data at the same time, please don't use -+ * a iw_handler but process it in your ioctl handler (i.e. use the -+ * old driver API). -+ */ -+static inline int ioctl_private_call(struct net_device * dev, -+ struct ifreq * ifr, -+ unsigned int cmd, -+ iw_handler handler) -+{ -+ struct iwreq * iwr = (struct iwreq *) ifr; -+ struct iw_priv_args * descr = NULL; -+ struct iw_request_info info; -+ int extra_size = 0; -+ int i; -+ int ret = -EINVAL; -+ -+ /* Get the description of the IOCTL */ -+ for(i = 0; i < dev->wireless_handlers->num_private_args; i++) -+ if(cmd == dev->wireless_handlers->private_args[i].cmd) { -+ descr = &(dev->wireless_handlers->private_args[i]); -+ break; -+ } -+ -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n", -+ ifr->ifr_name, cmd); -+ if(descr) { -+ printk(KERN_DEBUG "Name %s, set %X, get %X\n", -+ descr->name, descr->set_args, descr->get_args); -+ } -+#endif /* WE_IOCTL_DEBUG */ -+ -+ /* Compute the size of the set/get arguments */ -+ if(descr != NULL) { -+ if(IW_IS_SET(cmd)) { -+ /* Size of set arguments */ -+ extra_size = get_priv_size(descr->set_args); -+ -+ /* Does it fits in iwr ? */ -+ if((descr->set_args & IW_PRIV_SIZE_FIXED) && -+ (extra_size < IFNAMSIZ)) -+ extra_size = 0; -+ } else { -+ /* Size of set arguments */ -+ extra_size = get_priv_size(descr->get_args); -+ -+ /* Does it fits in iwr ? */ -+ if((descr->get_args & IW_PRIV_SIZE_FIXED) && -+ (extra_size < IFNAMSIZ)) -+ extra_size = 0; -+ } -+ } -+ -+ /* Prepare the call */ -+ info.cmd = cmd; -+ info.flags = 0; -+ -+ /* Check if we have a pointer to user space data or not. */ -+ if(extra_size == 0) { -+ /* No extra arguments. Trivial to handle */ -+ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u)); -+ } else { -+ char * extra; -+ int err; -+ -+ /* Check what user space is giving us */ -+ if(IW_IS_SET(cmd)) { -+ /* Check NULL pointer */ -+ if((iwr->u.data.pointer == NULL) && -+ (iwr->u.data.length != 0)) -+ return -EFAULT; -+ -+ /* Does it fits within bounds ? */ -+ if(iwr->u.data.length > (descr->set_args & -+ IW_PRIV_SIZE_MASK)) -+ return -E2BIG; -+ } else { -+ /* Check NULL pointer */ -+ if(iwr->u.data.pointer == NULL) -+ return -EFAULT; -+ } -+ -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Malloc %d bytes\n", extra_size); -+#endif /* WE_IOCTL_DEBUG */ -+ -+ /* Always allocate for max space. Easier, and won't last -+ * long... */ -+ extra = kmalloc(extra_size, GFP_KERNEL); -+ if (extra == NULL) { -+ return -ENOMEM; -+ } -+ -+ /* If it is a SET, get all the extra data in here */ -+ if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) { -+ err = copy_from_user(extra, iwr->u.data.pointer, -+ extra_size); -+ if (err) { -+ kfree(extra); -+ return -EFAULT; -+ } -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length); -+#endif /* WE_IOCTL_DEBUG */ -+ } -+ -+ /* Call the handler */ -+ ret = handler(dev, &info, &(iwr->u), extra); -+ -+ /* If we have something to return to the user */ -+ if (!ret && IW_IS_GET(cmd)) { -+ err = copy_to_user(iwr->u.data.pointer, extra, -+ extra_size); -+ if (err) -+ ret = -EFAULT; -+#ifdef WE_IOCTL_DEBUG -+ printk(KERN_DEBUG "Wrote %d elem\n", -+ iwr->u.data.length); -+#endif /* WE_IOCTL_DEBUG */ -+ } -+ -+ /* Cleanup - I told you it wasn't that long ;-) */ -+ kfree(extra); -+ } -+ -+ -+ /* Call commit handler if needed and defined */ -+ if(ret == -EIWCOMMIT) -+ ret = call_commit_handler(dev); -+ -+ return ret; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Main IOCTl dispatcher. Called from the main networking code -+ * (dev_ioctl() in net/core/dev.c). -+ * Check the type of IOCTL and call the appropriate wrapper... -+ */ -+int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd) -+{ -+ struct net_device *dev; -+ iw_handler handler; -+ -+ /* Permissions are already checked in dev_ioctl() before calling us. -+ * The copy_to/from_user() of ifr is also dealt with in there */ -+ -+ /* Make sure the device exist */ -+ if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL) -+ return -ENODEV; -+ -+ /* A bunch of special cases, then the generic case... -+ * Note that 'cmd' is already filtered in dev_ioctl() with -+ * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */ -+ switch(cmd) -+ { -+ case SIOCGIWSTATS: -+ /* Get Wireless Stats */ -+ return dev_iwstats(dev, ifr); -+ -+ case SIOCGIWPRIV: -+ /* Check if we have some wireless handlers defined */ -+ if(dev->wireless_handlers != NULL) { -+ /* We export to user space the definition of -+ * the private handler ourselves */ -+ return ioctl_export_private(dev, ifr); -+ } -+ // ## Fall-through for old API ## -+ default: -+ /* Generic IOCTL */ -+ /* Basic check */ -+ if (!netif_device_present(dev)) -+ return -ENODEV; -+ /* New driver API : try to find the handler */ -+ handler = get_handler(dev, cmd); -+ if(handler != NULL) { -+ /* Standard and private are not the same */ -+ if(cmd < SIOCIWFIRSTPRIV) -+ return ioctl_standard_call(dev, -+ ifr, -+ cmd, -+ handler); -+ else -+ return ioctl_private_call(dev, -+ ifr, -+ cmd, -+ handler); -+ } -+ /* Old driver API : call driver ioctl handler */ -+ if (dev->do_ioctl) { -+ return dev->do_ioctl(dev, ifr, cmd); -+ } -+ return -EOPNOTSUPP; -+ } -+ /* Not reached */ -+ return -EINVAL; -+} diff --git a/recipes/linux/files/iw_handlers.w14-5.diff b/recipes/linux/files/iw_handlers.w14-5.diff deleted file mode 100644 index 539b160068..0000000000 --- a/recipes/linux/files/iw_handlers.w14-5.diff +++ /dev/null @@ -1,838 +0,0 @@ -diff -u -p -r --new-file linux/include/linux-w13/rtnetlink.h linux/include/linux/rtnetlink.h ---- linux/include/linux-w13/rtnetlink.h Thu Jun 6 14:44:08 2002 -+++ linux/include/linux/rtnetlink.h Thu Jun 6 15:47:44 2002 -@@ -440,12 +440,14 @@ enum - #define IFLA_COST IFLA_COST - IFLA_PRIORITY, - #define IFLA_PRIORITY IFLA_PRIORITY -- IFLA_MASTER -+ IFLA_MASTER, - #define IFLA_MASTER IFLA_MASTER -+ IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ -+#define IFLA_WIRELESS IFLA_WIRELESS - }; - - --#define IFLA_MAX IFLA_MASTER -+#define IFLA_MAX IFLA_WIRELESS - - #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) - #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) -diff -u -p -r --new-file linux/include/linux-w13/wireless.h linux/include/linux/wireless.h ---- linux/include/linux-w13/wireless.h Thu Jun 6 15:00:28 2002 -+++ linux/include/linux/wireless.h Thu Jun 6 15:47:44 2002 -@@ -1,10 +1,10 @@ - /* - * This file define a set of standard wireless extensions - * -- * Version : 13 6.12.01 -+ * Version : 14 25.1.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _LINUX_WIRELESS_H -@@ -40,7 +40,7 @@ - * # include/linux/netdevice.h (one place) - * # include/linux/proc_fs.h (one place) - * -- * New driver API (2001 -> onward) : -+ * New driver API (2002 -> onward) : - * ------------------------------- - * This file is only concerned with the user space API and common definitions. - * The new driver API is defined and documented in : -@@ -49,6 +49,11 @@ - * Note as well that /proc/net/wireless implementation has now moved in : - * # include/linux/wireless.c - * -+ * Wireless Events (2002 -> onward) : -+ * -------------------------------- -+ * Events are defined at the end of this file, and implemented in : -+ * # include/linux/wireless.c -+ * - * Other comments : - * -------------- - * Do not add here things that are redundant with other mechanisms -@@ -75,7 +80,7 @@ - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ --#define WIRELESS_EXT 13 -+#define WIRELESS_EXT 14 - - /* - * Changes : -@@ -141,6 +146,13 @@ - * - Document creation of new driver API. - * - Extract union iwreq_data from struct iwreq (for new driver API). - * - Rename SIOCSIWNAME as SIOCSIWCOMMIT -+ * -+ * V13 to V14 -+ * ---------- -+ * - Wireless Events support : define struct iw_event -+ * - Define additional specific event numbers -+ * - Add "addr" and "param" fields in union iwreq_data -+ * - AP scanning stuff (SIOCSIWSCAN and friends) - */ - - /**************************** CONSTANTS ****************************/ -@@ -175,6 +187,8 @@ - #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ - #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ - #define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */ -+#define SIOCSIWSCAN 0x8B18 /* trigger scanning */ -+#define SIOCGIWSCAN 0x8B19 /* get scanning results */ - - /* 802.11 specific support */ - #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ -@@ -238,6 +252,15 @@ - #define IW_IS_SET(cmd) (!((cmd) & 0x1)) - #define IW_IS_GET(cmd) ((cmd) & 0x1) - -+/* ----------------------- WIRELESS EVENTS ----------------------- */ -+/* Those are *NOT* ioctls, do not issue request on them !!! */ -+/* Most events use the same identifier as ioctl requests */ -+ -+#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ -+#define IWEVQUAL 0x8C01 /* Quality part of statistics */ -+ -+#define IWEVFIRST 0x8C00 -+ - /* ------------------------- PRIVATE INFO ------------------------- */ - /* - * The following is used with SIOCGIWPRIV. It allow a driver to define -@@ -340,6 +363,19 @@ - #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ - #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -+/* Scanning request flags */ -+#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ -+#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ -+#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ -+#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ -+#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ -+#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ -+#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ -+#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ -+#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ -+/* Maximum size of returned data */ -+#define IW_SCAN_MAX_DATA 4096 /* In bytes */ -+ - /****************************** TYPES ******************************/ - - /* --------------------------- SUBTYPES --------------------------- */ -@@ -466,9 +502,12 @@ union iwreq_data - - struct iw_point encoding; /* Encoding stuff : tokens */ - struct iw_param power; /* PM duration/timeout */ -+ struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ -+ struct sockaddr addr; /* Destination address (hw) */ - -+ struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ - }; - -@@ -595,5 +634,36 @@ struct iw_priv_args - __u16 get_args; /* Type and number of args */ - char name[IFNAMSIZ]; /* Name of the extension */ - }; -+ -+/* ----------------------- WIRELESS EVENTS ----------------------- */ -+/* -+ * Wireless events are carried through the rtnetlink socket to user -+ * space. They are encapsulated in the IFLA_WIRELESS field of -+ * a RTM_NEWLINK message. -+ */ -+ -+/* -+ * A Wireless Event. Contains basically the same data as the ioctl... -+ */ -+struct iw_event -+{ -+ __u16 len; /* Real lenght of this stuff */ -+ __u16 cmd; /* Wireless IOCTL */ -+ union iwreq_data u; /* IOCTL fixed payload */ -+}; -+ -+/* Size of the Event prefix (including padding and alignement junk) */ -+#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) -+/* Size of the various events */ -+#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) -+#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) -+#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) -+#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point)) -+#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) -+#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) -+#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) -+ -+/* Note : in the case of iw_point, the extra data will come at the -+ * end of the event */ - - #endif /* _LINUX_WIRELESS_H */ -diff -u -p -r --new-file linux/include/net-w13/iw_handler.h linux/include/net/iw_handler.h ---- linux/include/net-w13/iw_handler.h Thu Jun 6 15:06:16 2002 -+++ linux/include/net/iw_handler.h Thu Jun 6 15:48:06 2002 -@@ -1,10 +1,10 @@ - /* - * This file define the new driver API for Wireless Extensions - * -- * Version : 2 6.12.01 -+ * Version : 3 17.1.02 - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved. - */ - - #ifndef _IW_HANDLER_H -@@ -33,7 +33,7 @@ - * o The user space interface is tied to ioctl because of the use - * copy_to/from_user. - * -- * New driver API (2001 -> onward) : -+ * New driver API (2002 -> onward) : - * ------------------------------- - * The new driver API is just a bunch of standard functions (handlers), - * each handling a specific Wireless Extension. The driver just export -@@ -206,7 +206,18 @@ - * will be needed... - * I just plan to increment with each new version. - */ --#define IW_HANDLER_VERSION 2 -+#define IW_HANDLER_VERSION 3 -+ -+/* -+ * Changes : -+ * -+ * V2 to V3 -+ * -------- -+ * - Move event definition in <linux/wireless.h> -+ * - Add Wireless Event support : -+ * o wireless_send_event() prototype -+ * o iwe_stream_add_event/point() inline functions -+ */ - - /**************************** CONSTANTS ****************************/ - -@@ -225,6 +236,7 @@ - #define IW_HEADER_TYPE_POINT 6 /* struct iw_point */ - #define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */ - #define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */ -+#define IW_HEADER_TYPE_QUAL 9 /* struct iw_quality */ - - /* Handling flags */ - /* Most are not implemented. I just use them as a reminder of some -@@ -233,7 +245,8 @@ - /* Wrapper level flags */ - #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */ - #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ --#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */ -+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ -+ /* SET : Omit payload from generated iwevent */ - /* Driver level flags */ - #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ - -@@ -303,25 +316,6 @@ struct iw_handler_def - * 'struct net_device' to here, to minimise bloat. */ - }; - --/* ----------------------- WIRELESS EVENTS ----------------------- */ --/* -- * Currently we don't support events, so let's just plan for the -- * future... -- */ -- --/* -- * A Wireless Event. -- */ --// How do we define short header ? We don't want a flag on length. --// Probably a flag on event ? Highest bit to zero... --struct iw_event --{ -- __u16 length; /* Lenght of this stuff */ -- __u16 event; /* Wireless IOCTL */ -- union iwreq_data header; /* IOCTL fixed payload */ -- char extra[0]; /* Optional IOCTL data */ --}; -- - /* ---------------------- IOCTL DESCRIPTION ---------------------- */ - /* - * One of the main goal of the new interface is to deal entirely with -@@ -369,6 +363,88 @@ extern int dev_get_wireless_info(char * - extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); - - /* Second : functions that may be called by driver modules */ --/* None yet */ - --#endif /* _LINUX_WIRELESS_H */ -+/* Send a single event to user space */ -+extern void wireless_send_event(struct net_device * dev, -+ unsigned int cmd, -+ union iwreq_data * wrqu, -+ char * extra); -+ -+/* We may need a function to send a stream of events to user space. -+ * More on that later... */ -+ -+/************************* INLINE FUNTIONS *************************/ -+/* -+ * Function that are so simple that it's more efficient inlining them -+ */ -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add an Wireless Event to a stream of events. -+ */ -+static inline char * -+iwe_stream_add_event(char * stream, /* Stream of events */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ int event_len) /* Real size of payload */ -+{ -+ /* Check if it's possible */ -+ if((stream + event_len) < ends) { -+ iwe->len = event_len; -+ memcpy(stream, (char *) iwe, event_len); -+ stream += event_len; -+ } -+ return stream; -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add an short Wireless Event containing a pointer to a -+ * stream of events. -+ */ -+static inline char * -+iwe_stream_add_point(char * stream, /* Stream of events */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ char * extra) -+{ -+ int event_len = IW_EV_POINT_LEN + iwe->u.data.length; -+ /* Check if it's possible */ -+ if((stream + event_len) < ends) { -+ iwe->len = event_len; -+ memcpy(stream, (char *) iwe, IW_EV_POINT_LEN); -+ memcpy(stream + IW_EV_POINT_LEN, extra, iwe->u.data.length); -+ stream += event_len; -+ } -+ return stream; -+} -+ -+/*------------------------------------------------------------------*/ -+/* -+ * Wrapper to add a value to a Wireless Event in a stream of events. -+ * Be careful, this one is tricky to use properly : -+ * At the first run, you need to have (value = event + IW_EV_LCP_LEN). -+ */ -+static inline char * -+iwe_stream_add_value(char * event, /* Event in the stream */ -+ char * value, /* Value in event */ -+ char * ends, /* End of stream */ -+ struct iw_event *iwe, /* Payload */ -+ int event_len) /* Real size of payload */ -+{ -+ /* Don't duplicate LCP */ -+ event_len -= IW_EV_LCP_LEN; -+ -+ /* Check if it's possible */ -+ if((value + event_len) < ends) { -+ /* Add new value */ -+ memcpy(value, (char *) iwe + IW_EV_LCP_LEN, event_len); -+ value += event_len; -+ /* Patch LCP */ -+ iwe->len = value - event; -+ memcpy(event, (char *) iwe, IW_EV_LCP_LEN); -+ } -+ return value; -+} -+ -+#endif /* _IW_HANDLER_H */ -diff -u -p -r --new-file linux/net/netsyms-w13.c linux/net/netsyms.c ---- linux/net/netsyms-w13.c Thu Jun 6 15:46:34 2002 -+++ linux/net/netsyms.c Thu Jun 6 15:47:44 2002 -@@ -588,4 +588,10 @@ EXPORT_SYMBOL(register_gifconf); - EXPORT_SYMBOL(net_call_rx_atomic); - EXPORT_SYMBOL(softnet_data); - -+#if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO) -+/* Don't include the whole header mess for a single function */ -+extern void wireless_send_event(struct net_device *dev, unsigned int cmd, union iwreq_data *wrqu, char *extra); -+EXPORT_SYMBOL(wireless_send_event); -+#endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */ -+ - #endif /* CONFIG_NET */ -diff -u -p -r --new-file linux/net/core/wireless-w13.c linux/net/core/wireless.c ---- linux/net/core/wireless-w13.c Thu Jun 6 15:46:45 2002 -+++ linux/net/core/wireless.c Thu Jun 6 15:48:06 2002 -@@ -2,7 +2,7 @@ - * This file implement the Wireless Extensions APIs. - * - * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> -- * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved. -+ * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved. - * - * (As all part of the Linux kernel, this file is GPL) - */ -@@ -25,6 +25,16 @@ - * o Added iw_handler handling ;-) - * o Added standard ioctl description - * o Initial dumb commit strategy based on orinoco.c -+ * -+ * v3 - 19.12.01 - Jean II -+ * o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call -+ * o Add event dispatcher function -+ * o Add event description -+ * o Propagate events as rtnetlink IFLA_WIRELESS option -+ * o Generate event on selected SET requests -+ * -+ * v4 - 18.04.01 - Jean II -+ * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 - */ - - /***************************** INCLUDES *****************************/ -@@ -33,6 +43,7 @@ - #include <linux/config.h> /* Not needed ??? */ - #include <linux/types.h> /* off_t */ - #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ -+#include <linux/rtnetlink.h> /* rtnetlink stuff */ - - #include <linux/wireless.h> /* Pretty obvious */ - #include <net/iw_handler.h> /* New driver API */ -@@ -44,14 +55,23 @@ - - /* Debuging stuff */ - #undef WE_IOCTL_DEBUG /* Debug IOCTL API */ -+#undef WE_EVENT_DEBUG /* Debug Event dispatcher */ -+ -+/* Options */ -+#define WE_EVENT_NETLINK /* Propagate events using rtnetlink */ -+#define WE_SET_EVENT /* Generate an event on some set commands */ - - /************************* GLOBAL VARIABLES *************************/ - /* - * You should not use global variables, because or re-entrancy. - * On our case, it's only const, so it's OK... - */ -+/* -+ * Meta-data about all the standard Wireless Extension request we -+ * know about. -+ */ - static const struct iw_ioctl_description standard_ioctl[] = { -- /* SIOCSIWCOMMIT (internal) */ -+ /* SIOCSIWCOMMIT */ - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* SIOCGIWNAME */ - { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP}, -@@ -99,18 +119,18 @@ static const struct iw_ioctl_description - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* SIOCGIWAPLIST */ - { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -- /* -- hole -- */ -- { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, -+ /* SIOCSIWSCAN */ -+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, -+ /* SIOCGIWSCAN */ -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_SCAN_MAX_DATA, 0}, - /* SIOCSIWESSID */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_EVENT}, - /* SIOCGIWESSID */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, IW_DESCR_FLAG_DUMP}, - /* SIOCSIWNICKN */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0}, - /* SIOCGIWNICKN */ -- { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE + 1, 0}, - /* -- hole -- */ - { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0}, - /* -- hole -- */ -@@ -136,7 +156,7 @@ static const struct iw_ioctl_description - /* SIOCGIWRETRY */ - { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, - /* SIOCSIWENCODE */ -- { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT}, -+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT}, - /* SIOCGIWENCODE */ - { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT}, - /* SIOCSIWPOWER */ -@@ -144,9 +164,38 @@ static const struct iw_ioctl_description - /* SIOCGIWPOWER */ - { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0}, - }; -+static const int standard_ioctl_num = (sizeof(standard_ioctl) / -+ sizeof(struct iw_ioctl_description)); -+ -+/* -+ * Meta-data about all the additional standard Wireless Extension events -+ * we know about. -+ */ -+static const struct iw_ioctl_description standard_event[] = { -+ /* IWEVTXDROP */ -+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0}, -+ /* IWEVQUAL */ -+ { IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0}, -+}; -+static const int standard_event_num = (sizeof(standard_event) / -+ sizeof(struct iw_ioctl_description)); - - /* Size (in bytes) of the various private data types */ --char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+static const char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 }; -+ -+/* Size (in bytes) of various events */ -+static const int event_type_size[] = { -+ IW_EV_LCP_LEN, -+ 0, -+ IW_EV_CHAR_LEN, -+ 0, -+ IW_EV_UINT_LEN, -+ IW_EV_FREQ_LEN, -+ IW_EV_POINT_LEN, /* Without variable payload */ -+ IW_EV_PARAM_LEN, -+ IW_EV_ADDR_LEN, -+ IW_EV_QUAL_LEN, -+}; - - /************************ COMMON SUBROUTINES ************************/ - /* -@@ -162,7 +211,8 @@ char priv_type_size[] = { 0, 1, 1, 0, 4, - static inline iw_handler get_handler(struct net_device *dev, - unsigned int cmd) - { -- unsigned int index; /* MUST be unsigned */ -+ /* Don't "optimise" the following variable, it will crash */ -+ unsigned int index; /* *MUST* be unsigned */ - - /* Check if we have some wireless handlers defined */ - if(dev->wireless_handlers == NULL) -@@ -269,9 +319,9 @@ static inline int sprintf_wireless_stats - stats->status, - stats->qual.qual, - stats->qual.updated & 1 ? '.' : ' ', -- stats->qual.level, -+ ((__u8) stats->qual.level), - stats->qual.updated & 2 ? '.' : ' ', -- stats->qual.noise, -+ ((__u8) stats->qual.noise), - stats->qual.updated & 4 ? '.' : ' ', - stats->discard.nwid, - stats->discard.code, -@@ -423,12 +473,14 @@ static inline int ioctl_standard_call(st - int ret = -EINVAL; - - /* Get the description of the IOCTL */ -+ if((cmd - SIOCIWFIRST) >= standard_ioctl_num) -+ return -EOPNOTSUPP; - descr = &(standard_ioctl[cmd - SIOCIWFIRST]); - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n", -+ printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n", - ifr->ifr_name, cmd); -- 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); -+ printk(KERN_DEBUG "%s (WE) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); - #endif /* WE_IOCTL_DEBUG */ - - /* Prepare the call */ -@@ -437,8 +489,16 @@ static inline int ioctl_standard_call(st - - /* Check if we have a pointer to user space data or not */ - if(descr->header_type != IW_HEADER_TYPE_POINT) { -+ - /* No extra arguments. Trivial to handle */ - ret = handler(dev, &info, &(iwr->u), NULL); -+ -+#ifdef WE_SET_EVENT -+ /* Generate an event to notify listeners of the change */ -+ if((descr->flags & IW_DESCR_FLAG_EVENT) && -+ ((ret == 0) || (ret == -EIWCOMMIT))) -+ wireless_send_event(dev, cmd, &(iwr->u), NULL); -+#endif /* WE_SET_EVENT */ - } else { - char * extra; - int err; -@@ -466,8 +526,8 @@ static inline int ioctl_standard_call(st - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Malloc %d bytes\n", -- descr->max_tokens * descr->token_size); -+ printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", -+ dev->name, descr->max_tokens * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - - /* Always allocate for max space. Easier, and won't last -@@ -488,7 +548,8 @@ static inline int ioctl_standard_call(st - return -EFAULT; - } - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Got %d bytes\n", -+ printk(KERN_DEBUG "%s (WE) : Got %d bytes\n", -+ dev->name, - iwr->u.data.length * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - } -@@ -504,11 +565,26 @@ static inline int ioctl_standard_call(st - if (err) - ret = -EFAULT; - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Wrote %d bytes\n", -+ printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n", -+ dev->name, - iwr->u.data.length * descr->token_size); - #endif /* WE_IOCTL_DEBUG */ - } - -+#ifdef WE_SET_EVENT -+ /* Generate an event to notify listeners of the change */ -+ if((descr->flags & IW_DESCR_FLAG_EVENT) && -+ ((ret == 0) || (ret == -EIWCOMMIT))) { -+ if(descr->flags & IW_DESCR_FLAG_RESTRICT) -+ /* If the event is restricted, don't -+ * export the payload */ -+ wireless_send_event(dev, cmd, &(iwr->u), NULL); -+ else -+ wireless_send_event(dev, cmd, &(iwr->u), -+ extra); -+ } -+#endif /* WE_SET_EVENT */ -+ - /* Cleanup - I told you it wasn't that long ;-) */ - kfree(extra); - } -@@ -558,11 +634,12 @@ static inline int ioctl_private_call(str - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n", -+ printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n", - ifr->ifr_name, cmd); - if(descr) { -- printk(KERN_DEBUG "Name %s, set %X, get %X\n", -- descr->name, descr->set_args, descr->get_args); -+ printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n", -+ dev->name, descr->name, -+ descr->set_args, descr->get_args); - } - #endif /* WE_IOCTL_DEBUG */ - -@@ -617,7 +694,8 @@ static inline int ioctl_private_call(str - } - - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Malloc %d bytes\n", extra_size); -+ printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n", -+ dev->name, extra_size); - #endif /* WE_IOCTL_DEBUG */ - - /* Always allocate for max space. Easier, and won't last -@@ -636,7 +714,8 @@ static inline int ioctl_private_call(str - return -EFAULT; - } - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length); -+ printk(KERN_DEBUG "%s (WE) : Got %d elem\n", -+ dev->name, iwr->u.data.length); - #endif /* WE_IOCTL_DEBUG */ - } - -@@ -650,8 +729,8 @@ static inline int ioctl_private_call(str - if (err) - ret = -EFAULT; - #ifdef WE_IOCTL_DEBUG -- printk(KERN_DEBUG "Wrote %d elem\n", -- iwr->u.data.length); -+ printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n", -+ dev->name, iwr->u.data.length); - #endif /* WE_IOCTL_DEBUG */ - } - -@@ -730,4 +809,178 @@ int wireless_process_ioctl(struct ifreq - } - /* Not reached */ - return -EINVAL; -+} -+ -+/************************* EVENT PROCESSING *************************/ -+/* -+ * Process events generated by the wireless layer or the driver. -+ * Most often, the event will be propagated through rtnetlink -+ */ -+ -+#ifdef WE_EVENT_NETLINK -+/* "rtnl" is defined in net/core/rtnetlink.c, but we need it here. -+ * It is declared in <linux/rtnetlink.h> */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Fill a rtnetlink message with our event data. -+ * Note that we propage only the specified event and don't dump the -+ * current wireless config. Dumping the wireless config is far too -+ * expensive (for each parameter, the driver need to query the hardware). -+ */ -+static inline int rtnetlink_fill_iwinfo(struct sk_buff * skb, -+ struct net_device * dev, -+ int type, -+ char * event, -+ int event_len) -+{ -+ struct ifinfomsg *r; -+ struct nlmsghdr *nlh; -+ unsigned char *b = skb->tail; -+ -+ nlh = NLMSG_PUT(skb, 0, 0, type, sizeof(*r)); -+ r = NLMSG_DATA(nlh); -+ r->ifi_family = AF_UNSPEC; -+ r->ifi_type = dev->type; -+ r->ifi_index = dev->ifindex; -+ r->ifi_flags = dev->flags; -+ r->ifi_change = 0; /* Wireless changes don't affect those flags */ -+ -+ /* Add the wireless events in the netlink packet */ -+ RTA_PUT(skb, IFLA_WIRELESS, -+ event_len, event); -+ -+ nlh->nlmsg_len = skb->tail - b; -+ return skb->len; -+ -+nlmsg_failure: -+rtattr_failure: -+ skb_trim(skb, b - skb->data); -+ return -1; -+} -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Create and broadcast and send it on the standard rtnetlink socket -+ * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c -+ * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field -+ * within a RTM_NEWLINK event. -+ */ -+static inline void rtmsg_iwinfo(struct net_device * dev, -+ char * event, -+ int event_len) -+{ -+ struct sk_buff *skb; -+ int size = NLMSG_GOODSIZE; -+ -+ skb = alloc_skb(size, GFP_ATOMIC); -+ if (!skb) -+ return; -+ -+ if (rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, -+ event, event_len) < 0) { -+ kfree_skb(skb); -+ return; -+ } -+ NETLINK_CB(skb).dst_groups = RTMGRP_LINK; -+ netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_ATOMIC); -+} -+#endif /* WE_EVENT_NETLINK */ -+ -+/* ---------------------------------------------------------------- */ -+/* -+ * Main event dispatcher. Called from other parts and drivers. -+ * Send the event on the apropriate channels. -+ * May be called from interrupt context. -+ */ -+void wireless_send_event(struct net_device * dev, -+ unsigned int cmd, -+ union iwreq_data * wrqu, -+ char * extra) -+{ -+ const struct iw_ioctl_description * descr = NULL; -+ int extra_len = 0; -+ struct iw_event *event; /* Mallocated whole event */ -+ int event_len; /* Its size */ -+ int hdr_len; /* Size of the event header */ -+ /* Don't "optimise" the following variable, it will crash */ -+ unsigned cmd_index; /* *MUST* be unsigned */ -+ -+ /* Get the description of the IOCTL */ -+ if(cmd <= SIOCIWLAST) { -+ cmd_index = cmd - SIOCIWFIRST; -+ if(cmd_index < standard_ioctl_num) -+ descr = &(standard_ioctl[cmd_index]); -+ } else { -+ cmd_index = cmd - IWEVFIRST; -+ if(cmd_index < standard_event_num) -+ descr = &(standard_event[cmd_index]); -+ } -+ /* Don't accept unknown events */ -+ if(descr == NULL) { -+ /* Note : we don't return an error to the driver, because -+ * the driver would not know what to do about it. It can't -+ * return an error to the user, because the event is not -+ * initiated by a user request. -+ * The best the driver could do is to log an error message. -+ * We will do it ourselves instead... -+ */ -+ printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n", -+ dev->name, cmd); -+ return; -+ } -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Got event 0x%04X\n", -+ dev->name, cmd); -+ printk(KERN_DEBUG "%s (WE) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens); -+#endif /* WE_EVENT_DEBUG */ -+ -+ /* Check extra parameters and set extra_len */ -+ if(descr->header_type == IW_HEADER_TYPE_POINT) { -+ /* Check if number of token fits within bounds */ -+ if(wrqu->data.length > descr->max_tokens) { -+ printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length); -+ return; -+ } -+ if(wrqu->data.length < descr->min_tokens) { -+ printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length); -+ return; -+ } -+ /* Calculate extra_len - extra is NULL for restricted events */ -+ if(extra != NULL) -+ extra_len = wrqu->data.length * descr->token_size; -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Event 0x%04X, tokens %d, extra_len %d\n", dev->name, cmd, wrqu->data.length, extra_len); -+#endif /* WE_EVENT_DEBUG */ -+ } -+ -+ /* Total length of the event */ -+ hdr_len = event_type_size[descr->header_type]; -+ event_len = hdr_len + extra_len; -+ -+#ifdef WE_EVENT_DEBUG -+ printk(KERN_DEBUG "%s (WE) : Event 0x%04X, hdr_len %d, event_len %d\n", dev->name, cmd, hdr_len, event_len); -+#endif /* WE_EVENT_DEBUG */ -+ -+ /* Create temporary buffer to hold the event */ -+ event = kmalloc(event_len, GFP_ATOMIC); -+ if(event == NULL) -+ return; -+ -+ /* Fill event */ -+ event->len = event_len; -+ event->cmd = cmd; -+ memcpy(&event->u, wrqu, hdr_len - IW_EV_LCP_LEN); -+ if(extra != NULL) -+ memcpy(((char *) event) + hdr_len, extra, extra_len); -+ -+#ifdef WE_EVENT_NETLINK -+ /* rtnetlink event channel */ -+ rtmsg_iwinfo(dev, (char *) event, event_len); -+#endif /* WE_EVENT_NETLINK */ -+ -+ /* Cleanup */ -+ kfree(event); -+ -+ return; /* Always success, I guess ;-) */ - } diff --git a/recipes/linux/files/linux-2.4.18-list_move.patch b/recipes/linux/files/linux-2.4.18-list_move.patch deleted file mode 100644 index faec56330b..0000000000 --- a/recipes/linux/files/linux-2.4.18-list_move.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- linux/include/linux/list.h~ 2001-12-21 17:42:03.000000000 +0000 -+++ linux/include/linux/list.h 2004-06-14 23:41:33.000000000 +0100 -@@ -105,6 +105,29 @@ - } - - /** -+ * list_move - delete from one list and add as another's head -+ * @list: the entry to move -+ * @head: the head that will precede our entry -+ */ -+static inline void list_move(struct list_head *list, struct list_head *head) -+{ -+ __list_del(list->prev, list->next); -+ list_add(list, head); -+} -+ -+/** -+ * list_move_tail - delete from one list and add as another's tail -+ * @list: the entry to move -+ * @head: the head that will follow our entry -+ */ -+static inline void list_move_tail(struct list_head *list, -+ struct list_head *head) -+{ -+ __list_del(list->prev, list->next); -+ list_add_tail(list, head); -+} -+ -+/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ |