⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/drivers/bluetooth/
hci.rs

1//! Bluetooth HCI (Host Controller Interface) Driver
2//!
3//! Implements the HCI transport layer, command/event protocol, device
4//! discovery, connection management, L2CAP basics, and SDP service discovery
5//! stubs.
6//!
7//! Reference: Bluetooth Core Specification v5.4, Volume 4 (HCI)
8
9#![allow(dead_code)]
10
11#[cfg(feature = "alloc")]
12#[allow(unused_imports)]
13use alloc::vec::Vec;
14use core::fmt;
15
16use crate::error::KernelError;
17
18// ---------------------------------------------------------------------------
19// HCI Packet Types
20// ---------------------------------------------------------------------------
21
22/// HCI packet type indicators (UART H4 transport)
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24#[repr(u8)]
25pub enum HciPacketType {
26    /// HCI Command packet (host -> controller)
27    Command = 0x01,
28    /// ACL Data packet (bidirectional)
29    AclData = 0x02,
30    /// SCO Data packet (bidirectional, synchronous)
31    ScoData = 0x03,
32    /// HCI Event packet (controller -> host)
33    Event = 0x04,
34}
35
36impl HciPacketType {
37    /// Parse packet type from raw byte
38    pub(crate) fn from_u8(val: u8) -> Option<Self> {
39        match val {
40            0x01 => Some(Self::Command),
41            0x02 => Some(Self::AclData),
42            0x03 => Some(Self::ScoData),
43            0x04 => Some(Self::Event),
44            _ => None,
45        }
46    }
47}
48
49// ---------------------------------------------------------------------------
50// OpCode Groups (OGF) and OpCode Command Fields (OCF)
51// ---------------------------------------------------------------------------
52
53/// OpCode Group Field values
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55#[repr(u8)]
56pub enum Ogf {
57    /// Link Control commands (connection management)
58    LinkControl = 0x01,
59    /// Link Policy commands
60    LinkPolicy = 0x02,
61    /// Controller & Baseband commands (configuration)
62    ControllerBaseband = 0x03,
63    /// Informational parameters (read-only queries)
64    Informational = 0x04,
65    /// Status parameters
66    StatusParameters = 0x05,
67    /// LE Controller commands
68    LeController = 0x08,
69}
70
71impl Ogf {
72    pub(crate) fn from_u8(val: u8) -> Option<Self> {
73        match val {
74            0x01 => Some(Self::LinkControl),
75            0x02 => Some(Self::LinkPolicy),
76            0x03 => Some(Self::ControllerBaseband),
77            0x04 => Some(Self::Informational),
78            0x05 => Some(Self::StatusParameters),
79            0x08 => Some(Self::LeController),
80            _ => None,
81        }
82    }
83}
84
85/// Build an HCI opcode from OGF and OCF fields
86/// Format: bits [15:10] = OGF, bits [9:0] = OCF
87pub const fn make_opcode(ogf: u8, ocf: u16) -> u16 {
88    ((ogf as u16) << 10) | (ocf & 0x03FF)
89}
90
91/// Extract OGF from an HCI opcode
92pub const fn opcode_ogf(opcode: u16) -> u8 {
93    (opcode >> 10) as u8
94}
95
96/// Extract OCF from an HCI opcode
97pub const fn opcode_ocf(opcode: u16) -> u16 {
98    opcode & 0x03FF
99}
100
101// Well-known HCI command opcodes
102/// HCI_Inquiry (OGF=0x01, OCF=0x0001)
103pub const HCI_INQUIRY: u16 = make_opcode(0x01, 0x0001);
104/// HCI_Create_Connection (OGF=0x01, OCF=0x0005)
105pub const HCI_CREATE_CONNECTION: u16 = make_opcode(0x01, 0x0005);
106/// HCI_Disconnect (OGF=0x01, OCF=0x0006)
107pub const HCI_DISCONNECT: u16 = make_opcode(0x01, 0x0006);
108/// HCI_Reset (OGF=0x03, OCF=0x0003)
109pub const HCI_RESET: u16 = make_opcode(0x03, 0x0003);
110/// HCI_Read_Local_Name (OGF=0x03, OCF=0x0014)
111pub const HCI_READ_LOCAL_NAME: u16 = make_opcode(0x03, 0x0014);
112/// HCI_Write_Scan_Enable (OGF=0x03, OCF=0x001A)
113pub const HCI_WRITE_SCAN_ENABLE: u16 = make_opcode(0x03, 0x001A);
114/// HCI_Read_BD_ADDR (OGF=0x04, OCF=0x0009)
115pub const HCI_READ_BD_ADDR: u16 = make_opcode(0x04, 0x0009);
116
117// ---------------------------------------------------------------------------
118// HCI Command Packet
119// ---------------------------------------------------------------------------
120
121/// Maximum HCI command parameter length
122pub const HCI_MAX_COMMAND_PARAMS: usize = 255;
123
124/// HCI Command packet header + parameters
125#[derive(Clone)]
126pub struct HciCommand {
127    /// Command opcode (OGF:OCF)
128    pub opcode: u16,
129    /// Parameter total length
130    pub param_len: u8,
131    /// Command parameters (up to 255 bytes)
132    pub params: [u8; HCI_MAX_COMMAND_PARAMS],
133}
134
135impl fmt::Debug for HciCommand {
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        f.debug_struct("HciCommand")
138            .field("opcode", &format_args!("0x{:04X}", self.opcode))
139            .field("ogf", &format_args!("0x{:02X}", opcode_ogf(self.opcode)))
140            .field("ocf", &format_args!("0x{:03X}", opcode_ocf(self.opcode)))
141            .field("param_len", &self.param_len)
142            .finish()
143    }
144}
145
146impl HciCommand {
147    /// Create a new HCI command with no parameters
148    pub fn new(opcode: u16) -> Self {
149        Self {
150            opcode,
151            param_len: 0,
152            params: [0u8; HCI_MAX_COMMAND_PARAMS],
153        }
154    }
155
156    /// Create a new HCI command with parameters
157    pub(crate) fn with_params(opcode: u16, params: &[u8]) -> Result<Self, KernelError> {
158        if params.len() > HCI_MAX_COMMAND_PARAMS {
159            return Err(KernelError::InvalidArgument {
160                name: "params",
161                value: "exceeds 255 bytes",
162            });
163        }
164        let mut cmd = Self::new(opcode);
165        cmd.param_len = params.len() as u8;
166        cmd.params[..params.len()].copy_from_slice(params);
167        Ok(cmd)
168    }
169
170    /// Serialize command to a byte buffer (H4 transport format)
171    /// Returns number of bytes written
172    pub(crate) fn serialize(&self, buf: &mut [u8]) -> Result<usize, KernelError> {
173        let total = 1 + 3 + self.param_len as usize; // type + header + params
174        if buf.len() < total {
175            return Err(KernelError::InvalidArgument {
176                name: "buffer",
177                value: "too small for HCI command",
178            });
179        }
180        buf[0] = HciPacketType::Command as u8;
181        buf[1] = (self.opcode & 0xFF) as u8;
182        buf[2] = (self.opcode >> 8) as u8;
183        buf[3] = self.param_len;
184        if self.param_len > 0 {
185            buf[4..4 + self.param_len as usize]
186                .copy_from_slice(&self.params[..self.param_len as usize]);
187        }
188        Ok(total)
189    }
190}
191
192// ---------------------------------------------------------------------------
193// HCI Event Packet
194// ---------------------------------------------------------------------------
195
196/// HCI Event codes
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198#[repr(u8)]
199pub enum HciEventCode {
200    /// Inquiry Complete
201    InquiryComplete = 0x01,
202    /// Inquiry Result
203    InquiryResult = 0x02,
204    /// Connection Complete
205    ConnectionComplete = 0x03,
206    /// Connection Request
207    ConnectionRequest = 0x04,
208    /// Disconnection Complete
209    DisconnectionComplete = 0x05,
210    /// Command Complete
211    CommandComplete = 0x0E,
212    /// Command Status
213    CommandStatus = 0x0F,
214    /// Number of Completed Packets
215    NumberOfCompletedPackets = 0x13,
216    /// Extended Inquiry Result
217    ExtendedInquiryResult = 0x2F,
218}
219
220impl HciEventCode {
221    pub(crate) fn from_u8(val: u8) -> Option<Self> {
222        match val {
223            0x01 => Some(Self::InquiryComplete),
224            0x02 => Some(Self::InquiryResult),
225            0x03 => Some(Self::ConnectionComplete),
226            0x04 => Some(Self::ConnectionRequest),
227            0x05 => Some(Self::DisconnectionComplete),
228            0x0E => Some(Self::CommandComplete),
229            0x0F => Some(Self::CommandStatus),
230            0x13 => Some(Self::NumberOfCompletedPackets),
231            0x2F => Some(Self::ExtendedInquiryResult),
232            _ => None,
233        }
234    }
235}
236
237/// Maximum HCI event parameter length
238pub const HCI_MAX_EVENT_PARAMS: usize = 255;
239
240/// HCI Event packet
241#[derive(Clone)]
242pub struct HciEvent {
243    /// Event code
244    pub event_code: u8,
245    /// Parameter total length
246    pub param_len: u8,
247    /// Event parameters
248    pub params: [u8; HCI_MAX_EVENT_PARAMS],
249}
250
251impl fmt::Debug for HciEvent {
252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253        f.debug_struct("HciEvent")
254            .field("event_code", &format_args!("0x{:02X}", self.event_code))
255            .field("param_len", &self.param_len)
256            .finish()
257    }
258}
259
260impl HciEvent {
261    /// Create a new empty event
262    pub fn new(event_code: u8) -> Self {
263        Self {
264            event_code,
265            param_len: 0,
266            params: [0u8; HCI_MAX_EVENT_PARAMS],
267        }
268    }
269
270    /// Parse an HCI event from a raw buffer (excluding H4 type byte)
271    pub(crate) fn parse(buf: &[u8]) -> Result<Self, KernelError> {
272        if buf.len() < 2 {
273            return Err(KernelError::InvalidArgument {
274                name: "event_buffer",
275                value: "too short for HCI event header",
276            });
277        }
278        let event_code = buf[0];
279        let param_len = buf[1];
280        if buf.len() < 2 + param_len as usize {
281            return Err(KernelError::InvalidArgument {
282                name: "event_buffer",
283                value: "truncated event parameters",
284            });
285        }
286        let mut evt = Self::new(event_code);
287        evt.param_len = param_len;
288        if param_len > 0 {
289            evt.params[..param_len as usize].copy_from_slice(&buf[2..2 + param_len as usize]);
290        }
291        Ok(evt)
292    }
293
294    /// Check if this is a Command Complete event
295    pub(crate) fn is_command_complete(&self) -> bool {
296        self.event_code == HciEventCode::CommandComplete as u8
297    }
298
299    /// Check if this is a Command Status event
300    pub(crate) fn is_command_status(&self) -> bool {
301        self.event_code == HciEventCode::CommandStatus as u8
302    }
303
304    /// For Command Complete events, extract the opcode that completed
305    pub(crate) fn command_complete_opcode(&self) -> Option<u16> {
306        if !self.is_command_complete() || self.param_len < 3 {
307            return None;
308        }
309        // params[0] = num_hci_command_packets, params[1..3] = opcode (LE)
310        Some(u16::from_le_bytes([self.params[1], self.params[2]]))
311    }
312
313    /// For Command Complete events, extract the status byte
314    pub(crate) fn command_complete_status(&self) -> Option<u8> {
315        if !self.is_command_complete() || self.param_len < 4 {
316            return None;
317        }
318        Some(self.params[3])
319    }
320
321    /// For Command Status events, extract the status byte
322    pub(crate) fn command_status(&self) -> Option<u8> {
323        if !self.is_command_status() || self.param_len < 1 {
324            return None;
325        }
326        Some(self.params[0])
327    }
328}
329
330// ---------------------------------------------------------------------------
331// ACL Data Packet
332// ---------------------------------------------------------------------------
333
334/// ACL packet boundary flags
335#[derive(Debug, Clone, Copy, PartialEq, Eq)]
336#[repr(u8)]
337pub enum AclBoundaryFlag {
338    /// First non-automatically-flushable packet
339    FirstNonFlushable = 0x00,
340    /// Continuing fragment
341    Continuing = 0x01,
342    /// First automatically flushable packet
343    FirstFlushable = 0x02,
344}
345
346/// ACL packet broadcast flag
347#[derive(Debug, Clone, Copy, PartialEq, Eq)]
348#[repr(u8)]
349pub enum AclBroadcastFlag {
350    /// Point-to-point
351    PointToPoint = 0x00,
352    /// Active Broadcast
353    ActiveBroadcast = 0x01,
354}
355
356/// Maximum ACL data payload
357pub const ACL_MAX_DATA_LEN: usize = 1021;
358
359/// ACL Data packet header
360#[derive(Debug, Clone, Copy, PartialEq, Eq)]
361pub struct AclHeader {
362    /// Connection handle (12 bits)
363    pub handle: u16,
364    /// Packet boundary flag (2 bits)
365    pub boundary: AclBoundaryFlag,
366    /// Broadcast flag (2 bits)
367    pub broadcast: AclBroadcastFlag,
368    /// Data total length
369    pub data_len: u16,
370}
371
372impl AclHeader {
373    /// Parse ACL header from 4 bytes
374    pub(crate) fn parse(buf: &[u8]) -> Result<Self, KernelError> {
375        if buf.len() < 4 {
376            return Err(KernelError::InvalidArgument {
377                name: "acl_buffer",
378                value: "too short for ACL header",
379            });
380        }
381        let hdr_word = u16::from_le_bytes([buf[0], buf[1]]);
382        let handle = hdr_word & 0x0FFF;
383        let pb = (hdr_word >> 12) & 0x03;
384        let bc = (hdr_word >> 14) & 0x03;
385        let data_len = u16::from_le_bytes([buf[2], buf[3]]);
386
387        let boundary = match pb {
388            0x00 => AclBoundaryFlag::FirstNonFlushable,
389            0x01 => AclBoundaryFlag::Continuing,
390            0x02 => AclBoundaryFlag::FirstFlushable,
391            _ => AclBoundaryFlag::FirstFlushable,
392        };
393        let broadcast = match bc {
394            0x00 => AclBroadcastFlag::PointToPoint,
395            0x01 => AclBroadcastFlag::ActiveBroadcast,
396            _ => AclBroadcastFlag::PointToPoint,
397        };
398
399        Ok(Self {
400            handle,
401            boundary,
402            broadcast,
403            data_len,
404        })
405    }
406
407    /// Serialize ACL header into 4 bytes
408    pub(crate) fn serialize(&self, buf: &mut [u8]) -> Result<(), KernelError> {
409        if buf.len() < 4 {
410            return Err(KernelError::InvalidArgument {
411                name: "buffer",
412                value: "too small for ACL header",
413            });
414        }
415        let hdr_word = (self.handle & 0x0FFF)
416            | ((self.boundary as u16) << 12)
417            | ((self.broadcast as u16) << 14);
418        buf[0..2].copy_from_slice(&hdr_word.to_le_bytes());
419        buf[2..4].copy_from_slice(&self.data_len.to_le_bytes());
420        Ok(())
421    }
422}
423
424// ---------------------------------------------------------------------------
425// BD_ADDR (Bluetooth Device Address)
426// ---------------------------------------------------------------------------
427
428/// Bluetooth device address (6 bytes, little-endian)
429pub type BdAddr = [u8; 6];
430
431/// Zero / unset BD_ADDR
432pub const BD_ADDR_ZERO: BdAddr = [0u8; 6];
433
434/// Format a BD_ADDR as colon-separated hex string
435pub(crate) fn format_bd_addr(addr: &BdAddr) -> [u8; 17] {
436    let hex = b"0123456789ABCDEF";
437    let mut out = [0u8; 17];
438    for i in 0..6 {
439        let offset = (5 - i) * 3; // reverse byte order for display
440        out[offset] = hex[(addr[i] >> 4) as usize];
441        out[offset + 1] = hex[(addr[i] & 0x0F) as usize];
442        if i > 0 {
443            out[offset + 2] = b':';
444        }
445    }
446    out
447}
448
449// ---------------------------------------------------------------------------
450// HCI USB Transport
451// ---------------------------------------------------------------------------
452
453/// USB HCI transport endpoint configuration
454#[derive(Debug, Clone, Copy)]
455pub struct HciUsbTransport {
456    /// USB device address
457    pub device_addr: u8,
458    /// Bulk OUT endpoint for HCI commands
459    pub cmd_endpoint: u8,
460    /// Bulk IN endpoint for HCI events
461    pub evt_endpoint: u8,
462    /// Bulk OUT endpoint for ACL data TX
463    pub acl_tx_endpoint: u8,
464    /// Bulk IN endpoint for ACL data RX
465    pub acl_rx_endpoint: u8,
466    /// Interrupt IN endpoint for events (alternative)
467    pub intr_endpoint: u8,
468    /// Whether the transport is active
469    pub active: bool,
470}
471
472impl Default for HciUsbTransport {
473    fn default() -> Self {
474        Self::new()
475    }
476}
477
478impl HciUsbTransport {
479    /// Create a new USB HCI transport (unconfigured)
480    pub fn new() -> Self {
481        Self {
482            device_addr: 0,
483            cmd_endpoint: 0x00,
484            evt_endpoint: 0x81,
485            acl_tx_endpoint: 0x02,
486            acl_rx_endpoint: 0x82,
487            intr_endpoint: 0x83,
488            active: false,
489        }
490    }
491
492    /// Configure the transport for a specific USB device
493    pub(crate) fn configure(&mut self, device_addr: u8) {
494        self.device_addr = device_addr;
495        self.active = true;
496    }
497
498    /// Send an HCI command over USB bulk OUT
499    pub(crate) fn send_command(&self, _cmd: &HciCommand) -> Result<(), KernelError> {
500        if !self.active {
501            return Err(KernelError::InvalidState {
502                expected: "active",
503                actual: "inactive",
504            });
505        }
506        // In a real implementation, this would submit a USB bulk transfer
507        // to the command endpoint. For now, this is a stub.
508        Ok(())
509    }
510
511    /// Send ACL data over USB bulk OUT
512    pub(crate) fn send_acl_data(
513        &self,
514        _header: &AclHeader,
515        _data: &[u8],
516    ) -> Result<(), KernelError> {
517        if !self.active {
518            return Err(KernelError::InvalidState {
519                expected: "active",
520                actual: "inactive",
521            });
522        }
523        Ok(())
524    }
525
526    /// Poll for an HCI event from USB interrupt/bulk IN endpoint
527    pub(crate) fn poll_event(&self) -> Result<Option<HciEvent>, KernelError> {
528        if !self.active {
529            return Err(KernelError::InvalidState {
530                expected: "active",
531                actual: "inactive",
532            });
533        }
534        // Stub: no real USB hardware, return None
535        Ok(None)
536    }
537
538    /// Poll for ACL data from USB bulk IN endpoint
539    pub(crate) fn poll_acl_data(
540        &self,
541    ) -> Result<Option<(AclHeader, [u8; ACL_MAX_DATA_LEN], usize)>, KernelError> {
542        if !self.active {
543            return Err(KernelError::InvalidState {
544                expected: "active",
545                actual: "inactive",
546            });
547        }
548        Ok(None)
549    }
550}
551
552// ---------------------------------------------------------------------------
553// Device Discovery
554// ---------------------------------------------------------------------------
555
556/// General Inquiry Access Code LAP (GIAC)
557pub const GIAC_LAP: u32 = 0x9E8B33;
558
559/// Limited Inquiry Access Code LAP (LIAC)
560pub const LIAC_LAP: u32 = 0x9E8B00;
561
562/// Scan enable modes for HCI_Write_Scan_Enable
563#[derive(Debug, Clone, Copy, PartialEq, Eq)]
564#[repr(u8)]
565pub enum ScanEnable {
566    /// No scans enabled
567    NoScans = 0x00,
568    /// Inquiry scan enabled
569    InquiryScanOnly = 0x01,
570    /// Page scan enabled
571    PageScanOnly = 0x02,
572    /// Both inquiry and page scan enabled
573    InquiryAndPageScan = 0x03,
574}
575
576/// Maximum number of discovered devices
577pub const MAX_DISCOVERED_DEVICES: usize = 16;
578
579/// A discovered Bluetooth device
580#[derive(Debug, Clone, Copy)]
581pub struct DiscoveredDevice {
582    /// Device Bluetooth address
583    pub addr: BdAddr,
584    /// Page scan repetition mode
585    pub page_scan_rep_mode: u8,
586    /// Class of device (3 bytes packed into u32)
587    pub class_of_device: u32,
588    /// Clock offset
589    pub clock_offset: u16,
590    /// RSSI (signed, dBm)
591    pub rssi: i8,
592    /// Device name (from name resolution or EIR)
593    pub name: [u8; 248],
594    /// Length of valid name bytes
595    pub name_len: usize,
596    /// Whether this entry is occupied
597    pub valid: bool,
598}
599
600impl DiscoveredDevice {
601    pub const fn empty() -> Self {
602        Self {
603            addr: BD_ADDR_ZERO,
604            page_scan_rep_mode: 0,
605            class_of_device: 0,
606            clock_offset: 0,
607            rssi: 0,
608            name: [0u8; 248],
609            name_len: 0,
610            valid: false,
611        }
612    }
613}
614
615/// Parse an Extended Inquiry Response (EIR) data block
616/// Returns (name_bytes, name_len) if a Complete/Shortened Local Name is found
617pub(crate) fn parse_eir_name(eir: &[u8]) -> Option<([u8; 248], usize)> {
618    let mut offset = 0;
619    while offset < eir.len() {
620        let length = eir[offset] as usize;
621        if length == 0 {
622            break;
623        }
624        if offset + 1 + length > eir.len() {
625            break;
626        }
627        let data_type = eir[offset + 1];
628        // 0x08 = Shortened Local Name, 0x09 = Complete Local Name
629        if data_type == 0x08 || data_type == 0x09 {
630            let name_data = &eir[offset + 2..offset + 1 + length];
631            let copy_len = name_data.len().min(248);
632            let mut name = [0u8; 248];
633            name[..copy_len].copy_from_slice(&name_data[..copy_len]);
634            return Some((name, copy_len));
635        }
636        offset += 1 + length;
637    }
638    None
639}
640
641// ---------------------------------------------------------------------------
642// Connection Management
643// ---------------------------------------------------------------------------
644
645/// Maximum number of simultaneous connections
646pub const MAX_CONNECTIONS: usize = 8;
647
648/// Connection state
649#[derive(Debug, Clone, Copy, PartialEq, Eq)]
650pub enum ConnectionState {
651    /// No connection
652    Idle,
653    /// Connection setup in progress
654    Connecting,
655    /// Connection established
656    Connected,
657    /// Disconnection in progress
658    Disconnecting,
659}
660
661/// An active HCI connection
662#[derive(Debug, Clone, Copy)]
663pub struct HciConnection {
664    /// Connection handle (assigned by controller)
665    pub handle: u16,
666    /// Remote device address
667    pub remote_addr: BdAddr,
668    /// Connection type (ACL = 0x01, SCO = 0x00)
669    pub link_type: u8,
670    /// Current state
671    pub state: ConnectionState,
672    /// Encryption enabled
673    pub encrypted: bool,
674    /// Link key (stub -- 16 bytes)
675    pub link_key: [u8; 16],
676    /// Whether a link key is present
677    pub has_link_key: bool,
678}
679
680impl HciConnection {
681    pub const fn empty() -> Self {
682        Self {
683            handle: 0,
684            remote_addr: BD_ADDR_ZERO,
685            link_type: 0x01,
686            state: ConnectionState::Idle,
687            encrypted: false,
688            link_key: [0u8; 16],
689            has_link_key: false,
690        }
691    }
692}
693
694// ---------------------------------------------------------------------------
695// L2CAP (Logical Link Control and Adaptation Protocol) Basics
696// ---------------------------------------------------------------------------
697
698/// L2CAP signaling channel CID
699pub const L2CAP_CID_SIGNALING: u16 = 0x0001;
700/// L2CAP connectionless channel CID
701pub const L2CAP_CID_CONNECTIONLESS: u16 = 0x0002;
702/// L2CAP ATT (Attribute Protocol) fixed channel CID
703pub const L2CAP_CID_ATT: u16 = 0x0004;
704/// L2CAP LE Signaling channel CID
705pub const L2CAP_CID_LE_SIGNALING: u16 = 0x0005;
706/// L2CAP SMP (Security Manager Protocol) fixed channel CID
707pub const L2CAP_CID_SMP: u16 = 0x0006;
708
709/// L2CAP header (4 bytes: length + channel ID)
710#[derive(Debug, Clone, Copy, PartialEq, Eq)]
711pub struct L2capHeader {
712    /// Payload length (excluding this header)
713    pub length: u16,
714    /// Channel ID
715    pub cid: u16,
716}
717
718impl L2capHeader {
719    /// Parse L2CAP header from 4 bytes
720    pub(crate) fn parse(buf: &[u8]) -> Result<Self, KernelError> {
721        if buf.len() < 4 {
722            return Err(KernelError::InvalidArgument {
723                name: "l2cap_buffer",
724                value: "too short for L2CAP header",
725            });
726        }
727        Ok(Self {
728            length: u16::from_le_bytes([buf[0], buf[1]]),
729            cid: u16::from_le_bytes([buf[2], buf[3]]),
730        })
731    }
732
733    /// Serialize L2CAP header into 4 bytes
734    pub(crate) fn serialize(&self, buf: &mut [u8]) -> Result<(), KernelError> {
735        if buf.len() < 4 {
736            return Err(KernelError::InvalidArgument {
737                name: "buffer",
738                value: "too small for L2CAP header",
739            });
740        }
741        buf[0..2].copy_from_slice(&self.length.to_le_bytes());
742        buf[2..4].copy_from_slice(&self.cid.to_le_bytes());
743        Ok(())
744    }
745}
746
747/// L2CAP signaling command codes
748#[derive(Debug, Clone, Copy, PartialEq, Eq)]
749#[repr(u8)]
750pub enum L2capSignalCode {
751    /// Connection Request
752    ConnectionRequest = 0x02,
753    /// Connection Response
754    ConnectionResponse = 0x03,
755    /// Configuration Request
756    ConfigurationRequest = 0x04,
757    /// Configuration Response
758    ConfigurationResponse = 0x05,
759    /// Disconnection Request
760    DisconnectionRequest = 0x06,
761    /// Disconnection Response
762    DisconnectionResponse = 0x07,
763    /// Information Request
764    InformationRequest = 0x0A,
765    /// Information Response
766    InformationResponse = 0x0B,
767}
768
769/// L2CAP signaling packet header (code + identifier + length)
770#[derive(Debug, Clone, Copy, PartialEq, Eq)]
771pub struct L2capSignalHeader {
772    pub code: u8,
773    pub identifier: u8,
774    pub length: u16,
775}
776
777impl L2capSignalHeader {
778    pub(crate) fn parse(buf: &[u8]) -> Result<Self, KernelError> {
779        if buf.len() < 4 {
780            return Err(KernelError::InvalidArgument {
781                name: "signal_buffer",
782                value: "too short for L2CAP signal header",
783            });
784        }
785        Ok(Self {
786            code: buf[0],
787            identifier: buf[1],
788            length: u16::from_le_bytes([buf[2], buf[3]]),
789        })
790    }
791}
792
793// ---------------------------------------------------------------------------
794// SDP (Service Discovery Protocol) Stubs
795// ---------------------------------------------------------------------------
796
797/// SDP PDU IDs
798#[derive(Debug, Clone, Copy, PartialEq, Eq)]
799#[repr(u8)]
800pub enum SdpPduId {
801    /// Error Response
802    ErrorResponse = 0x01,
803    /// Service Search Request
804    ServiceSearchRequest = 0x02,
805    /// Service Search Response
806    ServiceSearchResponse = 0x03,
807    /// Service Attribute Request
808    ServiceAttributeRequest = 0x04,
809    /// Service Attribute Response
810    ServiceAttributeResponse = 0x05,
811    /// Service Search Attribute Request
812    ServiceSearchAttributeRequest = 0x06,
813    /// Service Search Attribute Response
814    ServiceSearchAttributeResponse = 0x07,
815}
816
817/// Common Bluetooth UUIDs (16-bit short form)
818pub const UUID_SDP: u16 = 0x0001;
819pub const UUID_RFCOMM: u16 = 0x0003;
820pub const UUID_L2CAP: u16 = 0x0100;
821pub const UUID_SERIAL_PORT: u16 = 0x1101;
822pub const UUID_OBEX_PUSH: u16 = 0x1105;
823pub const UUID_A2DP_SOURCE: u16 = 0x110A;
824pub const UUID_A2DP_SINK: u16 = 0x110B;
825pub const UUID_HFP: u16 = 0x111E;
826pub const UUID_HID: u16 = 0x1124;
827
828/// SDP service record (stub)
829#[derive(Debug, Clone, Copy)]
830pub struct SdpServiceRecord {
831    /// Service record handle
832    pub handle: u32,
833    /// Primary service class UUID (16-bit)
834    pub service_class_uuid: u16,
835    /// Protocol descriptor (L2CAP PSM or RFCOMM channel)
836    pub protocol_channel: u16,
837    /// Whether this record is valid
838    pub valid: bool,
839}
840
841impl SdpServiceRecord {
842    pub const fn empty() -> Self {
843        Self {
844            handle: 0,
845            service_class_uuid: 0,
846            protocol_channel: 0,
847            valid: false,
848        }
849    }
850}
851
852/// Maximum number of SDP service records
853pub const MAX_SDP_RECORDS: usize = 8;
854
855/// Check if a 16-bit UUID matches a service record
856pub(crate) fn sdp_uuid_match(record: &SdpServiceRecord, uuid: u16) -> bool {
857    record.valid && record.service_class_uuid == uuid
858}
859
860// ---------------------------------------------------------------------------
861// Bluetooth Controller State Machine
862// ---------------------------------------------------------------------------
863
864/// Bluetooth controller state
865#[derive(Debug, Clone, Copy, PartialEq, Eq)]
866pub enum ControllerState {
867    /// Controller is powered off
868    Off,
869    /// Controller is initializing (reset sequence)
870    Initializing,
871    /// Controller is ready for commands
872    Ready,
873    /// Inquiry scan is active
874    Scanning,
875    /// At least one connection is active
876    Connected,
877}
878
879/// Statistics for the Bluetooth controller
880#[derive(Debug, Clone, Copy, Default)]
881pub struct BluetoothStats {
882    pub commands_sent: u64,
883    pub events_received: u64,
884    pub acl_packets_sent: u64,
885    pub acl_packets_received: u64,
886    pub errors: u64,
887}
888
889/// Main Bluetooth HCI controller
890pub struct BluetoothController {
891    /// Current controller state
892    state: ControllerState,
893    /// Local BD_ADDR (read from controller)
894    local_addr: BdAddr,
895    /// Local device name
896    local_name: [u8; 248],
897    /// Length of valid local name bytes
898    local_name_len: usize,
899    /// USB HCI transport
900    transport: HciUsbTransport,
901    /// Active connections
902    connections: [HciConnection; MAX_CONNECTIONS],
903    /// Number of active connections
904    connection_count: usize,
905    /// Discovered devices (from inquiry)
906    discovered: [DiscoveredDevice; MAX_DISCOVERED_DEVICES],
907    /// Number of discovered devices
908    discovered_count: usize,
909    /// SDP service records (local)
910    sdp_records: [SdpServiceRecord; MAX_SDP_RECORDS],
911    /// Number of registered SDP records
912    sdp_record_count: usize,
913    /// Next L2CAP signaling identifier
914    next_signal_id: u8,
915    /// Statistics
916    stats: BluetoothStats,
917}
918
919impl fmt::Debug for BluetoothController {
920    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
921        f.debug_struct("BluetoothController")
922            .field("state", &self.state)
923            .field("local_addr", &format_args!("{:?}", self.local_addr))
924            .field("connections", &self.connection_count)
925            .field("discovered", &self.discovered_count)
926            .finish()
927    }
928}
929
930impl Default for BluetoothController {
931    fn default() -> Self {
932        Self::new()
933    }
934}
935
936impl BluetoothController {
937    /// Create a new Bluetooth controller (uninitialized)
938    pub fn new() -> Self {
939        Self {
940            state: ControllerState::Off,
941            local_addr: BD_ADDR_ZERO,
942            local_name: [0u8; 248],
943            local_name_len: 0,
944            transport: HciUsbTransport::new(),
945            connections: [HciConnection::empty(); MAX_CONNECTIONS],
946            connection_count: 0,
947            discovered: {
948                // const array init without requiring Copy on large struct
949                let empty = DiscoveredDevice::empty();
950                [empty; MAX_DISCOVERED_DEVICES]
951            },
952            discovered_count: 0,
953            sdp_records: [SdpServiceRecord::empty(); MAX_SDP_RECORDS],
954            sdp_record_count: 0,
955            next_signal_id: 1,
956            stats: BluetoothStats::default(),
957        }
958    }
959
960    /// Get current controller state
961    pub(crate) fn state(&self) -> ControllerState {
962        self.state
963    }
964
965    /// Get the local BD_ADDR
966    pub(crate) fn local_addr(&self) -> &BdAddr {
967        &self.local_addr
968    }
969
970    /// Get controller statistics
971    pub(crate) fn stats(&self) -> &BluetoothStats {
972        &self.stats
973    }
974
975    /// Get number of active connections
976    pub(crate) fn connection_count(&self) -> usize {
977        self.connection_count
978    }
979
980    /// Get number of discovered devices
981    pub(crate) fn discovered_count(&self) -> usize {
982        self.discovered_count
983    }
984
985    // ----- Initialization and Reset -----
986
987    /// Initialize the controller: configure USB transport and send HCI_Reset
988    pub(crate) fn initialize(&mut self, usb_device_addr: u8) -> Result<(), KernelError> {
989        if self.state != ControllerState::Off {
990            return Err(KernelError::InvalidState {
991                expected: "Off",
992                actual: "not Off",
993            });
994        }
995
996        self.state = ControllerState::Initializing;
997        self.transport.configure(usb_device_addr);
998
999        // Send HCI_Reset
1000        self.send_reset()?;
1001
1002        self.state = ControllerState::Ready;
1003        Ok(())
1004    }
1005
1006    /// Send HCI_Reset command
1007    pub(crate) fn send_reset(&mut self) -> Result<(), KernelError> {
1008        let cmd = HciCommand::new(HCI_RESET);
1009        self.transport.send_command(&cmd)?;
1010        self.stats.commands_sent += 1;
1011        Ok(())
1012    }
1013
1014    /// Send HCI_Read_BD_ADDR command
1015    pub(crate) fn read_bd_addr(&mut self) -> Result<(), KernelError> {
1016        self.ensure_ready()?;
1017        let cmd = HciCommand::new(HCI_READ_BD_ADDR);
1018        self.transport.send_command(&cmd)?;
1019        self.stats.commands_sent += 1;
1020        Ok(())
1021    }
1022
1023    /// Send HCI_Read_Local_Name command
1024    pub(crate) fn read_local_name(&mut self) -> Result<(), KernelError> {
1025        self.ensure_ready()?;
1026        let cmd = HciCommand::new(HCI_READ_LOCAL_NAME);
1027        self.transport.send_command(&cmd)?;
1028        self.stats.commands_sent += 1;
1029        Ok(())
1030    }
1031
1032    /// Send HCI_Write_Scan_Enable command
1033    pub(crate) fn write_scan_enable(&mut self, mode: ScanEnable) -> Result<(), KernelError> {
1034        self.ensure_ready()?;
1035        let cmd = HciCommand::with_params(HCI_WRITE_SCAN_ENABLE, &[mode as u8])?;
1036        self.transport.send_command(&cmd)?;
1037        self.stats.commands_sent += 1;
1038        Ok(())
1039    }
1040
1041    // ----- Device Discovery -----
1042
1043    /// Start inquiry (device discovery)
1044    /// inquiry_length: N * 1.28s (range 1..=30)
1045    /// max_responses: max number of responses (0 = unlimited)
1046    pub(crate) fn start_inquiry(
1047        &mut self,
1048        inquiry_length: u8,
1049        max_responses: u8,
1050    ) -> Result<(), KernelError> {
1051        self.ensure_ready()?;
1052
1053        // Clear previous results
1054        self.discovered_count = 0;
1055        for dev in &mut self.discovered {
1056            dev.valid = false;
1057        }
1058
1059        // Build Inquiry command parameters:
1060        // LAP (3 bytes, GIAC), inquiry_length, max_responses
1061        let lap_bytes = GIAC_LAP.to_le_bytes();
1062        let params = [
1063            lap_bytes[0],
1064            lap_bytes[1],
1065            lap_bytes[2],
1066            inquiry_length.clamp(1, 30),
1067            max_responses,
1068        ];
1069        let cmd = HciCommand::with_params(HCI_INQUIRY, &params)?;
1070        self.transport.send_command(&cmd)?;
1071        self.stats.commands_sent += 1;
1072
1073        self.state = ControllerState::Scanning;
1074        Ok(())
1075    }
1076
1077    /// Process an Inquiry Result event and store discovered device
1078    pub(crate) fn handle_inquiry_result(
1079        &mut self,
1080        addr: BdAddr,
1081        page_scan_rep_mode: u8,
1082        class_of_device: u32,
1083        clock_offset: u16,
1084    ) {
1085        if self.discovered_count >= MAX_DISCOVERED_DEVICES {
1086            return;
1087        }
1088
1089        // Check for duplicate
1090        for dev in &self.discovered[..self.discovered_count] {
1091            if dev.valid && dev.addr == addr {
1092                return;
1093            }
1094        }
1095
1096        let slot = &mut self.discovered[self.discovered_count];
1097        slot.addr = addr;
1098        slot.page_scan_rep_mode = page_scan_rep_mode;
1099        slot.class_of_device = class_of_device;
1100        slot.clock_offset = clock_offset;
1101        slot.valid = true;
1102        self.discovered_count += 1;
1103    }
1104
1105    /// Handle Inquiry Complete event
1106    pub(crate) fn handle_inquiry_complete(&mut self) {
1107        if self.state == ControllerState::Scanning {
1108            if self.connection_count > 0 {
1109                self.state = ControllerState::Connected;
1110            } else {
1111                self.state = ControllerState::Ready;
1112            }
1113        }
1114    }
1115
1116    /// Get a discovered device by index
1117    pub(crate) fn get_discovered(&self, index: usize) -> Option<&DiscoveredDevice> {
1118        if index < self.discovered_count {
1119            let dev = &self.discovered[index];
1120            if dev.valid {
1121                return Some(dev);
1122            }
1123        }
1124        None
1125    }
1126
1127    // ----- Connection Management -----
1128
1129    /// Create a connection to a remote device
1130    pub(crate) fn create_connection(&mut self, addr: &BdAddr) -> Result<(), KernelError> {
1131        self.ensure_ready_or_connected()?;
1132
1133        if self.connection_count >= MAX_CONNECTIONS {
1134            return Err(KernelError::ResourceExhausted {
1135                resource: "bluetooth connections",
1136            });
1137        }
1138
1139        // Build HCI_Create_Connection parameters:
1140        // BD_ADDR (6), Packet_Type (2), Page_Scan_Rep_Mode (1),
1141        // Reserved (1), Clock_Offset (2), Allow_Role_Switch (1)
1142        let mut params = [0u8; 13];
1143        params[0..6].copy_from_slice(addr);
1144        // Packet type: DM1 + DH1 + DM3 + DH3 + DM5 + DH5
1145        params[6..8].copy_from_slice(&0xCC18u16.to_le_bytes());
1146        params[8] = 0x02; // R2 page scan repetition mode
1147        params[9] = 0x00; // reserved
1148        params[10..12].copy_from_slice(&0x0000u16.to_le_bytes()); // clock offset
1149        params[12] = 0x01; // allow role switch
1150
1151        let cmd = HciCommand::with_params(HCI_CREATE_CONNECTION, &params)?;
1152        self.transport.send_command(&cmd)?;
1153        self.stats.commands_sent += 1;
1154
1155        // Allocate a connection slot in Connecting state
1156        for conn in &mut self.connections {
1157            if conn.state == ConnectionState::Idle {
1158                conn.remote_addr = *addr;
1159                conn.state = ConnectionState::Connecting;
1160                break;
1161            }
1162        }
1163
1164        Ok(())
1165    }
1166
1167    /// Handle Connection Complete event from controller
1168    pub(crate) fn handle_connection_complete(
1169        &mut self,
1170        status: u8,
1171        handle: u16,
1172        addr: &BdAddr,
1173        link_type: u8,
1174    ) -> Result<(), KernelError> {
1175        // Find the connection slot for this address
1176        for conn in &mut self.connections {
1177            if conn.state == ConnectionState::Connecting && conn.remote_addr == *addr {
1178                if status == 0x00 {
1179                    conn.handle = handle;
1180                    conn.link_type = link_type;
1181                    conn.state = ConnectionState::Connected;
1182                    self.connection_count += 1;
1183                    self.state = ControllerState::Connected;
1184                } else {
1185                    conn.state = ConnectionState::Idle;
1186                    conn.remote_addr = BD_ADDR_ZERO;
1187                }
1188                return Ok(());
1189            }
1190        }
1191        Err(KernelError::NotFound {
1192            resource: "connection slot",
1193            id: 0,
1194        })
1195    }
1196
1197    /// Disconnect from a remote device
1198    pub(crate) fn disconnect(&mut self, handle: u16, reason: u8) -> Result<(), KernelError> {
1199        // Find connection by handle
1200        let found = self.connections.iter_mut().any(|conn| {
1201            if conn.state == ConnectionState::Connected && conn.handle == handle {
1202                conn.state = ConnectionState::Disconnecting;
1203                true
1204            } else {
1205                false
1206            }
1207        });
1208
1209        if !found {
1210            return Err(KernelError::NotFound {
1211                resource: "connection",
1212                id: handle as u64,
1213            });
1214        }
1215
1216        let mut params = [0u8; 3];
1217        params[0..2].copy_from_slice(&handle.to_le_bytes());
1218        params[2] = reason;
1219
1220        let cmd = HciCommand::with_params(HCI_DISCONNECT, &params)?;
1221        self.transport.send_command(&cmd)?;
1222        self.stats.commands_sent += 1;
1223        Ok(())
1224    }
1225
1226    /// Handle Disconnection Complete event
1227    pub(crate) fn handle_disconnection_complete(&mut self, _status: u8, handle: u16) {
1228        for conn in &mut self.connections {
1229            if conn.handle == handle
1230                && (conn.state == ConnectionState::Connected
1231                    || conn.state == ConnectionState::Disconnecting)
1232            {
1233                *conn = HciConnection::empty();
1234                if self.connection_count > 0 {
1235                    self.connection_count -= 1;
1236                }
1237                break;
1238            }
1239        }
1240
1241        if self.connection_count == 0 && self.state == ControllerState::Connected {
1242            self.state = ControllerState::Ready;
1243        }
1244    }
1245
1246    /// Find a connection by handle
1247    pub(crate) fn find_connection(&self, handle: u16) -> Option<&HciConnection> {
1248        self.connections
1249            .iter()
1250            .find(|c| c.state == ConnectionState::Connected && c.handle == handle)
1251    }
1252
1253    /// Store a link key for a connection (stub)
1254    pub(crate) fn store_link_key(&mut self, addr: &BdAddr, key: &[u8; 16]) {
1255        for conn in &mut self.connections {
1256            if conn.state == ConnectionState::Connected && conn.remote_addr == *addr {
1257                conn.link_key = *key;
1258                conn.has_link_key = true;
1259                return;
1260            }
1261        }
1262    }
1263
1264    // ----- ACL Data -----
1265
1266    /// Send ACL data to a connected device
1267    pub(crate) fn send_acl(&mut self, handle: u16, data: &[u8]) -> Result<(), KernelError> {
1268        let conn = self
1269            .connections
1270            .iter()
1271            .find(|c| c.state == ConnectionState::Connected && c.handle == handle);
1272        if conn.is_none() {
1273            return Err(KernelError::NotFound {
1274                resource: "connection",
1275                id: handle as u64,
1276            });
1277        }
1278        if data.len() > ACL_MAX_DATA_LEN {
1279            return Err(KernelError::InvalidArgument {
1280                name: "acl_data",
1281                value: "exceeds max ACL data length",
1282            });
1283        }
1284
1285        let header = AclHeader {
1286            handle,
1287            boundary: AclBoundaryFlag::FirstFlushable,
1288            broadcast: AclBroadcastFlag::PointToPoint,
1289            data_len: data.len() as u16,
1290        };
1291        self.transport.send_acl_data(&header, data)?;
1292        self.stats.acl_packets_sent += 1;
1293        Ok(())
1294    }
1295
1296    // ----- SDP Stubs -----
1297
1298    /// Register a local SDP service record
1299    pub(crate) fn register_sdp_record(
1300        &mut self,
1301        uuid: u16,
1302        channel: u16,
1303    ) -> Result<u32, KernelError> {
1304        if self.sdp_record_count >= MAX_SDP_RECORDS {
1305            return Err(KernelError::ResourceExhausted {
1306                resource: "SDP service records",
1307            });
1308        }
1309        let handle = (self.sdp_record_count as u32) + 0x10000;
1310        let slot = &mut self.sdp_records[self.sdp_record_count];
1311        slot.handle = handle;
1312        slot.service_class_uuid = uuid;
1313        slot.protocol_channel = channel;
1314        slot.valid = true;
1315        self.sdp_record_count += 1;
1316        Ok(handle)
1317    }
1318
1319    /// Search for a service by UUID in local records
1320    pub(crate) fn sdp_search_local(&self, uuid: u16) -> Option<&SdpServiceRecord> {
1321        self.sdp_records[..self.sdp_record_count]
1322            .iter()
1323            .find(|r| sdp_uuid_match(r, uuid))
1324    }
1325
1326    // ----- Event Processing -----
1327
1328    /// Process a received HCI event
1329    pub(crate) fn process_event(&mut self, event: &HciEvent) {
1330        self.stats.events_received += 1;
1331
1332        match HciEventCode::from_u8(event.event_code) {
1333            Some(HciEventCode::CommandComplete) => {
1334                // Command completed -- status in params[3] if present
1335                if let Some(opcode) = event.command_complete_opcode() {
1336                    self.handle_command_complete(opcode, event);
1337                }
1338            }
1339            Some(HciEventCode::CommandStatus) => {
1340                // Command accepted/rejected -- status in params[0]
1341            }
1342            Some(HciEventCode::InquiryComplete) => {
1343                self.handle_inquiry_complete();
1344            }
1345            Some(HciEventCode::InquiryResult) => {
1346                self.process_inquiry_result(event);
1347            }
1348            Some(HciEventCode::ConnectionComplete) => {
1349                self.process_connection_complete(event);
1350            }
1351            Some(HciEventCode::DisconnectionComplete) => {
1352                self.process_disconnection_complete(event);
1353            }
1354            Some(HciEventCode::ExtendedInquiryResult) => {
1355                self.process_extended_inquiry_result(event);
1356            }
1357            _ => {
1358                // Unknown or unhandled event
1359            }
1360        }
1361    }
1362
1363    /// Handle Command Complete event internals
1364    fn handle_command_complete(&mut self, opcode: u16, event: &HciEvent) {
1365        match opcode {
1366            HCI_READ_BD_ADDR => {
1367                // params: [num_cmds, opcode_lo, opcode_hi, status, BD_ADDR[6]]
1368                if event.param_len >= 10 {
1369                    let status = event.params[3];
1370                    if status == 0x00 {
1371                        self.local_addr.copy_from_slice(&event.params[4..10]);
1372                    }
1373                }
1374            }
1375            HCI_READ_LOCAL_NAME => {
1376                // params: [num_cmds, opcode_lo, opcode_hi, status, name[248]]
1377                if event.param_len >= 5 {
1378                    let status = event.params[3];
1379                    if status == 0x00 {
1380                        let name_start = 4;
1381                        let name_end = (event.param_len as usize).min(252);
1382                        let name_slice = &event.params[name_start..name_end];
1383                        // Find null terminator
1384                        let len = name_slice
1385                            .iter()
1386                            .position(|&b| b == 0)
1387                            .unwrap_or(name_slice.len());
1388                        let copy_len = len.min(248);
1389                        self.local_name[..copy_len].copy_from_slice(&name_slice[..copy_len]);
1390                        self.local_name_len = copy_len;
1391                    }
1392                }
1393            }
1394            HCI_RESET => {
1395                if event.param_len >= 4 && event.params[3] == 0x00 {
1396                    self.state = ControllerState::Ready;
1397                }
1398            }
1399            _ => {}
1400        }
1401    }
1402
1403    /// Parse Inquiry Result event and store device info
1404    fn process_inquiry_result(&mut self, event: &HciEvent) {
1405        if event.param_len < 1 {
1406            return;
1407        }
1408        let num_responses = event.params[0] as usize;
1409        // Each response: BD_ADDR(6) + page_scan_rep(1) + reserved(2) + CoD(3) +
1410        // clock(2) = 14
1411        let mut offset = 1;
1412        for _ in 0..num_responses {
1413            if offset + 14 > event.param_len as usize {
1414                break;
1415            }
1416            let mut addr = BD_ADDR_ZERO;
1417            addr.copy_from_slice(&event.params[offset..offset + 6]);
1418            let psrm = event.params[offset + 6];
1419            // skip 2 reserved bytes
1420            let cod = u32::from_le_bytes([
1421                event.params[offset + 9],
1422                event.params[offset + 10],
1423                event.params[offset + 11],
1424                0,
1425            ]);
1426            let clock = u16::from_le_bytes([event.params[offset + 12], event.params[offset + 13]]);
1427            self.handle_inquiry_result(addr, psrm, cod, clock);
1428            offset += 14;
1429        }
1430    }
1431
1432    /// Parse Connection Complete event
1433    fn process_connection_complete(&mut self, event: &HciEvent) {
1434        // params: status(1), handle(2), BD_ADDR(6), link_type(1), encryption(1)
1435        if event.param_len < 11 {
1436            return;
1437        }
1438        let status = event.params[0];
1439        let handle = u16::from_le_bytes([event.params[1], event.params[2]]);
1440        let mut addr = BD_ADDR_ZERO;
1441        addr.copy_from_slice(&event.params[3..9]);
1442        let link_type = event.params[9];
1443        let _ = self.handle_connection_complete(status, handle, &addr, link_type);
1444    }
1445
1446    /// Parse Disconnection Complete event
1447    fn process_disconnection_complete(&mut self, event: &HciEvent) {
1448        // params: status(1), handle(2), reason(1)
1449        if event.param_len < 4 {
1450            return;
1451        }
1452        let status = event.params[0];
1453        let handle = u16::from_le_bytes([event.params[1], event.params[2]]);
1454        self.handle_disconnection_complete(status, handle);
1455    }
1456
1457    /// Parse Extended Inquiry Result event
1458    fn process_extended_inquiry_result(&mut self, event: &HciEvent) {
1459        // params: num_responses(1) + BD_ADDR(6) + psrm(1) + reserved(1)
1460        //       + CoD(3) + clock(2) + rssi(1) + EIR(240)
1461        if event.param_len < 15 {
1462            return;
1463        }
1464        let mut addr = BD_ADDR_ZERO;
1465        addr.copy_from_slice(&event.params[1..7]);
1466        let psrm = event.params[7];
1467        let cod = u32::from_le_bytes([event.params[9], event.params[10], event.params[11], 0]);
1468        let clock = u16::from_le_bytes([event.params[12], event.params[13]]);
1469        let rssi = event.params[14] as i8;
1470
1471        self.handle_inquiry_result(addr, psrm, cod, clock);
1472
1473        // Try to extract name from EIR data
1474        if event.param_len > 15 {
1475            let eir_data = &event.params[15..event.param_len as usize];
1476            if let Some((name, name_len)) = parse_eir_name(eir_data) {
1477                // Update the discovered device with the name
1478                for dev in &mut self.discovered[..self.discovered_count] {
1479                    if dev.valid && dev.addr == addr {
1480                        dev.name = name;
1481                        dev.name_len = name_len;
1482                        dev.rssi = rssi;
1483                        break;
1484                    }
1485                }
1486            }
1487        }
1488    }
1489
1490    /// Poll the transport and process any pending events
1491    pub(crate) fn poll(&mut self) -> Result<(), KernelError> {
1492        if self.state == ControllerState::Off {
1493            return Ok(());
1494        }
1495
1496        // Poll for HCI events
1497        if let Some(event) = self.transport.poll_event()? {
1498            self.process_event(&event);
1499        }
1500
1501        // Poll for ACL data
1502        if let Some((_header, _data, _len)) = self.transport.poll_acl_data()? {
1503            self.stats.acl_packets_received += 1;
1504        }
1505
1506        Ok(())
1507    }
1508
1509    // ----- Internal Helpers -----
1510
1511    fn ensure_ready(&self) -> Result<(), KernelError> {
1512        match self.state {
1513            ControllerState::Ready | ControllerState::Scanning | ControllerState::Connected => {
1514                Ok(())
1515            }
1516            ControllerState::Off => Err(KernelError::InvalidState {
1517                expected: "Ready",
1518                actual: "Off",
1519            }),
1520            ControllerState::Initializing => Err(KernelError::InvalidState {
1521                expected: "Ready",
1522                actual: "Initializing",
1523            }),
1524        }
1525    }
1526
1527    fn ensure_ready_or_connected(&self) -> Result<(), KernelError> {
1528        match self.state {
1529            ControllerState::Ready | ControllerState::Connected => Ok(()),
1530            _ => Err(KernelError::InvalidState {
1531                expected: "Ready or Connected",
1532                actual: "other",
1533            }),
1534        }
1535    }
1536
1537    fn next_signal_identifier(&mut self) -> u8 {
1538        let id = self.next_signal_id;
1539        self.next_signal_id = self.next_signal_id.wrapping_add(1);
1540        if self.next_signal_id == 0 {
1541            self.next_signal_id = 1; // identifier must be non-zero
1542        }
1543        id
1544    }
1545}
1546
1547// ---------------------------------------------------------------------------
1548// Module-Level Init
1549// ---------------------------------------------------------------------------
1550
1551/// Initialize the HCI subsystem (called from bluetooth::init)
1552pub fn init() {
1553    crate::println!("[BT-HCI] HCI driver initialized");
1554}
1555
1556// ---------------------------------------------------------------------------
1557// Unit Tests
1558// ---------------------------------------------------------------------------
1559
1560#[cfg(test)]
1561mod tests {
1562    use super::*;
1563
1564    #[test]
1565    fn test_make_opcode() {
1566        // HCI_Reset: OGF=0x03, OCF=0x0003
1567        let op = make_opcode(0x03, 0x0003);
1568        assert_eq!(opcode_ogf(op), 0x03);
1569        assert_eq!(opcode_ocf(op), 0x0003);
1570        assert_eq!(op, HCI_RESET);
1571    }
1572
1573    #[test]
1574    fn test_opcode_constants() {
1575        assert_eq!(opcode_ogf(HCI_INQUIRY), 0x01);
1576        assert_eq!(opcode_ocf(HCI_INQUIRY), 0x0001);
1577        assert_eq!(opcode_ogf(HCI_READ_BD_ADDR), 0x04);
1578        assert_eq!(opcode_ocf(HCI_READ_BD_ADDR), 0x0009);
1579        assert_eq!(opcode_ogf(HCI_WRITE_SCAN_ENABLE), 0x03);
1580        assert_eq!(opcode_ocf(HCI_WRITE_SCAN_ENABLE), 0x001A);
1581    }
1582
1583    #[test]
1584    fn test_hci_packet_type_roundtrip() {
1585        assert_eq!(HciPacketType::from_u8(0x01), Some(HciPacketType::Command));
1586        assert_eq!(HciPacketType::from_u8(0x02), Some(HciPacketType::AclData));
1587        assert_eq!(HciPacketType::from_u8(0x03), Some(HciPacketType::ScoData));
1588        assert_eq!(HciPacketType::from_u8(0x04), Some(HciPacketType::Event));
1589        assert_eq!(HciPacketType::from_u8(0x05), None);
1590    }
1591
1592    #[test]
1593    fn test_hci_command_no_params() {
1594        let cmd = HciCommand::new(HCI_RESET);
1595        assert_eq!(cmd.opcode, HCI_RESET);
1596        assert_eq!(cmd.param_len, 0);
1597    }
1598
1599    #[test]
1600    fn test_hci_command_with_params() {
1601        let params = [0x03u8]; // inquiry + page scan
1602        let cmd = HciCommand::with_params(HCI_WRITE_SCAN_ENABLE, &params).unwrap();
1603        assert_eq!(cmd.opcode, HCI_WRITE_SCAN_ENABLE);
1604        assert_eq!(cmd.param_len, 1);
1605        assert_eq!(cmd.params[0], 0x03);
1606    }
1607
1608    #[test]
1609    fn test_hci_command_serialize() {
1610        let cmd = HciCommand::new(HCI_RESET);
1611        let mut buf = [0u8; 16];
1612        let len = cmd.serialize(&mut buf).unwrap();
1613        assert_eq!(len, 4); // type(1) + header(3) + params(0)
1614        assert_eq!(buf[0], 0x01); // Command type
1615        assert_eq!(u16::from_le_bytes([buf[1], buf[2]]), HCI_RESET);
1616        assert_eq!(buf[3], 0); // param_len
1617    }
1618
1619    #[test]
1620    fn test_hci_event_parse() {
1621        // Command Complete for HCI_Reset, status 0x00
1622        let raw = [
1623            0x0E, // event code: Command Complete
1624            0x04, // param_len
1625            0x01, // num_hci_command_packets
1626            0x03, 0x0C, // opcode (HCI_RESET = 0x0C03 LE)
1627            0x00, // status success
1628        ];
1629        let evt = HciEvent::parse(&raw).unwrap();
1630        assert_eq!(evt.event_code, 0x0E);
1631        assert_eq!(evt.param_len, 4);
1632        assert!(evt.is_command_complete());
1633        assert!(!evt.is_command_status());
1634        assert_eq!(evt.command_complete_opcode(), Some(HCI_RESET));
1635        assert_eq!(evt.command_complete_status(), Some(0x00));
1636    }
1637
1638    #[test]
1639    fn test_acl_header_roundtrip() {
1640        let header = AclHeader {
1641            handle: 0x0042,
1642            boundary: AclBoundaryFlag::FirstFlushable,
1643            broadcast: AclBroadcastFlag::PointToPoint,
1644            data_len: 128,
1645        };
1646        let mut buf = [0u8; 4];
1647        header.serialize(&mut buf).unwrap();
1648        let parsed = AclHeader::parse(&buf).unwrap();
1649        assert_eq!(parsed.handle, 0x0042);
1650        assert_eq!(parsed.boundary, AclBoundaryFlag::FirstFlushable);
1651        assert_eq!(parsed.broadcast, AclBroadcastFlag::PointToPoint);
1652        assert_eq!(parsed.data_len, 128);
1653    }
1654
1655    #[test]
1656    fn test_l2cap_header_roundtrip() {
1657        let hdr = L2capHeader {
1658            length: 48,
1659            cid: L2CAP_CID_ATT,
1660        };
1661        let mut buf = [0u8; 4];
1662        hdr.serialize(&mut buf).unwrap();
1663        let parsed = L2capHeader::parse(&buf).unwrap();
1664        assert_eq!(parsed.length, 48);
1665        assert_eq!(parsed.cid, L2CAP_CID_ATT);
1666    }
1667
1668    #[test]
1669    fn test_controller_state_machine() {
1670        let mut ctrl = BluetoothController::new();
1671        assert_eq!(ctrl.state(), ControllerState::Off);
1672
1673        // Initialize transitions Off -> Initializing -> Ready
1674        ctrl.initialize(1).unwrap();
1675        assert_eq!(ctrl.state(), ControllerState::Ready);
1676
1677        // Cannot initialize twice
1678        assert!(ctrl.initialize(2).is_err());
1679    }
1680
1681    #[test]
1682    fn test_inquiry_result_handling() {
1683        let mut ctrl = BluetoothController::new();
1684        ctrl.state = ControllerState::Scanning;
1685
1686        let addr: BdAddr = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66];
1687        ctrl.handle_inquiry_result(addr, 0x01, 0x001F00, 0x0000);
1688        assert_eq!(ctrl.discovered_count(), 1);
1689
1690        let dev = ctrl.get_discovered(0).unwrap();
1691        assert_eq!(dev.addr, addr);
1692        assert_eq!(dev.class_of_device, 0x001F00);
1693
1694        // Duplicate address should not add a second entry
1695        ctrl.handle_inquiry_result(addr, 0x01, 0x001F00, 0x0000);
1696        assert_eq!(ctrl.discovered_count(), 1);
1697    }
1698
1699    #[test]
1700    fn test_eir_name_parsing() {
1701        // EIR data with Complete Local Name
1702        let eir = [
1703            0x05, // length=5
1704            0x09, // type = Complete Local Name
1705            b'T', b'e', b's', b't', // "Test"
1706            0x00, // terminator
1707        ];
1708        let (name, len) = parse_eir_name(&eir).unwrap();
1709        assert_eq!(len, 4);
1710        assert_eq!(&name[..4], b"Test");
1711    }
1712
1713    #[test]
1714    fn test_sdp_record_registration() {
1715        let mut ctrl = BluetoothController::new();
1716        let handle = ctrl.register_sdp_record(UUID_SERIAL_PORT, 1).unwrap();
1717        assert!(handle >= 0x10000);
1718
1719        let record = ctrl.sdp_search_local(UUID_SERIAL_PORT);
1720        assert!(record.is_some());
1721        assert_eq!(record.unwrap().protocol_channel, 1);
1722
1723        // Non-existent UUID
1724        assert!(ctrl.sdp_search_local(UUID_HID).is_none());
1725    }
1726
1727    #[test]
1728    fn test_connection_lifecycle() {
1729        let mut ctrl = BluetoothController::new();
1730        ctrl.state = ControllerState::Ready;
1731        ctrl.transport.active = true;
1732
1733        let addr: BdAddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
1734        ctrl.create_connection(&addr).unwrap();
1735
1736        // Simulate Connection Complete (success)
1737        ctrl.handle_connection_complete(0x00, 0x0040, &addr, 0x01)
1738            .unwrap();
1739        assert_eq!(ctrl.connection_count(), 1);
1740        assert_eq!(ctrl.state(), ControllerState::Connected);
1741        assert!(ctrl.find_connection(0x0040).is_some());
1742
1743        // Disconnect
1744        ctrl.disconnect(0x0040, 0x13).unwrap(); // 0x13 = Remote User Terminated
1745        ctrl.handle_disconnection_complete(0x00, 0x0040);
1746        assert_eq!(ctrl.connection_count(), 0);
1747        assert_eq!(ctrl.state(), ControllerState::Ready);
1748    }
1749
1750    #[test]
1751    fn test_format_bd_addr() {
1752        let addr: BdAddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
1753        let formatted = format_bd_addr(&addr);
1754        assert_eq!(&formatted, b"FF:EE:DD:CC:BB:AA");
1755    }
1756}