看了android2.2的settings的源码,没有对wps的支持,但是现在好多android的手机都有对wps的支持,moto的里程碑2和mt870我都测试过,对wps支持的不错。http://digi.it.sohu.com/20100705/n273288063_6.shtml这个连接是介绍一款三星的手机,也有对wps的支持。
我现在想写段程序实现对wps的支持,但是无从下手,希望大虾们能给点思路。

解决方案 »

  1.   


     int wps_get_config(struct wpa_supplicant *wpa_s)
     {
      const struct wpa_config_blob *blob;
      const u8 *pos;
      const u8 *end;
      u16 tlv_type, tlv_len;
      u16 auth_type = 0;
      u16 encryption_type = 0;
      u8 *network_key = NULL;
      size_t network_key_len = 0;
      struct wpa_ssid *ssid = NULL;
      void *tmp = NULL;
     
      blob = wpa_config_get_blob(wpa_s->conf, WPS_BLOB_NAME_RESULT);
      if (NULL == blob)
      return -1;
     
      pos = blob->data;
      end = pos   blob->len;
     
      do {
      tlv_type = TLV_GET_TYPE(pos);
      tlv_len  = TLV_GET_LEN(pos);
      pos = TLV_GET_VAL(pos);
     
      switch (tlv_type) {
      case WPS_ELEM_NETWORK_INDEX:
      ssid = wpa_config_add_network(wpa_s->conf);
      if (NULL == ssid) {
      wpa_printf(MSG_ERROR, "Can't add network %s", __func__);
      return -1;
      }
      wpa_config_set_network_defaults(ssid);
     
      ssid->disabled = 1;
      ssid->proto = 0;
      ssid->key_mgmt = 0;
      ssid->pairwise_cipher = 0;
      ssid->group_cipher = 0;
      break;
      case WPS_ELEM_SSID:
      tmp = ssid->ssid;
      ssid->ssid = os_realloc(ssid->ssid, tlv_len);
      if (NULL != ssid->ssid) {
      os_memcpy(ssid->ssid, pos, tlv_len);
      ssid->ssid_len = tlv_len;
      /* Use SSID specific probe req in case this is a hidden SSID */
      ssid->scan_ssid = 1;
      } else {
      os_free(tmp);
      ssid->ssid_len = 0;
      }
      wpa_printf(MSG_WARNING, "EAP-WPS: SSID %s",
      wpa_ssid_txt((u8 *)pos, tlv_len));
      break;
      case WPS_ELEM_AUTHENTICATION_TYPE_FLAGS:
      auth_type = WPA_GET_BE16(pos);
     
      if (auth_type & WPS_AUTHENTICATION_TYPE_Shared) {
      ssid->auth_alg = WPA_AUTH_ALG_SHARED;
      wpa_printf(MSG_DEBUG, "EAP-WPS: shared key authentication");
      } else {
      ssid->auth_alg = WPA_AUTH_ALG_OPEN;
      wpa_printf(MSG_DEBUG, "EAP-WPS: open system authentication");
      }
     
      if (auth_type & WPS_AUTHENTICATION_TYPE_OPEN) {
      ssid->key_mgmt = WPA_KEY_MGMT_NONE;
      } else {
      if (auth_type &
      (WPS_AUTHENTICATION_TYPE_WPAPSK |
       WPS_AUTHENTICATION_TYPE_WPA)) {
      ssid->proto |= WPA_PROTO_WPA;
      wpa_printf(MSG_DEBUG, "EAP-WPS: protocol WPA");
      if (auth_type & WPS_AUTHENTICATION_TYPE_WPAPSK) {
      ssid->key_mgmt |= WPA_KEY_MGMT_PSK;
      wpa_printf(MSG_DEBUG, "EAP-WPS: key management PSK");
      }
      }
     
      if (auth_type &
      (WPS_AUTHENTICATION_TYPE_WPA2PSK |
       WPS_AUTHENTICATION_TYPE_WPA2)) {
      ssid->proto |= WPA_PROTO_RSN;
      wpa_printf(MSG_DEBUG, "EAP-WPS: protocol RSN");
      if (auth_type & WPS_AUTHENTICATION_TYPE_WPA2PSK) {
      ssid->key_mgmt |= WPA_KEY_MGMT_PSK;
      wpa_printf(MSG_DEBUG, "EAP-WPS: key management PSK");
      }
      }
      }
      break;
      case WPS_ELEM_ENCRYPTION_TYPE_FLAGS:
      encryption_type = WPA_GET_BE16(pos);
     
      if (encryption_type & WPS_ENCRYPTION_TYPE_NONE) {
      ssid->pairwise_cipher |= WPA_CIPHER_NONE;
      /*
       * Don't set group_cipher to WPA_CIPHER_NONE as this will end up
       * writing group=NONE to the configuration file (i.e. save_config)
       * which is an illegal value. Setting pairwise above is enough
       * to configure the supplicant for unencrypted traffic.
       */
      wpa_printf(MSG_DEBUG, "EAP-WPS: cipher NONE");
      }
     
      if (encryption_type & WPS_ENCRYPTION_TYPE_WEP) {
      ssid->pairwise_cipher |= WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104;
      ssid->group_cipher |= WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104;
      wpa_printf(MSG_DEBUG, "EAP-WPS: cipher WEP");
      }
     
      /*
       * WPS has a protocol problem in that a Credential contains a
       * single encryption type, but this doesn't account for AP that
       * use different ciphers for group and pairwise keys. The safest
       * approach is to enable both TKIP and CCMP, and let the upper
       * layer sort things out based on the advertised WPA/RSN IE.
       */
      if (encryption_type & WPS_ENCRYPTION_TYPE_TKIP ||
      encryption_type & WPS_ENCRYPTION_TYPE_AES) {
      ssid->pairwise_cipher |= WPA_CIPHER_TKIP | WPA_CIPHER_CCMP;
      ssid->group_cipher |= WPA_CIPHER_TKIP | WPA_CIPHER_CCMP;
      wpa_printf(MSG_DEBUG, "EAP-WPS: cipher TKIP/CCMP");
      }
      break;
      case WPS_ELEM_NETWORK_KEY:
      network_key = (u8 *)pos;
      network_key_len = tlv_len;
     
      if (network_key) {
      wpa_hexdump_key(MSG_DEBUG, "EAP-WPS: Network key",
      network_key, network_key_len);
      if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
      if (network_key_len < WPS_WPAPSK_PASSPHRASE_LEN) {
      size_t len = network_key_len;
     
      ssid->psk_set = 0;
      os_free(ssid->passphrase);
      ssid->passphrase = os_malloc(len  1);
      if (NULL == ssid->passphrase) {
      wpa_printf(MSG_DEBUG, "EAP-WPS: alloc failed for passphrase");
      } else {
      os_memcpy(ssid->passphrase, network_key, len);
      ssid->passphrase[len] = '\0';
      }
      wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-WPS: passphrase",
      (u8 *) ssid->passphrase,
      os_strlen(ssid->passphrase));
      wpa_config_update_psk(ssid);
      } else {
      ssid->psk_set = 1;
      hexstr2bin((const char *)network_key, ssid->psk,
      PMK_LEN);
      }
      wpa_hexdump_key(MSG_DEBUG, "EAP-WPS: psk", ssid->psk,
      PMK_LEN);
      } else {
      wpa_printf(MSG_ERROR, "EAP-WPS: key management not PSK");
      }
      ssid->disabled = 0;
      }
      break;
      }
     
      pos  = tlv_len;
      } while (pos < end);
     
      return 0;
      

  2.   

    尝试从开源项目移植
     int wpa_parse_wps_ie(const u8 *wps_ie, size_t wps_ie_len,
           struct wps_ie_data *data)
     {
      const struct wps_ie_hdr *hdr;
      const u8 *pos;
      int left;
      u16 elem, len;
     
      data->proto = WPA_PROTO_WPS;
     
      if (0 == wps_ie_len) {
      /* No WPS IE - fail silently */
      return -1;
      }
     
      if (wps_ie_len < sizeof(struct wps_ie_hdr)) {
      wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
         __func__, (unsigned long) wps_ie_len);
      return -1;
      }
     
      hdr = (const struct wps_ie_hdr *) wps_ie;
     
      if (hdr->elem_id != GENERIC_INFO_ELEM ||
          hdr->len != wps_ie_len - 2 ||
          os_memcmp(hdr->oui, WPS_OUI_TYPE, WPS_SELECTOR_LEN) != 0 ||
          hdr->version != WPS_VERSION) {
      wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
         __func__);
      return -1;
      }
     
      pos = (const u8 *) (hdr   1);
      left = wps_ie_len - sizeof(*hdr);
     
      while (left >= 2) {
      elem = WPA_GET_BE16(pos);
      len  = WPA_GET_BE16(pos 2);
      pos   = 4;
      left -= 4;
     
      if ((0 == len) || (len > left)) {
      wpa_printf(MSG_DEBUG, "%s: bad length %d (left %d)\n",
      __func__, len, left);
      return -1;
      }
      switch (elem) {
      case WPS_ELEM_DEVICE_PASSWORD_ID:
      if (data->selected_registrar)
      data->device_password_id = WPA_GET_BE16(pos);
      break;
      case WPS_ELEM_CONFIG_METHODS:
      data->config_method = WPA_GET_BE16(pos);
      break;
      case WPS_ELEM_SELECTED_REGISTRAR:
      data->selected_registrar = *pos;
      break;
      case WPS_ELEM_UUID_E:
      os_memcpy(data->uuid, pos, sizeof(data->uuid));
      break;
      }
      pos   = len;
      left -= len;
      }
      return 0;
     }
     
     static u8 * wps_write_tlv(u8 *buf, u16 type, u16 len, u8 *val)
     {
      WPA_PUT_BE16(buf, type);
      WPA_PUT_BE16(buf   2, len);
      os_memcpy(buf   4, val, len);
     
      return (buf   4   len);
     }
     
     static inline u8 * wps_write_tlv_u8(u8 *buf, u16 type, u8 val)
     {
      return wps_write_tlv(buf, type, 1, &val);
     }
     
     static inline u8 * wps_write_tlv_u16(u8 *buf, u16 type, u16 val)
     {
      u16 be_val = host_to_be16(val);
     
      return wps_write_tlv(buf, type, 2, (u8 *)&be_val);
     }
     
     int wpa_create_wps_ie(const char *uuid_str, u16 method, u8 *wps_ie,
      size_t *wps_ie_len)
     {
      u8 *pos = wps_ie;
      u8 uuid_e[WPS_UUID_LEN];
     
      *wps_ie_len = 0;
     
      if (uuid_str) {
      if (uuid_str2bin(uuid_str, uuid_e)) {
      wpa_printf(MSG_ERROR, "EAP-WPS: bad UUID format %s", uuid_str);
      return -1;
      }
      }
     
      *pos   = GENERIC_INFO_ELEM;
      pos  ; /* skip length initially */
      os_memcpy(pos, WPS_OUI_TYPE, WPS_SELECTOR_LEN);
      pos  = WPS_SELECTOR_LEN;
      pos = wps_write_tlv_u8(pos, WPS_ELEM_VERSION, WPS_VERSION);
      pos = wps_write_tlv_u8(pos, WPS_ELEM_REQUEST_TYPE,
      WPS_REQUEST_TYPE_ENROLLEE_OPEN);
      pos = wps_write_tlv_u16(pos, WPS_ELEM_CONFIG_METHODS,
      WPS_CONFIG_METHOD_DEFAULT);
      pos = wps_write_tlv(pos, WPS_ELEM_UUID_E, WPS_UUID_LEN, uuid_e);
      pos = wps_write_tlv(pos, WPS_ELEM_PRIMARY_DEVICE_TYPE, 8,
      (u8 *)"\x00\x01\x00\x50\xf2\x04\x00\x01");
      pos = wps_write_tlv_u8(pos, WPS_ELEM_RF_BANDS,
      WPS_RF_BAND_2_4GHZ | WPS_RF_BAND_5_0GHZ);
      pos = wps_write_tlv_u16(pos, WPS_ELEM_ASSOCIATION_STATE,
      WPS_ASSOCIATION_STATE_NOT_ASSOCIATED);
      pos = wps_write_tlv_u16(pos, WPS_ELEM_CONFIGURATION_ERROR,
      WPS_CONFIGURATION_ERROR_NO_ERROR);
      pos = wps_write_tlv_u16(pos, WPS_ELEM_DEVICE_PASSWORD_ID,
      WPS_CONFIG_METHOD_PBC == method ?
      WPS_DEVICE_PASSWORD_ID_PBC : WPS_DEVICE_PASSWORD_ID_PIN);
     
      *wps_ie_len = (size_t)pos - (size_t)wps_ie;
     
      wps_ie[1] = (u8)(*wps_ie_len) - 2;
     
      return 0;
     }
     
     static void wps_walktime_timeout(void *eloop_ctx, void *timeout_ctx)
     {
      struct wpa_supplicant *wpa_s = eloop_ctx;
     
      wpa_msg(wpa_s, MSG_DEBUG, "WPS walk time expired");
      wpa_s->wps_config_method = 0;
     }
     
     int wps_config_pbc(struct wpa_supplicant *wpa_s)
     {
      wpa_s->wps_config_method = WPS_CONFIG_METHOD_PBC;
     
      os_free(wpa_s->wps_pin);
      wpa_s->wps_pin = os_strdup(WPS_PIN_PBC);
     
      eloop_cancel_timeout(wps_walktime_timeout, wpa_s, NULL);
      eloop_register_timeout(WPS_WALK_TIME, 0, wps_walktime_timeout, wpa_s, NULL);
     
      return 0;
     }
     
     int wps_cancel_walktime_timeout(struct wpa_supplicant *wpa_s)
     {
      eloop_cancel_timeout(wps_walktime_timeout, wpa_s, NULL);
      wpa_s->wps_config_method = 0;
     
      return 0;
     }
      

  3.   

    楼上的,加你qq了但是一直没有反应  -_-#通过result.capabilities现在可以判断出支持wps的热点,现在的问题是用wps方式连接wifi, WifiConfiguration应该怎么配置,我是需要通过wps按钮的方式连接,请指教。
      

  4.   

    發現<android>/external/wpa_supplicant_6/wpa_supplicant/wpa_supplicant.c
    有wps的函式