iwinfo: add hw info support for Rt3xxx SoCs
[openwrt.git] / package / iwinfo / src / iwinfo_utils.c
index ec6aa22..164e51f 100644 (file)
@@ -145,7 +145,7 @@ struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id)
                        (e->subsystem_device_id != id->subsystem_device_id))
                        continue;
 
-               return e;
+               return (struct iwinfo_hardware_entry *)e;
        }
 
        return NULL;
@@ -165,7 +165,8 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
        while (fgets(buf, sizeof(buf), mtd) > 0)
        {
                if (fscanf(mtd, "mtd%d: %*x %x %127s", &off, &len, buf) < 3 ||
-                   strcmp(buf, "\"boardconfig\""))
+                   (strcmp(buf, "\"boardconfig\"") && strcmp(buf, "\"EEPROM\"") &&
+                    strcmp(buf, "\"factory\"")))
                {
                        off = -1;
                        continue;
@@ -184,7 +185,7 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
        if ((fd = open(buf, O_RDONLY)) < 0)
                return -1;
 
-       bc = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_LOCKED, fd, 0);
+       bc = mmap(NULL, len, PROT_READ, MAP_PRIVATE|MAP_LOCKED, fd, 0);
 
        if ((void *)bc != MAP_FAILED)
        {
@@ -193,6 +194,7 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
 
                for (off = len / 2 - 0x800; off >= 0; off -= 0x800)
                {
+                       /* AR531X board data magic */
                        if ((bc[off] == 0x3533) && (bc[off + 1] == 0x3131))
                        {
                                id->vendor_id = bc[off + 0x7d];
@@ -201,6 +203,36 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
                                id->subsystem_device_id = bc[off + 0x83];
                                break;
                        }
+
+                       /* AR5416 EEPROM magic */
+                       else if ((bc[off] == 0xA55A) || (bc[off] == 0x5AA5))
+                       {
+                               id->vendor_id = bc[off + 0x0D];
+                               id->device_id = bc[off + 0x0E];
+                               id->subsystem_vendor_id = bc[off + 0x13];
+                               id->subsystem_device_id = bc[off + 0x14];
+                               break;
+                       }
+
+                       /* Rt3xxx SoC */
+                       else if ((bc[off] == 0x3352) || (bc[off] == 0x5233) ||
+                                (bc[off] == 0x3350) || (bc[off] == 0x5033) ||
+                                (bc[off] == 0x3050) || (bc[off] == 0x5030) ||
+                                (bc[off] == 0x3052) || (bc[off] == 0x5230))
+                       {
+                               /* vendor: RaLink */
+                               id->vendor_id = 0x1814;
+                               id->subsystem_vendor_id = 0x1814;
+
+                               /* device */
+                               if (bc[off] & 0xf0 == 0x30)
+                                       id->device_id = (bc[off] >> 8) | (bc[off] & 0x00ff) << 8;
+                               else
+                                       id->device_id = bc[off];
+
+                               /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */
+                               id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8;
+                       }
                }
 
                munmap(bc, len);
@@ -210,3 +242,106 @@ int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
 
        return (id->vendor_id && id->device_id) ? 0 : -1;
 }
+
+void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
+                                         uint8_t defcipher, uint8_t defauth)
+{
+       uint16_t i, count;
+
+       static unsigned char ms_oui[3]        = { 0x00, 0x50, 0xf2 };
+       static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
+
+       data += 2;
+       len -= 2;
+
+       if (!memcmp(data, ms_oui, 3))
+               c->wpa_version += 1;
+       else if (!memcmp(data, ieee80211_oui, 3))
+               c->wpa_version += 2;
+
+       if (len < 4)
+       {
+               c->group_ciphers |= defcipher;
+               c->pair_ciphers  |= defcipher;
+               c->auth_suites   |= defauth;
+               return;
+       }
+
+       if (!memcmp(data, ms_oui, 3) || !memcmp(data, ieee80211_oui, 3))
+       {
+               switch (data[3])
+               {
+                       case 1: c->group_ciphers |= IWINFO_CIPHER_WEP40;  break;
+                       case 2: c->group_ciphers |= IWINFO_CIPHER_TKIP;   break;
+                       case 4: c->group_ciphers |= IWINFO_CIPHER_CCMP;   break;
+                       case 5: c->group_ciphers |= IWINFO_CIPHER_WEP104; break;
+                       case 6:  /* AES-128-CMAC */ break;
+                       default: /* proprietary */  break;
+               }
+       }
+
+       data += 4;
+       len -= 4;
+
+       if (len < 2)
+       {
+               c->pair_ciphers |= defcipher;
+               c->auth_suites  |= defauth;
+               return;
+       }
+
+       count = data[0] | (data[1] << 8);
+       if (2 + (count * 4) > len)
+               return;
+
+       for (i = 0; i < count; i++)
+       {
+               if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
+                       !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
+               {
+                       switch (data[2 + (i * 4) + 3])
+                       {
+                               case 1: c->pair_ciphers |= IWINFO_CIPHER_WEP40;  break;
+                               case 2: c->pair_ciphers |= IWINFO_CIPHER_TKIP;   break;
+                               case 4: c->pair_ciphers |= IWINFO_CIPHER_CCMP;   break;
+                               case 5: c->pair_ciphers |= IWINFO_CIPHER_WEP104; break;
+                               case 6:  /* AES-128-CMAC */ break;
+                               default: /* proprietary */  break;
+                       }
+               }
+       }
+
+       data += 2 + (count * 4);
+       len -= 2 + (count * 4);
+
+       if (len < 2)
+       {
+               c->auth_suites |= defauth;
+               return;
+       }
+
+       count = data[0] | (data[1] << 8);
+       if (2 + (count * 4) > len)
+               return;
+
+       for (i = 0; i < count; i++)
+       {
+               if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
+                       !memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
+               {
+                       switch (data[2 + (i * 4) + 3])
+                       {
+                               case 1: c->auth_suites |= IWINFO_KMGMT_8021x; break;
+                               case 2: c->auth_suites |= IWINFO_KMGMT_PSK;   break;
+                               case 3:  /* FT/IEEE 802.1X */                 break;
+                               case 4:  /* FT/PSK */                         break;
+                               case 5:  /* IEEE 802.1X/SHA-256 */            break;
+                               case 6:  /* PSK/SHA-256 */                    break;
+                               default: /* proprietary */                    break;
+                       }
+               }
+       }
+
+       data += 2 + (count * 4);
+       len -= 2 + (count * 4);
+}