stm32驱动wifi 88W8686 WM-G-MR-09

stm32驱动wifi 88W8686 WM-G-MR-09
stm32驱动wifi 88W8686 WM-G-MR-09

#include "wifi.h"

#include

#include

#include

/********************************************************

Local Constants

********************************************************/

//! Approximate amount of data needed to pass a scan result back to iwlist

#define M AX_SCAN_CELL_SIZE (I W_EV_ADDR_LEN \

+ M RVDRV_MAX_SSID_LENGTH \

+ I W_EV_UINT_LEN \

+ I W_EV_FREQ_LEN \

+ I W_EV_QUAL_LEN \

+ M RVDRV_MAX_SSID_LENGTH \

+ I W_EV_PARAM_LEN \

+ 40) /* 40 for WPAIE */

//! Memory needed to store a max sized Channel List TLV for a firmware scan

#define C HAN_TLV_MAX_SIZE (sizeof(M rvlIEtypesHeader_t) \

+ (M RVDRV_MAX_CHANNELS_PER_SCAN \

* sizeof(C hanScanParamSet_t)))

//! Memory needed to store a max number/size SSID TLV for a firmware scan

#define S SID_TLV_MAX_SIZE (1 * sizeof(M rvlIEtypes_SsIdParamSet_t))

//! WPS TLV MAX size is MAX IE size plus 2 bytes for u16 MRVL TLV extension

#define W PS_TLV_MAX_SIZE (sizeof(I EEEtypes_VendorSpecific_t) + 2)

//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max

#define M AX_SCAN_CFG_ALLOC (sizeof(w lan_scan_cmd_config) \

+ sizeof(M rvlIEtypes_NumProbes_t) \

+ C HAN_TLV_MAX_SIZE \

+ S SID_TLV_MAX_SIZE \

+ W PS_TLV_MAX_SIZE)

//! The maximum number of channels the firmware can scan per command

#define M RVDRV_MAX_CHANNELS_PER_SCAN 14

/**

* @brief Number of channels to scan per firmware scan command issuance.

*

* Number restricted to prevent hitting the limit on the amount of scan data * returned in a single firmware scan command.

*/

#define M RVDRV_CHANNELS_PER_SCAN_CMD 4

//! Macro to enable/disable SSID checking before storing a scan table

#ifdef D ISCARD_BAD_SSID

#define C HECK_SSID_IS_VALID(x) s sid_valid(&bssidEntry.Ssid)

#else

#define C HECK_SSID_IS_VALID(x) TRUE

#endif

/********************************************************

Local Variables and Types

********************************************************/

/**

* @brief Interally used to send a configured scan cmd between driver routines

*/

typedef union

{

wlan_scan_cmd_config config; //!< Scan configuration (variable length) u8 configAllocBuf[M AX_SCAN_CFG_ALLOC]; //!< Max allocated block

} w lan_scan_cmd_config_tlv;

/**

* @brief Check if a scanned network compatible with the driver settings

*

* WEP WPA WPA2 ad-hoc encrypt Network

* enabled enabled enabled AES mode Privacy WPA WPA2 Compatible

* 0 0 0 0 NONE 0 0 0 yes No security

* 0 1 0 0 x 1x 1 x yes WPA

* 0 0 1 0 x 1x x 1 yes WPA2

* 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES

*

* 1 0 0 0 NONE 1 0 0 yes Static WEP

* 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP

*

*

* @param Adapter A pointer to wlan_adapter

* @param index Index in ScanTable to check against current driver settings

* @param mode Network mode: Infrastructure or IBSS

*

* @return Index in ScanTable, or error code if negative

*/

static int

IsNetworkCompatible(w lan_adapter * Adapter, int index, int mode)

{

BSSDescriptor_t *pBSSDesc;

ENTER();

pBSSDesc = &Adapter->ScanTable[index];

/* D on't check for compatibility if roaming */

if ((Adapter->MediaConnectStatus == WlanMediaStateConnected)

&& (Adapter->InfrastructureMode == W lan802_11Infrastructure)

&& (pBSSDesc->InfrastructureMode == W lan802_11Infrastructure)) {

LEAVE();

return index;

}

if (Adapter->wps.SessionEnable == TRUE) {

printf("Return success directly in WPS period\n");

LEAVE();

return index;

}

if (pBSSDesc->InfrastructureMode == mode) {

if (Adapter->SecInfo.WEPStatus == W lan802_11WEPDisabled

&& !Adapter->SecInfo.WPAEnabled

&& !Adapter->SecInfo.W PA2Enabled

&& pBSSDesc->wpaIE.VendHdr.ElementId != W PA_IE

&& pBSSDesc->rsnIE.IeeeHdr.ElementId != R SN_IE

&& !Adapter->AdhocAESEnabled

&& Adapter->SecInfo.EncryptionMode == C IPHER_NONE

&& !pBSSDesc->Privacy) {

/* no security */

LEAVE();

return index;

} else if (Adapter->SecInfo.WEPStatus == W lan802_11WEPEnabled

&& !Adapter->SecInfo.WPAEnabled

&& !Adapter->SecInfo.W PA2Enabled

&& !Adapter->AdhocAESEnabled && pBSSDesc->Privacy) {

/* static WEP enabled */

LEAVE();

return index;

} else if (Adapter->SecInfo.WEPStatus == W lan802_11WEPDisabled

&& Adapter->SecInfo.WPAEnabled

&& !Adapter->SecInfo.W PA2Enabled

&& (pBSSDesc->wpaIE.VendHdr.ElementId == W PA_IE)

&& !Adapter->AdhocAESEnabled

/* P rivacy bit may NOT be set in some APs like LinkSys WRT54G && pBSSDesc->Privacy */

) {

/* WPA enabled */

printf("IsNetworkCompatible() WPA: index=%d wpa_ie=%#x "

"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "

"privacy=%#x\n",

index,

pBSSDesc->wpaIE.VendHdr.ElementId,

pBSSDesc->rsnIE.IeeeHdr.ElementId,

(Adapter->SecInfo.WEPStatus ==

Wlan802_11WEPEnabled) ? "e" : "d",

(Adapter->SecInfo.WPAEnabled) ? "e" : "d",

(Adapter->SecInfo.W PA2Enabled) ? "e" : "d",

Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);

LEAVE();

return index;

} else if (Adapter->SecInfo.WEPStatus == W lan802_11WEPDisabled

&& !Adapter->SecInfo.WPAEnabled

&& Adapter->SecInfo.W PA2Enabled

&& (pBSSDesc->rsnIE.IeeeHdr.ElementId == R SN_IE)

&& !Adapter->AdhocAESEnabled

/* P rivacy bit may NOT be set in some APs like LinkSys WRT54G && pBSSDesc->Privacy */

) {

/* W PA2 enabled */

printf( "IsNetworkCompatible() WPA2: index=%d wpa_ie=%#x "

"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "

"privacy=%#x\n",

index,

pBSSDesc->wpaIE.VendHdr.ElementId,

pBSSDesc->rsnIE.IeeeHdr.ElementId,

(Adapter->SecInfo.WEPStatus ==

Wlan802_11WEPEnabled) ? "e" : "d",

(Adapter->SecInfo.WPAEnabled) ? "e" : "d",

(Adapter->SecInfo.W PA2Enabled) ? "e" : "d",

Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);

LEAVE();

return index;

} else if (Adapter->SecInfo.WEPStatus == W lan802_11WEPDisabled

&& !Adapter->SecInfo.WPAEnabled

&& !Adapter->SecInfo.W PA2Enabled

&& (pBSSDesc->wpaIE.VendHdr.ElementId != W PA_IE)

&& (pBSSDesc->rsnIE.IeeeHdr.ElementId != R SN_IE)

&& Adapter->AdhocAESEnabled

&& Adapter->SecInfo.EncryptionMode == C IPHER_NONE

&& pBSSDesc->Privacy) {

/* A d-hoc AES enabled */

LEAVE();

return index;

} else if (Adapter->SecInfo.WEPStatus == W lan802_11WEPDisabled

&& !Adapter->SecInfo.WPAEnabled

&& !Adapter->SecInfo.W PA2Enabled

&& (pBSSDesc->wpaIE.VendHdr.ElementId != W PA_IE)

&& (pBSSDesc->rsnIE.IeeeHdr.ElementId != R SN_IE)

&& !Adapter->AdhocAESEnabled

&& Adapter->SecInfo.EncryptionMode != C IPHER_NONE

&& pBSSDesc->Privacy) {

/* dynamic WEP enabled */

printf( "IsNetworkCompatible() dynamic WEP: index=%d "

"wpa_ie=%#x wpa2_ie=%#x EncMode=%#x privacy=%#x\n",

index,

pBSSDesc->wpaIE.VendHdr.ElementId,

pBSSDesc->rsnIE.IeeeHdr.ElementId,

Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);

LEAVE();

return index;

}

/* s ecurity doesn't match */

printf( "IsNetworkCompatible() FAILED: index=%d wpa_ie=%#x "

"wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", index,

pBSSDesc->wpaIE.VendHdr.ElementId,

pBSSDesc->rsnIE.IeeeHdr.ElementId,

(Adapter->SecInfo.WEPStatus ==

Wlan802_11WEPEnabled) ? "e" : "d",

(Adapter->SecInfo.WPAEnabled) ? "e" : "d",

(Adapter->SecInfo.W PA2Enabled) ? "e" : "d",

Adapter->SecInfo.EncryptionMode, pBSSDesc->Privacy);

LEAVE();

return -ECONNREFUSED;

}

/* m ode doesn't match */

LEAVE();

return -ENETUNREACH;

}

/**

* @brief This function validates a SSID as being able to be printed

*

* @param pSsid SSID structure to validate

*

* @return TRUE or FALSE

*/

static BOOLEAN

s sid_valid(W LAN_802_11_SSID * pSsid)

{

int ssidIdx;

for (ssidIdx = 0; ssidIdx < pSsid->SsidLength; ssidIdx++) {

if (!isprint(pSsid->Ssid[ssidIdx])) {

return FALSE;

}

}

return TRUE;

}

/**

* @brief Post process the scan table after a new scan command has completed *

* Inspect each entry of the scan table and try to find an entry that

* matches our current associated/joined network from the scan. If

* one is found, update the stored copy of the BSSDescriptor for our

* current network.

*

* Debug dump the current scan table contents if compiled accordingly.

*

* @param priv A pointer to wlan_private structure

*

* @return void

*/

static void

w lan_scan_process_results(w lan_private * priv)

{

wlan_adapter *Adapter = priv->adapter;

int i;

//int foundCurrent;

//foundCurrent = FALSE;

if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {

Adapter->CurBssParams.BSSDescriptor.pBeaconBuf = NULL;

Adapter->CurBssParams.BSSDescriptor.beaconBufSize = 0;

Adapter->CurBssParams.BSSDescriptor.beaconBufSizeMax = 0;

i = FindSSIDInList(Adapter,

&Adapter->CurBssParams.BSSDescriptor.Ssid,

Adapter->CurBssParams.BSSDescriptor.MacAddress,

Adapter->InfrastructureMode);

if (i >= 0) {

printf("Found current ssid/bssid in list @ index #%d\n", i);

/* Make a copy of current BSSID descriptor */

memcpy(&Adapter->CurBssParams.BSSDescriptor,

&Adapter->ScanTable[i],

sizeof(Adapter->CurBssParams.BSSDescriptor));

}

}

for (i = 0; i < Adapter->NumInScanTable; i++) {

printf( "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "

"RSSI[%03d], SSID[%s]\n",

i,

Adapter->ScanTable[i].MacAddress[0],

Adapter->ScanTable[i].MacAddress[1],

Adapter->ScanTable[i].MacAddress[2],

Adapter->ScanTable[i].MacAddress[3],

Adapter->ScanTable[i].MacAddress[4],

Adapter->ScanTable[i].MacAddress[5],

(s32) Adapter->ScanTable[i].Rssi,

Adapter->ScanTable[i].Ssid.Ssid);

}

}

/**

* @brief Create a channel list for the driver to scan based on region info

*

* Use the driver region/band information to construct a comprehensive list

* of channels to scan. This routine is used for any scan that is not

* provided a specific channel list to scan.

*

* @param priv A pointer to wlan_private structure

* @param scanChanList Output parameter: Resulting channel list to scan

* @param filteredScan Flag indicating whether or not a BSSID or SSID filter * is being sent in the command to firmware. Used to

* increase the number of channels sent in a scan

* command and to disable the firmware channel scan

* filter.

*

* @return void

*/

static void

w lan_scan_create_channel_list(w lan_private * priv,

ChanScanParamSet_t * scanChanList,

BOOLEAN filteredScan)

{

wlan_adapter *Adapter = priv->adapter;

REGION_CHANNEL *scanRegion;

CHANNEL_FREQ_POWER *cfp;

int rgnIdx;

int chanIdx;

int nextChan;

u8 scanType;

chanIdx = 0;

/* S et the default scan type to the user specified type, will later

* be changed to passive on a per channel basis if restricted by

* regulatory requirements (11d or 11h)

*/

scanType = Adapter->ScanType;

for (rgnIdx = 0; rgnIdx < NELEMENTS(Adapter->r egion_channel); rgnIdx++) { if (w lan_get_state_11d(priv) == E NABLE_11D &&

Adapter->MediaConnectStatus != WlanMediaStateConnected) {

/* Scan all the supported chan for the first scan */

if (!Adapter->u niversal_channel[rgnIdx].Valid)

continue;

scanRegion = &Adapter->u niversal_channel[rgnIdx];

/* c lear the parsed_region_chan for the first scan */

memset(&Adapter->p arsed_region_chan, 0x00,

sizeof(Adapter->p arsed_region_chan));

} else {

if (!Adapter->r egion_channel[rgnIdx].Valid)

continue;

scanRegion = &Adapter->r egion_channel[rgnIdx];

}

for (nextChan = 0;

nextChan < scanRegion->NrCFP; nextChan++, chanIdx++) {

cfp = scanRegion->CFP + nextChan;

if (w lan_get_state_11d(priv) == E NABLE_11D) {

scanType =

wlan_get_scan_type_11d(cfp->Channel,

&Adapter->p arsed_region_chan);

}

switch (scanRegion->Band) {

case B AND_B:

case B AND_G:

default:

scanChanList[chanIdx].RadioType = H ostCmd_SCAN_RADIO_TYPE_BG; break;

}

if (scanType == H ostCmd_SCAN_TYPE_PASSIVE) {

scanChanList[chanIdx].MaxScanTime =

wlan_cpu_to_le16(Adapter->PassiveScanTime);

scanChanList[chanIdx].ChanScanMode.PassiveScan = TRUE;

} else {

scanChanList[chanIdx].MaxScanTime =

wlan_cpu_to_le16(Adapter->ActiveScanTime);

scanChanList[chanIdx].ChanScanMode.PassiveScan = FALSE;

}

scanChanList[chanIdx].ChanNumber = cfp->Channel;

if (filteredScan) {

scanChanList[chanIdx].MaxScanTime =

wlan_cpu_to_le16(Adapter->SpecificScanTime);

scanChanList[chanIdx].ChanScanMode.DisableChanFilt = TRUE;

}

}

}

}

static void

w lan_add_wps_probe_request_ie(w lan_private * priv, u8 ** ppTlvOut)

{

wlan_adapter *Adapter = priv->adapter;

MrvlIEtypesHeader_t *tlv;

if (Adapter->wps.wpsIe.VendHdr.Len) {

tlv = (M rvlIEtypesHeader_t *) * ppTlvOut;

tlv->Type = w lan_cpu_to_le16(T LV_TYPE_WPS_ENROLLEE_PROBE_REQ_TLV);

tlv->Len = w lan_cpu_to_le16(Adapter->wps.wpsIe.VendHdr.Len);

*ppTlvOut += sizeof(M rvlIEtypesHeader_t);

memcpy(*ppTlvOut,

Adapter->wps.wpsIe.VendHdr.Oui,

Adapter->wps.wpsIe.VendHdr.Len);

*ppTlvOut += (Adapter->wps.wpsIe.VendHdr.Len

+ sizeof(M rvlIEtypesHeader_t));

}

}

/**

* @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds *

* Application layer or other functions can invoke wlan_scan_networks

* with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct. * This structure is used as the basis of one or many wlan_scan_cmd_config

* commands that are sent to the command processing module and sent to

* firmware.

*

* Create a wlan_scan_cmd_config based on the following user supplied

* parameters (if present):

* - SSID filter

* - BSSID filter

* - Number of Probes to be sent

* - Channel list

*

* If the SSID or BSSID filter is not present, disable/clear the filter.

* If the number of probes is not set, use the adapter default setting

* Qualify the channel

*

* @param priv A pointer to wlan_private structure

* @param pUserScanIn NULL or pointer to scan configuration parameters

* @param pScanCfgOut Output parameter: Resulting scan configuration

* @param ppChanTlvOut Output parameter: Pointer to the start of the

* channel TLV portion of the output scan config

* @param pScanChanList Output parameter: Pointer to the resulting channel * list to scan

* @param pMaxChanPerScan Output parameter: Number of channels to scan for

* each issuance of the firmware scan command

* @param pFilteredScan Output parameter: Flag indicating whether or not

* a BSSID or SSID filter is being sent in the

* command to firmware. Used to increase the number

* of channels sent in a scan command and to

* disable the firmware channel scan filter.

* @param pScanCurrentOnly Output parameter: Flag indicating whether or not

* we are only scanning our current active channel

*

* @return void

*/

static void

w lan_scan_setup_scan_config(w lan_private * priv,

const w lan_ioctl_user_scan_cfg * pUserScanIn,

wlan_scan_cmd_config * pScanCfgOut,

MrvlIEtypes_ChanListParamSet_t ** ppChanTlvOut,

ChanScanParamSet_t * pScanChanList,

int *pMaxChanPerScan,

BOOLEAN * pFilteredScan,

BOOLEAN * pScanCurrentOnly)

{

wlan_adapter *Adapter = priv->adapter;

const u8 zeroMac[E TH_ALEN] = { 0, 0, 0, 0, 0, 0 };

MrvlIEtypes_NumProbes_t *pNumProbesTlv;

u8 *pTlvPos;

u16 numProbes;

u16 ssidLen;

int chanIdx;

int scanType;

int scanDur;

int channel;

int radioType;

int ssidIdx;

BOOLEAN ssidFilter;

MrvlIEtypes_WildCardSsIdParamSet_t *pWildCardSsidTlv;

/* T he tlvBufferLen is calculated for each scan command. The TLVs added

* in this routine will be preserved since the routine that sends

* the command will append channelTLVs at *ppChanTlvOut. The difference * between the *ppChanTlvOut and the tlvBuffer start will be used

* to calculate the size of anything we add in this routine.

*/

pScanCfgOut->tlvBufferLen = 0;

/* R unning tlv pointer. Assigned to ppChanTlvOut at end of function

* so later routines know where channels can be added to the command buf */

pTlvPos = pScanCfgOut->tlvBuffer;

/*

* Set the initial scan paramters for progressive scanning. If a specific * BSSID or SSID is used, the number of channels in the scan command

* will be increased to the absolute maximum

*/

*pMaxChanPerScan = M RVDRV_MAX_CHANNELS_PER_SCAN;

/* I nitialize the scan as un-filtered; the flag is later set to

* TRUE below if a SSID or BSSID filter is sent in the command

*/

*pFilteredScan = FALSE;

/* I nitialize the scan as not being only on the current channel. If

* the channel list is customized, only contains one channel, and

* is the active channel, this is set true and data flow is not halted. */

*pScanCurrentOnly = FALSE;

if (pUserScanIn) {

/* D efault the ssidFilter flag to TRUE, set false under certain

* wildcard conditions and qualified by the existence of an SSID

* list before marking the scan as filtered

*/

ssidFilter = TRUE;

/* S et the bss type scan filter, use Adapter setting if unset */

pScanCfgOut->bssType = (pUserScanIn->bssType ? pUserScanIn->bssType : Adapter->ScanMode);

/* S et the number of probes to send, use Adapter setting if unset */

numProbes = (pUserScanIn->numProbes ? pUserScanIn->numProbes :

Adapter->ScanProbes);

/*

* Set the BSSID filter to the incoming configuration,

* if non-zero. If not set, it will remain disabled (all zeros).

*/

memcpy(pScanCfgOut->specificBSSID,

pUserScanIn->specificBSSID,

sizeof(pScanCfgOut->specificBSSID));

for (ssidIdx = 0; ((ssidIdx < NELEMENTS(pUserScanIn->ssidList))

&& (*pUserScanIn->ssidList[ssidIdx].ssid

|| pUserScanIn->ssidList[ssidIdx].maxLen));

ssidIdx++) {

ssidLen = strlen(pUserScanIn->ssidList[ssidIdx].ssid) + 1;

pWildCardSsidTlv = (M rvlIEtypes_WildCardSsIdParamSet_t *) pTlvPos; pWildCardSsidTlv->Header.Type

= w lan_cpu_to_le16(T LV_TYPE_WILDCARDSSID);

pWildCardSsidTlv->Header.Len

= ssidLen + sizeof(pWildCardSsidTlv->MaxSsidLength);

pWildCardSsidTlv->MaxSsidLength

= pUserScanIn->ssidList[ssidIdx].maxLen;

memcpy(pWildCardSsidTlv->SsId,

pUserScanIn->ssidList[ssidIdx].ssid, ssidLen);

pTlvPos += (sizeof(pWildCardSsidTlv->Header)

+ pWildCardSsidTlv->Header.Len);

pWildCardSsidTlv->Header.Len

= w lan_cpu_to_le16(pWildCardSsidTlv->Header.Len);

printf( "Scan: ssidList[%d]: %s, %d\n",

ssidIdx,

pWildCardSsidTlv->SsId, pWildCardSsidTlv->MaxSsidLength);

/* Empty wildcard ssid with a maxlen will match many or potentially * all SSIDs (maxlen == 32), therefore do not treat the scan

* as filtered.

*/

if ((ssidLen == 0) && pWildCardSsidTlv->MaxSsidLength) {

ssidFilter = FALSE;

}

}

/*

* The default number of channels sent in the command is low to

* ensure the response buffer from the firmware does not truncate

* scan results. That is not an issue with an SSID or BSSID

* filter applied to the scan results in the firmware.

*/

if ((ssidIdx && ssidFilter)

|| memcmp(pScanCfgOut->specificBSSID, &zeroMac, sizeof(zeroMac))) { *pFilteredScan = TRUE;

}

} else {

pScanCfgOut->bssType = Adapter->ScanMode;

numProbes = Adapter->ScanProbes;

}

/* I f the input config or adapter has the number of Probes set, add tlv */ if (numProbes) {

printf( "Scan: numProbes = %d\n", numProbes);

pNumProbesTlv = (M rvlIEtypes_NumProbes_t *) pTlvPos;

pNumProbesTlv->Header.Type = w lan_cpu_to_le16(T LV_TYPE_NUMPROBES);

pNumProbesTlv->Header.Len = sizeof(pNumProbesTlv->NumProbes);

pNumProbesTlv->NumProbes = w lan_cpu_to_le16(numProbes);

pTlvPos += sizeof(pNumProbesTlv->Header) + pNumProbesTlv->Header.Len;

pNumProbesTlv->Header.Len =

wlan_cpu_to_le16(pNumProbesTlv->Header.Len);

}

wlan_add_wps_probe_request_ie(priv, &pTlvPos);

/*

* Set the output for the channel TLV to the address in the tlv buffer

* past any TLVs that were added in this fuction (SSID, numProbes).

* Channel TLVs will be added past this for each scan command, preserving * the TLVs that were previously added.

*/

*ppChanTlvOut = (M rvlIEtypes_ChanListParamSet_t *) pTlvPos;

if (pUserScanIn && pUserScanIn->chanList[0].chanNumber) {

printf( "Scan: Using supplied channel list\n");

for (chanIdx = 0;

chanIdx < W LAN_IOCTL_USER_SCAN_CHAN_MAX

&& pUserScanIn->chanList[chanIdx].chanNumber; chanIdx++) {

channel = pUserScanIn->chanList[chanIdx].chanNumber;

(pScanChanList + chanIdx) ->ChanNumber = channel;

radioType = pUserScanIn->chanList[chanIdx].radioType;

(pScanChanList + chanIdx) ->RadioType = radioType;

scanType = pUserScanIn->chanList[chanIdx].scanType;

if (scanType == H ostCmd_SCAN_TYPE_PASSIVE) {

(pScanChanList + chanIdx) ->ChanScanMode.PassiveScan = TRUE;

} else {

(pScanChanList + chanIdx) ->ChanScanMode.PassiveScan = FALSE;

}

if (pUserScanIn->chanList[chanIdx].scanTime) {

scanDur = pUserScanIn->chanList[chanIdx].scanTime;

} else {

if (scanType == H ostCmd_SCAN_TYPE_PASSIVE) {

scanDur = Adapter->PassiveScanTime;

} else if (*pFilteredScan) {

scanDur = Adapter->SpecificScanTime;

} else {

scanDur = Adapter->ActiveScanTime;

}

}

(pScanChanList + chanIdx) ->MinScanTime =

wlan_cpu_to_le16(scanDur);

(pScanChanList + chanIdx) ->MaxScanTime =

wlan_cpu_to_le16(scanDur);

}

/* Check if we are only scanning the current channel */

if ((chanIdx == 1)

&& (pUserScanIn->chanList[0].chanNumber

== priv->adapter->CurBssParams.BSSDescriptor.Channel)) {

*pScanCurrentOnly = TRUE;

printf( "Scan: Scanning current channel only");

}

} else {

printf( "Scan: Creating full region channel list\n");

wlan_scan_create_channel_list(priv, pScanChanList, *pFilteredScan);

}

}

/**

* @brief Construct and send multiple scan config commands to the firmware

*

* Previous routines have created a wlan_scan_cmd_config with any requested

* TLVs. This function splits the channel TLV into maxChanPerScan lists

* and sends the portion of the channel TLV along with the other TLVs

* to the wlan_cmd routines for execution in the firmware.

*

* @param priv A pointer to wlan_private structure

* @param maxChanPerScan Maximum number channels to be included in each

* scan command sent to firmware

* @param filteredScan Flag indicating whether or not a BSSID or SSID

* filter is being used for the firmware command

* scan command sent to firmware

* @param pScanCfgOut Scan configuration used for this scan.

* @param pChanTlvOut Pointer in the pScanCfgOut where the channel TLV

* should start. This is past any other TLVs that

* must be sent down in each firmware command.

* @param pScanChanList List of channels to scan in maxChanPerScan segments *

* @return WLAN_STATUS_SUCCESS or error return otherwise

*/

static int

w lan_scan_channel_list(w lan_private * priv,

int maxChanPerScan,

BOOLEAN filteredScan,

wlan_scan_cmd_config * pScanCfgOut,

MrvlIEtypes_ChanListParamSet_t * pChanTlvOut,

ChanScanParamSet_t * pScanChanList)

{

ChanScanParamSet_t *pTmpChan;

//ChanScanParamSet_t *pStartChan;

//u8 scanBand;

int doneEarly;

int tlvIdx;

int totalscantime;

int ret;

ENTER();

if (pScanCfgOut == 0 || pChanTlvOut == 0 || pScanChanList == 0) {

printf( "Scan: Null detect: %p, %p, %p\n",

pScanCfgOut, pChanTlvOut, pScanChanList);

return W LAN_STATUS_FAILURE;

}

ret = W LAN_STATUS_SUCCESS;

pChanTlvOut->Header.Type = w lan_cpu_to_le16(T LV_TYPE_CHANLIST);

/* Set the temp channel struct pointer to the start of the desired list */ pTmpChan = pScanChanList;

/* L oop through the desired channel list, sending a new firmware scan

* commands for each maxChanPerScan channels (or for 1,6,11 individually * if configured accordingly)

*/

while (pTmpChan->ChanNumber) {

tlvIdx = 0;

totalscantime = 0;

pChanTlvOut->Header.Len = 0;

// scanBand = pTmpChan->RadioType;

// pStartChan = pTmpChan;

doneEarly = FALSE;

/* C onstruct the Channel TLV for the scan command. Continue to

* insert channel TLVs until:

* - the tlvIdx hits the maximum configured per scan command

* - the next channel to insert is 0 (end of desired channel list)

* - doneEarly is set (controlling individual scanning of 1,6,11)

*/

while (tlvIdx < maxChanPerScan && pTmpChan->ChanNumber && !doneEarly) { printf( "Scan: Chan(%3d), Radio(%d), Mode(%d,%d), Dur(%d)\n",

pTmpChan->ChanNumber,

pTmpChan->RadioType,

pTmpChan->ChanScanMode.PassiveScan,

pTmpChan->ChanScanMode.DisableChanFilt,

pTmpChan->MaxScanTime);

/* Copy the current channel TLV to the command being prepared */

memcpy(pChanTlvOut->ChanScanParam + tlvIdx,

pTmpChan, sizeof(pChanTlvOut->ChanScanParam));

/* Increment the TLV header length by the size appended */

pChanTlvOut->Header.Len += sizeof(pChanTlvOut->ChanScanParam);

/*

* The tlv buffer length is set to the number of bytes of the

* between the channel tlv pointer and the start of the

* tlv buffer. This compensates for any TLVs that were appended * before the channel list.

*/

pScanCfgOut->tlvBufferLen = ((u8 *) pChanTlvOut

- pScanCfgOut->tlvBuffer);

/* Add the size of the channel tlv header and the data length */

pScanCfgOut->tlvBufferLen += (sizeof(pChanTlvOut->Header)

+ pChanTlvOut->Header.Len);

/* Increment the index to the channel tlv we are constructing */

tlvIdx++;

/* Count the total scan time per command */

totalscantime += pTmpChan->MaxScanTime;

doneEarly = FALSE;

/* S top the loop if the *current* channel is in the 1,6,11 set

* and we are not filtering on a BSSID or SSID.

*/

if (!filteredScan && (pTmpChan->ChanNumber == 1

|| pTmpChan->ChanNumber == 6

|| pTmpChan->ChanNumber == 11)) {

doneEarly = TRUE;

}

/* Increment the tmp pointer to the next channel to be scanned */

pTmpChan++;

/* S top the loop if the *next* channel is in the 1,6,11 set.

* This will cause it to be the only channel scanned on the next

* interation

*/

if (!filteredScan && (pTmpChan->ChanNumber == 1

|| pTmpChan->ChanNumber == 6

|| pTmpChan->ChanNumber == 11)) {

doneEarly = TRUE;

}

}

/* The total scan time should be less than scan command timeout value */ if (totalscantime > M RVDRV_MAX_TOTAL_SCAN_TIME) {

printf(

"Total scan time %d ms is over limit (%d ms), scan skipped\n", totalscantime, M RVDRV_MAX_TOTAL_SCAN_TIME);

ret = W LAN_STATUS_FAILURE;

break;

}

pChanTlvOut->Header.Len = w lan_cpu_to_le16(pChanTlvOut->Header.Len);

/* Send the scan command to the firmware with the specified cfg */

ret = PrepareAndSendCommand(priv, H ostCmd_CMD_802_11_SCAN, 0,

HostCmd_OPTION_WAITFORRSP, 0,

pScanCfgOut);

}

LEAVE();

if (ret) {

return W LAN_STATUS_FAILURE;

}

return W LAN_STATUS_SUCCESS;

}

/**

* @brief Internal function used to start a scan based on an input config

*

* Use the input user scan configuration information when provided in

* order to send the appropriate scan commands to firmware to populate or

* update the internal driver scan table

*

* @param priv A pointer to wlan_private structure

* @param pUserScanIn Pointer to the input configuration for the requested

* scan.

*

* @return WLAN_STATUS_SUCCESS or < 0 if error

*/

static int

w lan_scan_networks(w lan_private * priv,

const w lan_ioctl_user_scan_cfg * pUserScanIn)

{

wlan_adapter *Adapter = priv->adapter;

MrvlIEtypes_ChanListParamSet_t *pChanTlvOut;

ChanScanParamSet_t scanChanList[W LAN_IOCTL_USER_SCAN_CHAN_MAX];

wlan_scan_cmd_config_tlv scanCfgOut;

BOOLEAN keepPreviousScan;

BOOLEAN filteredScan;

BOOLEAN scanCurrentChanOnly;

int maxChanPerScan;

int ret;

BOOLEAN bBgScan;

ENTER();

memset(scanChanList, 0x00, sizeof(scanChanList));

memset(&scanCfgOut, 0x00, sizeof(scanCfgOut));

keepPreviousScan = FALSE;

wlan_scan_setup_scan_config(priv,

pUserScanIn,

&scanCfgOut.config,

&pChanTlvOut,

scanChanList,

&maxChanPerScan,

&filteredScan, &scanCurrentChanOnly);

if (pUserScanIn) {

keepPreviousScan = pUserScanIn->keepPreviousScan;

}

if (keepPreviousScan == FALSE) {

memset(Adapter->ScanTable, 0x00,

sizeof(B SSDescriptor_t) * M RVDRV_MAX_BSSID_LIST);

Adapter->NumInScanTable = 0;

Adapter->pBeaconBufEnd = Adapter->beaconBuffer;

}

/* Keep the data path active if we are only scanning our current channel */

if (!scanCurrentChanOnly) {

// printf( "Scan: WMM Queue stop\n");

// priv->wlan_https://www.360docs.net/doc/2615204388.html,dev->watchdog_timeo = MRVDRV_SCAN_WATCHDOG_TIMEOUT;

/* I f WMM queues are in use, only stop the internal data queues */

wmm_stop_queue(priv);

}

bBgScan = priv->adapter->bgScanConfig->Enable;

if (priv->adapter->bgScanConfig->Enable == TRUE) {

wlan_bg_scan_enable(priv, FALSE);

}

ret = w lan_scan_channel_list(priv,

maxChanPerScan,

filteredScan,

&scanCfgOut.config,

pChanTlvOut, scanChanList);

/* P rocess the resulting scan table:

* - Remove any bad ssids

* - Update our current BSS information from scan data

*/

wlan_scan_process_results(priv);

if (bBgScan == TRUE) {

wlan_bg_scan_enable(priv, TRUE);

}

printf( "Scan: WMM Queue start\n");

//priv->wlan_https://www.360docs.net/doc/2615204388.html,dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT; xzw1234 if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {

wmm_start_queue(priv);

}

os_carrier_on(priv);

os_start_queue(priv);

LEAVE();

return ret;

}

/**

* @brief Create a brief scan resp to relay basic BSS info to the app layer

*

* When the beacon/probe response has not been buffered, use the saved BSS

* information available to provide a minimum response for the application

* ioctl retrieval routines. Include:

* - Timestamp

* - Beacon Period

* - Capabilities (including WMM Element if available)

* - SSID

*

* @param ppBuffer Output parameter: Buffer used to create basic scan rsp

* @param pBSSDesc Pointer to a BSS entry in the scan table to create

* scan response from for delivery to the application layer

*

* @return void

*/

static void

w lan_scan_create_brief_table_entry(u8 ** ppBuffer, B SSDescriptor_t * pBSSDesc)

{

u8 *pTmpBuf = *ppBuffer;

u8 tmpSSIDHdr[2];

u8 ieLen;

if (c opy_to_user(pTmpBuf, pBSSDesc->TimeStamp,

sizeof(pBSSDesc->TimeStamp))) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += sizeof(pBSSDesc->TimeStamp);

if (c opy_to_user(pTmpBuf, &pBSSDesc->BeaconPeriod,

sizeof(pBSSDesc->BeaconPeriod))) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += sizeof(pBSSDesc->BeaconPeriod);

if (c opy_to_user(pTmpBuf, &pBSSDesc->Cap, sizeof(pBSSDesc->Cap))) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += sizeof(pBSSDesc->Cap);

tmpSSIDHdr[0] = 0; /* Element ID for SSID is zero */

tmpSSIDHdr[1] = pBSSDesc->Ssid.SsidLength;

if (c opy_to_user(pTmpBuf, tmpSSIDHdr, sizeof(tmpSSIDHdr))) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += sizeof(tmpSSIDHdr);

if (c opy_to_user(pTmpBuf, pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength)) { PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += pBSSDesc->Ssid.SsidLength;

if (pBSSDesc->wmmIE.VendHdr.ElementId == W MM_IE) {

ieLen = sizeof(I EEEtypes_Header_t) + pBSSDesc->wmmIE.VendHdr.Len;

if (c opy_to_user(pTmpBuf, &pBSSDesc->wmmIE, ieLen)) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += ieLen;

}

if (pBSSDesc->wpaIE.VendHdr.ElementId == W PA_IE) {

ieLen = sizeof(I EEEtypes_Header_t) + pBSSDesc->wpaIE.VendHdr.Len;

if (c opy_to_user(pTmpBuf, &pBSSDesc->wpaIE, ieLen)) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += ieLen;

}

if (pBSSDesc->rsnIE.IeeeHdr.ElementId == R SN_IE) {

ieLen = sizeof(I EEEtypes_Header_t) + pBSSDesc->rsnIE.IeeeHdr.Len;

if (c opy_to_user(pTmpBuf, &pBSSDesc->rsnIE, ieLen)) {

PRINTM(INFO, "Copy to user failed\n");

return;

}

pTmpBuf += ieLen;

}

*ppBuffer = pTmpBuf;

}

/**

* @brief Inspect the scan response buffer for pointers to expected TLVs

*

* TLVs can be included at the end of the scan response BSS information.

* Parse the data in the buffer for pointers to TLVs that can potentially * be passed back in the response

*

* @param pTlv Pointer to the start of the TLV buffer to parse

* @param tlvBufSize Size of the TLV buffer

* @param ppTsfTlv Output parameter: Pointer to the TSF TLV if found

*

* @return void

*/

static void

w lan_ret_802_11_scan_get_tlv_ptrs(M rvlIEtypes_Data_t * pTlv,

int tlvBufSize,

MrvlIEtypes_TsfTimestamp_t ** ppTsfTlv)

{

MrvlIEtypes_Data_t *pCurrentTlv;

int tlvBufLeft;

u16 tlvType;

u16 tlvLen;

pCurrentTlv = pTlv;

tlvBufLeft = tlvBufSize;

*ppTsfTlv = NULL;

PRINTM(INFO, "SCAN_RESP: tlvBufSize = %d\n", tlvBufSize);

HEXDUMP("SCAN_RESP: TLV Buf", (u8 *) pTlv, tlvBufSize);

while (tlvBufLeft >= sizeof(M rvlIEtypesHeader_t)) {

tlvType = w lan_le16_to_cpu(pCurrentTlv->Header.Type);

tlvLen = w lan_le16_to_cpu(pCurrentTlv->Header.Len);

switch (tlvType) {

case T LV_TYPE_TSFTIMESTAMP:

PRINTM(INFO, "SCAN_RESP: TSF Timestamp TLV, len = %d\n", tlvLen); *ppTsfTlv = (M rvlIEtypes_TsfTimestamp_t *) pCurrentTlv;

break;

default:

PRINTM(INFO, "SCAN_RESP: Unhandled TLV = %d\n", tlvType);

/* G ive up, this seems corrupted */

return;

} /* switch */

tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);

pCurrentTlv = (M rvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);

} /* while */

}

/**

* @brief Interpret a BSS scan response returned from the firmware

*

* Parse the various fixed fields and IEs passed back for a a BSS probe

* response or beacon from the scan command. Record information as needed

* in the scan table BSSDescriptor_t for that entry.

*

* @param pBSSIDEntry Output parameter: Pointer to the BSS Entry

*

* @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE

*/

static int

InterpretBSSDescriptionWithIE(B SSDescriptor_t * pBSSEntry,

u8 ** pBeaconInfo, int *bytesLeft)

{

IEEEtypes_ElementId_e elemID;

IEEEtypes_FhParamSet_t *pFH;

IEEEtypes_DsParamSet_t *pDS;

IEEEtypes_CfParamSet_t *pCF;

IEEEtypes_IbssParamSet_t *pIbss;

IEEEtypes_CapInfo_t *pCap;

WLAN_802_11_FIXED_IEs fixedIE;

u8 *pCurrentPtr;

u8 *pRate;

u8 elemLen;

u16 totalIeLen;

u8 bytesToCopy;

u8 rateSize;

u16 beaconSize;

BOOLEAN foundDataRateIE;

int bytesLeftForCurrentBeacon;

IEEEtypes_ERPInfo_t *pERPInfo;

IEEEtypes_VendorSpecific_t *pVendorIe;

const u8 w pa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };

const u8 w mm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };

const u8 w ps_oui[4] = { 0x00, 0x50, 0xf2, 0x04 };

IEEEtypes_CountryInfoSet_t *pcountryinfo;

ENTER();

foundDataRateIE = FALSE;

rateSize = 0;

beaconSize = 0;

if (*bytesLeft >= sizeof(beaconSize)) {

/* E xtract & convert beacon size from the command buffer */

memcpy(&beaconSize, *pBeaconInfo, sizeof(beaconSize));

beaconSize = w lan_le16_to_cpu(beaconSize);

*bytesLeft -= sizeof(beaconSize);

*pBeaconInfo += sizeof(beaconSize);

}

if (beaconSize == 0 || beaconSize > *bytesLeft) {

*pBeaconInfo += *bytesLeft;

*bytesLeft = 0;

return W LAN_STATUS_FAILURE;

}

/* Initialize the current working beacon pointer for this BSS iteration */ pCurrentPtr = *pBeaconInfo;

/* Advance the return beacon pointer past the current beacon */

*pBeaconInfo += beaconSize;

*bytesLeft -= beaconSize;

bytesLeftForCurrentBeacon = beaconSize;

memcpy(pBSSEntry->MacAddress, pCurrentPtr, M RVDRV_ETH_ADDR_LEN);

PRINTM(INFO, "InterpretIE: AP MAC Addr-%02x:%02x:%02x:%02x:%02x:%02x\n", pBSSEntry->MacAddress[0], pBSSEntry->MacAddress[1],

pBSSEntry->MacAddress[2], pBSSEntry->MacAddress[3],

pBSSEntry->MacAddress[4], pBSSEntry->MacAddress[5]);

pCurrentPtr += M RVDRV_ETH_ADDR_LEN;

bytesLeftForCurrentBeacon -= M RVDRV_ETH_ADDR_LEN;

if (bytesLeftForCurrentBeacon < 12) {

PRINTM(INFO, "InterpretIE: Not enough bytes left\n");

return W LAN_STATUS_FAILURE;

}

/*

* next 4 fields are RSSI, time stamp, beacon interval,

* and capability information

*/

/* R SSI is 1 byte long */

pBSSEntry->Rssi = w lan_le32_to_cpu((LONG) (*pCurrentPtr));

PRINTM(INFO, "InterpretIE: RSSI=%02X\n", *pCurrentPtr);

pCurrentPtr += 1;

bytesLeftForCurrentBeacon -= 1;

/*

* The RSSI is not part of the beacon/probe response. After we have

* advanced pCurrentPtr past the RSSI field, save the remaining

* data for use at the application layer

*/

pBSSEntry->pBeaconBuf = pCurrentPtr;

pBSSEntry->beaconBufSize = bytesLeftForCurrentBeacon;

/* t ime stamp is 8 bytes long */

memcpy(fixedIE.Timestamp, pCurrentPtr, 8);

memcpy(pBSSEntry->TimeStamp, pCurrentPtr, 8);

pCurrentPtr += 8;

bytesLeftForCurrentBeacon -= 8;

/* b eacon interval is 2 bytes long */

memcpy(&fixedIE.BeaconInterval, pCurrentPtr, 2);

pBSSEntry->BeaconPeriod = w lan_le16_to_cpu(fixedIE.BeaconInterval);

pCurrentPtr += 2;

bytesLeftForCurrentBeacon -= 2;

/* c apability information is 2 bytes long */

memcpy(&fixedIE.Capabilities, pCurrentPtr, 2);

PRINTM(INFO, "InterpretIE: fixedIE.Capabilities=0x%X\n",

fixedIE.Capabilities);

fixedIE.Capabilities = w lan_le16_to_cpu(fixedIE.Capabilities);

pCap = (I EEEtypes_CapInfo_t *) & fixedIE.Capabilities;

memcpy(&pBSSEntry->Cap, pCap, sizeof(I EEEtypes_CapInfo_t));

pCurrentPtr += 2;

bytesLeftForCurrentBeacon -= 2;

/* r est of the current buffer are IE's */

PRINTM(INFO, "InterpretIE: IELength for this AP = %d\n",

bytesLeftForCurrentBeacon);

HEXDUMP("InterpretIE: IE info", (u8 *) pCurrentPtr,

bytesLeftForCurrentBeacon);

if (pCap->Privacy) {

PRINTM(INFO, "InterpretIE: AP WEP enabled\n");

pBSSEntry->Privacy = W lan802_11PrivFilter8021xWEP;

} else {

pBSSEntry->Privacy = W lan802_11PrivFilterAcceptAll;

}

if (pCap->Ibss == 1) {

pBSSEntry->InfrastructureMode = W lan802_11IBSS;

} else {

pBSSEntry->InfrastructureMode = W lan802_11Infrastructure;

}

/* process variable IE */

while (bytesLeftForCurrentBeacon >= 2) {

elemID = (I EEEtypes_ElementId_e) (*((u8 *) pCurrentPtr));

elemLen = *((u8 *) pCurrentPtr + 1);

totalIeLen = elemLen + sizeof(I EEEtypes_Header_t);

if (bytesLeftForCurrentBeacon < elemLen) {

PRINTM(INFO, "InterpretIE: Error in processing IE, "

"bytes left < IE length\n");

bytesLeftForCurrentBeacon = 0;

continue;

}

switch (elemID) {

case SSID:

pBSSEntry->Ssid.SsidLength = elemLen;

memcpy(pBSSEntry->Ssid.Ssid, (pCurrentPtr + 2), elemLen);

PRINTM(INFO, "InterpretIE: Ssid: %-32s\n", pBSSEntry->Ssid.Ssid); break;

case S UPPORTED_RATES:

memcpy(pBSSEntry->DataRates, pCurrentPtr + 2, elemLen);

memcpy(pBSSEntry->SupportedRates, pCurrentPtr + 2, elemLen);

HEXDUMP("InterpretIE: SupportedRates:",

pBSSEntry->SupportedRates, elemLen);

rateSize = elemLen;

foundDataRateIE = TRUE;

break;

case E XTRA_IE:

PRINTM(INFO, "InterpretIE: EXTRA_IE Found!\n");

pBSSEntry->e xtra_ie = 1;

break;

case F H_PARAM_SET:

pFH = (I EEEtypes_FhParamSet_t *) pCurrentPtr;

pBSSEntry->NetworkTypeInUse = W lan802_11FH;

memcpy(&pBSSEntry->PhyParamSet.FhParamSet, pFH,

sizeof(I EEEtypes_FhParamSet_t));

pBSSEntry->PhyParamSet.FhParamSet.DwellTime

=

wlan_le16_to_cpu(pBSSEntry->PhyParamSet.FhParamSet.DwellTime); break;

case D S_PARAM_SET:

pDS = (I EEEtypes_DsParamSet_t *) pCurrentPtr;

pBSSEntry->NetworkTypeInUse = W lan802_11DS;

pBSSEntry->Channel = pDS->CurrentChan;

memcpy(&pBSSEntry->PhyParamSet.DsParamSet, pDS,

sizeof(I EEEtypes_DsParamSet_t));

break;

case C F_PARAM_SET:

pCF = (I EEEtypes_CfParamSet_t *) pCurrentPtr;

memcpy(&pBSSEntry->SsParamSet.CfParamSet, pCF,

sizeof(I EEEtypes_CfParamSet_t));

break;

case I BSS_PARAM_SET:

pIbss = (I EEEtypes_IbssParamSet_t *) pCurrentPtr;

pBSSEntry->ATIMWindow = w lan_le32_to_cpu(pIbss->AtimWindow);

memcpy(&pBSSEntry->SsParamSet.IbssParamSet, pIbss,

sizeof(I EEEtypes_IbssParamSet_t));

break;

/* Handle Country Info IE */

case C OUNTRY_INFO:

pcountryinfo = (I EEEtypes_CountryInfoSet_t *) pCurrentPtr;

if (pcountryinfo->Len < sizeof(pcountryinfo->CountryCode) ||

pcountryinfo->Len + 2 >

sizeof(I EEEtypes_CountryInfoFullSet_t)) {

PRINTM(INFO,

"InterpretIE: 11D- Err "

"CountryInfo len =%d min=%d max=%d\n",

pcountryinfo->Len, sizeof(pcountryinfo->CountryCode), sizeof(I EEEtypes_CountryInfoFullSet_t));

LEAVE();

return W LAN_STATUS_FAILURE;

}

memcpy(&pBSSEntry->CountryInfo,

pcountryinfo, pcountryinfo->Len + 2);

HEXDUMP("InterpretIE: 11D- CountryInfo:",

(u8 *) pcountryinfo, (u32) (pcountryinfo->Len + 2));

break;

case E RP_INFO:

pERPInfo = (I EEEtypes_ERPInfo_t *) pCurrentPtr;

pBSSEntry->ERPFlags = pERPInfo->ERPFlags;

break;

case E XTENDED_SUPPORTED_RATES:

/*

* only process extended supported rate

* if data rate is already found.

* data rate IE should come before

* extended supported rate IE

*/

if (foundDataRateIE) {

if ((elemLen + rateSize) > W LAN_SUPPORTED_RATES) {

bytesToCopy = (W LAN_SUPPORTED_RATES - rateSize);

} else {

bytesToCopy = elemLen;

}

pRate = (u8 *) pBSSEntry->DataRates;

pRate += rateSize;

memcpy(pRate, pCurrentPtr + 2, bytesToCopy);

pRate = (u8 *) pBSSEntry->SupportedRates;

pRate += rateSize;

memcpy(pRate, pCurrentPtr + 2, bytesToCopy);

}

HEXDUMP("InterpretIE: ExtSupportedRates:",

pBSSEntry->SupportedRates, elemLen + rateSize);

break;

case V ENDOR_SPECIFIC_221:

pVendorIe = (I EEEtypes_VendorSpecific_t *) pCurrentPtr;

if ((!memcmp

(pVendorIe->VendHdr.Oui, w pa_oui,

sizeof(pVendorIe->VendHdr.Oui)))

&& (pVendorIe->VendHdr.OuiType == w pa_oui[3])) {

pBSSEntry->wpaIE.VendHdr.Len

= (MIN(totalIeLen, sizeof(pBSSEntry->wpaIE))

- sizeof(I EEEtypes_Header_t));

奋斗STM32开发板Tiny NRF24L01转USB虚拟串口例程手册

奋斗版 STM32 开发板例程手册———NRF24L01+转 USB 虚拟串口实验
https://www.360docs.net/doc/2615204388.html,
NRF24L01+转 USB 虚拟串口实验
实验平台:奋斗版STM32开发板Tiny 实验内容:板子通过USB加电后,先向串口1输出一串测试数据,然后USB被PC识 别出来,虚拟出一个串口号给这个USB设备,此时可以通过在PC端的串口助手类 软件选择该串口号。进入串口软件界面,可以通过软件无线收发一帧长度最长 为32字节的数据。该例程可以和V3及MINI板的NRF24L01 UCGUI例程配合使用。
预先需要掌握的知识 2.4G通信模块NRF24L01 1. 产品特性
2.4GHz 全球开放ISM 频段,最大0dBm 发射功率,免许可证使用 支持六路通道的数据接收 低工作电压:1.9 1.9~3.6V 低电压工作 高速率:2Mbps,由于空中传输时间很短,极大的降低了无线传输中的碰撞现象(软件设置1Mbps或者2Mbps的空中传输速率) 多频点:125 频点,满足多点通信和跳频通信需要 超小型:内置2.4GHz天线,体积小巧,15x29mm(包括天线) 低功耗:当工作在应答模式通信时,快速的空中传输及启动时间,极大的降低了电流消耗。 低应用成本:NRF24L01 集成了所有与RF协议相关的高速信号处理部分,比如:自动重发丢失数据包和自动产生应答信号等, NRF24L01的SPI接口可以利用单片机的硬件SPI口连接或用单片机I/O口进行模拟,内部有FIFO可以与各种高低速微处理器接口, 便于使用低成本单片机。 便于开发:由于链路层完全集成在模块上,非常便于开发。 自动重发功能,自动检测和重发丢失的数据包,重发时间及重发次数可软件控制 自动存储未收到应答信号的数据包 自动应答功能,在收到有效数据后,模块自动发送应答信号,无须另行编程 载波检测—固定频率检测 内置硬件CRC 检错和点对多点通信地址控制 数据包传输错误计数器及载波检测功能可用于跳频设置 可同时设置六路接收通道地址,可有选择性的打开接收通道 标准插针Dip2.54MM 间距接口,便于嵌入式应用
2.基本电气特性
淘宝店铺:https://www.360docs.net/doc/2615204388.html,
1

STM32利用虚拟串口调试

STM32串口利用虚拟串口调试 解决*** error 30: undefined name of virtual register 问题 以下摘录于网络。 1. 利用VSPD将PC上的两个虚拟串口连接起来。如图我将COM2 和COM3连接起来。点击Addr pair。 2. 可以看到Virtual ports上将两个虚拟串口连接到了一起了。 3.虚拟串口准备就绪了。先将直接输入命令的方式来调试。我们打开KEIL MDK的,设置成仿真的模式。点DEBUG.在COMMAND串口输入: MODE COM2 38400, 0, 8, 1

说明: MODE命令的作用是设置被绑定计算机串口的参数。基本使用方式为:

MODE COMx baudrate, parity, databits, stopbits 其中: COMx(x = 1,2,…)代表计算机的串口号; baudrate代表串口的波特率;parity代表校验方式; databits代表数据位长度; stopbits代表停止位长度。 例如:MODE COM1 9600, n, 8, 1 设置串口1。波特率为9 600,无校验位,8位数据,1位停止位。 MODE COM2 19200, 1, 8, 1 设置串口2。波特率为19 200,奇校验,8位数据,1位停止位。 4、点回车后,再输入ASSIGN COM2 S1OUT 说明: COMx代表计算机的串口,可以是COM1、COM2、COM3或其他; inreg和outreg代表单片机的串口。对于只有一个串口的普通单片机,即SIN和SOUT;对于有两个或者多个串口的单片机,即SnIN和SnOUT(n=0,1,…即单片机的串口号)。 例如:ASSIGN COM1 < SIN > SOUT 将计算机的串口1绑定到单片机的串口(针对只有一个串口的单片机)。 ASSIGN COM2 < SIN > SOUT 将计算机的串口2绑定到单片机的串口0(针对有多个串口的单片机,注意串口号的位置)。 需要注意的是,参数的括号是不能省略的,而outreg则是没有括号的。

STM32F107+ULN2003+步进电机

STM32F107+ULN2003+步进电机,主要是步进电机部分,只写了正转,控制转速靠延时函数delayl(),反转的话还要写一个函数,将那把个数倒过来送过去,先送9,最后送8. int main(void) { /*!< At this stage the microcontroller clock setting is already configured, this is done through SystemInit() function which is called from startup file (startup_stm32f10x_xx.s) before to branch to application main. To reconfigure the default setting of SystemInit() function, refer to system_stm32f10x.c file */ uint32_t Times = 0; uint8_t ucStr[80] = {0}; uint32_t num = 0; /* 3?ê??ˉ°???LED??ê?μ? */ SZ_STM32_LEDInit(LED1); SZ_STM32_LEDInit(LED2); SZ_STM32_LEDInit(LED3); SZ_STM32_LEDInit(LED4); SZ_STM32_SysTickInit(1000); SZ_STM32_COMInit(COM1, 115200); COTR_Init(); /* Infinite loop ?÷?-?· */ while (1) { /* LED1??ê?μ?×′ì?è?·′ */ LED1OBB = !LED1OBB; */ Zhengzhuan(); } } /*********μ??ú**********************/ void delayl(unsigned int dl) { unsigned int i,y; for(i = 0; i < 5000; i++)

基于STM32和L6208的步进电机控制系统

基于STM32和L6208的步进电机控制系统 摘要:本文介绍了步进电机的基本工作原理及控制方法,通过对ARM公司的STM32F103XX处理器Cortex-M3和ST公司步进电机驱动芯片L6208性能和驱动原理的深入分析,阐述了一种新型驱动步进电机的控制系统。本控制系统能够实时、准确、可靠地控制两相两极的步进电机。 关键词:STM32、L6208、步进电机 Abstract:This paper introduced the basic work principle and control methods, By introducing the performance of STM32F103XX and thorough analyzing the drive principle of DMOS driver for bipolar steeper motor L6208, I expounded a new control system for driving steeper motor. This control system can control bipolar stepper motor real-time, well and truly and reliably. Key words: STM32, L6208, stepper motor 第1章引言 本系统采用STM32F103XX微控制器驱动双极性步进电机的方法,执行整步和半步模式来控制步进电机。用户可以选择:操作模式(整步/半步);电机旋转方式(顺时针/逆时针);当前控制模式(快速/慢速)。这种方法使用中密度STM32F103XX微控制器和全集成两相步进电机驱动L6208,这是性价比最高和最简单的方式获得最小的CPU负载。Cortex-M3是专门在微控制系统和无线网络等对功耗和成本敏感的嵌入式应用领域实现高系统性能而设计的,它大大简化了编程的复杂性,集高性能、低功耗、低成本于一体。 本设计的主要特点: 1、不需反馈器件,比其他运动控制系统成本低。 2、尤其在低速扭转力和强稳定性方面具有优势。 3、低功耗,高性能并且灵活,可用于机器人控制,机械工具转弯处,影像和其它精准 的轴位置控制环境。 4、高性能的STM32F103XX微控制器驱动步进电机依赖于控制器的低计算环境。 第2章方案比较与论证 总体系统框图如图1所示:

基于STM32的步进电机控制系统

基于STM32的步进电机控制系统

摘要 本文的主要工作是基于STM32步进电机控制系统的设计。随着越来越多的高科技产品逐渐融入了日常生活中,步进电机控制系统发生了巨大的变化。单片机、C 语言等前沿学科的技术的日趋成熟与实用化,使得步进电机的控制系统有了新的的研究方向与意义。本文描述了一个由STM32微处理器、步进电机、LCD显示器、键盘等模块构成的,提供基于STM32的PWM细分技术的步进电机控制系统。该系统采用STM32微处理器为核心,在MDK的环境下进行编程,根据键盘的输入,使STM32产生周期性PWM信号,用此信号对步进电机的速度及转动方向进行控制,并且通过LCD显示出数据。结果表明该系统具有结构简单、工作可靠、精度高等特点. 关键词:STM32微处理器;步进电机;LCD显示;PWM信号;细分技术

Abstract As well as the high-tech products gradually integrated into the daily life,servo control system has undergone tremendous changes.SCM and C language of the frontier disciplines such mature technology and practical,steering control system is a new research direction and meaning.This paper describes a STM32 microprocessors, steering, LCD display and keyboard, Based on the STM32 servo control system of PWM signal,This system uses STM32 microprocessor as the core, MDK in the environment, according to the keyboard input , STM32 produce periodic PWM signal, with this signal to the velocity and Angle of steering gear control, and through the LCD display data. The features of the simple hardware, stable operation and high precision are incarnated in the proposed system. Keywords:STM32 microprocessors; Steering system; LCD display;pulse width modulation signal;Subdivide technology

用stm32库函数编写的modbus源代码

用stm32库函数编写的modbus源代码 说在前面的话: 1.请勿盲目抄袭。这个协议使用了一个定时器,所以在别处请不要再使用,如果定时器不够用,可以做虚拟定时器。也就是采用一个物理的定时器产生时基。在这个定时器的中断函数中可以给相应的多个定时器自加1.每个虚拟定时器可以用两个变量分别控制打开关闭,和计时。这个已经试验通过了可行的。其实就跟我们使用物理的定时器一样,只不过物理的定时器是用晶振产生时基。 2.这段代码已经调试通过了,也硬件试验过,没有问题,如果你出现问题了,看看你在主函数的的各种基本配置有没有完成。如果要使用06和10号功能,你还需要在主函数中建立一个100个元素的数组,每个元素是16位。 3.写这个文档的时候,这个协议已经是半年前完成的了。所以有些东西记得不是很清楚了,如果说错了,请以实际为准。只是不想让这份代码死在电脑中了,所以才想起来要拿出来分享,支持开源精神。 4.如果实在实在是没有弄出来,请联系我,可以共同交流,我的邮箱:xiaozuoadamszju@https://www.360docs.net/doc/2615204388.html,

#include"stm32f10x.h" /* 此Modbus协议暂时只支持RTU模式,只支持作为Modbus从设备。 暂时支持的功能码(16进制)如下表所示: 01.读线圈状态(读多个输出位的状态,有效地位为0-31) 02.读输入位状态(读多个输入位的状态,有效地位为0-31) 03.读保持寄存器(读多个保持寄存器的数值,有效地位为0-99) 04.读输入寄存器(读多个输入寄存器的数值,有效地址为0-1) 05.强制单个线圈(强制单个输出位的状态,有效地位为0-31) 06.预制单个寄存器(设定一个寄存器的数值,有效地址为0-99) 0F.强制多个线圈(强制多个输出位的状态,有效地址为0-31) 10.预制多个寄存器(设定多个寄存器的数值,有效地址为0-99) 暂时支持的错误代码为: 01 不合法功能代码从机接收的是一种不能执行功能代码。发出查询命令后,

【设计教程大集合】STM32F3XX大全

STM32F3系列是意法半导体ARM? Cortex?-M4微控制器产品组合的入门级产品。经过市场检验的M4处理器内核可支持DSP指令,内置浮点单元(FPU),运行频率高达72MHz,若再搭配意法半导体独有的且基于内核耦合存储器(CCM-SRAM) 的程序加速(Routine Booster) 功能,其电机控制等例行程序的执行速度可比原来提升43%。STM32F3系列属于共有600余款产品的STM32产品家族,性能表现比STM32F1 Cortex-M3系列更加出色。STM32系列产品的软硬件具有广泛的共性,并提供简单易用的设计工具和开发生态系统。 基本资料 【产品新闻】意法半导体(ST)推出闪存容量高达512KB的STM32F3微控制器,大幅提升系统集成度 【数据手册】STM32F358xC、STM32F378xx、STM32F318、STM32F302、STM32F303等ARM Cortex-M4 32位内核 【硬件资源】STM32F3系列固件、软件、工具资源 【视频】意法半导体STM32F3系列探索套件(discovery kit)介绍 进阶设计 目前意法半导体针对智慧型手机Sensor Hub提供采用Cortex-M0核心开发的STM32F072、采用Cortex-M4核心开发的STM32F301和STM32F401,以及采用Cortex-M4核心开发的STM32F429,其中三星(Samsung)智慧型手机Note 3的Sensor Hub中,即搭载该公司STM32F401。 【STM32F303开发】+视觉姿态识别 对一个目标进行姿态识别,以简单的三角形为例,目标放置在一个旋转平台上,初始姿态位置,通过图像识别姿态,并将姿态数据传送给nucleo,nucleo驱动舵机进行角度调整。

Android设备与STM32单片机通信方式探讨

Android设备与STM32单片机通信方式探讨 摘要:随着科学技术的进步与人们生活水平的提升,Android设备也以其成本低廉、开发难度小、开放性强等优势,成为人们手中主要的网络设备。而Android平板电脑是当前非常流行的一种移动终端,本文便以Android平板电脑为例,研究Android设备与STM32单片机之间的音频通信、串口通信以及Bluetooth通信三种通信方式。 关键词:Android设备STM32单片机通信方式 中图分类号:TP368.1 文献标识码:A 文章编号:1007-9416(2016)01-0000-00 所谓STM32,指的是以ARMCortex-M3为基础的STMicroelectronics嵌入式32为微处理器,具有成本低、性能高、能耗少等优势。从性能的角度出发,微处理器可以分为基本型、互联型以及增强型几个种类,以适用于产品的不同性能要求。而Android则是一种以Linux为基础的操作系统,普遍适用于智能终端设备,如平板电脑、智能手机等,越来越受到市场的广泛认同。 1 音频通信 耳机孔是Android设备中必不可少的,用于输入与输出麦克和耳机中的音频信号,耳机引脚的构成如图1所示:

图1 耳机引脚的构成 根据图1所示,可以运用两个声道中的任意一个,作为Android设备向STM32单片机进行信号传输的通信线,而MIC 麦克则可以作为STM32单片机向Android设备进行信号传输的通信线[1]。由于音频信号是一种模拟信号,因此,需要调制传输过程中的数字信号,现阶段常用的调制方法有AM、FM以及PM,其中,AM虽然相对简单,但在抗干扰能力方面相对较差,所以,当前普遍运用的方法是FM与PM。应用相关广泛的音频调制方式为DTMF,市场上有很多与之相对应的编解码芯片,这些芯片能够在很大程度上简化对STM32单片机的开发环节。 在音频通信的过程中,其运作难点主要集中在调制与解调方面,STM32单片机可以运用当前相对成熟的芯片来完成对硬件的调制与解调工作,但是,Android设备在这方面却需要自行完成[2]。另外,一般情况下,20kHz是音频信号传输过程中的普遍上限,所以,运用音频进行通信的速率也相对较低,这种方式只适用于手持式刷卡机。 2串口通信 在嵌入式系统中,串口通信是最常见的通信方式,运用这种方式进行通信,STM32单片机的开发难度相对较小,其引脚、波特率、中断函数等参数都可以进行有针对性的设置,操作简单方便。

STM32 虚拟串口win7(64位)或XP驱动

;------------------------------------------------------------------------------ ; STMicroelectronics Comunication Device Class driver (CDC) INF FILE ; (C)2009 Copyright STMicroelectronics ;------------------------------------------------------------------------------ [Version] Signature="$Windows NT$" Class=Ports ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} Provider=%MANUFACTURER% LayoutFile=layout.inf ;CatalogFile=%FILENAME%.cat DriverVer= 9/20/2009,1.2.0 [Manufacturer] %MANUFACTURER%=DeviceList,NTamd64 [DestinationDirs] DefaultDestDir=12 ;------------------------------------------------------------------------------ ; Windows 2000/XP/Vista32 Support ;------------------------------------------------------------------------------ [DriverInstall.nt] include=mdmcpq.inf CopyFiles=DriverCopyFiles.nt AddReg=DriverInstall.nt.AddReg [DriverCopyFiles.nt] usbser.sys,,,0x20 [DriverInstall.nt.AddReg] HKR,,DevLoader,,*ntkern HKR,,NTMPDriver,,%DRIVERFILENAME%.sys HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" [DriverInstall.nt.Services] AddService=usbser, 0x00000002, DriverService.nt [DriverService.nt] DisplayName=%SERVICE%

7. STM32 控制步进电机正方转

实验目的:利用STM32 来控制步进电机正反转 实验设备:STM32开发板,两相步进电机,24V&5V直流电源,丝杆导轨,DM422C 驱动器 图1 实物图 第一步弄清楚驱动器接线 1.1 ENA可以悬空 大部分使用者就是将ENA悬空的,就是电机通常不锁轴 1.2 OPTO 是共阳极端 1.2.1 如果用的是AVR ,就直接接到AVR 5V接线柱上。 1.2.2 如果用的是ARM,就将OPTO接到5V 电源上,记得电源要和ARM共地,这样才能识别接的电源是5V 第二步弄清楚脉冲的发送形式,即Delay函数作用 清楚脉冲的发送形式,即Delay函数作用,

弄清楚接口由哪个GPIO口控制,然后连接硬件图, 通过电源IO控指示灯检验信号发送: 第三步主程序 下面这个程序是 /* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" void Delay (u32 nCount) { for(; nCount != 0; nCount--); } void GPIO_Config() { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);

STM32F103ZE手册

EM-STM3210E评估板用户手册 V1.0 深圳市英蓓特信息技术有限公司 Embest info & Tech Co., Ltd. 地址:深圳市罗湖区太宁路85号罗湖科技大厦509室(518020) Telephone: 86-755-25532557 25638952 25535753 25505451 Fax: 86-755-25616057 E-mail: sales@https://www.360docs.net/doc/2615204388.html, support.realview@https://www.360docs.net/doc/2615204388.html, Website: https://www.360docs.net/doc/2615204388.html, https://www.360docs.net/doc/2615204388.html,

第一章概述 EM-STM3210E是英蓓特公司新推出的一款基于ST意法半导体STM32系列处理器(Cortex-M3内核)的全功能评估板。功能接口丰富,是一个用于应用开发很好的平台,也是学习者的首选。配合本公司的调试工具ULINK2一起使用,更是为大家提供了一个良好的开发环境,从而为自己的应用开发节省了时间,提高的效率。 EM-STM3210E评估板主要性能: ◆处理器:STM32F103ZE,主频:72MHz ◆2MB NOR FLASH ◆128KB SRAM ◆128MB NAND FLASH ◆8M byte SPI Flash ◆RTC( 带后备电池) ◆启动跳线设置 ◆两路可选电源:5VDC供电,USB供电 ◆一个SD存储卡接口 ◆TFT- LCD屏接口 ◆一个温度传感器 ◆一路DAC音频输出 ◆20Pin JTAG调试接口 ◆2个三线RS232串行口 ◆一个USB Device接口 ◆一个具有控制四个方向和确定功能的摇杆手柄 ◆四个功能按键:Reset,Wakeup,Temper和User按键 ◆四个Led灯 ◆四位八段数码管输出 ◆一个CAN总线接口,通过DB9接口引出 ◆一路AD输入 ◆四个26Pin用户扩展接口

基于STM32的步进电机控制系统

基于STM32的步进电机控制系统 沈阳航空航天大学 2010年6月

摘要 本文的主要工作是基于STM32步进电机控制系统的设计。随着越来越多的高科技产品逐渐融入了日常生活中,步进电机控制系统发生了巨大的变化。单片机、C 语言等前沿学科的技术的日趋成熟与实用化,使得步进电机的控制系统有了新的的研究方向与意义。本文描述了一个由STM32微处理器、步进电机、LCD显示器、键盘等模块构成的,提供基于STM32的PWM细分技术的步进电机控制系统。该系统采用STM32微处理器为核心,在MDK的环境下进行编程,根据键盘的输入,使STM32产生周期性PWM信号,用此信号对步进电机的速度及转动方向进行控制,并且通过LCD显示出数据。结果表明该系统具有结构简单、工作可靠、精度高等特点. 关键词:STM32微处理器;步进电机;LCD显示;PWM信号;细分技术

Abstract As well as the high-tech products gradually integrated into the daily life,servo control system has undergone tremendous changes.SCM and C language of the frontier disciplines such mature technology and practical,steering control system is a new research direction and meaning.This paper describes a STM32 microprocessors, steering, LCD display and keyboard, Based on the STM32 servo control system of PWM signal,This system uses STM32 microprocessor as the core, MDK in the environment, according to the keyboard input , STM32 produce periodic PWM signal, with this signal to the velocity and Angle of steering gear control, and through the LCD display data. The features of the simple hardware, stable operation and high precision are incarnated in the proposed system. Keywords:STM32 microprocessors; Steering system; LCD display;pulse width modulation signal;Subdivide technology

stm32103与window虚拟串口

现在很多电脑已经不带232了,特别是手提电脑。这使很多使用手提在外调试人员非常不方便。或许你可以买一条市面上usb转232转换线,但这些线抗干扰不是太好,在一些干扰大的地方会发生连接中断的问题,所以往往要加光耦隔离器。在一些高端的单片机一般带USB接口,如果可以使用这些接口做一个USB的虚拟com口将会非常实用,但是使用USB一般要编写上位机驱程。没有windows驱程编写基础的朋友一般很为难。其实微软的CDC类中含有这一类USB转com的类,Windows也自带这方面的驱程。就像市面上的usb鼠标,u盘一样,windows里面已经有了他们的驱动函数库,只要我们按照windows的CDC描述来配置USB就可以了。 关于CDC的类描述类容请参考Universal Serial Bus Class Definitions for Communication Devices 的PDF文件。它是下面所有内容的纲领。 下面讲解下制作步骤: 1:把对应的描述符发送出去:下面是发送内容 const USB_DEVICE_DESCRIPTOR DeviceDescr = { // device descriptor 0x12, DESC_DEVICE, LE_WORD(0x0101), // bcdUSB 0x02, // bDeviceClass 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol MAX_PACKET_SIZE0, // bMaxPacketSize //设备ID LE_WORD(0xFFFF), // idVendor LE_WORD(0x0005), // idProduct LE_WORD(0x0100), // bcdDevice /* 不要使用原来的ID 0x71,0x04, // PHILIPS公司的设备ID Vendor ID = PHILIPS Semiconductor,Inc. 0x78,0x23, // 设备制造商定的产品ID Product ID 0x00,0x01, // 设备系列号Device release number in binary-coded decimal */ 0x01, // iManufacturer 0x02, // iProduct 0x03, // iSerialNumber

STM32控制步进电机程序

#include "sys.h" #include "usart.h" #include "delay.h" #include "led.h" #include "timer.h" #include "key.h" int main(void) { u8 t; u32 v=100; Stm32_Clock_Init(9); //系统时钟设置 delay_init(72); //延时初始化 uart_init(72,9600); //串口初始化 LED_Init(); //初始化与LED连接的硬件接口KEY_Init(); //初始化与按键连接的硬件接口 RCC->APB2ENR|=1<<2; //使能PORTA时钟 GPIOA->CRL&=0X0FFFFFFF; GPIOA->CRL|=0X30000000;//PA7推挽输出 GPIOA->ODR|=1<<7; //PA7 输出高 GPIOA->CRL&=0XFF0FFFFF; GPIOA->CRL|=0X00300000;//PA5推挽输出 GPIOA->ODR|=1<<5; //PA5 输出高 LED1=1; LED0=1; while(1) { t=KEY_Scan(0); //得到键值 switch(t) { case KEY0_PRES: v=v+10; TIM3_Int_Init(v,7199);//10Khz的计数频率 TIM3->CR1|=0x01; break; case KEY1_PRES: v=v-10 ; TIM3_Int_Init(v,7199);//10Khz的计数频率 TIM3->CR1|=0x01; //使能定时器3 break; case WKUP_PRES: TIM3->CR1&=0xFE;//关定时器3; break; }

STM32用IO口控制步进电机的简单程序

STM32用IO口控制步进电机的简单程序 练习IO口库函数操作。//相序uint16_tphasecw[4] ={0x2000,0x0001,0x0004,0x0008};//D-C-B- Auint16_tphaseccw[4]={0x0008,0x0004,0x0001,0x2000};//A-B-C-D //步进电机相关IO口初始化 //IN4:PC13//IN3:PC0//IN2:PC2//IN1:PC3voidMoto_Init(void){GPIO_InitTypeDefG PIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABL E);//GPIOCLOCKENABLEGPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;GPIO_Ini tStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//50MHz速率 GPIO_Init(GPIOC,&GPIO_InitStructure);GPIO_ResetBits(GPIOC,GPIO_Pin_13);// 输出低电平 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_Init(GPIOC,&GPIO_InitStructur e);GPIO_ResetBits(GPIOC,GPIO_Pin_0);GPIO_InitStructure.GPIO_Pin=GPIO_Pin _2;GPIO_Init(GPIOC,&GPIO_InitStructure);GPIO_ResetBits(GPIOC,GPIO_Pin_2); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;GPIO_Init(GPIOC,&GPIO_InitStructur e);GPIO_ResetBits(GPIOC,GPIO_Pin_3);} //电机正转voidMotorcw(void){uint8_ti;for(i=0;i记得使能IO口时钟。 tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

STM32的USB虚拟串口设计

毕业设计 [论文] 题目:基于STM32的USB虚拟串口 学院: 专业: 姓名: 学号: 指导老师: 完成时间:2014年5月19日

摘要 USB接口由于支持热插拔和标准统一等特点得到了广泛应用,越来越多的电脑设备开始采用USB接口进行数据的传输,而如何在不改变现有应用软件的情况下,将设备移植到USB接口成为人们研究的热门。 论文以USB通信设备类中的抽象控制模型为基础,研究了通信设备类及实现虚拟设备的原理,设计并实现了基于通信设备类的虚拟串口驱动程序。 论文研究设计了基于通信设备类的虚拟串口驱动程序的结构和实现方案,程序主要由通信命令转换和数据传输两部分构成,通信命令转换符合通信设备类中抽象控制模型的规范,数据传输部分对现有虚拟串口的实现技术进行了改进。论文的主要工作如下: 1)研究了USB协议的请求和传输模式,分析了通信设备类实现虚拟设备的方案。 2)给出了一种符合通信设备类中抽象控制模型的虚拟串口实现方案。该方案提供了 一种基于通信设备类开发虚拟设备的模板,对设计中的诸多问题进行了详细的说明,并改进了虚拟串口驱动程序中数据的处理流程。 3)将改进后的数据处理流程应用于虚拟串口的实现中,生成了一种基于通信设备类 的稳定、高速的虚拟串口。最后,在串口测试软件下对虚拟串口驱动程序进行了测试,达到了预期目标。 关键字:通讯设备类;枚举过程;虚拟串口程序;抽象控制模型

Abstract USB interface supports plug and play which has unified standards, so it has a wide ra nge of applications. More and more computer device use USB interface to transfer data, so how to make many old deaves to support USB interface without changing current applicati on is becoming the hot field. USB Communication Device Class and it's abstract control model are studied, princip les of Communication Device Class and implementation techniques of abstract device are a lso analyzed in the thesis. On the basis of this, design and implementation of virtual serial port driver based on Communication Device Class are given. The overall structure and implementation scheme of virtual serial port driver based on CDC are designed. The virtual serial port driver is made up of two parts which are commu nication command transfer module and data transmission module. The communication com mand transfer module satisfies the specification of abstract control model, and the data tran sfer part improves the technique of current virtual serial port. The main works in the thesis are as follows: 1)The request and transfer model for USB protocol are studied, and the implementation t echniques of virtual serial port are analyzed. 2)The implementation scheme of virtual serial port driver that satisfy abstract control mo de in CDC is graven. A new template for the development of virtual serial port based o n CDC is brought out, and it describes some issues for the virtual serial port driver in d etails, at the same time, the processing steps for virtual serial port driver is improved. 3)The improved data processing steps for virtual serial port driver is applied in the impl ementation of ritual serial port driver, and a stable, high-speed virtual serial port is ma de. At last, the test for the virtual serial port driveon ActiveSync is given, and the test r esult show that it's function is achieved the requirement goals. Keywords: Communication Device Class ;Enumeration Process; Virtual Serial Port Driver ;Abstract Control Model

步进电机-插补算法stm32

#include "stm32f10x.h" #include "delay.h" #include "misc.h" #include #include "stm32f10x_tim.h" #include "stm32f10x_rcc.h" #include "stm32f10x_usart.h" #include voidRCC_Configuration(void); voidGPIO_Configuration(void); voidNVIC_Configuration(void); voidTIM_Configuration(void); voidUSART_Configuration(void); intfputc(intch,FILE *f); intfgetc(FILE *f); float Mx=1.44f,My=2.88f;//起点 float Nx=10.0f,Ny=7.61f;//终点 float X1,Y1; float X2,Y2; float X3,Y3;//三种方法走后的坐标 float k;//斜率 float b;//y=kx+b float X,Y;//实际运行的坐标 float Delta1,Delta2,Delta3,Delta4;//三种方法的误差,4为不走最后一步的误差float Delta;//实际误差 // float DeltaMax;//最大误差 char way;//选择的走法 int a;//TIM6 中断次数 intnum=0;//总步数 inttx=1,ty=1;//用来判断中断是否发生 intnumx,numy;//计XY的步数 int counter=0;//计数值 float time;//时间 float nxd,nyd;//开始减速坐标 floatnx,ny;//nx=Nx-0.0144f; float fenmu;//公式中分母 // intfrex[20]={2,10,30,60,100,150,220,300,390,500}; // intfrey[20]={2,10,30,60,100,150,220,300,390,500}; int frex[20]={1098,2931,7585,18242,37754,62245,81757,92414,97068,98901}; int frey[20]={1098,2931,7585,18242,37754,62245,81757,92414,97068,98901}; intprex[20]={0};

相关文档
最新文档