fe35cb68d6
Ports the ESP32 Wi-Fi emulation (esp32c3_wifi, esp32_wifi_ap, esp32_wlan_*) from the lcgamboa/PICSimLab QEMU fork and integrates it behind the esp32c3_wifi NIC model, plus the supporting radio peripherals (ANA/PHYA/FE/PWR manager). - Exposes an open SSID 'qemu' bridged to the host via QEMU user-mode NAT (libslirp, now enabled in the native build). - Adds ESP-IDF 5.5 compatibility fixes: channel resolution from the beacon DS Parameter Set IE / AP lookup, persistent SYSCON register backing (phy_module_has_clock_bits), DMA inlink/outlink descriptor mirroring, RX descriptor ring reset on item.next==0, and descriptor ownership/length semantics. - xteink-emu now starts with -nic user,model=esp32c3_wifi and synthesizes an eFuse image with a fixed guest MAC. Verified against a stock Arduino-ESP32 sketch: scans, finds 'qemu', associates, gets DHCP 192.168.4.15, and completes an outbound TCP connection. Unmodified CrossPoint firmware still needs the power-button hold during boot (tracked separately).
281 lines
11 KiB
C
281 lines
11 KiB
C
/**
|
|
* QEMU WLAN device emulation
|
|
*
|
|
* Copyright (c) 2008 Clemens Kolbitsch
|
|
*
|
|
* 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.
|
|
*
|
|
* Modifications:
|
|
* 2008-February-24 Clemens Kolbitsch :
|
|
* New implementation based on ne2000.c
|
|
* 18/1/22 Martin Johnson : Modified for esp32 wifi emulation
|
|
*
|
|
*/
|
|
|
|
#ifndef esp32_wlan_h
|
|
#define esp32_wlan_h 1
|
|
|
|
|
|
//#define DEBUG_Esp32_WLAN
|
|
|
|
#ifdef DEBUG_Esp32_WLAN
|
|
#define DEBUG_PRINT_AP(x) \
|
|
do { \
|
|
struct timeval __tt; \
|
|
gettimeofday(&__tt, NULL); \
|
|
printf("%u:%u ", (unsigned)__tt.tv_sec, (unsigned)__tt.tv_usec); \
|
|
printf x ;\
|
|
} while (0)
|
|
#else
|
|
#define DEBUG_PRINT_AP(x)
|
|
#endif
|
|
|
|
|
|
#define IEEE80211_IDLE 0xff
|
|
|
|
#define IEEE80211_TYPE_MGT 0x00
|
|
#define IEEE80211_TYPE_CTL 0x01
|
|
#define IEEE80211_TYPE_DATA 0x02
|
|
|
|
#define IEEE80211_ENCAPSULATED 0xA0
|
|
#define IEEE80211_ENCAPSULATED_PROTECTED 0xB0
|
|
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_BEACON 0x08
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_ACTION 0x0d
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_PROBE_REQ 0x04
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_PROBE_RESP 0x05
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION 0x0b
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION 0x0c
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_REQ 0x00
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_RESP 0x01
|
|
#define IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION 0x0a
|
|
|
|
#define IEEE80211_TYPE_CTL_SUBTYPE_ACK 0x0d
|
|
|
|
#define IEEE80211_TYPE_DATA_SUBTYPE_DATA 0x00
|
|
|
|
#define IEEE80211_BEACON_PARAM_SSID 0x00
|
|
#define IEEE80211_BEACON_PARAM_RATES 0x01
|
|
#define IEEE80211_BEACON_PARAM_CHANNEL 0x03
|
|
#define IEEE80211_BEACON_PARAM_EXTENDED_RATES 0x32
|
|
#define IEEE80211_BEACON_PARAM_TIM 0x05
|
|
|
|
|
|
#define IEEE80211_HEADER_SIZE 24
|
|
|
|
typedef struct beacon_info_t {
|
|
uint64_t timestamp;
|
|
uint16_t interval;
|
|
uint16_t capability;
|
|
} QEMU_PACKED beacon_info_t;
|
|
|
|
typedef uint8_t macaddr_t[6];
|
|
|
|
#define BROADCAST (uint8_t[]){0xff,0xff,0xff,0xff,0xff,0xff}
|
|
|
|
typedef struct mac80211_frame {
|
|
struct mac80211_frame_control {
|
|
unsigned protocol_version : 2;
|
|
unsigned type : 2;
|
|
unsigned sub_type : 4;
|
|
unsigned flags:8;
|
|
} QEMU_PACKED frame_control;
|
|
uint16_t duration_id;
|
|
macaddr_t destination_address;
|
|
macaddr_t source_address;
|
|
macaddr_t bssid_address;
|
|
struct mac80211_sequence_control {
|
|
unsigned fragment_number : 4;
|
|
unsigned sequence_number : 12;
|
|
} QEMU_PACKED sequence_control;
|
|
// variable length, 2312 byte plus 4 byte frame-checksum
|
|
union {
|
|
uint8_t data_and_fcs[2316];
|
|
beacon_info_t beacon_info;
|
|
};
|
|
unsigned int frame_length;
|
|
int signal_strength;
|
|
int pos;
|
|
struct mac80211_frame *next_frame;
|
|
} QEMU_PACKED mac80211_frame;
|
|
|
|
typedef struct access_point_info {
|
|
const char *ssid;
|
|
int channel;
|
|
int sigstrength;
|
|
macaddr_t mac_address;
|
|
} access_point_info;
|
|
|
|
enum esp32_ap_state {
|
|
Esp32_WLAN__STATE_NOT_AUTHENTICATED,
|
|
Esp32_WLAN__STATE_AUTHENTICATED,
|
|
Esp32_WLAN__STATE_ASSOCIATED,
|
|
Esp32_WLAN__STATE_STA_NOT_AUTHENTICATED,
|
|
Esp32_WLAN__STATE_STA_AUTHENTICATED,
|
|
Esp32_WLAN__STATE_STA_ASSOCIATED,
|
|
Esp32_WLAN__STATE_STA_DHCP,
|
|
};
|
|
|
|
#define Esp32_WLAN__MAX_INJECT_QUEUE_SIZE 20
|
|
|
|
typedef struct {
|
|
signed rssi:8; /**< Received Signal Strength Indicator(RSSI) of packet. unit: dBm */
|
|
unsigned rate:5; /**< PHY rate encoding of the packet. Only valid for non HT(11bg) packet */
|
|
unsigned :1; /**< reserved */
|
|
unsigned sig_mode:2; /**< 0: non HT(11bg) packet; 1: HT(11n) packet; 3: VHT(11ac) packet */
|
|
unsigned legacy_length:12; /**< copy of the length */
|
|
unsigned damatch0:1; /* destination matches address0 */
|
|
unsigned damatch1:1; /* destination matches address1 */
|
|
unsigned bssidmatch0:1; /* bssid matches address0 */
|
|
unsigned bssidmatch1:1; /* bssid matches address1 */
|
|
unsigned mcs:7; /**< Modulation Coding Scheme. If is HT(11n) packet, shows the modulation, range from 0 to 76(MSC0 ~ MCS76) */
|
|
unsigned cwb:1; /**< Channel Bandwidth of the packet. 0: 20MHz; 1: 40MHz */
|
|
unsigned :16; /**< reserved */
|
|
unsigned smoothing:1; /**< reserved */
|
|
unsigned not_sounding:1; /**< reserved */
|
|
unsigned :1; /**< reserved */
|
|
unsigned aggregation:1; /**< Aggregation. 0: MPDU packet; 1: AMPDU packet */
|
|
unsigned stbc:2; /**< Space Time Block Code(STBC). 0: non STBC packet; 1: STBC packet */
|
|
unsigned fec_coding:1; /**< Flag is set for 11n packets which are LDPC */
|
|
unsigned sgi:1; /**< Short Guide Interval(SGI). 0: Long GI; 1: Short GI */
|
|
signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: 0.25dBm*/
|
|
unsigned ampdu_cnt:8; /**< ampdu cnt */
|
|
unsigned channel:4; /**< primary channel on which this packet is received */
|
|
unsigned secondary_channel:4; /**< secondary channel on which this packet is received. 0: none; 1: above; 2: below */
|
|
unsigned :8; /**< reserved */
|
|
unsigned timestamp:32; /**< timestamp. The local time when this packet is received. It is precise only if modem sleep or light sleep is not enabled. unit: microsecond */
|
|
unsigned :32; /**< reserved */
|
|
unsigned :31; /**< reserved */
|
|
unsigned ant:1; /**< antenna number from which this packet is received. 0: WiFi antenna 0; 1: WiFi antenna 1 */
|
|
unsigned sig_len:12; /**< length of packet including Frame Check Sequence(FCS) */
|
|
unsigned sig_len_copy:12; /**< another copy of the length */
|
|
unsigned rx_state:8; /**< state of the packet. 0: no error; others: error numbers which are not public */
|
|
} QEMU_PACKED wifi_pkt_rx_ctrl_t;
|
|
|
|
|
|
typedef struct {
|
|
signed rssi:8; /**< Received Signal Strength Indicator(RSSI) of packet. unit: dBm */
|
|
unsigned rate:5; /**< PHY rate encoding of the packet. Only valid for non HT(11bg) packet */
|
|
unsigned :1; /**< reserved */
|
|
unsigned sig_mode:2; /**< 0: non HT(11bg) packet; 1: HT(11n) packet; 3: VHT(11ac) packet */
|
|
unsigned legacy_length:12; /**< copy of the length */
|
|
unsigned damatch0:1; /* destination matches address0 */
|
|
unsigned damatch1:1; /* destination matches address1 */
|
|
unsigned bssidmatch0:1; /* bssid matches address0 */
|
|
unsigned bssidmatch1:1; /* bssid matches address1 */
|
|
unsigned mcs:7; /**< Modulation Coding Scheme. If is HT(11n) packet, shows the modulation, range from 0 to 76(MSC0 ~ MCS76) */
|
|
unsigned cwb:1; /**< Channel Bandwidth of the packet. 0: 20MHz; 1: 40MHz */
|
|
unsigned :16; /**< reserved */
|
|
unsigned smoothing:1; /**< reserved */
|
|
unsigned not_sounding:1; /**< reserved */
|
|
unsigned :1; /**< reserved */
|
|
unsigned aggregation:1; /**< Aggregation. 0: MPDU packet; 1: AMPDU packet */
|
|
unsigned stbc:2; /**< Space Time Block Code(STBC). 0: non STBC packet; 1: STBC packet */
|
|
unsigned fec_coding:1; /**< Flag is set for 11n packets which are LDPC */
|
|
unsigned sgi:1; /**< Short Guide Interval(SGI). 0: Long GI; 1: Short GI */
|
|
unsigned :8; /**< reserved */
|
|
unsigned ampdu_cnt:8; /**< ampdu cnt */
|
|
unsigned channel:4; /**< primary channel on which this packet is received */
|
|
unsigned secondary_channel:4; /**< secondary channel on which this packet is received. 0: none; 1: above; 2: below */
|
|
unsigned :8; /**< reserved */
|
|
unsigned timestamp:32; /**< timestamp. The local time when this packet is received. It is precise only if modem sleep or light sleep is not enabled. unit: microsecond */
|
|
unsigned :32; /**< reserved */
|
|
signed noise_floor:8; /**< noise floor of Radio Frequency Module(RF). unit: dBm*/
|
|
unsigned :24; /**< reserved */
|
|
unsigned :32; /**< reserved */
|
|
unsigned :31; /**< reserved */
|
|
unsigned ant:1; /**< antenna number from which this packet is received. 0: WiFi antenna 0; 1: WiFi antenna 1 */
|
|
unsigned :32; /**< reserved */
|
|
unsigned :32; /**< reserved */
|
|
unsigned :32; /**< reserved */
|
|
unsigned sig_len:12; /**< length of packet including Frame Check Sequence(FCS) */
|
|
unsigned sig_len_copy:12; /**< another copy of the length */
|
|
unsigned rx_state:8; /**< state of the packet. 0: no error; others: error numbers which are not public */
|
|
} QEMU_PACKED wifi_pkt_rx_ctrl_c3_t;
|
|
|
|
extern int esp32_wifi_channel;
|
|
|
|
typedef uint8_t ip4_t[4];
|
|
|
|
#define DHCP_CHADDR_LEN 16
|
|
#define DHCP_SNAME_LEN 64
|
|
#define DHCP_FILE_LEN 128
|
|
|
|
typedef struct ip_header_t {
|
|
uint8_t version_size;
|
|
uint8_t dscp_ecn;
|
|
uint8_t len_h;
|
|
uint8_t len_l;
|
|
uint32_t z;
|
|
uint8_t ttl;
|
|
uint8_t protocol;
|
|
uint16_t checksum;
|
|
ip4_t source_ip;
|
|
ip4_t dest_ip;
|
|
}ip_header_t ;
|
|
|
|
typedef struct udp_header_t {
|
|
uint8_t src_port_h;
|
|
uint8_t src_port_l;
|
|
uint8_t dest_port_h;
|
|
uint8_t dest_port_l;
|
|
uint8_t len_h;
|
|
uint8_t len_l;
|
|
uint16_t checksum;
|
|
} udp_header_t;
|
|
|
|
typedef struct dhcp_t {
|
|
uint8_t opcode;
|
|
uint8_t htype;
|
|
uint8_t hlen;
|
|
uint8_t hops;
|
|
uint32_t xid;
|
|
uint16_t secs;
|
|
uint16_t flags;
|
|
ip4_t ciaddr;
|
|
ip4_t yiaddr;
|
|
ip4_t siaddr;
|
|
ip4_t giaddr;
|
|
uint8_t chaddr[DHCP_CHADDR_LEN];
|
|
char bp_sname[DHCP_SNAME_LEN];
|
|
char bp_file[DHCP_FILE_LEN];
|
|
uint32_t magic_cookie;
|
|
uint8_t bp_options[0];
|
|
} dhcp_t;
|
|
|
|
typedef struct dhcp_request_t {
|
|
ip_header_t ipheader;
|
|
udp_header_t udpheader;
|
|
dhcp_t dhcp;
|
|
} dhcp_request_t;
|
|
|
|
typedef struct arp_header_t {
|
|
uint16_t htype;
|
|
uint16_t ptype;
|
|
uint8_t hlen;
|
|
uint8_t plen;
|
|
uint16_t operation;
|
|
uint8_t sender_mac[6];
|
|
uint8_t sender_ip[4];
|
|
uint8_t target_mac[6];
|
|
uint8_t target_ip[4];
|
|
}arp_header_t;
|
|
|
|
#endif // esp32_wlan_h
|