ZG2100 Network interface source

drv/zg2100/zg_if.c

Committer:
donatien
Date:
2010-08-06
Revision:
4:e00281c7453d
Parent:
1:3a7c15057192

File content as of revision 4:e00281c7453d:


/*
Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "netCfg.h"
#if NET_ZG2100

#include "zg_defs.h"
#include "zg_drv.h"
#include "zg_if.h"

//#define __DEBUG
#include "dbg/dbg.h"

#include "string.h"

char m_ssid[ZG_SSID_LEN+1] = {0};
zg_err connection_result = (zg_err)0; //Disc

#ifdef __DEBUG
/*inline*/ void hexdump(byte* buffer, int size) {
    for(int i = 0; i < size; ++i) {
        if((i%16)!=0) {
            DBG(" ");
        } else {
            DBG("%04X:  ", (i));
        }
        DBG("%02hhx", buffer[i]);
        if((i%16) ==  7) { 
            DBG(" ");
        }
        if((i%16) == 15) {
            DBG("\n");
        }
    }
    DBG("\n\n\n");
}
#else
#define hexdump(a,b) 
#endif

void zg_scan(byte channel)
{
  //Prepare request
  ZG_SCAN_REQ* req = (ZG_SCAN_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_SCAN_REQ));
  
  req->probe_delay = HTODS(ZG_SCAN_PROBE_DELAY);
  
  req->min_chan_time = HTODS(ZG_SCAN_MIN_CHAN_TIME);
  req->max_chan_time = HTODS(ZG_SCAN_MAX_CHAN_TIME);
  
  memset(req->bssid_mask, 0xFF, ZG_MACADDR_LEN); //Broadcast
  
  req->bss_type = ZG_BSS_ANY;
  req->probe_req = ZG_PROBE_ACTIVE;
  
  req->ssid_len = 0; //Do not filter by SSID
  
  req->channels_count = 1; //Scan on all ETSI channels (1~13)
  req->channels[0] = channel;
  
  //hexdump(fifo_buf, sizeof(ZG_SCAN_REQ));
  
  DBG("\r\n\r\n");
  
  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_SCAN, fifo_buf, sizeof(ZG_SCAN_REQ));
}

void zg_on_scan_results(byte* buf, int len)
{
  int i;
  int j;
  uint32_t rate;
  char ssid[ZG_SSID_LEN + 1];
  ZG_SCAN_ITEM* it;
  //Get result header
  ZG_SCAN_RES* res = (ZG_SCAN_RES*)buf;
  
  //hexdump(buf, len);
  
  DBG("\r\nScan result %d, with %d networks found\n", 
  res->result, res->results_count);
  
  if( res->result != 1 )
  {
    return; //Error
  }
  it = (ZG_SCAN_ITEM*)(buf + sizeof(ZG_SCAN_RES));
  for( i = 0; i < res->results_count; i++ )
  {
    //Display info
    DBG("\r\n---Result #%2d---\n",i+1);
    
    memset(ssid, 0, ZG_SSID_LEN + 1);
    memcpy(ssid, it->ssid, it->ssid_len);
    DBG("SSID : %s\n", ssid);

    DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x\n", 
    it->bssid[0], it->bssid[1], it->bssid[2],
    it->bssid[3], it->bssid[4], it->bssid[5]);
    
    DBG("Supported rates : ");
    for( j = 0; j < it->supported_rates_count; j++ )
    {
      rate = it->supported_rates[j];
      rate = rate * 500;
      DBG("%u Kbps; ", rate);
    }
    DBG("\n");
    
    DBG("RSSI : %d\n", it->rssi);
    DBG("Channel : %d\n", it->channel);
    DBG("Type : %d\n", it->bss_type);
    
    DBG("---------------\n");
    
    it++; //Next result
  }
}

void zg_set_ssid(const char* ssid)
{
  strcpy(m_ssid, ssid);
}

void zg_set_wep_key(const byte* key, int len)
{
  //Write 4 wep keys
  ZG_WEP_REQ* req = (ZG_WEP_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_WEP_REQ));
  
  req->slot = 3; //WEP key slot
  
  req->key_size = len; //FIXME: Assert 5 or 13 bytes long  
  req->default_key = 0;
  
  strncpy(req->ssid, m_ssid, ZG_SSID_LEN);
  req->ssid_len = strlen(m_ssid);
  
  memcpy((void*)req->keys, key, len);
  
  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_WEP_KEY, fifo_buf, sizeof(ZG_WEP_REQ));
}

void zg_set_wpa_pass(const char* pass)
{
  //Compute PNK key with this passphrase
  //On completion, zg_on_psk_key will be called
  ZG_PSK_CALC_REQ* req = (ZG_PSK_CALC_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_PSK_CALC_REQ));
  
  req->config = 0;
  
  req->phrase_len = strlen(pass);
  
  strncpy(req->ssid, m_ssid, ZG_SSID_LEN);
  req->ssid_len = strlen(m_ssid);
  
  strncpy(req->pass_phrase, pass, ZG_WPA_PASS_LEN);
  
  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_PSK_CALC, fifo_buf, sizeof(ZG_PSK_CALC_REQ));
}

void zg_on_psk_key(byte* buf, int len)
{
  //Now the key has been computed and we can write it
  ZG_PSK_CALC_RES* res = (ZG_PSK_CALC_RES*) buf;
  if( (res->result != 1) || (res->key_returned != 1) )
  {
    DBG("Could not compute key, error %d\n", res->result);
    return; //Error
  }
  
  DBG("PMK key is :\n");
  hexdump(res->key, ZG_PMK_LEN);
  
  byte key[ZG_PMK_LEN];
  memcpy(key, res->key, ZG_PMK_LEN);
  
  //Send next request
  zg_set_psk_key(key, ZG_PMK_LEN);
}

void zg_set_psk_key(const byte* key, int len)
{
  ZG_PMK_REQ* req = (ZG_PMK_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_PMK_REQ));
  
  req->slot = 0; //WPA/WPA2 PSK slot
  
  strncpy(req->ssid, m_ssid, ZG_SSID_LEN);
  req->ssid_len = strlen(m_ssid);
  
  memcpy(req->key, key, ZG_PMK_LEN);

  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_PMK_KEY, fifo_buf, sizeof(ZG_FIFO_MGMT_PMK_KEY)); 
}

void zg_connect(ZG_BSS_TYPE type, ZG_SECURITY security)
{
  ZG_CONNECT_REQ* req = (ZG_CONNECT_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_CONNECT_REQ));
  
  req->security = security;
  
  strncpy(req->ssid, m_ssid, ZG_SSID_LEN);
  req->ssid_len = strlen(m_ssid);
  
  req->sleep_duration = HTODS( 0 );
  
  req->bss_type = type;
  
  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_CONNECT, fifo_buf, sizeof(ZG_CONNECT_REQ)); 
}

void zg_on_connect(zg_err result)
{
  connection_result = result;
}

zg_err zg_get_connection_result()
{
  return connection_result;
}

void zg_disconnect()
{
  ZG_DISCONNECT_REQ* req = (ZG_DISCONNECT_REQ*)fifo_buf;
  memset((void*)req, 0, sizeof(ZG_DISCONNECT_REQ));
  
  req->reason_code = HTODS( 0 );
  req->disconnect = true;
  req->deauth_frame = true;
    
  //Send request
  zg_mgmt_req(ZG_FIFO_MGMT_DISC, fifo_buf, sizeof(ZG_DISCONNECT_REQ)); 
  
  connection_result = (zg_err)0;
}

#endif