50 #include "../../../dev/ble-hal.h" 53 #define LOG_MODULE "L2CAP" 54 #define LOG_LEVEL LOG_LEVEL_MAC 56 #define MS_TO_CLOCK_SECONDS(X) ((int)(((double)((X)*CLOCK_SECOND)) / 1000.0)) 60 static uint8_t ble_addr[BLE_ADDR_SIZE];
65 uint8_t sdu[BLE_L2CAP_NODE_MTU];
69 uint16_t current_index;
77 } ble_mac_l2cap_channel_t;
80 ble_mac_l2cap_channel_t channel_own;
81 ble_mac_l2cap_channel_t channel_peer;
82 l2cap_buffer_t tx_buffer;
83 l2cap_buffer_t rx_buffer;
87 static uint8_t l2cap_channel_count;
88 static l2cap_channel_t l2cap_channels[L2CAP_CHANNELS];
89 static process_event_t l2cap_tx_event;
91 static l2cap_channel_t *
92 get_channel_for_addr(
const linkaddr_t *peer_addr)
95 l2cap_channel_t *channel;
96 for(i = 0; i < l2cap_channel_count; i++) {
97 channel = &l2cap_channels[i];
105 static l2cap_channel_t *
106 get_channel_for_cid(uint16_t own_cid)
108 uint8_t i = own_cid - L2CAP_FLOW_CHANNEL;
109 if(i >= 0 && i < l2cap_channel_count) {
110 return &l2cap_channels[own_cid - L2CAP_FLOW_CHANNEL];
116 PROCESS(ble_l2cap_tx_process,
"BLE L2CAP TX process");
119 init_adv_data(
char *adv_data)
121 uint8_t adv_data_len = 0;
122 memset(adv_data, 0x00, BLE_ADV_DATA_LEN);
124 adv_data[adv_data_len++] = 2;
125 adv_data[adv_data_len++] = 0x01;
126 adv_data[adv_data_len++] = 0x05;
128 adv_data[adv_data_len++] = 2;
129 adv_data[adv_data_len++] = 0x0A;
130 adv_data[adv_data_len++] = 0;
132 adv_data[adv_data_len++] = 3;
133 adv_data[adv_data_len++] = 0x03;
134 adv_data[adv_data_len++] = 0x20;
135 adv_data[adv_data_len++] = 0x18;
137 adv_data[adv_data_len++] = 1;
138 adv_data[adv_data_len++] = 0x05;
140 adv_data[adv_data_len++] = 1;
141 adv_data[adv_data_len++] = 0x07;
146 init_scan_resp_data(
char *scan_resp_data)
148 uint8_t scan_resp_data_len = 0;
149 memset(scan_resp_data, 0x00, BLE_SCAN_RESP_DATA_LEN);
151 scan_resp_data[scan_resp_data_len++] = 1 + strlen(BLE_DEVICE_NAME);
152 scan_resp_data[scan_resp_data_len++] = 0x09;
153 memcpy(&scan_resp_data[scan_resp_data_len],
154 BLE_DEVICE_NAME, strlen(BLE_DEVICE_NAME));
155 scan_resp_data_len += strlen(BLE_DEVICE_NAME);
157 scan_resp_data[scan_resp_data_len++] = 5;
158 scan_resp_data[scan_resp_data_len++] = 0x12;
159 scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MIN & 0xFF);
160 scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MIN >> 8) & 0xFF);
161 scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MAX & 0xFF);
162 scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MAX >> 8) & 0xFF);
164 return scan_resp_data_len;
168 input_l2cap_conn_req(uint8_t *data)
170 uint8_t identifier = data[0];
173 uint8_t resp_data[18];
174 l2cap_channel_t *channel;
176 memcpy(&len, &data[1], 2);
179 LOG_WARN(
"l2cap_conn_req: invalid len: %d\n", len);
184 if(l2cap_channel_count >= L2CAP_CHANNELS) {
185 LOG_WARN(
"l2cap_conn_req: maximum supported L2CAP channels reached\n");
189 channel = &l2cap_channels[l2cap_channel_count];
191 memcpy(&le_psm, &data[3], 2);
192 memset(&channel->channel_peer, 0x00,
sizeof(ble_mac_l2cap_channel_t));
193 memcpy(&channel->channel_peer.cid, &data[5], 2);
194 memcpy(&channel->channel_peer.mtu, &data[7], 2);
195 memcpy(&channel->channel_peer.mps, &data[9], 2);
196 memcpy(&channel->channel_peer.credits, &data[11], 2);
197 linkaddr_copy(&channel->peer_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER));
199 LOG_INFO(
"recv CONN_REQ (MTU: %4d, MPS: %4d, credits: %4d)\n",
200 channel->channel_peer.mtu, channel->channel_peer.mps, channel->channel_peer.credits);
202 l2cap_channel_count++;
212 resp_data[4] = L2CAP_CODE_CONN_RSP;
214 resp_data[5] = identifier;
219 memcpy(&resp_data[8], &channel->channel_own.cid, 2);
220 memcpy(&resp_data[10], &channel->channel_own.mtu, 2);
221 memcpy(&resp_data[12], &channel->channel_own.mps, 2);
222 memcpy(&resp_data[14], &channel->channel_own.credits, 2);
224 memset(&resp_data[16], 0x00, 2);
228 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
239 for(i = 0; i < L2CAP_CHANNELS; i++) {
240 l2cap_channels[i].channel_own.cid = L2CAP_FLOW_CHANNEL + i;
241 l2cap_channels[i].channel_own.credits = L2CAP_CREDIT_NEW;
242 l2cap_channels[i].channel_own.mps = (BLE_L2CAP_NODE_FRAG_LEN - L2CAP_SUBSEQ_HEADER_SIZE);
243 l2cap_channels[i].channel_own.mtu = BLE_L2CAP_NODE_MTU;
247 NETSTACK_RADIO.init();
248 NETSTACK_RADIO.get_object(RADIO_CONST_BLE_BD_ADDR, &ble_addr, BLE_ADDR_SIZE);
250 uint8_t adv_data_len, scan_resp_data_len;
251 char adv_data[BLE_ADV_DATA_LEN];
252 char scan_resp_data[BLE_SCAN_RESP_DATA_LEN];
254 NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_INTERVAL, BLE_ADV_INTERVAL);
255 NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_TYPE, BLE_ADV_DIR_IND_LDC);
256 NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE, BLE_ADDR_TYPE_PUBLIC);
257 NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_CHANNEL_MAP, 0x01);
259 adv_data_len = init_adv_data(adv_data);
260 scan_resp_data_len = init_scan_resp_data(scan_resp_data);
263 NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_PAYLOAD, adv_data, adv_data_len);
264 NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_SCAN_RESPONSE, scan_resp_data, scan_resp_data_len);
267 NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_ENABLE, 1);
273 check_own_l2cap_credits(l2cap_channel_t *channel)
275 uint16_t credits_new = 0;
276 uint16_t credits_current;
278 credits_current = channel->channel_own.credits;
279 if(credits_current < L2CAP_CREDIT_THRESHOLD) {
280 credits_new = L2CAP_CREDIT_NEW;
282 LOG_DBG(
"check for new credits: current credits: %2d, new credits: %2d\n", credits_current, credits_new);
287 send_l2cap_credit(l2cap_channel_t *channel, uint16_t credits)
299 data[4] = L2CAP_CODE_CREDIT;
306 memcpy(&data[8], &channel->channel_own.cid, 2);
307 data[10] = credits & 0xFF;
308 data[11] = credits >> 8;
310 channel->channel_own.credits += credits;
314 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
319 send(mac_callback_t sent_callback,
void *ptr)
322 l2cap_channel_t *channel;
324 LOG_DBG(
"send %d\n", data_len);
327 if(data_len > BLE_L2CAP_NODE_MTU) {
328 LOG_WARN(
"send message is too long\n");
329 mac_call_sent_callback(sent_callback, ptr,
MAC_TX_ERR, 0);
333 for(i = 0; i < l2cap_channel_count; i++) {
334 channel = &l2cap_channels[i];
336 || (
linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &channel->peer_addr) != 0)) {
337 if(channel->tx_buffer.sdu_length > 0) {
338 LOG_WARN(
"send() another L2CAP message active (trying to send %4d bytes)\n", data_len);
342 LOG_DBG(
"send() adding to L2CAP CID: %2d\n", channel->channel_own.cid);
343 channel->tx_buffer.sdu_length = data_len;
344 if(channel->tx_buffer.sdu_length > 0) {
347 process_post(&ble_l2cap_tx_process, l2cap_tx_event, (
void *)channel);
354 input_l2cap_connection_udate_resp(uint8_t *data)
359 memcpy(&len, &data[1], 2);
362 LOG_WARN(
"input_l2cap_connection_update_resp: invalid len: %d\n", len);
366 memcpy(&result, &data[3], 2);
367 if(result != 0x0000) {
368 LOG_WARN(
"input_l2cap_connection_update_resp: result: 0x%04X\n", result);
374 input_l2cap_credit(uint8_t *data)
379 l2cap_channel_t *channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_SENDER));
382 memcpy(&len, &data[1], 2);
385 LOG_WARN(
"process_l2cap_credit: invalid len: %d\n", len);
390 memcpy(&cid, &data[3], 2);
391 memcpy(&credits, &data[5], 2);
393 channel->channel_peer.credits += credits;
397 input_l2cap_frame_signal_channel(uint8_t *data, uint8_t data_len)
399 if(data[4] == L2CAP_CODE_CREDIT) {
400 input_l2cap_credit(&data[5]);
401 }
else if(data[4] == L2CAP_CODE_CONN_REQ) {
402 input_l2cap_conn_req(&data[5]);
403 }
else if(data[4] == L2CAP_CODE_CONN_UPDATE_RSP) {
404 input_l2cap_connection_udate_resp(&data[5]);
406 LOG_WARN(
"l2cap_frame_signal_channel: unknown signal channel code: %d\n", data[4]);
411 input_l2cap_frame_flow_channel(l2cap_channel_t *channel, uint8_t *data, uint16_t data_len)
414 uint16_t payload_len;
417 LOG_WARN(
"l2cap_frame: illegal L2CAP frame data_len: %d\n", data_len);
422 if(channel->rx_buffer.sdu_length == 0) {
424 memcpy(&frame_len, &data[0], 2);
425 payload_len = frame_len - 2;
427 if(payload_len > BLE_L2CAP_NODE_MTU) {
428 LOG_WARN(
"l2cap_frame: illegal L2CAP frame payload_len: %d\n", payload_len);
433 memcpy(&channel->rx_buffer.sdu_length, &data[4], 2);
435 memcpy(channel->rx_buffer.sdu, &data[6], payload_len);
436 channel->rx_buffer.current_index = payload_len;
439 memcpy(&frame_len, &data[0], 2);
440 payload_len = frame_len;
442 if(payload_len > BLE_L2CAP_NODE_MTU - channel->rx_buffer.current_index) {
443 LOG_WARN(
"l2cap_frame: illegal L2CAP frame payload_len: %d\n", payload_len);
449 memcpy(&channel->rx_buffer.sdu[channel->rx_buffer.current_index], &data[4], payload_len);
450 channel->rx_buffer.current_index += payload_len;
453 if((channel->rx_buffer.sdu_length > 0) &&
454 (channel->rx_buffer.sdu_length == channel->rx_buffer.current_index)) {
457 memcpy(
packetbuf_dataptr(), channel->rx_buffer.sdu, channel->rx_buffer.sdu_length);
459 NETSTACK_NETWORK.input();
462 channel->rx_buffer.sdu_length = 0;
463 channel->rx_buffer.current_index = 0;
472 uint8_t frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE);
474 l2cap_channel_t *channel;
477 if(frame_type == FRAME_BLE_RX_EVENT) {
478 memcpy(&channel_id, &data[2], 2);
479 channel = get_channel_for_cid(channel_id);
480 LOG_DBG(
"input %d bytes\n", len);
481 if(channel_id == L2CAP_SIGNAL_CHANNEL) {
482 input_l2cap_frame_signal_channel(data, len);
483 }
else if(channel == NULL) {
484 LOG_WARN(
"input (RX_EVENT): no channel found for CID: %d\n", channel_id);
487 input_l2cap_frame_flow_channel(channel, data, len);
488 channel->channel_own.credits--;
489 credits = check_own_l2cap_credits(channel);
491 send_l2cap_credit(channel, credits);
496 if(frame_type == FRAME_BLE_TX_EVENT) {
497 channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
498 if(channel == NULL) {
499 LOG_WARN(
"input (TX_EVENT): no channel found for CID: %d\n", channel_id);
500 }
else if(channel->tx_buffer.sdu_length > 0) {
501 process_post(&ble_l2cap_tx_process, l2cap_tx_event, (
void *)channel);
525 return BLE_L2CAP_NODE_MTU;
543 l2cap_channel_t *channel = (l2cap_channel_t *)data;
544 uint8_t first_fragment;
549 LOG_DBG(
"starting ble_mac_tx_process\n");
553 if(channel != NULL) {
554 NETSTACK_RADIO.get_value(RADIO_CONST_BLE_BUFFER_AMOUNT, (
radio_value_t *)&num_buffer);
555 first_fragment = (channel->tx_buffer.current_index == 0);
556 used_mps = MIN(channel->channel_own.mps, channel->channel_peer.mps);
557 credits = channel->channel_peer.credits;
559 LOG_DBG(
"process: sending - first: %d, used_mps: %3d, num_buffers: %2d, credits: %2d\n",
560 first_fragment, used_mps, num_buffer, credits);
561 if((channel->tx_buffer.sdu_length > 0) && (num_buffer > 0) && (credits > 0)) {
565 used_mps -= L2CAP_FIRST_HEADER_SIZE;
566 data_len = MIN(channel->tx_buffer.sdu_length, used_mps);
567 frame_len = data_len + 2;
575 used_mps -= L2CAP_SUBSEQ_HEADER_SIZE;
576 data_len = MIN((channel->tx_buffer.sdu_length - channel->tx_buffer.current_index), used_mps);
577 frame_len = data_len;
586 &channel->tx_buffer.sdu[channel->tx_buffer.current_index],
589 channel->tx_buffer.current_index += data_len;
592 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
595 channel->channel_peer.credits--;
598 if(channel->tx_buffer.current_index == channel->tx_buffer.sdu_length) {
599 channel->tx_buffer.current_index = 0;
600 channel->tx_buffer.sdu_length = 0;
604 LOG_WARN(
"process. channel is NULL\n");
609 LOG_DBG(
"stopped ble_mac_tx_process\n");
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define PROCESS(name, strname)
Declare a process.
int(* on)(void)
Turn the MAC layer on.
void packetbuf_clear(void)
Clear and reset the packetbuf.
int packetbuf_hdralloc(int size)
Extend the header of the packetbuf, for outbound packets.
The structure of a MAC protocol driver in Contiki.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
The MAC layer transmission could not be performed because of a fatal error.
The MAC layer transmission could not be performed because of an error.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
const linkaddr_t linkaddr_null
The null link-layer address.
int(* off)(void)
Turn the MAC layer off.
void process_exit(struct process *p)
Cause a process to exit.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Linked list manipulation routines.
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
int packetbuf_copyfrom(const void *from, uint16_t len)
Copy from external data into the packetbuf.
MAC layer that implements BLE L2CAP credit-based flow control channels to support IPv6 over BLE (RFC ...
Memory block allocation routines.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
process_event_t process_alloc_event(void)
Allocate a global event number.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
void(* send)(mac_callback_t sent_callback, void *ptr)
Send a packet from the packetbuf.
void(* init)(void)
Initialize the MAC driver.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
The MAC layer did not get an acknowledgement for the packet.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
int(* max_payload)(void)
Read out estimated max payload size based on payload in packetbuf.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void process_start(struct process *p, process_data_t data)
Start a process.