/* * 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; }
/************************************************************************** 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 */ } }
/* * 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)); }
/* * 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)); }