| /* |
| * 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 "syscfg/syscfg.h" |
| |
| #if MYNEWT_VAL(BLE_CONTROLLER) |
| |
| #if !MYNEWT_VAL(MCU_DEBUG_DSER_BLE_HCI_CMAC_LL) |
| #define MCU_DIAG_SER_DISABLE |
| #endif |
| |
| #include <assert.h> |
| #include <string.h> |
| #include "mcu/mcu.h" |
| #include "cmac_driver/cmac_shared.h" |
| #include "nimble/ble_hci_trans.h" |
| #include "os/os_mbuf.h" |
| #include "ble_hci_trans_h4.h" |
| #include "ble_hci_cmac_priv.h" |
| |
| struct ble_hci_cmac_ll_api { |
| ble_hci_trans_rx_cmd_fn *cmd_cb; |
| void *cmd_arg; |
| ble_hci_trans_rx_acl_fn *acl_cb; |
| void *acl_arg; |
| }; |
| |
| static struct ble_hci_cmac_ll_api g_ble_hci_cmac_ll_api; |
| static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_ll_rx_state; |
| |
| static int |
| ble_hci_cmac_ll_frame_cb(uint8_t pkt_type, void *data) |
| { |
| int rc; |
| |
| MCU_DIAG_SER('F'); |
| |
| switch (pkt_type) { |
| case BLE_HCI_TRANS_H4_PKT_TYPE_CMD: |
| rc = g_ble_hci_cmac_ll_api.cmd_cb(data, g_ble_hci_cmac_ll_api.cmd_arg); |
| break; |
| case BLE_HCI_TRANS_H4_PKT_TYPE_ACL: |
| rc = g_ble_hci_cmac_ll_api.acl_cb(data, g_ble_hci_cmac_ll_api.acl_arg); |
| break; |
| default: |
| assert(0); |
| break; |
| } |
| |
| return rc; |
| } |
| |
| static int |
| ble_hci_cmac_ll_mbox_read_cb(const void *data, uint16_t len) |
| { |
| int rlen; |
| |
| MCU_DIAG_SER('R'); |
| rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_ll_rx_state, data, len, |
| ble_hci_cmac_ll_frame_cb); |
| |
| /* There should be no oom on LL side due to flow control used */ |
| assert(rlen >= 0); |
| |
| return rlen; |
| } |
| |
| static void |
| ble_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; |
| } |
| |
| int |
| ble_hci_trans_ll_evt_tx(uint8_t *evt) |
| { |
| uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_EVT; |
| |
| cmac_mbox_write(&pkt_type, sizeof(pkt_type)); |
| cmac_mbox_write(evt, evt[1] + 2); |
| |
| ble_hci_trans_buf_free(evt); |
| |
| return 0; |
| } |
| |
| int |
| ble_hci_trans_ll_acl_tx(struct os_mbuf *om) |
| { |
| uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_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; |
| } |
| |
| void |
| ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, void *cmd_arg, |
| ble_hci_trans_rx_acl_fn *acl_cb, void *acl_arg) |
| { |
| g_ble_hci_cmac_ll_api.cmd_cb = cmd_cb; |
| g_ble_hci_cmac_ll_api.cmd_arg = cmd_arg; |
| g_ble_hci_cmac_ll_api.acl_cb = acl_cb; |
| g_ble_hci_cmac_ll_api.acl_arg = acl_arg; |
| |
| /* Setup callbacks for mailboxes */ |
| cmac_mbox_set_read_cb(ble_hci_cmac_ll_mbox_read_cb); |
| cmac_mbox_set_write_notif_cb(ble_hci_cmac_ll_mbox_write_notif_cb); |
| |
| /* Synchronize with SYS */ |
| cmac_shared_sync(); |
| } |
| |
| #endif |