/* SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #define CROS_VPD_REGION_NAME "region" /* * wrdd_domain_value is ISO 3166-2 * ISO 3166-2 code consists of two parts, separated by a hyphen * The first part is the ISO 3166-1 alpha-2 code of the country; * The second part is a string of up to three alphanumeric characters */ #define VARIANT_SEPARATOR '.' struct wrdd_code_value_pair { const char *code; u16 value; }; /* Retrieve the regulatory domain information from VPD and * return it as an uint16. * WARNING: if domain information is not found in the VPD, * this function will fall back to the default value */ uint16_t wifi_regulatory_domain(void) { static struct wrdd_code_value_pair wrdd_table[] = { { /* Indonesia * Alpha-2 code 'ID' * Full name 'the Republic of Indonesia' * Alpha-3 code 'IDN' * Numeric code '360' */ .code = "id", .value = WRDD_REGULATORY_DOMAIN_INDONESIA } }; const char *wrdd_domain_key = CROS_VPD_REGION_NAME; int i; struct wrdd_code_value_pair *p; /* wrdd_domain_value is ISO 3166-2 */ char wrdd_domain_code[7]; char *separator; /* If not found for any reason fall backto the default value */ if (!vpd_gets(wrdd_domain_key, wrdd_domain_code, ARRAY_SIZE(wrdd_domain_code), VPD_RO_THEN_RW)) { printk(BIOS_DEBUG, "Error: Could not locate '%s' in VPD\n", wrdd_domain_key); return WRDD_DEFAULT_REGULATORY_DOMAIN; } printk(BIOS_DEBUG, "Found '%s'='%s' in VPD\n", wrdd_domain_key, wrdd_domain_code); separator = memchr(wrdd_domain_code, VARIANT_SEPARATOR, ARRAY_SIZE(wrdd_domain_code)); if (separator) { *separator = '\0'; } for (i = 0; i < ARRAY_SIZE(wrdd_table); i++) { p = &wrdd_table[i]; if (strncmp(p->code, wrdd_domain_code, ARRAY_SIZE(wrdd_domain_code)) == 0) return p->value; } return WRDD_DEFAULT_REGULATORY_DOMAIN; }