linux/drivers/staging/wlags49_h2/wl_util.c
<<
>>
Prefs
   1/*******************************************************************************
   2 * Agere Systems Inc.
   3 * Wireless device driver for Linux (wlags49).
   4 *
   5 * Copyright (c) 1998-2003 Agere Systems Inc.
   6 * All rights reserved.
   7 *   http://www.agere.com
   8 *
   9 * Initially developed by TriplePoint, Inc.
  10 *   http://www.triplepoint.com
  11 *
  12 *------------------------------------------------------------------------------
  13 *
  14 *   This file defines misc utility functions.
  15 *
  16 *------------------------------------------------------------------------------
  17 *
  18 * SOFTWARE LICENSE
  19 *
  20 * This software is provided subject to the following terms and conditions,
  21 * which you should read carefully before using the software.  Using this
  22 * software indicates your acceptance of these terms and conditions.  If you do
  23 * not agree with these terms and conditions, do not use the software.
  24 *
  25 * Copyright © 2003 Agere Systems Inc.
  26 * All rights reserved.
  27 *
  28 * Redistribution and use in source or binary forms, with or without
  29 * modifications, are permitted provided that the following conditions are met:
  30 *
  31 * . Redistributions of source code must retain the above copyright notice, this
  32 *    list of conditions and the following Disclaimer as comments in the code as
  33 *    well as in the documentation and/or other materials provided with the
  34 *    distribution.
  35 *
  36 * . Redistributions in binary form must reproduce the above copyright notice,
  37 *    this list of conditions and the following Disclaimer in the documentation
  38 *    and/or other materials provided with the distribution.
  39 *
  40 * . Neither the name of Agere Systems Inc. nor the names of the contributors
  41 *    may be used to endorse or promote products derived from this software
  42 *    without specific prior written permission.
  43 *
  44 * Disclaimer
  45 *
  46 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
  47 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
  48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
  49 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
  50 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
  51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  54 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
  55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  57 * DAMAGE.
  58 *
  59 ******************************************************************************/
  60
  61/*******************************************************************************
  62 *  include files
  63 ******************************************************************************/
  64#include <wl_version.h>
  65
  66#include <linux/kernel.h>
  67// #include <linux/sched.h>
  68// #include <linux/ptrace.h>
  69#include <linux/ctype.h>
  70// #include <linux/string.h>
  71// #include <linux/timer.h>
  72// #include <linux/interrupt.h>
  73// #include <linux/in.h>
  74// #include <linux/delay.h>
  75// #include <asm/io.h>
  76// // #include <asm/bitops.h>
  77
  78#include <linux/netdevice.h>
  79#include <linux/etherdevice.h>
  80// #include <linux/skbuff.h>
  81// #include <linux/if_arp.h>
  82// #include <linux/ioport.h>
  83
  84#include <debug.h>
  85#include <hcf.h>
  86// #include <hcfdef.h>
  87
  88#include <wl_if.h>
  89#include <wl_internal.h>
  90#include <wl_util.h>
  91#include <wl_wext.h>
  92#include <wl_main.h>
  93
  94
  95
  96/*******************************************************************************
  97 * global variables
  98 ******************************************************************************/
  99
 100/* A matrix which maps channels to frequencies */
 101static const long chan_freq_list[][2] =
 102{
 103    {1,2412},
 104    {2,2417},
 105    {3,2422},
 106    {4,2427},
 107    {5,2432},
 108    {6,2437},
 109    {7,2442},
 110    {8,2447},
 111    {9,2452},
 112    {10,2457},
 113    {11,2462},
 114    {12,2467},
 115    {13,2472},
 116    {14,2484},
 117    {36,5180},
 118    {40,5200},
 119    {44,5220},
 120    {48,5240},
 121    {52,5260},
 122    {56,5280},
 123    {60,5300},
 124    {64,5320},
 125    {149,5745},
 126    {153,5765},
 127    {157,5785},
 128    {161,5805}
 129};
 130
 131#if DBG
 132extern dbg_info_t *DbgInfo;
 133#endif  /* DBG */
 134
 135
 136
 137
 138/*******************************************************************************
 139 *      dbm()
 140 *******************************************************************************
 141 *
 142 *  DESCRIPTION:
 143 *
 144 *      Return an energy value in dBm.
 145 *
 146 *  PARAMETERS:
 147 *
 148 *      value - the energy value to be converted
 149 *
 150 *  RETURNS:
 151 *
 152 *      the value in dBm
 153 *
 154 ******************************************************************************/
 155int dbm( int value )
 156{
 157    /* Truncate the value to be between min and max. */
 158    if( value < HCF_MIN_SIGNAL_LEVEL )
 159        value = HCF_MIN_SIGNAL_LEVEL;
 160
 161    if( value > HCF_MAX_SIGNAL_LEVEL )
 162        value = HCF_MAX_SIGNAL_LEVEL;
 163
 164    /* Return the energy value in dBm. */
 165    return ( value - HCF_0DBM_OFFSET );
 166} // dbm
 167/*============================================================================*/
 168
 169
 170
 171
 172/*******************************************************************************
 173 *      percent()
 174 *******************************************************************************
 175 *
 176 *  DESCRIPTION:
 177 *
 178 *      Return a value as a percentage of min to max.
 179 *
 180 *  PARAMETERS:
 181 *
 182 *      value   - the value in question
 183 *      min     - the minimum range value
 184 *      max     - the maximum range value
 185 *
 186 *  RETURNS:
 187 *
 188 *      the percentage value
 189 *
 190 ******************************************************************************/
 191int percent( int value, int min, int max )
 192{
 193    /* Truncate the value to be between min and max. */
 194    if( value < min )
 195        value = min;
 196
 197    if( value > max )
 198        value = max;
 199
 200    /* Return the value as a percentage of min to max. */
 201    return ((( value - min ) * 100 ) / ( max - min ));
 202} // percent
 203/*============================================================================*/
 204
 205
 206
 207
 208/*******************************************************************************
 209 *      is_valid_key_string()
 210 *******************************************************************************
 211 *
 212 *  DESCRIPTION:
 213 *
 214 *      Checks to determine if the WEP key string is valid
 215 *
 216 *  PARAMETERS:
 217 *
 218 *      s - the string in question
 219 *
 220 *  RETURNS:
 221 *
 222 *      non-zero if the string contains a valid key
 223 *
 224 ******************************************************************************/
 225int is_valid_key_string( char *s )
 226{
 227    int l;
 228    int i;
 229    /*------------------------------------------------------------------------*/
 230
 231
 232    l = strlen( s );
 233
 234    /* 0x followed by 5 or 13 hexadecimal digit pairs is valid */
 235    if( s[0] == '0' && ( s[1] == 'x' || s[1] == 'X' )) {
 236        if( l == 12 || l == 28 ) {
 237            for( i = 2; i < l; i++ ) {
 238                if( !isxdigit( s[i] ))
 239                    return 0;
 240            }
 241
 242            return 1;
 243        } else {
 244            return 0;
 245        }
 246    }
 247
 248    /* string with 0, 5, or 13 characters is valid */
 249    else
 250    {
 251        return( l == 0 || l == 5 || l == 13 );
 252    }
 253} // is_valid_key_string
 254/*============================================================================*/
 255
 256
 257
 258
 259/*******************************************************************************
 260 *      key_string2key()
 261 *******************************************************************************
 262 *
 263 *  DESCRIPTION:
 264 *
 265 *      Converts a key_string to a key, Assumes the key_string is validated with
 266 *  is_valid_key_string().
 267 *
 268 *  PARAMETERS:
 269 *
 270 *      ks  - the valid key string
 271 *      key - a pointer to a KEY_STRUCT where the converted key information will
 272 *            be stored.
 273 *
 274 *  RETURNS:
 275 *
 276 *      N/A
 277 *
 278 ******************************************************************************/
 279void key_string2key( char *ks, KEY_STRCT *key )
 280{
 281    int l,i,n;
 282    char *p;
 283    /*------------------------------------------------------------------------*/
 284
 285
 286    l = strlen( ks );
 287
 288    /* 0x followed by hexadecimal digit pairs */
 289    if( ks[0] == '0' && ( ks[1] == 'x' || ks[1] == 'X' )) {
 290        n = 0;
 291        p = (char *)key->key;
 292
 293        for( i = 2; i < l; i+=2 ) {
 294                        *p++ = (hex_to_bin(ks[i]) << 4) + hex_to_bin(ks[i+1]);
 295           n++;
 296        }
 297
 298        /* Note that endian translation of the length field is not needed here
 299          because it's performed in wl_put_ltv() */
 300        key->len = n;
 301    }
 302    /* character string */
 303    else
 304    {
 305        strcpy( (char *)key->key, ks );
 306        key->len = l;
 307    }
 308
 309    return;
 310} // key_string2key
 311/*============================================================================*/
 312
 313
 314
 315
 316/*******************************************************************************
 317 *      wl_has_wep()
 318 *******************************************************************************
 319 *
 320 *  DESCRIPTION:
 321 *
 322 *      Checks to see if the device supports WEP
 323 *
 324 *  PARAMETERS:
 325 *
 326 *      ifbp    - the IFB pointer of the device in question
 327 *
 328 *  RETURNS:
 329 *
 330 *      1 if WEP is known enabled, else 0
 331 *
 332 ******************************************************************************/
 333int wl_has_wep (IFBP ifbp)
 334{
 335    CFG_PRIVACY_OPT_IMPLEMENTED_STRCT ltv;
 336        int rc, privacy;
 337    /*------------------------------------------------------------------------*/
 338
 339
 340        /* This function allows us to distiguish bronze cards from other types, to
 341       know if WEP exists. Does not distinguish (because there's no way to)
 342       between silver and gold cards. */
 343    ltv.len = 2;
 344    ltv.typ = CFG_PRIVACY_OPT_IMPLEMENTED;
 345
 346        rc = hcf_get_info( ifbp, (LTVP) &ltv );
 347
 348        privacy = CNV_LITTLE_TO_INT( ltv.privacy_opt_implemented );
 349
 350        //return rc ? 0 : privacy;
 351    return 1;
 352} // wl_has_wep
 353/*============================================================================*/
 354
 355
 356
 357
 358/*******************************************************************************
 359 *      wl_hcf_error()
 360 *******************************************************************************
 361 *
 362 *  DESCRIPTION:
 363 *
 364 *      Report the type of HCF error message
 365 *
 366 *  PARAMETERS:
 367 *
 368 *      none
 369 *
 370 *  RETURNS:
 371 *
 372 *      A descriptive string indicating the error, quiet otherwise.
 373 *
 374 ******************************************************************************/
 375void wl_hcf_error( struct net_device *dev, int hcfStatus )
 376{
 377    char     buffer[64], *pMsg;
 378    /*------------------------------------------------------------------------*/
 379
 380
 381    if( hcfStatus != HCF_SUCCESS ) {
 382        switch( hcfStatus ) {
 383
 384        case HCF_ERR_TIME_OUT:
 385
 386            pMsg = "Expected adapter event did not occur in expected time";
 387            break;
 388
 389
 390        case HCF_ERR_NO_NIC:
 391
 392            pMsg = "Card not found (ejected unexpectedly)";
 393            break;
 394
 395
 396        case HCF_ERR_LEN:
 397
 398            pMsg = "Command buffer size insufficient";
 399            break;
 400
 401
 402        case HCF_ERR_INCOMP_PRI:
 403
 404            pMsg = "Primary functions are not compatible";
 405            break;
 406
 407
 408        case HCF_ERR_INCOMP_FW:
 409
 410            pMsg = "Primary functions are compatible, "
 411                "station/ap functions are not";
 412            break;
 413
 414
 415        case HCF_ERR_BUSY:
 416
 417            pMsg = "Inquire cmd while another Inquire in progress";
 418            break;
 419
 420
 421        //case HCF_ERR_SEQ_BUG:
 422
 423        //    pMsg = "Unexpected command completed";
 424        //    break;
 425
 426
 427        case HCF_ERR_DEFUNCT_AUX:
 428
 429            pMsg = "Timeout on ack for enable/disable of AUX registers";
 430            break;
 431
 432
 433        case HCF_ERR_DEFUNCT_TIMER:
 434            pMsg = "Timeout on timer calibration during initialization process";
 435            break;
 436
 437
 438        case HCF_ERR_DEFUNCT_TIME_OUT:
 439            pMsg = "Timeout on Busy bit drop during BAP setup";
 440            break;
 441
 442
 443        case HCF_ERR_DEFUNCT_CMD_SEQ:
 444            pMsg = "Hermes and HCF are out of sync";
 445            break;
 446
 447
 448        default:
 449
 450            sprintf( buffer, "Error code %d", hcfStatus );
 451            pMsg = buffer;
 452            break;
 453        }
 454
 455        printk( KERN_INFO "%s: Wireless, HCF failure: \"%s\"\n",
 456                dev->name, pMsg );
 457    }
 458} // wl_hcf_error
 459/*============================================================================*/
 460
 461
 462
 463
 464/*******************************************************************************
 465 *      wl_endian_translate_event()
 466 *******************************************************************************
 467 *
 468 *  DESCRIPTION:
 469 *
 470 *      Determines what type of data is in the mailbox and performs the proper
 471 *  endian translation.
 472 *
 473 *  PARAMETERS:
 474 *
 475 *      pLtv - an LTV pointer
 476 *
 477 *  RETURNS:
 478 *
 479 *      N/A
 480 *
 481 ******************************************************************************/
 482void wl_endian_translate_event( ltv_t *pLtv )
 483{
 484    DBG_FUNC( "wl_endian_translate_event" );
 485    DBG_ENTER( DbgInfo );
 486
 487
 488    switch( pLtv->typ ) {
 489    case CFG_TALLIES:
 490        break;
 491
 492
 493    case CFG_SCAN:
 494        {
 495            int numAPs;
 496            SCAN_RS_STRCT *pAps = (SCAN_RS_STRCT*)&pLtv->u.u8[0];
 497
 498            numAPs = (hcf_16)(( (size_t)( pLtv->len - 1 ) * 2 ) /
 499                                (sizeof( SCAN_RS_STRCT )));
 500
 501            while( numAPs >= 1 ) {
 502                numAPs--;
 503
 504                pAps[numAPs].channel_id           =
 505                    CNV_LITTLE_TO_INT( pAps[numAPs].channel_id );
 506
 507                pAps[numAPs].noise_level          =
 508                    CNV_LITTLE_TO_INT( pAps[numAPs].noise_level );
 509
 510                pAps[numAPs].signal_level         =
 511                    CNV_LITTLE_TO_INT( pAps[numAPs].signal_level );
 512
 513                pAps[numAPs].beacon_interval_time =
 514                    CNV_LITTLE_TO_INT( pAps[numAPs].beacon_interval_time );
 515
 516                pAps[numAPs].capability           =
 517                    CNV_LITTLE_TO_INT( pAps[numAPs].capability );
 518
 519                pAps[numAPs].ssid_len             =
 520                    CNV_LITTLE_TO_INT( pAps[numAPs].ssid_len );
 521
 522                pAps[numAPs].ssid_val[pAps[numAPs].ssid_len] = 0;
 523
 524            }
 525        }
 526        break;
 527
 528
 529    case CFG_ACS_SCAN:
 530        {
 531            PROBE_RESP *probe_resp = (PROBE_RESP *)pLtv;
 532
 533            probe_resp->frameControl   = CNV_LITTLE_TO_INT( probe_resp->frameControl );
 534            probe_resp->durID          = CNV_LITTLE_TO_INT( probe_resp->durID );
 535            probe_resp->sequence       = CNV_LITTLE_TO_INT( probe_resp->sequence );
 536            probe_resp->dataLength     = CNV_LITTLE_TO_INT( probe_resp->dataLength );
 537
 538#ifndef WARP
 539            probe_resp->lenType        = CNV_LITTLE_TO_INT( probe_resp->lenType );
 540#endif // WARP
 541
 542            probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
 543            probe_resp->capability     = CNV_LITTLE_TO_INT( probe_resp->capability );
 544            probe_resp->flags          = CNV_LITTLE_TO_INT( probe_resp->flags );
 545        }
 546        break;
 547
 548
 549    case CFG_LINK_STAT:
 550#define ls ((LINK_STATUS_STRCT *)pLtv)
 551            ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
 552        break;
 553#undef ls
 554
 555    case CFG_ASSOC_STAT:
 556        {
 557            ASSOC_STATUS_STRCT *pAs = (ASSOC_STATUS_STRCT *)pLtv;
 558
 559            pAs->assocStatus = CNV_LITTLE_TO_INT( pAs->assocStatus );
 560        }
 561        break;
 562
 563
 564    case CFG_SECURITY_STAT:
 565        {
 566            SECURITY_STATUS_STRCT *pSs = (SECURITY_STATUS_STRCT *)pLtv;
 567
 568            pSs->securityStatus = CNV_LITTLE_TO_INT( pSs->securityStatus );
 569            pSs->reason         = CNV_LITTLE_TO_INT( pSs->reason );
 570        }
 571        break;
 572
 573
 574    case CFG_WMP:
 575        break;
 576
 577
 578    case CFG_NULL:
 579        break;
 580
 581
 582    default:
 583        break;
 584    }
 585
 586    DBG_LEAVE( DbgInfo );
 587    return;
 588} // wl_endian_translate_event
 589/*============================================================================*/
 590
 591
 592/*******************************************************************************
 593 *      msf_assert()
 594 *******************************************************************************
 595 *
 596 *  DESCRIPTION:
 597 *
 598 *      Print statement used to display asserts from within the HCF. Only called
 599 *  when asserts in the HCF are turned on. See hcfcfg.h for more information.
 600 *
 601 *  PARAMETERS:
 602 *
 603 *      file_namep  - the filename in which the assert occurred.
 604 *      line_number - the line number on which the assert occurred.
 605 *      trace       - a comment associated with the assert.
 606 *      qual        - return code or other value related to the assert
 607 *
 608 *  RETURNS:
 609 *
 610 *      N/A
 611 *
 612 ******************************************************************************/
 613void msf_assert( unsigned int line_number, hcf_16 trace, hcf_32 qual )
 614{
 615    DBG_PRINT( "HCF ASSERT: Line %d, VAL: 0x%.8x\n", line_number, /*;?*/(u32)qual );
 616} // msf_assert
 617/*============================================================================*/
 618
 619
 620
 621
 622/*******************************************************************************
 623 *      wl_parse_ds_ie()
 624 *******************************************************************************
 625 *
 626 *  DESCRIPTION:
 627 *
 628 *      This function parses the Direct Sequence Parameter Set IE, used to
 629 *      determine channel/frequency information.
 630 *
 631 *  PARAMETERS:
 632 *
 633 *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
 634 *                  response.
 635 *
 636 *  RETURNS:
 637 *
 638 *      The channel on which the BSS represented by this probe response is
 639 *      transmitting.
 640 *
 641 ******************************************************************************/
 642hcf_8 wl_parse_ds_ie( PROBE_RESP *probe_rsp )
 643{
 644    int     i;
 645    int     ie_length = 0;
 646    hcf_8   *buf;
 647    hcf_8   buf_size;
 648    /*------------------------------------------------------------------------*/
 649
 650
 651    if( probe_rsp == NULL ) {
 652        return 0;
 653    }
 654
 655    buf      = probe_rsp->rawData;
 656    buf_size = sizeof( probe_rsp->rawData );
 657
 658
 659    for( i = 0; i < buf_size; i++ ) {
 660        if( buf[i] == DS_INFO_ELEM ) {
 661            /* Increment by 1 to get the length, and test it; in a DS element,
 662               length should always be 1 */
 663            i++;
 664            ie_length = buf[i];
 665
 666            if( buf[i] == 1 ) {
 667                /* Get the channel information */
 668                i++;
 669                return buf[i];
 670            }
 671        }
 672    }
 673
 674    /* If we get here, we didn't find a DS-IE, which is strange */
 675    return 0;
 676} // wl_parse_ds_ie
 677
 678
 679/*******************************************************************************
 680 *      wl_parse_wpa_ie()
 681 *******************************************************************************
 682 *
 683 *  DESCRIPTION:
 684 *
 685 *      This function parses the Probe Response for a valid WPA-IE.
 686 *
 687 *  PARAMETERS:
 688 *
 689 *      probe_rsp - a pointer to a PROBE_RESP structure containing the probe
 690 *                  response
 691 *      length    - a pointer to an hcf_16 in which the size of the WPA-IE will
 692 *                  be stored (if found).
 693 *
 694 *  RETURNS:
 695 *
 696 *      A pointer to the location in the probe response buffer where a valid
 697 *      WPA-IE lives. The length of this IE is written back to the 'length'
 698 *      argument passed to the function.
 699 *
 700 ******************************************************************************/
 701hcf_8 * wl_parse_wpa_ie( PROBE_RESP *probe_rsp, hcf_16 *length )
 702{
 703    int     i;
 704    int     ie_length = 0;
 705    hcf_8   *buf;
 706    hcf_8   buf_size;
 707    hcf_8   wpa_oui[] = WPA_OUI_TYPE;
 708    /*------------------------------------------------------------------------*/
 709
 710
 711    if( probe_rsp == NULL || length == NULL ) {
 712        return NULL;
 713    }
 714
 715    buf      = probe_rsp->rawData;
 716    buf_size = sizeof( probe_rsp->rawData );
 717    *length  = 0;
 718
 719
 720    for( i = 0; i < buf_size; i++ ) {
 721        if( buf[i] == GENERIC_INFO_ELEM ) {
 722            /* Increment by one to get the IE length */
 723            i++;
 724            ie_length = probe_rsp->rawData[i];
 725
 726            /* Increment by one to point to the IE payload */
 727            i++;
 728
 729            /* Does the IE contain a WPA OUI? If not, it's a proprietary IE */
 730            if( memcmp( &buf[i], &wpa_oui, WPA_SELECTOR_LEN ) == 0 ) {
 731                /* Pass back length and return a pointer to the WPA-IE */
 732                /* NOTE: Length contained in the WPA-IE is only the length of
 733                   the payload. The entire WPA-IE, including the IE identifier
 734                   and the length, is 2 bytes larger */
 735                *length = ie_length + 2;
 736
 737                /* Back up the pointer 2 bytes to include the IE identifier and
 738                   the length in the buffer returned */
 739                i -= 2;
 740                return &buf[i];
 741            }
 742
 743            /* Increment past this non-WPA IE and continue looking */
 744            i += ( ie_length - 1 );
 745        }
 746    }
 747
 748    /* If we're here, we didn't find a WPA-IE in the buffer */
 749    return NULL;
 750} // wl_parse_wpa_ie
 751
 752
 753/*******************************************************************************
 754 *      wl_print_wpa_ie()
 755 *******************************************************************************
 756 *
 757 *  DESCRIPTION:
 758 *
 759 *      Function used to take a WPA Information Element (WPA-IE) buffer and
 760 *      display it in a readable format.
 761 *
 762 *  PARAMETERS:
 763 *
 764 *      buffer - the byte buffer containing the WPA-IE
 765 *      length - the length of the above buffer
 766 *
 767 *  RETURNS:
 768 *
 769 *      A pointer to the formatted WPA-IE string. Note that the format used is
 770 *      byte-by-byte printing as %02x hex values with no spaces. This is
 771 *      required for proper operation with some WPA supplicants.
 772 *
 773 ******************************************************************************/
 774hcf_8 * wl_print_wpa_ie( hcf_8 *buffer, int length )
 775{
 776    int count;
 777    int rows;
 778    int remainder;
 779    int rowsize = 4;
 780    hcf_8 row_buf[64];
 781    static hcf_8 output[512];
 782    /*------------------------------------------------------------------------*/
 783
 784
 785    memset( output, 0, sizeof( output ));
 786    memset( row_buf, 0, sizeof( row_buf ));
 787
 788
 789    /* Determine how many rows will be needed, and the remainder */
 790    rows = length / rowsize;
 791    remainder = length % rowsize;
 792
 793
 794    /* Format the rows */
 795    for( count = 0; count < rows; count++ ) {
 796        sprintf( row_buf, "%02x%02x%02x%02x",
 797                 buffer[count*rowsize], buffer[count*rowsize+1],
 798                 buffer[count*rowsize+2], buffer[count*rowsize+3]);
 799        strcat( output, row_buf );
 800    }
 801
 802    memset( row_buf, 0, sizeof( row_buf ));
 803
 804
 805    /* Format the remainder */
 806    for( count = 0; count < remainder; count++ ) {
 807        sprintf( row_buf, "%02x", buffer[(rows*rowsize)+count]);
 808        strcat( output, row_buf );
 809    }
 810
 811    return output;
 812} // wl_print_wpa_ie
 813/*============================================================================*/
 814
 815
 816
 817
 818/*******************************************************************************
 819 *      wl_is_a_valid_chan()
 820 *******************************************************************************
 821 *
 822 *  DESCRIPTION:
 823 *
 824 *      Checks if a given channel is valid
 825 *
 826 *  PARAMETERS:
 827 *
 828 *      channel - the channel
 829 *
 830 *  RETURNS:
 831 *
 832 *      1 if TRUE
 833 *      0 if FALSE
 834 *
 835 ******************************************************************************/
 836int wl_is_a_valid_chan( int channel )
 837{
 838    int i;
 839    /*------------------------------------------------------------------------*/
 840
 841
 842    /* Strip out the high bit set by the FW for 802.11a channels */
 843    if( channel & 0x100 ) {
 844        channel = channel & 0x0FF;
 845    }
 846
 847    /* Iterate through the matrix and retrieve the frequency */
 848    for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
 849        if( chan_freq_list[i][0] == channel ) {
 850            return 1;
 851        }
 852    }
 853
 854    return 0;
 855} // wl_is_a_valid_chan
 856/*============================================================================*/
 857
 858
 859
 860
 861/*******************************************************************************
 862 *      wl_get_chan_from_freq()
 863 *******************************************************************************
 864 *
 865 *  DESCRIPTION:
 866 *
 867 *      Checks if a given frequency is valid
 868 *
 869 *  PARAMETERS:
 870 *
 871 *      freq - the frequency
 872 *
 873 *  RETURNS:
 874 *
 875 *      1 if TRUE
 876 *      0 if FALSE
 877 *
 878 ******************************************************************************/
 879int wl_is_a_valid_freq( long frequency )
 880{
 881    int i;
 882    /*------------------------------------------------------------------------*/
 883
 884
 885    /* Iterate through the matrix and retrieve the channel */
 886    for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
 887        if( chan_freq_list[i][1] == frequency ) {
 888            return 1;
 889        }
 890    }
 891
 892    return 0;
 893} // wl_is_a_valid_freq
 894/*============================================================================*/
 895
 896
 897
 898
 899/*******************************************************************************
 900 *      wl_get_freq_from_chan()
 901 *******************************************************************************
 902 *
 903 *  DESCRIPTION:
 904 *
 905 *      Function used to look up the frequency for a given channel on which the
 906 *      adapter is Tx/Rx.
 907 *
 908 *  PARAMETERS:
 909 *
 910 *      channel - the channel
 911 *
 912 *  RETURNS:
 913 *
 914 *      The corresponding frequency
 915 *
 916 ******************************************************************************/
 917long wl_get_freq_from_chan( int channel )
 918{
 919    int i;
 920    /*------------------------------------------------------------------------*/
 921
 922
 923    /* Strip out the high bit set by the FW for 802.11a channels */
 924    if( channel & 0x100 ) {
 925        channel = channel & 0x0FF;
 926    }
 927
 928    /* Iterate through the matrix and retrieve the frequency */
 929    for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
 930        if( chan_freq_list[i][0] == channel ) {
 931            return chan_freq_list[i][1];
 932        }
 933    }
 934
 935    return 0;
 936} // wl_get_freq_from_chan
 937/*============================================================================*/
 938
 939
 940
 941
 942/*******************************************************************************
 943 *      wl_get_chan_from_freq()
 944 *******************************************************************************
 945 *
 946 *  DESCRIPTION:
 947 *
 948 *      Function used to look up the channel for a given frequency on which the
 949 *      adapter is Tx/Rx.
 950 *
 951 *  PARAMETERS:
 952 *
 953 *      frequency - the frequency
 954 *
 955 *  RETURNS:
 956 *
 957 *      The corresponding channel
 958 *
 959 ******************************************************************************/
 960int wl_get_chan_from_freq( long frequency )
 961{
 962    int i;
 963    /*------------------------------------------------------------------------*/
 964
 965
 966    /* Iterate through the matrix and retrieve the channel */
 967    for( i = 0; i < ARRAY_SIZE(chan_freq_list); i++ ) {
 968        if( chan_freq_list[i][1] == frequency ) {
 969            return chan_freq_list[i][0];
 970        }
 971    }
 972
 973    return 0;
 974} // wl_get_chan_from_freq
 975/*============================================================================*/
 976
 977
 978
 979
 980/*******************************************************************************
 981 *      wl_process_link_status()
 982 *******************************************************************************
 983 *
 984 *  DESCRIPTION:
 985 *
 986 *      Process the link status message signaled by the device.
 987 *
 988 *  PARAMETERS:
 989 *
 990 *      lp - a pointer to the device's private structure
 991 *
 992 *  RETURNS:
 993 *
 994 *      N/A
 995 *
 996 ******************************************************************************/
 997void wl_process_link_status( struct wl_private *lp )
 998{
 999    hcf_16 link_stat;
1000    /*------------------------------------------------------------------------*/
1001
1002    DBG_FUNC( "wl_process_link_status" );
1003    DBG_ENTER( DbgInfo );
1004
1005    if( lp != NULL ) {
1006        //link_stat = lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_FW;
1007        link_stat = lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW;
1008        switch( link_stat ) {
1009        case 1:
1010            DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
1011            wl_wext_event_ap( lp->dev );
1012            break;
1013        case 2:
1014            DBG_TRACE( DbgInfo, "Link Status : Disconnected\n"  );
1015            break;
1016        case 3:
1017            DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
1018            break;
1019        case 4:
1020            DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
1021            break;
1022        case 5:
1023            DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
1024            break;
1025        default:
1026            DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n", link_stat );
1027            break;
1028        }
1029    }
1030    DBG_LEAVE( DbgInfo );
1031    return;
1032} // wl_process_link_status
1033/*============================================================================*/
1034
1035
1036
1037
1038/*******************************************************************************
1039 *      wl_process_probe_response()
1040 *******************************************************************************
1041 *
1042 *  DESCRIPTION:
1043 *
1044 *      Process the probe responses retunred by the device as a result of an
1045 *      active scan.
1046 *
1047 *  PARAMETERS:
1048 *
1049 *      lp - a pointer to the device's private structure
1050 *
1051 *  RETURNS:
1052 *
1053 *      N/A
1054 *
1055 ******************************************************************************/
1056void wl_process_probe_response( struct wl_private *lp )
1057{
1058    PROBE_RESP  *probe_rsp;
1059    hcf_8       *wpa_ie = NULL;
1060    hcf_16      wpa_ie_len = 0;
1061    /*------------------------------------------------------------------------*/
1062
1063
1064    DBG_FUNC( "wl_process_probe_response" );
1065    DBG_ENTER( DbgInfo );
1066
1067
1068    if( lp != NULL ) {
1069        probe_rsp = (PROBE_RESP *)&lp->ProbeResp;
1070
1071        wl_endian_translate_event( (ltv_t *)probe_rsp );
1072
1073        DBG_TRACE( DbgInfo, "(%s) =========================\n", lp->dev->name );
1074        DBG_TRACE( DbgInfo, "(%s) length      : 0x%04x.\n",  lp->dev->name,
1075                probe_rsp->length );
1076
1077        if( probe_rsp->length > 1 ) {
1078            DBG_TRACE( DbgInfo, "(%s) infoType    : 0x%04x.\n", lp->dev->name,
1079                    probe_rsp->infoType );
1080
1081            DBG_TRACE( DbgInfo, "(%s) signal      : 0x%02x.\n", lp->dev->name,
1082                    probe_rsp->signal );
1083
1084            DBG_TRACE( DbgInfo, "(%s) silence     : 0x%02x.\n", lp->dev->name,
1085                    probe_rsp->silence );
1086
1087            DBG_TRACE( DbgInfo, "(%s) rxFlow      : 0x%02x.\n", lp->dev->name,
1088                    probe_rsp->rxFlow );
1089
1090            DBG_TRACE( DbgInfo, "(%s) rate        : 0x%02x.\n", lp->dev->name,
1091                    probe_rsp->rate );
1092
1093            DBG_TRACE( DbgInfo, "(%s) frame cntl  : 0x%04x.\n", lp->dev->name,
1094                    probe_rsp->frameControl );
1095
1096            DBG_TRACE( DbgInfo, "(%s) durID       : 0x%04x.\n", lp->dev->name,
1097                    probe_rsp->durID );
1098
1099                DBG_TRACE(DbgInfo, "(%s) address1    : %pM\n", lp->dev->name,
1100                        probe_rsp->address1);
1101
1102                DBG_TRACE(DbgInfo, "(%s) address2    : %pM\n", lp->dev->name,
1103                        probe_rsp->address2);
1104
1105                DBG_TRACE(DbgInfo, "(%s) BSSID       : %pM\n", lp->dev->name,
1106                        probe_rsp->BSSID);
1107
1108            DBG_TRACE( DbgInfo, "(%s) sequence    : 0x%04x.\n", lp->dev->name,
1109                    probe_rsp->sequence );
1110
1111                DBG_TRACE(DbgInfo, "(%s) address4    : %pM\n", lp->dev->name,
1112                        probe_rsp->address4);
1113
1114            DBG_TRACE( DbgInfo, "(%s) datalength  : 0x%04x.\n", lp->dev->name,
1115                    probe_rsp->dataLength );
1116
1117                DBG_TRACE(DbgInfo, "(%s) DA          : %pM\n", lp->dev->name,
1118                        probe_rsp->DA);
1119
1120                DBG_TRACE(DbgInfo, "(%s) SA          : %pM\n", lp->dev->name,
1121                        probe_rsp->SA);
1122
1123#ifdef WARP
1124
1125            DBG_TRACE( DbgInfo, "(%s) channel     : %d\n", lp->dev->name,
1126                    probe_rsp->channel );
1127
1128            DBG_TRACE( DbgInfo, "(%s) band        : %d\n", lp->dev->name,
1129                    probe_rsp->band );
1130#else
1131            DBG_TRACE( DbgInfo, "(%s) lenType     : 0x%04x.\n", lp->dev->name,
1132                    probe_rsp->lenType );
1133#endif  // WARP
1134
1135            DBG_TRACE( DbgInfo, "(%s) timeStamp   : %d.%d.%d.%d.%d.%d.%d.%d\n",
1136                    lp->dev->name,
1137                    probe_rsp->timeStamp[0],
1138                    probe_rsp->timeStamp[1],
1139                    probe_rsp->timeStamp[2],
1140                    probe_rsp->timeStamp[3],
1141                    probe_rsp->timeStamp[4],
1142                    probe_rsp->timeStamp[5],
1143                    probe_rsp->timeStamp[6],
1144                    probe_rsp->timeStamp[7]);
1145
1146            DBG_TRACE( DbgInfo, "(%s) beaconInt   : 0x%04x.\n", lp->dev->name,
1147                    probe_rsp->beaconInterval );
1148
1149            DBG_TRACE( DbgInfo, "(%s) capability  : 0x%04x.\n", lp->dev->name,
1150                    probe_rsp->capability );
1151
1152            DBG_TRACE( DbgInfo, "(%s) SSID len    : 0x%04x.\n", lp->dev->name,
1153                    probe_rsp->rawData[1] );
1154
1155
1156            if( probe_rsp->rawData[1] > 0 ) {
1157                char ssid[HCF_MAX_NAME_LEN];
1158
1159                memset( ssid, 0, sizeof( ssid ));
1160                strncpy( ssid, &probe_rsp->rawData[2],
1161                            probe_rsp->rawData[1] );
1162
1163                DBG_TRACE( DbgInfo, "(%s) SSID        : %s\n",
1164                            lp->dev->name, ssid );
1165            }
1166
1167
1168            /* Parse out the WPA-IE, if one exists */
1169            wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
1170            if( wpa_ie != NULL ) {
1171                DBG_TRACE( DbgInfo, "(%s) WPA-IE      : %s\n",
1172                lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
1173            }
1174
1175            DBG_TRACE( DbgInfo, "(%s) flags       : 0x%04x.\n",
1176                        lp->dev->name, probe_rsp->flags );
1177        }
1178
1179        DBG_TRACE( DbgInfo, "\n" );
1180
1181
1182        /* If probe response length is 1, then the scan is complete */
1183        if( probe_rsp->length == 1 ) {
1184            DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
1185            lp->probe_results.num_aps = lp->probe_num_aps;
1186            lp->probe_results.scan_complete = TRUE;
1187
1188            /* Reset the counter for the next scan request */
1189            lp->probe_num_aps = 0;
1190
1191            /* Send a wireless extensions event that the scan completed */
1192            wl_wext_event_scan_complete( lp->dev );
1193        } else {
1194            /* Only copy to the table if the entry is unique; APs sometimes
1195                respond more than once to a probe */
1196            if( lp->probe_num_aps == 0 ) {
1197                /* Copy the info to the ScanResult structure in the private
1198                adapter struct */
1199                memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1200                        probe_rsp, sizeof( PROBE_RESP ));
1201
1202                /* Increment the number of APs detected */
1203                lp->probe_num_aps++;
1204            } else {
1205                int count;
1206                int unique = 1;
1207
1208                for( count = 0; count < lp->probe_num_aps; count++ ) {
1209                    if( memcmp( &( probe_rsp->BSSID ),
1210                        lp->probe_results.ProbeTable[count].BSSID,
1211                        ETH_ALEN ) == 0 ) {
1212                        unique = 0;
1213                    }
1214                }
1215
1216                if( unique ) {
1217                    /* Copy the info to the ScanResult structure in the
1218                    private adapter struct. Only copy if there's room in the
1219                    table */
1220                    if( lp->probe_num_aps < MAX_NAPS )
1221                    {
1222                        memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
1223                                probe_rsp, sizeof( PROBE_RESP ));
1224                    }
1225                    else
1226                    {
1227                        DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
1228                    }
1229
1230                    /* Increment the number of APs detected. Note I do this
1231                        here even when I don't copy the probe response to the
1232                        buffer in order to detect the overflow condition */
1233                    lp->probe_num_aps++;
1234                }
1235            }
1236        }
1237    }
1238
1239    DBG_LEAVE( DbgInfo );
1240    return;
1241} // wl_process_probe_response
1242/*============================================================================*/
1243
1244
1245
1246
1247/*******************************************************************************
1248 *      wl_process_updated_record()
1249 *******************************************************************************
1250 *
1251 *  DESCRIPTION:
1252 *
1253 *      Process the updated information record message signaled by the device.
1254 *
1255 *  PARAMETERS:
1256 *
1257 *      lp - a pointer to the device's private structure
1258 *
1259 *  RETURNS:
1260 *
1261 *      N/A
1262 *
1263 ******************************************************************************/
1264void wl_process_updated_record( struct wl_private *lp )
1265{
1266    DBG_FUNC( "wl_process_updated_record" );
1267    DBG_ENTER( DbgInfo );
1268
1269
1270    if( lp != NULL ) {
1271        lp->updatedRecord.u.u16[0] = CNV_LITTLE_TO_INT( lp->updatedRecord.u.u16[0] );
1272
1273        switch( lp->updatedRecord.u.u16[0] ) {
1274        case CFG_CUR_COUNTRY_INFO:
1275            DBG_TRACE( DbgInfo, "Updated Record: CFG_CUR_COUNTRY_INFO\n" );
1276            wl_connect( lp );
1277            break;
1278
1279        case CFG_PORT_STAT:
1280            DBG_TRACE( DbgInfo, "Updated Record: WAIT_FOR_CONNECT (0xFD40)\n" );
1281            //wl_connect( lp );
1282            break;
1283
1284        default:
1285            DBG_TRACE( DbgInfo, "UNKNOWN: 0x%04x\n",
1286                       lp->updatedRecord.u.u16[0] );
1287        }
1288    }
1289
1290    DBG_LEAVE( DbgInfo );
1291    return;
1292} // wl_process_updated_record
1293/*============================================================================*/
1294
1295
1296
1297
1298/*******************************************************************************
1299 *      wl_process_assoc_status()
1300 *******************************************************************************
1301 *
1302 *  DESCRIPTION:
1303 *
1304 *      Process the association status event signaled by the device.
1305 *
1306 *  PARAMETERS:
1307 *
1308 *      lp - a pointer to the device's private structure
1309 *
1310 *  RETURNS:
1311 *
1312 *      N/A
1313 *
1314 ******************************************************************************/
1315void wl_process_assoc_status( struct wl_private *lp )
1316{
1317    ASSOC_STATUS_STRCT *assoc_stat;
1318    /*------------------------------------------------------------------------*/
1319
1320
1321    DBG_FUNC( "wl_process_assoc_status" );
1322    DBG_ENTER( DbgInfo );
1323
1324
1325    if( lp != NULL ) {
1326        assoc_stat = (ASSOC_STATUS_STRCT *)&lp->assoc_stat;
1327
1328        wl_endian_translate_event( (ltv_t *)assoc_stat );
1329
1330        switch( assoc_stat->assocStatus ) {
1331        case 1:
1332            DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
1333            break;
1334
1335        case 2:
1336            DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
1337            break;
1338
1339        case 3:
1340            DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
1341            break;
1342
1343        default:
1344            DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
1345                        assoc_stat->assocStatus );
1346            break;
1347        }
1348
1349        DBG_TRACE(DbgInfo, "STA Address        : %pM\n", assoc_stat->staAddr);
1350
1351        if(( assoc_stat->assocStatus == 2 )  && ( assoc_stat->len == 8 )) {
1352                DBG_TRACE(DbgInfo, "Old AP Address     : %pM\n",
1353                        assoc_stat->oldApAddr);
1354        }
1355    }
1356
1357    DBG_LEAVE( DbgInfo );
1358    return;
1359} // wl_process_assoc_status
1360/*============================================================================*/
1361
1362
1363
1364
1365/*******************************************************************************
1366 *      wl_process_security_status()
1367 *******************************************************************************
1368 *
1369 *  DESCRIPTION:
1370 *
1371 *      Process the security status message signaled by the device.
1372 *
1373 *  PARAMETERS:
1374 *
1375 *      lp - a pointer to the device's private structure
1376 *
1377 *  RETURNS:
1378 *
1379 *      N/A
1380 *
1381 ******************************************************************************/
1382void wl_process_security_status( struct wl_private *lp )
1383{
1384    SECURITY_STATUS_STRCT *sec_stat;
1385    /*------------------------------------------------------------------------*/
1386
1387
1388    DBG_FUNC( "wl_process_security_status" );
1389    DBG_ENTER( DbgInfo );
1390
1391
1392    if( lp != NULL ) {
1393        sec_stat = (SECURITY_STATUS_STRCT *)&lp->sec_stat;
1394
1395        wl_endian_translate_event( (ltv_t *)sec_stat );
1396
1397        switch( sec_stat->securityStatus ) {
1398        case 1:
1399            DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
1400            break;
1401
1402        case 2:
1403            DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
1404            break;
1405
1406        case 3:
1407            DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
1408            break;
1409
1410        case 4:
1411            DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
1412            break;
1413
1414        case 5:
1415            DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
1416            break;
1417
1418        default:
1419            DBG_TRACE( DbgInfo, "Security Status : UNKNOWN (0x%04x)\n",
1420                        sec_stat->securityStatus );
1421            break;
1422        }
1423
1424        DBG_TRACE(DbgInfo, "STA Address     : %pM\n", sec_stat->staAddr);
1425        DBG_TRACE(DbgInfo, "Reason          : 0x%04x\n", sec_stat->reason);
1426
1427    }
1428
1429    DBG_LEAVE( DbgInfo );
1430    return;
1431} // wl_process_security_status
1432/*============================================================================*/
1433
1434int wl_get_tallies(struct wl_private *lp,
1435                   CFG_HERMES_TALLIES_STRCT *tallies)
1436{
1437    int ret = 0;
1438    int status;
1439    CFG_HERMES_TALLIES_STRCT *pTallies;
1440
1441    DBG_FUNC( "wl_get_tallies" );
1442    DBG_ENTER(DbgInfo);
1443
1444    /* Get the current tallies from the adapter */
1445    lp->ltvRecord.len = 1 + HCF_TOT_TAL_CNT * sizeof(hcf_16);
1446    lp->ltvRecord.typ = CFG_TALLIES;
1447
1448    status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1449
1450    if( status == HCF_SUCCESS ) {
1451        pTallies = (CFG_HERMES_TALLIES_STRCT *)&(lp->ltvRecord.u.u32);
1452        memcpy(tallies, pTallies, sizeof(*tallies));
1453        DBG_TRACE( DbgInfo, "Get tallies okay, dixe: %d\n", sizeof(*tallies) );
1454    } else {
1455        DBG_TRACE( DbgInfo, "Get tallies failed\n" );
1456        ret = -EFAULT;
1457    }
1458
1459    DBG_LEAVE( DbgInfo );
1460
1461    return ret;
1462}
1463
1464