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