/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #if MYNEWT_VAL(BLE_CONTROLLER) /* to enable dser diag */ #include #endif /* BLE_CONTROLLER */ #include #if !MYNEWT_VAL(BLE_CONTROLLER) #include #endif /* !BLE_CONTROLLER */ #include #include #include #include static struct hci_h4_sm hci_cmac_h4sm; static int hci_cmac_acl_tx(struct os_mbuf *om) { uint8_t pkt_type = HCI_H4_ACL; struct os_mbuf *om_next; cmac_mbox_write(&pkt_type, sizeof(pkt_type)); while (om) { om_next = SLIST_NEXT(om, om_next); cmac_mbox_write(om->om_data, om->om_len); os_mbuf_free(om); om = om_next; } return 0; } #if !MYNEWT_VAL(BLE_CONTROLLER) static int hci_cmac_hs_frame_cb(uint8_t pkt_type, void *data) { int rc; switch (pkt_type) { case HCI_H4_ACL: rc = ble_transport_to_hs_acl(data); break; case HCI_H4_EVT: rc = ble_transport_to_hs_evt(data); break; default: assert(0); break; } return rc; } static int hci_cmac_hs_mbox_read_cb(const void *data, uint16_t len) { int rlen; rlen = hci_h4_sm_rx(&hci_cmac_h4sm, data, len); assert(rlen >= 0); return rlen; } static void hci_cmac_hs_mbox_write_notif_cb(void) { cmac_host_signal2cmac(); } void ble_transport_ll_init(void) { hci_h4_sm_init(&hci_cmac_h4sm, &hci_h4_allocs_from_ll, hci_cmac_hs_frame_cb); /* We can now handle data from CMAC, initialize it */ cmac_mbox_set_read_cb(hci_cmac_hs_mbox_read_cb); cmac_mbox_set_write_notif_cb(hci_cmac_hs_mbox_write_notif_cb); cmac_host_init(); } #endif /* !BLE_CONTROLLER */ #if MYNEWT_VAL(BLE_CONTROLLER) #if !MYNEWT_VAL(MCU_DEBUG_DSER_BLE_HCI_CMAC_LL) #define MCU_DIAG_SER_DISABLE #endif static int hci_cmac_ll_frame_cb(uint8_t pkt_type, void *data) { int rc; switch (pkt_type) { case HCI_H4_CMD: rc = ble_transport_to_ll_cmd(data); break; case HCI_H4_ACL: rc = ble_transport_to_ll_acl(data); break; default: assert(0); break; } return rc; } static int hci_cmac_ll_mbox_read_cb(const void *data, uint16_t len) { int rlen; MCU_DIAG_SER('R'); rlen = hci_h4_sm_rx(&hci_cmac_h4sm, data, len); assert(rlen >= 0); return rlen; } static void hci_cmac_ll_mbox_write_notif_cb(void) { MCU_DIAG_SER('W'); CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk; } void ble_transport_hs_init(void) { hci_h4_sm_init(&hci_cmac_h4sm, &hci_h4_allocs_from_hs, hci_cmac_ll_frame_cb); /* Setup callbacks for mailboxes */ cmac_mbox_set_read_cb(hci_cmac_ll_mbox_read_cb); cmac_mbox_set_write_notif_cb(hci_cmac_ll_mbox_write_notif_cb); /* Synchronize with SYS */ cmac_shared_sync(); } #endif #if !MYNEWT_VAL(BLE_CONTROLLER) int ble_transport_to_ll_cmd_impl(void *buf) { uint8_t pkt_type = HCI_H4_CMD; uint8_t *cmd = buf; cmac_mbox_write(&pkt_type, sizeof(pkt_type)); cmac_mbox_write(cmd, cmd[2] + 3); ble_transport_free(buf); return 0; } int ble_transport_to_ll_acl_impl(struct os_mbuf *om) { return hci_cmac_acl_tx(om); } #endif #if MYNEWT_VAL(BLE_CONTROLLER) int ble_transport_to_hs_acl_impl(struct os_mbuf *om) { return hci_cmac_acl_tx(om); } int ble_transport_to_hs_evt_impl(void *buf) { uint8_t pkt_type = HCI_H4_EVT; uint8_t *evt = buf; os_sr_t sr; OS_ENTER_CRITICAL(sr); cmac_mbox_write(&pkt_type, sizeof(pkt_type)); cmac_mbox_write(evt, evt[1] + 2); ble_transport_free(buf); OS_EXIT_CRITICAL(sr); return 0; } #endif /* BLE_CONTROLLER */