blob: 3531529c717b83c4b636abfe81f22294e078268b [file] [log] [blame]
/*
* 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