16size_t att_read_req(uint16_t handle, uint8_t *out,
size_t cap)
22 out[0] = AttOp::ATT_OP_READ_REQ;
23 out[1] = (uint8_t)handle;
24 out[2] = (uint8_t)(handle >> 8);
28size_t att_read_rsp(
const uint8_t *val,
size_t vlen, uint8_t *out,
size_t cap)
30 if (!out || (vlen && !val) || cap < 1 + vlen)
34 out[0] = AttOp::ATT_OP_READ_RSP;
37 memcpy(out + 1, val, vlen);
42static size_t att_handle_value(uint8_t op, uint16_t handle,
const uint8_t *val,
size_t vlen, uint8_t *out,
size_t cap)
44 if (!out || (vlen && !val) || cap < 3 + vlen)
49 out[1] = (uint8_t)handle;
50 out[2] = (uint8_t)(handle >> 8);
53 memcpy(out + 3, val, vlen);
58size_t att_write_req(uint16_t handle,
const uint8_t *val,
size_t vlen, uint8_t *out,
size_t cap)
60 return att_handle_value(AttOp::ATT_OP_WRITE_REQ, handle, val, vlen, out, cap);
63size_t att_notify(uint16_t handle,
const uint8_t *val,
size_t vlen, uint8_t *out,
size_t cap)
65 return att_handle_value(AttOp::ATT_OP_HANDLE_VALUE_NTF, handle, val, vlen, out, cap);
68size_t att_error_rsp(uint8_t req_op, uint16_t handle, uint8_t error, uint8_t *out,
size_t cap)
74 out[0] = AttOp::ATT_OP_ERROR_RSP;
76 out[2] = (uint8_t)handle;
77 out[3] = (uint8_t)(handle >> 8);
82bool att_parse(
const uint8_t *pdu,
size_t len, AttPdu *out)
84 if (!pdu || !out || len < 1)
97 case AttOp::ATT_OP_ERROR_RSP:
102 out->req_op = pdu[1];
103 out->handle = (uint16_t)(pdu[2] | (pdu[3] << 8));
106 case AttOp::ATT_OP_READ_REQ:
111 out->handle = (uint16_t)(pdu[1] | (pdu[2] << 8));
113 case AttOp::ATT_OP_READ_RSP:
116 out->value = pdu + 1;
117 out->value_len = len - 1;
120 case AttOp::ATT_OP_WRITE_REQ:
121 case AttOp::ATT_OP_HANDLE_VALUE_NTF:
126 out->handle = (uint16_t)(pdu[1] | (pdu[2] << 8));
129 out->value = pdu + 3;
130 out->value_len = len - 3;
133 case AttOp::ATT_OP_WRITE_RSP:
142void put_hex16(
pc_sb *b, uint16_t v)
144 char t[7] =
"0x0000";
145 static const char *H =
"0123456789abcdef";
146 for (
int i = 0; i < 4; i++)
148 t[2 + i] = H[(v >> ((3 - i) * 4)) & 0xF];
154size_t pc_gatt_char_json(
const GattChar *chars,
size_t n,
char *out,
size_t cap)
156 if (!out || cap == 0 || (n && !chars))
160 pc_sb b = {out, cap, 0,
true};
162 for (
size_t i = 0; i < n; i++)
171 put_hex16(&b, chars[i].uuid);
Bluetooth ATT protocol codec + GATT characteristic bridge (PC_ENABLE_BLE_GATT).
Bounded no-heap string builder that fails closed on overflow (one shared copy).
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
void pc_sb_u32(pc_sb *b, uint32_t v)
Append v as decimal (no leading zeros; "0" for zero).
Bump-append target; ok latches false once an append would overflow cap.