mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-13 22:47:47 +00:00

* add macaddress db, add vendor name in bluetooth rx app * show "missing macaddress.db" instead of unknown if db not found * bluetooth rx list with colors based on mac vendor * bug fix
131 lines
4.4 KiB
Python
131 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright (C) 2025 Tommaso Ventafridda
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2, or (at your option)
|
|
# any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; see the file COPYING. If not, write to
|
|
# the Free Software Foundation, Inc., 51 Franklin Street,
|
|
# Boston, MA 02110-1301, USA.
|
|
#
|
|
# -------------------------------------------------------------------------------------
|
|
# Create macaddress.db, used for BLE receiver application, using
|
|
# https://standards-oui.ieee.org/oui/oui.txt as a source.
|
|
# -------------------------------------------------------------------------------------
|
|
|
|
import urllib.request
|
|
import unicodedata
|
|
import re
|
|
from typing import List, Tuple
|
|
|
|
|
|
def download_oui_file() -> str:
|
|
"""Download the OUI file from IEEE"""
|
|
url = "https://standards-oui.ieee.org/oui/oui.txt"
|
|
print(f"Downloading OUI database from {url}...")
|
|
try:
|
|
with urllib.request.urlopen(url) as response:
|
|
content = response.read().decode("utf-8")
|
|
print("Download completed successfully.")
|
|
return content
|
|
except Exception as e:
|
|
print(f"Error downloading OUI file: {e}")
|
|
raise
|
|
|
|
|
|
def parse_oui_data(content: str) -> List[Tuple[str, str]]:
|
|
"""Parse the OUI file content and extract MAC prefixes and vendor names"""
|
|
entries = []
|
|
lines = content.split("\n")
|
|
|
|
for _, line in enumerate(lines):
|
|
# Look for lines with (hex) pattern
|
|
if "(hex)" in line:
|
|
# Extract MAC prefix and vendor name
|
|
match = re.match(
|
|
r"^([0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2})\s+\(hex\)\s+(.+)$",
|
|
line.strip(),
|
|
)
|
|
if match:
|
|
# Remove dashes: "28-6F-B9" -> "286FB9"
|
|
mac_prefix = match.group(1).replace(
|
|
"-", ""
|
|
)
|
|
vendor_name = match.group(2).strip()
|
|
|
|
# Normalize vendor name and limit to 63 characters
|
|
vendor_name = (
|
|
unicodedata.normalize("NFKD", vendor_name[:63])
|
|
.encode("ascii", "ignore")
|
|
.decode("ascii")
|
|
)
|
|
|
|
if mac_prefix and vendor_name:
|
|
entries.append((mac_prefix, vendor_name))
|
|
|
|
print(f"Parsed {len(entries)} MAC address entries.")
|
|
return entries
|
|
|
|
|
|
def create_database(
|
|
entries: List[Tuple[str, str]], output_filename: str = "macaddress.db"
|
|
):
|
|
"""Create the binary database file."""
|
|
# Sort entries by MAC prefix for binary search
|
|
entries.sort(key=lambda x: x[0])
|
|
|
|
mac_prefixes = bytearray()
|
|
vendor_data = bytearray()
|
|
row_count = 0
|
|
|
|
for mac_prefix, vendor_name in entries:
|
|
# MAC prefix: 6 hex chars + null terminator = 7 bytes
|
|
mac_prefixes += bytearray(mac_prefix + "\0", encoding="ascii")
|
|
|
|
# Vendor name: pad to 64 bytes
|
|
vendor_bytes = vendor_name.encode("ascii", "ignore")
|
|
vendor_padding = bytearray("\0" * (64 - len(vendor_bytes)), encoding="ascii")
|
|
vendor_data += vendor_bytes + vendor_padding
|
|
|
|
row_count += 1
|
|
|
|
# Write database: index section followed by data section
|
|
with open(output_filename, "wb") as database:
|
|
database.write(mac_prefixes + vendor_data)
|
|
|
|
print(f"Created database '{output_filename}' with {row_count} MAC address entries.")
|
|
print(f"Index section: {len(mac_prefixes)} bytes")
|
|
print(f"Data section: {len(vendor_data)} bytes")
|
|
print(f"Total database size: {len(mac_prefixes) + len(vendor_data)} bytes")
|
|
|
|
|
|
def main():
|
|
"""Main function to create the MAC address database."""
|
|
try:
|
|
oui_content = download_oui_file()
|
|
entries = parse_oui_data(oui_content)
|
|
|
|
if not entries:
|
|
print("No valid entries found in OUI file!")
|
|
return
|
|
|
|
create_database(entries)
|
|
|
|
print("MAC address database creation completed successfully!")
|
|
|
|
except Exception as e:
|
|
print(f"Error creating MAC address database: {e}")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
exit(main())
|