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 memcpy(&channel->rx_buffer.sdu_length, &data[4], 2);
426 payload_len = frame_len - 2;
428 memcpy(channel->rx_buffer.sdu, &data[6], payload_len);
429 channel->rx_buffer.current_index = payload_len;
432 memcpy(&frame_len, &data[0], 2);
433 payload_len = frame_len;
435 memcpy(&channel->rx_buffer.sdu[channel->rx_buffer.current_index], &data[4], payload_len);
436 channel->rx_buffer.current_index += payload_len;
439 if((channel->rx_buffer.sdu_length > 0) &&
440 (channel->rx_buffer.sdu_length == channel->rx_buffer.current_index)) {
443 memcpy(
packetbuf_dataptr(), channel->rx_buffer.sdu, channel->rx_buffer.sdu_length);
445 NETSTACK_NETWORK.input();
448 channel->rx_buffer.sdu_length = 0;
449 channel->rx_buffer.current_index = 0;
458 uint8_t frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE);
460 l2cap_channel_t *channel;
463 if(frame_type == FRAME_BLE_RX_EVENT) {
464 memcpy(&channel_id, &data[2], 2);
465 channel = get_channel_for_cid(channel_id);
466 LOG_DBG(
"input %d bytes\n", len);
467 if(channel_id == L2CAP_SIGNAL_CHANNEL) {
468 input_l2cap_frame_signal_channel(data, len);
469 }
else if(channel == NULL) {
470 LOG_WARN(
"input (RX_EVENT): no channel found for CID: %d\n", channel_id);
473 input_l2cap_frame_flow_channel(channel, data, len);
474 channel->channel_own.credits--;
475 credits = check_own_l2cap_credits(channel);
477 send_l2cap_credit(channel, credits);
482 if(frame_type == FRAME_BLE_TX_EVENT) {
483 channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
484 if(channel == NULL) {
485 LOG_WARN(
"input (TX_EVENT): no channel found for CID: %d\n", channel_id);
486 }
else if(channel->tx_buffer.sdu_length > 0) {
487 process_post(&ble_l2cap_tx_process, l2cap_tx_event, (
void *)channel);
511 return BLE_L2CAP_NODE_MTU;
529 l2cap_channel_t *channel = (l2cap_channel_t *)data;
530 uint8_t first_fragment;
535 LOG_DBG(
"starting ble_mac_tx_process\n");
539 if(channel != NULL) {
540 NETSTACK_RADIO.get_value(RADIO_CONST_BLE_BUFFER_AMOUNT, (
radio_value_t *)&num_buffer);
541 first_fragment = (channel->tx_buffer.current_index == 0);
542 used_mps = MIN(channel->channel_own.mps, channel->channel_peer.mps);
543 credits = channel->channel_peer.credits;
545 LOG_DBG(
"process: sending - first: %d, used_mps: %3d, num_buffers: %2d, credits: %2d\n",
546 first_fragment, used_mps, num_buffer, credits);
547 if((channel->tx_buffer.sdu_length > 0) && (num_buffer > 0) && (credits > 0)) {
551 used_mps -= L2CAP_FIRST_HEADER_SIZE;
552 data_len = MIN(channel->tx_buffer.sdu_length, used_mps);
553 frame_len = data_len + 2;
561 used_mps -= L2CAP_SUBSEQ_HEADER_SIZE;
562 data_len = MIN((channel->tx_buffer.sdu_length - channel->tx_buffer.current_index), used_mps);
563 frame_len = data_len;
572 &channel->tx_buffer.sdu[channel->tx_buffer.current_index],
575 channel->tx_buffer.current_index += data_len;
578 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
581 channel->channel_peer.credits--;
584 if(channel->tx_buffer.current_index == channel->tx_buffer.sdu_length) {
585 channel->tx_buffer.current_index = 0;
586 channel->tx_buffer.sdu_length = 0;
590 LOG_WARN(
"process. channel is NULL\n");
595 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.
The MAC layer did not get an acknowledgement for the packet.
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.
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.
The MAC layer transmission could not be performed because of an error.
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 ...
The MAC layer transmission could not be performed because of a fatal error.
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.
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.