1 // Copyright 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use crate::ffi; 16 use crate::llcp::iso; 17 use crate::packets::{hci, llcp}; 18 use std::collections::HashMap; 19 use std::convert::TryFrom; 20 use thiserror::Error; 21 22 struct Link { 23 acl_connection_handle: u16, 24 role: hci::Role, 25 } 26 27 pub struct LinkLayer { 28 ops: ffi::ControllerOps, 29 links: HashMap<u16, Link>, 30 iso: iso::IsoManager, 31 } 32 33 #[derive(Error, Debug)] 34 pub enum LinkLayerError { 35 #[error("Unknown peer")] 36 UnknownPeer, 37 #[error("Link already exists")] 38 LinkAlreadyExists, 39 #[error("Unhandled HCI packet")] 40 UnhandledHciPacket, 41 #[error("Invalid HCI packet")] 42 InvalidHciPacket, 43 #[error("Invalid LLCP packet")] 44 InvalidLlcpPacket, 45 } 46 47 impl LinkLayer { new(ops: ffi::ControllerOps) -> LinkLayer48 pub fn new(ops: ffi::ControllerOps) -> LinkLayer { 49 let iso = iso::IsoManager::new(ops.clone()); 50 LinkLayer { ops, links: HashMap::new(), iso } 51 } 52 add_link( &mut self, acl_connection_handle: u16, _peer_address: hci::Address, role: hci::Role, ) -> Result<(), LinkLayerError>53 pub fn add_link( 54 &mut self, 55 acl_connection_handle: u16, 56 _peer_address: hci::Address, 57 role: hci::Role, 58 ) -> Result<(), LinkLayerError> { 59 if self.links.contains_key(&acl_connection_handle) { 60 return Err(LinkLayerError::LinkAlreadyExists); 61 } 62 63 self.links.insert(acl_connection_handle, Link { acl_connection_handle, role }); 64 self.iso.add_acl_connection(acl_connection_handle, role); 65 Ok(()) 66 } 67 remove_link(&mut self, acl_connection_handle: u16) -> Result<(), LinkLayerError>68 pub fn remove_link(&mut self, acl_connection_handle: u16) -> Result<(), LinkLayerError> { 69 if self.links.remove(&acl_connection_handle).is_none() { 70 return Err(LinkLayerError::UnknownPeer); 71 } 72 73 self.iso.remove_acl_connection(acl_connection_handle); 74 Ok(()) 75 } 76 tick(&mut self)77 pub fn tick(&mut self) {} 78 ingest_hci(&mut self, packet: hci::Command) -> Result<(), LinkLayerError>79 pub fn ingest_hci(&mut self, packet: hci::Command) -> Result<(), LinkLayerError> { 80 use hci::CommandChild::*; 81 match packet.specialize() { 82 Disconnect(packet) => self.iso.hci_disconnect(packet), 83 LeSetCigParameters(packet) => self.iso.hci_le_set_cig_parameters(packet), 84 LeSetCigParametersTest(packet) => self.iso.hci_le_set_cig_parameters_test(packet), 85 LeCreateCis(packet) => self.iso.hci_le_create_cis(packet), 86 LeRemoveCig(packet) => self.iso.hci_le_remove_cig(packet), 87 LeAcceptCisRequest(packet) => self.iso.hci_le_accept_cis_request(packet), 88 LeRejectCisRequest(packet) => self.iso.hci_le_reject_cis_request(packet), 89 LeSetupIsoDataPath(packet) => self.iso.hci_le_setup_iso_data_path(packet), 90 LeRemoveIsoDataPath(packet) => self.iso.hci_le_remove_iso_data_path(packet), 91 _ => Err(LinkLayerError::UnhandledHciPacket)?, 92 }; 93 Ok(()) 94 } 95 ingest_llcp( &mut self, acl_connection_handle: u16, packet: llcp::LlcpPacket, ) -> Result<(), LinkLayerError>96 pub fn ingest_llcp( 97 &mut self, 98 acl_connection_handle: u16, 99 packet: llcp::LlcpPacket, 100 ) -> Result<(), LinkLayerError> { 101 use llcp::LlcpPacketChild::*; 102 match packet.specialize() { 103 RejectExtInd(packet) => match llcp::Opcode::try_from(packet.get_reject_opcode()) { 104 Ok(llcp::Opcode::LlCisReq) => { 105 self.iso.ll_reject_ext_ind(acl_connection_handle, packet) 106 } 107 _ => unreachable!(), 108 }, 109 CisReq(packet) => self.iso.ll_cis_req(acl_connection_handle, packet), 110 CisRsp(packet) => self.iso.ll_cis_rsp(acl_connection_handle, packet), 111 CisInd(packet) => self.iso.ll_cis_ind(acl_connection_handle, packet), 112 CisTerminateInd(packet) => self.iso.ll_cis_terminate_ind(acl_connection_handle, packet), 113 _ => unimplemented!(), 114 } 115 Ok(()) 116 } 117 get_cis_connection_handle(&self, cig_id: u8, cis_id: u8) -> Option<u16>118 pub fn get_cis_connection_handle(&self, cig_id: u8, cis_id: u8) -> Option<u16> { 119 self.iso.get_cis_connection_handle(|cis| cis.cig_id == cig_id && cis.cis_id == cis_id) 120 } 121 get_cis(&self, cis_connection_handle: u16) -> Option<&iso::Cis>122 pub fn get_cis(&self, cis_connection_handle: u16) -> Option<&iso::Cis> { 123 self.iso.get_cis(cis_connection_handle) 124 } 125 } 126