Esempio n. 1
0
/*
 * Performs the sequence necessary to write a config/info item.
 *
 * Arguments:
 *	hw		device structure
 *	rid		config/info record id (in host order)
 *	buf		host side record buffer
 *	len		buffer length (in bytes)
 *
 * Returns:
 *	0		success
 */
static int hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
{
  int result = 0;
  hfa384x_rec_t	rec;

  rec.rid = host2hfa384x_16(rid);
  rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
  /* write the record header */
  result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
  if ( result ) {
    printf("Failure writing record header\n");
    return -1;
  }
  /* write the record data (if there is any) */
  if ( len > 0 ) {
    result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
    if ( result ) {
      printf("Failure writing record data\n");
      return -1;
    }
  }
  /* Trigger setting of record */
  result = hfa384x_cmd_access( hw, 1, rid);
  return result;
}
/*----------------------------------------------------------------
* prism2mgmt_scan
*
* Initiate a scan for BSSs.
*
* This function corresponds to MLME-scan.request and part of
* MLME-scan.confirm.  As far as I can tell in the standard, there
* are no restrictions on when a scan.request may be issued.  We have
* to handle in whatever state the driver/MAC happen to be.
*
* Arguments:
*	wlandev		wlan device structure
*	msgp		ptr to msg buffer
*
* Returns:
*	0	success and done
*	<0	success, but we're waiting for something to finish.
*	>0	an error occurred while handling the message.
* Side effects:
*
* Call context:
*	process thread  (usually)
*	interrupt
----------------------------------------------------------------*/
int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
{
    int 			result = 0;
    hfa384x_t		*hw = wlandev->priv;
    p80211msg_dot11req_scan_t	*msg = msgp;
    u16                  roamingmode, word;
    int                     i, timeout;
    int                     istmpenable = 0;

    hfa384x_HostScanRequest_data_t  scanreq;

    DBFENTER;

    /* gatekeeper check */
    if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
                                 hw->ident_sta_fw.minor,
                                 hw->ident_sta_fw.variant) <
            HFA384x_FIRMWARE_VERSION(1,3,2)) {
        WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n");
        result = 1;
        msg->resultcode.data = P80211ENUM_resultcode_not_supported;
        goto exit;
    }

    memset(&scanreq, 0, sizeof(scanreq));

    /* save current roaming mode */
    result = hfa384x_drvr_getconfig16(hw,
                                      HFA384x_RID_CNFROAMINGMODE, &roamingmode);
    if ( result ) {
        WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n",
                       result);
        msg->resultcode.data =
            P80211ENUM_resultcode_implementation_failure;
        goto exit;
    }

    /* drop into mode 3 for the scan */
    result = hfa384x_drvr_setconfig16(hw,
                                      HFA384x_RID_CNFROAMINGMODE,
                                      HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
    if ( result ) {
        WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n",
                       result);
        msg->resultcode.data =
            P80211ENUM_resultcode_implementation_failure;
        goto exit;
    }

    /* active or passive? */
    if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
                                 hw->ident_sta_fw.minor,
                                 hw->ident_sta_fw.variant) >
            HFA384x_FIRMWARE_VERSION(1,5,0)) {
        if (msg->scantype.data != P80211ENUM_scantype_active) {
            word = host2hfa384x_16(msg->maxchanneltime.data);
        } else {
            word = 0;
        }
        result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
        if ( result ) {
            WLAN_LOG_WARNING("Passive scan not supported with "
                             "current firmware.  (<1.5.1)\n");
        }
    }

    /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
    word = HFA384x_RATEBIT_2;
    scanreq.txRate = host2hfa384x_16(word);

    /* set up the channel list */
    word = 0;
    for (i = 0; i < msg->channellist.data.len; i++) {
        u8 channel = msg->channellist.data.data[i];
        if (channel > 14) continue;
        /* channel 1 is BIT0 ... channel 14 is BIT13 */
        word |= (1 << (channel-1));
    }
    scanreq.channelList = host2hfa384x_16(word);

    /* set up the ssid, if present. */
    scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
    memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);

    /* Enable the MAC port if it's not already enabled  */
    result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
    if ( result ) {
        WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. "
                       "result=%d\n", result);
        msg->resultcode.data =
            P80211ENUM_resultcode_implementation_failure;
        goto exit;
    }
    if (word == HFA384x_PORTSTATUS_DISABLED) {
        u16 wordbuf[17];

        result = hfa384x_drvr_setconfig16(hw,
                                          HFA384x_RID_CNFROAMINGMODE,
                                          HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
        if ( result ) {
            WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result);
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        /* Construct a bogus SSID and assign it to OwnSSID and
         * DesiredSSID
         */
        wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
        get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
        result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
                                         wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
        if ( result ) {
            WLAN_LOG_ERROR("Failed to set OwnSSID.\n");
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
                                         wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
        if ( result ) {
            WLAN_LOG_ERROR("Failed to set DesiredSSID.\n");
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        /* bsstype */
        result = hfa384x_drvr_setconfig16(hw,
                                          HFA384x_RID_CNFPORTTYPE,
                                          HFA384x_PORTTYPE_IBSS);
        if ( result ) {
            WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n");
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        /* ibss options */
        result = hfa384x_drvr_setconfig16(hw,
                                          HFA384x_RID_CREATEIBSS,
                                          HFA384x_CREATEIBSS_JOINCREATEIBSS);
        if ( result ) {
            WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n");
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        result = hfa384x_drvr_enable(hw, 0);
        if ( result ) {
            WLAN_LOG_ERROR("drvr_enable(0) failed. "
                           "result=%d\n", result);
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
        istmpenable = 1;
    }

    /* Figure out our timeout first Kus, then HZ */
    timeout = msg->channellist.data.len * msg->maxchanneltime.data;
    timeout = (timeout * HZ)/1000;

    /* Issue the scan request */
    hw->scanflag = 0;

    WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));

    result = hfa384x_drvr_setconfig( hw,
                                     HFA384x_RID_HOSTSCAN, &scanreq,
                                     sizeof(hfa384x_HostScanRequest_data_t));
    if ( result ) {
        WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n",
                       result);
        msg->resultcode.data =
            P80211ENUM_resultcode_implementation_failure;
        goto exit;
    }

    /* sleep until info frame arrives */
    wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);

    msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
    if (hw->scanflag == -1)
        hw->scanflag = 0;

    msg->numbss.data = hw->scanflag;

    hw->scanflag = 0;

    /* Disable port if we temporarily enabled it. */
    if (istmpenable) {
        result = hfa384x_drvr_disable(hw, 0);
        if ( result ) {
            WLAN_LOG_ERROR("drvr_disable(0) failed. "
                           "result=%d\n", result);
            msg->resultcode.data =
                P80211ENUM_resultcode_implementation_failure;
            goto exit;
        }
    }

    /* restore original roaming mode */
    result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
                                      roamingmode);
    if ( result ) {
        WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n",
                       result);
        msg->resultcode.data =
            P80211ENUM_resultcode_implementation_failure;
        goto exit;
    }

    result = 0;
    msg->resultcode.data = P80211ENUM_resultcode_success;

exit:
    msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;

    DBFEXIT;
    return result;
}
Esempio n. 3
0
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
static void prism2_transmit(
			    struct nic *nic,
			    const char *d,			/* Destination */
			    unsigned int t,			/* Type */
			    unsigned int s,			/* size */
			    const char *p)			/* Packet */
{
  hfa384x_t *hw = &hw_global;
  hfa384x_tx_frame_t txdesc;
  wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
  uint16_t fid;
  uint16_t status;
  int result;

  // Request FID allocation
  result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
  if (result != 0) {
    printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
    return;
  }
  if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
  fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);

  /* Build Tx frame structure */
  memset(&txdesc, 0, sizeof(txdesc));
  txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
				       HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
  txdesc.frame_control =  host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
				       WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
				       WLAN_SET_FC_TODS(1) );
  memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
  memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
  memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
  txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
  /* Set up SNAP header */
  /* Let OUI default to RFC1042 (0x000000) */
  p80211hdr.snap.type = htons(t);

  /* Copy txdesc, p80211hdr and payload parts to FID */
  result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
  if ( result ) return; /* fail */
  result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
  if ( result ) return; /* fail */
  result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (uint8_t*)p, s );
  if ( result ) return; /* fail */

  /* Issue Tx command */
  result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
  if ( result != 0 ) {
    printf("hfa384x: Transmit failed with result %#hx.\n", result);
    return;
  }

  /* Wait for transmit completion (or exception) */
  result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
				  200, 500, "Tx to complete\n" );
  if ( !result ) return; /* timeout failure */
  if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
    fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
    printf ( "Tx exception occurred with fid %#hx\n", fid );
    result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
    if ( result ) return; /* fail */
    printf("hfa384x: Tx error occurred (status %#hx):\n", status);
    if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
    if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
    if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
    if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
    if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
    return; /* fail */
  }
}
Esempio n. 4
0
/*
 * Performs the sequence necessary to write a 16/32 bit config/info item.
 *
 * Arguments:
 *	hw		device structure
 *	rid		config/info record id (in host order)
 *	val		16/32 bit value to store (in host order)
 *
 * Returns:
 *	0		success
 */
static int hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t *val)
{
  uint16_t value;
  value = host2hfa384x_16(*val);
  return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint16_t));
}
Esempio n. 5
0
/*
 * Performs the sequence necessary to write a 16/32 bit config/info item.
 *
 * Arguments:
 *	hw		device structure
 *	rid		config/info record id (in host order)
 *	val		16/32 bit value to store (in host order)
 *
 * Returns: 
 *	0		success
 */
static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
{
  UINT16 value;
  value = host2hfa384x_16(*val);
  return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
}