static inline struct net_pkt *prepare_arp_reply(struct net_if *iface, struct net_pkt *req, struct net_eth_addr *addr) { struct net_pkt *pkt; struct net_buf *frag; struct net_arp_hdr *hdr; struct net_eth_hdr *eth; pkt = net_pkt_get_reserve_tx(sizeof(struct net_eth_hdr), K_FOREVER); if (!pkt) { goto fail; } frag = net_pkt_get_frag(pkt, K_FOREVER); if (!frag) { goto fail; } net_pkt_frag_add(pkt, frag); net_pkt_set_iface(pkt, iface); hdr = NET_ARP_HDR(pkt); eth = NET_ETH_HDR(pkt); eth->type = htons(NET_ETH_PTYPE_ARP); memset(ð->dst.addr, 0xff, sizeof(struct net_eth_addr)); memcpy(ð->src.addr, net_if_get_link_addr(iface)->addr, sizeof(struct net_eth_addr)); hdr->hwtype = htons(NET_ARP_HTYPE_ETH); hdr->protocol = htons(NET_ETH_PTYPE_IP); hdr->hwlen = sizeof(struct net_eth_addr); hdr->protolen = sizeof(struct in_addr); hdr->opcode = htons(NET_ARP_REPLY); memcpy(&hdr->dst_hwaddr.addr, ð->src.addr, sizeof(struct net_eth_addr)); memcpy(&hdr->src_hwaddr.addr, addr, sizeof(struct net_eth_addr)); net_ipaddr_copy(&hdr->dst_ipaddr, &NET_ARP_HDR(req)->src_ipaddr); net_ipaddr_copy(&hdr->src_ipaddr, &NET_ARP_HDR(req)->dst_ipaddr); net_buf_add(frag, sizeof(struct net_arp_hdr)); return pkt; fail: net_pkt_unref(pkt); return NULL; }
static uint8_t read_cb(const struct bt_gatt_attr *attr, void *user_data) { struct read_data *data = user_data; struct bt_att *att = data->att; struct bt_conn *conn = att->chan.conn; int read; BT_DBG("handle 0x%04x", attr->handle); data->rsp = net_buf_add(data->buf, sizeof(*data->rsp)); /* * If any attribute is founded in handle range it means that error * should be changed from pre-set: invalid handle error to no error. */ data->err = 0x00; if (!attr->read) { data->err = BT_ATT_ERR_READ_NOT_PERMITTED; return BT_GATT_ITER_STOP; } /* Check attribute permissions */ data->err = check_perm(conn, attr, BT_GATT_PERM_READ_MASK); if (data->err) { return BT_GATT_ITER_STOP; } /* Read attribute value and store in the buffer */ read = attr->read(conn, attr, data->buf->data + data->buf->len, att->chan.tx.mtu - data->buf->len, data->offset); if (read < 0) { data->err = err_to_att(read); return BT_GATT_ITER_STOP; } net_buf_add(data->buf, read); return BT_GATT_ITER_CONTINUE; }
static void eth_rx(struct device *port) { struct eth_runtime *context = port->driver_data; struct eth_config *config = port->config->config_info; uint32_t base_addr = config->base_addr; struct net_buf *buf; uint32_t frm_len = 0; /* Check whether the RX descriptor is still owned by the device. If not, * process the received frame or an error that may have occurred. */ if (context->rx_desc.own == 1) { ETH_ERR("Spurious receive interrupt from Ethernet MAC.\n"); return; } if (!net_driver_ethernet_is_opened()) { goto release_desc; } if (context->rx_desc.err_summary) { ETH_ERR("Error receiving frame: RDES0 = %08x, RDES1 = %08x.\n", context->rx_desc.rdes0, context->rx_desc.rdes1); goto release_desc; } frm_len = context->rx_desc.frm_len; if (frm_len > UIP_BUFSIZE) { ETH_ERR("Frame too large: %u.\n", frm_len); goto release_desc; } buf = ip_buf_get_reserve_rx(0); if (buf == NULL) { ETH_ERR("Failed to obtain RX buffer.\n"); goto release_desc; } memcpy(net_buf_add(buf, frm_len), (void *)context->rx_buf, frm_len); uip_len(buf) = frm_len; net_driver_ethernet_recv(buf); release_desc: /* Return ownership of the RX descriptor to the device. */ context->rx_desc.own = 1; /* Request that the device check for an available RX descriptor, since * ownership of the descriptor was just transferred to the device. */ eth_write(base_addr, REG_ADDR_RX_POLL_DEMAND, 1); }
struct bt_conn *bt_conn_create_br(const bt_addr_t *peer, const struct bt_br_conn_param *param) { struct bt_hci_cp_connect *cp; struct bt_conn *conn; struct net_buf *buf; conn = bt_conn_lookup_addr_br(peer); if (conn) { switch (conn->state) { return conn; case BT_CONN_CONNECT: case BT_CONN_CONNECTED: return conn; default: bt_conn_unref(conn); return NULL; } } conn = bt_conn_add_br(peer); if (!conn) { return NULL; } buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT, sizeof(*cp)); if (!buf) { bt_conn_unref(conn); return NULL; } cp = net_buf_add(buf, sizeof(*cp)); memset(cp, 0, sizeof(*cp)); memcpy(&cp->bdaddr, peer, sizeof(cp->bdaddr)); cp->packet_type = sys_cpu_to_le16(0xcc18); /* DM1 DH1 DM3 DH5 DM5 DH5 */ cp->pscan_rep_mode = 0x02; /* R2 */ cp->allow_role_switch = param->allow_role_switch ? 0x01 : 0x00; cp->clock_offset = 0x0000; /* TODO used cached clock offset */ if (bt_hci_cmd_send_sync(BT_HCI_OP_CONNECT, buf, NULL) < 0) { bt_conn_unref(conn); return NULL; } bt_conn_set_state(conn, BT_CONN_CONNECT); conn->role = BT_CONN_ROLE_MASTER; return conn; }
static int gatt_prepare_write(struct bt_conn *conn, uint16_t handle, uint16_t offset, const void *data, uint16_t length, bt_gatt_rsp_func_t func) { struct net_buf *buf; struct bt_att_prepare_write_req *req; static struct prepare_write_data prep_data; uint16_t len; if (prep_data.func) { return -EBUSY; } len = min(length, bt_att_get_mtu(conn) - sizeof(*req) - 1); prep_data.func = func; prep_data.handle = handle; prep_data.offset = offset + len; prep_data.data = data + len; prep_data.length = length - len; buf = bt_att_create_pdu(conn, BT_ATT_OP_PREPARE_WRITE_REQ, sizeof(*req) + len); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->handle = sys_cpu_to_le16(handle); req->offset = sys_cpu_to_le16(offset); memcpy(req->value, data, len); net_buf_add(buf, len); BT_DBG("handle 0x%04x offset %u len %u", handle, offset, len); return gatt_send(conn, buf, att_prepare_write_rsp, &prep_data, NULL); }
static int att_notify(struct bt_conn *conn, uint16_t handle, const void *data, size_t len) { struct net_buf *buf; struct bt_att_notify *nfy; buf = bt_att_create_pdu(conn, BT_ATT_OP_NOTIFY, sizeof(*nfy) + len); if (!buf) { BT_WARN("No buffer available to send notification"); return -ENOMEM; } BT_DBG("conn %p handle 0x%04x", conn, handle); nfy = net_buf_add(buf, sizeof(*nfy)); nfy->handle = sys_cpu_to_le16(handle); net_buf_add(buf, len); memcpy(nfy->value, data, len); bt_l2cap_send(conn, BT_L2CAP_CID_ATT, buf); return 0; }
static void l2cap_chan_update_credits(struct bt_l2cap_le_chan *chan) { struct net_buf *buf; struct bt_l2cap_sig_hdr *hdr; struct bt_l2cap_le_credits *ev; uint16_t credits; /* Only give more credits if it went bellow the defined threshold */ if (chan->rx.credits.nsig > L2CAP_LE_CREDITS_THRESHOLD) { goto done; } /* Restore credits */ credits = L2CAP_LE_MAX_CREDITS - chan->rx.credits.nsig; l2cap_chan_rx_give_credits(chan, credits); buf = bt_l2cap_create_pdu(&le_sig); if (!buf) { BT_ERR("Unable to send credits"); return; } hdr = net_buf_add(buf, sizeof(*hdr)); hdr->code = BT_L2CAP_LE_CREDITS; hdr->ident = get_ident(); hdr->len = sys_cpu_to_le16(sizeof(*ev)); ev = net_buf_add(buf, sizeof(*ev)); ev->cid = sys_cpu_to_le16(chan->rx.cid); ev->credits = sys_cpu_to_le16(credits); bt_l2cap_send(chan->chan.conn, BT_L2CAP_CID_LE_SIG, buf); done: BT_DBG("chan %p credits %u", chan, chan->rx.credits.nsig); }
static struct net_buf *l2cap_create_le_sig_pdu(uint8_t code, uint8_t ident, uint16_t len) { struct net_buf *buf; struct bt_l2cap_sig_hdr *hdr; buf = bt_l2cap_create_pdu(NULL, 0); hdr = net_buf_add(buf, sizeof(*hdr)); hdr->code = code; hdr->ident = ident; hdr->len = sys_cpu_to_le16(len); return buf; }
static void le_conn_param_update_req(struct bt_l2cap *l2cap, uint8_t ident, struct net_buf *buf) { struct bt_conn *conn = l2cap->chan.chan.conn; struct bt_le_conn_param param; struct bt_l2cap_conn_param_rsp *rsp; struct bt_l2cap_conn_param_req *req = (void *)buf->data; bool accepted; if (buf->len < sizeof(*req)) { BT_ERR("Too small LE conn update param req"); return; } if (conn->role != BT_HCI_ROLE_MASTER) { l2cap_send_reject(conn, ident, BT_L2CAP_REJ_NOT_UNDERSTOOD, NULL, 0); return; } param.interval_min = sys_le16_to_cpu(req->min_interval); param.interval_max = sys_le16_to_cpu(req->max_interval); param.latency = sys_le16_to_cpu(req->latency); param.timeout = sys_le16_to_cpu(req->timeout); BT_DBG("min 0x%04x max 0x%04x latency: 0x%04x timeout: 0x%04x", param.interval_min, param.interval_max, param.latency, param.timeout); buf = l2cap_create_le_sig_pdu(BT_L2CAP_CONN_PARAM_RSP, ident, sizeof(*rsp)); accepted = le_param_req(conn, ¶m); rsp = net_buf_add(buf, sizeof(*rsp)); if (accepted) { rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_ACCEPTED); } else { rsp->result = sys_cpu_to_le16(BT_L2CAP_CONN_PARAM_REJECTED); } bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); if (accepted) { bt_conn_le_conn_update(conn, ¶m); } }
static int gatt_exec_write(struct bt_conn *conn, bt_gatt_rsp_func_t func) { struct net_buf *buf; struct bt_att_exec_write_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_EXEC_WRITE_REQ, sizeof(*req)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->flags = BT_ATT_FLAG_EXEC; BT_DBG(""); return gatt_send(conn, buf, att_write_rsp, func, NULL); }
static int ssp_confirm_reply(struct bt_conn *conn) { struct bt_hci_cp_user_confirm_reply *cp; struct net_buf *buf; BT_DBG(""); buf = bt_hci_cmd_create(BT_HCI_OP_USER_CONFIRM_REPLY, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_copy(&cp->bdaddr, &conn->br.dst); return bt_hci_cmd_send_sync(BT_HCI_OP_USER_CONFIRM_REPLY, buf, NULL); }
static int pin_code_neg_reply(const bt_addr_t *bdaddr) { struct bt_hci_cp_pin_code_neg_reply *cp; struct net_buf *buf; BT_DBG(""); buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_copy(&cp->bdaddr, bdaddr); return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_NEG_REPLY, buf, NULL); }
static int ssp_passkey_reply(struct bt_conn *conn, unsigned int passkey) { struct bt_hci_cp_user_passkey_reply *cp; struct net_buf *buf; BT_DBG(""); buf = bt_hci_cmd_create(BT_HCI_OP_USER_PASSKEY_REPLY, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_copy(&cp->bdaddr, &conn->br.dst); cp->passkey = sys_cpu_to_le32(passkey); return bt_hci_cmd_send_sync(BT_HCI_OP_USER_PASSKEY_REPLY, buf, NULL); }
static void l2cap_send_reject(struct bt_conn *conn, uint8_t ident, uint16_t reason, void *data, uint8_t data_len) { struct bt_l2cap_cmd_reject *rej; struct net_buf *buf; buf = l2cap_create_le_sig_pdu(BT_L2CAP_CMD_REJECT, ident, sizeof(*rej) + data_len); rej = net_buf_add(buf, sizeof(*rej)); rej->reason = sys_cpu_to_le16(reason); if (data) { net_buf_add_mem(buf, data, data_len); } bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); }
static uint8_t att_mtu_req(struct bt_att *att, struct net_buf *buf) { struct bt_conn *conn = att->chan.conn; struct bt_att_exchange_mtu_req *req; struct bt_att_exchange_mtu_rsp *rsp; struct net_buf *pdu; uint16_t mtu_client, mtu_server; req = (void *)buf->data; mtu_client = sys_le16_to_cpu(req->mtu); BT_DBG("Client MTU %u", mtu_client); /* Check if MTU is valid */ if (mtu_client < BT_ATT_DEFAULT_LE_MTU) { return BT_ATT_ERR_INVALID_PDU; } pdu = bt_att_create_pdu(conn, BT_ATT_OP_MTU_RSP, sizeof(*rsp)); if (!pdu) { return BT_ATT_ERR_UNLIKELY; } mtu_server = CONFIG_BLUETOOTH_ATT_MTU; BT_DBG("Server MTU %u", mtu_server); rsp = net_buf_add(pdu, sizeof(*rsp)); rsp->mtu = sys_cpu_to_le16(mtu_server); bt_l2cap_send(conn, BT_L2CAP_CID_ATT, pdu); /* BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part F] page 484: * * A device's Exchange MTU Request shall contain the same MTU as the * device's Exchange MTU Response (i.e. the MTU shall be symmetric). */ att->chan.rx.mtu = min(mtu_client, mtu_server); att->chan.tx.mtu = att->chan.rx.mtu; BT_DBG("Negotiated MTU %u", att->chan.rx.mtu); return 0; }
static int conn_auth(struct bt_conn *conn) { struct bt_hci_cp_auth_requested *auth; struct net_buf *buf; BT_DBG(""); buf = bt_hci_cmd_create(BT_HCI_OP_AUTH_REQUESTED, sizeof(*auth)); if (!buf) { return -ENOBUFS; } auth = net_buf_add(buf, sizeof(*auth)); auth->handle = sys_cpu_to_le16(conn->handle); atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR); return bt_hci_cmd_send_sync(BT_HCI_OP_AUTH_REQUESTED, buf, NULL); }
static struct net_buf *l2cap_chan_create_seg(struct bt_l2cap_le_chan *ch, struct net_buf *buf, size_t sdu_hdr_len) { struct net_buf *seg; uint16_t headroom; uint16_t len; /* Segment if data (+ data headroom) is bigger than MPS */ if (buf->len + sdu_hdr_len > ch->tx.mps) { goto segment; } headroom = sizeof(struct bt_hci_acl_hdr) + sizeof(struct bt_l2cap_hdr) + sdu_hdr_len; /* Check if original buffer has enough headroom */ if (net_buf_headroom(buf) >= headroom) { if (sdu_hdr_len) { /* Push SDU length if set */ net_buf_push_le16(buf, buf->len); } return net_buf_ref(buf); } segment: seg = bt_l2cap_create_pdu(&le_data); if (!seg) { return NULL; } if (sdu_hdr_len) { net_buf_add_le16(seg, buf->len); } len = min(min(buf->len, L2CAP_LE_MIN_MTU - sdu_hdr_len), ch->tx.mps); memcpy(net_buf_add(seg, len), buf->data, len); net_buf_pull(buf, len); BT_DBG("ch %p seg %p len %u", ch, seg, seg->len); return seg; }
static struct net_buf *create_frag(struct bt_conn *conn, struct net_buf *buf) { struct net_buf *frag; uint16_t frag_len; frag = bt_conn_create_pdu(&frag_buf, 0); if (conn->state != BT_CONN_CONNECTED) { net_buf_unref(frag); return NULL; } frag_len = min(conn_mtu(conn), net_buf_tailroom(frag)); memcpy(net_buf_add(frag, frag_len), buf->data, frag_len); net_buf_pull(buf, frag_len); return frag; }
int bt_l2cap_update_conn_param(struct bt_conn *conn, const struct bt_le_conn_param *param) { struct bt_l2cap_conn_param_req *req; struct net_buf *buf; buf = l2cap_create_le_sig_pdu(BT_L2CAP_CONN_PARAM_REQ, get_ident(), sizeof(*req)); req = net_buf_add(buf, sizeof(*req)); req->min_interval = sys_cpu_to_le16(param->interval_min); req->max_interval = sys_cpu_to_le16(param->interval_max); req->latency = sys_cpu_to_le16(param->latency); req->timeout = sys_cpu_to_le16(param->timeout); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); return 0; }
static int gatt_read_blob(struct bt_conn *conn, struct bt_gatt_read_params *params) { struct net_buf *buf; struct bt_att_read_blob_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_READ_BLOB_REQ, sizeof(*req)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->handle = sys_cpu_to_le16(params->handle); req->offset = sys_cpu_to_le16(params->offset); BT_DBG("handle 0x%04x offset 0x%04x", params->handle, params->offset); return gatt_send(conn, buf, att_read_rsp, params, NULL); }
static int bt_hci_stop_scanning(void) { #ifdef NOT_USED_FOR_NOW struct net_buf *buf, *rsp; struct bt_hci_cp_le_set_scan_enable *scan_enable; int err; if (!atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { return -EALREADY; } buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(*scan_enable)); if (!buf) { return -ENOBUFS; } scan_enable = net_buf_add(buf, sizeof(*scan_enable)); memset(scan_enable, 0, sizeof(*scan_enable)); scan_enable->filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; scan_enable->enable = BT_HCI_LE_SCAN_DISABLE; err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_SCAN_ENABLE, buf, &rsp); if (err) { return err; } /* Update scan state in case of success (0) status */ err = rsp->data[0]; if (!err) { atomic_clear_bit(bt_dev.flags, BT_DEV_SCANNING); } net_buf_unref(rsp); return err; #endif nble_gap_stop_scan_req(); return 0; }
int tcp_tx(struct net_context *ctx, uint8_t *buf, size_t size) { struct net_buf *nbuf = NULL; uint8_t *ptr; int rc = 0; nbuf = ip_buf_get_tx(ctx); if (nbuf == NULL) { printk("[%s:%d] Unable to get buffer\n", __func__, __LINE__); return -EINVAL; } ptr = net_buf_add(nbuf, size); memcpy(ptr, buf, size); ip_buf_appdatalen(nbuf) = size; do { rc = net_send(nbuf); if (rc >= 0) { ip_buf_unref(nbuf); return 0; } switch (rc) { case -EINPROGRESS: printk("%s: no connection yet, try again\n", __func__); fiber_sleep(TCP_RETRY_TIMEOUT); break; case -EAGAIN: case -ECONNRESET: printk("%s: no connection, try again later\n", __func__); fiber_sleep(TCP_RETRY_TIMEOUT); break; default: printk("%s: sending %d bytes failed\n", __func__, size); ip_buf_unref(nbuf); return -EIO; } } while (1); return 0; }
static int att_find_info(struct bt_conn *conn, struct bt_gatt_discover_params *params) { struct net_buf *buf; struct bt_att_find_info_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_INFO_REQ, sizeof(*req)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->start_handle = sys_cpu_to_le16(params->start_handle); req->end_handle = sys_cpu_to_le16(params->end_handle); BT_DBG("start_handle 0x%04x end_handle 0x%04x", params->start_handle, params->end_handle); return gatt_send(conn, buf, att_find_info_rsp, params, NULL); }
static int pin_code_reply(struct bt_conn *conn, const char *pin, uint8_t len) { struct bt_hci_cp_pin_code_reply *cp; struct net_buf *buf; BT_DBG(""); buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_REPLY, sizeof(*cp)); if (!buf) { return -ENOBUFS; } cp = net_buf_add(buf, sizeof(*cp)); bt_addr_copy(&cp->bdaddr, &conn->br.dst); cp->pin_len = len; strncpy(cp->pin_code, pin, sizeof(cp->pin_code)); return bt_hci_cmd_send_sync(BT_HCI_OP_PIN_CODE_REPLY, buf, NULL); }
static void le_disconn_req(struct bt_l2cap *l2cap, uint8_t ident, struct net_buf *buf) { struct bt_conn *conn = l2cap->chan.chan.conn; struct bt_l2cap_le_chan *chan; struct bt_l2cap_disconn_req *req = (void *)buf->data; struct bt_l2cap_disconn_rsp *rsp; uint16_t scid; if (buf->len < sizeof(*req)) { BT_ERR("Too small LE conn req packet size"); return; } scid = sys_le16_to_cpu(req->scid); BT_DBG("scid 0x%04x dcid 0x%04x", scid, sys_le16_to_cpu(req->dcid)); chan = l2cap_remove_tx_cid(conn, scid); if (!chan) { struct bt_l2cap_cmd_reject_cid_data data; data.scid = req->scid; data.dcid = req->dcid; l2cap_send_reject(conn, ident, BT_L2CAP_REJ_INVALID_CID, &data, sizeof(data)); return; } buf = l2cap_create_le_sig_pdu(BT_L2CAP_DISCONN_RSP, ident, sizeof(*rsp)); rsp = net_buf_add(buf, sizeof(*rsp)); rsp->dcid = sys_cpu_to_le16(chan->rx.cid); rsp->scid = sys_cpu_to_le16(chan->tx.cid); bt_l2cap_chan_del(&chan->chan); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); }
static int l2cap_le_conn_req(struct bt_l2cap_le_chan *ch) { struct net_buf *buf; struct bt_l2cap_le_conn_req *req; ch->chan.ident = get_ident(); buf = l2cap_create_le_sig_pdu(BT_L2CAP_LE_CONN_REQ, ch->chan.ident, sizeof(*req)); req = net_buf_add(buf, sizeof(*req)); req->psm = sys_cpu_to_le16(ch->chan.psm); req->scid = sys_cpu_to_le16(ch->rx.cid); req->mtu = sys_cpu_to_le16(ch->rx.mtu); req->mps = sys_cpu_to_le16(ch->rx.mps); req->credits = sys_cpu_to_le16(ch->rx.init_credits); l2cap_chan_send_req(ch, buf, L2CAP_CONN_TIMEOUT); return 0; }
static int gatt_write_ccc(struct bt_conn *conn, uint16_t handle, uint16_t value, bt_att_func_t func, struct bt_gatt_subscribe_params *params) { struct net_buf *buf; struct bt_att_write_req *req; buf = bt_att_create_pdu(conn, BT_ATT_OP_WRITE_REQ, sizeof(*req) + sizeof(uint16_t)); if (!buf) { return -ENOMEM; } req = net_buf_add(buf, sizeof(*req)); req->handle = sys_cpu_to_le16(handle); net_buf_add_le16(buf, value); BT_DBG("handle 0x%04x value 0x%04x", handle, value); return gatt_send(conn, buf, func, params, NULL); }
static struct net_buf *h4_evt_recv(int *remaining) { struct bt_hci_evt_hdr hdr; struct net_buf *buf; /* We can ignore the return value since we pass len == min */ h4_read(h4_dev, (void *)&hdr, sizeof(hdr), sizeof(hdr)); *remaining = hdr.len; buf = bt_buf_get_evt(); if (buf) { memcpy(net_buf_add(buf, sizeof(hdr)), &hdr, sizeof(hdr)); } else { BT_ERR("No available event buffers!"); } BT_DBG("len %u", hdr.len); return buf; }
static struct net_buf *h4_acl_recv(int *remaining) { struct bt_hci_acl_hdr hdr; struct net_buf *buf; /* We can ignore the return value since we pass len == min */ h4_read(h4_dev, (void *)&hdr, sizeof(hdr), sizeof(hdr)); buf = bt_buf_get_acl(); if (buf) { memcpy(net_buf_add(buf, sizeof(hdr)), &hdr, sizeof(hdr)); } else { BT_ERR("No available ACL buffers!"); } *remaining = sys_le16_to_cpu(hdr.len); BT_DBG("len %u", *remaining); return buf; }
int bt_conn_le_conn_update(struct bt_conn *conn, const struct bt_le_conn_param *param) { struct hci_cp_le_conn_update *conn_update; struct net_buf *buf; buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_UPDATE, sizeof(*conn_update)); if (!buf) { return -ENOBUFS; } conn_update = net_buf_add(buf, sizeof(*conn_update)); memset(conn_update, 0, sizeof(*conn_update)); conn_update->handle = sys_cpu_to_le16(conn->handle); conn_update->conn_interval_min = sys_cpu_to_le16(param->interval_min); conn_update->conn_interval_max = sys_cpu_to_le16(param->interval_max); conn_update->conn_latency = sys_cpu_to_le16(param->latency); conn_update->supervision_timeout = sys_cpu_to_le16(param->timeout); return bt_hci_cmd_send(BT_HCI_OP_LE_CONN_UPDATE, buf); }