int bt_le_set_auto_conn(bt_addr_le_t *addr, const struct bt_le_conn_param *param) { struct bt_conn *conn; if (param && !bt_le_conn_params_valid(param->interval_min, param->interval_max, param->latency, param->timeout)) { return -EINVAL; } conn = bt_conn_lookup_addr_le(addr); if (!conn) { conn = bt_conn_add_le(addr); if (!conn) { return -ENOMEM; } } if (param) { bt_conn_set_param_le(conn, param); if (!atomic_test_and_set_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_ref(conn); } } else { if (atomic_test_and_clear_bit(conn->flags, BT_CONN_AUTO_CONNECT)) { bt_conn_unref(conn); if (conn->state == BT_CONN_CONNECT_SCAN) { bt_conn_set_state(conn, BT_CONN_DISCONNECTED); } } } if (conn->state == BT_CONN_DISCONNECTED && atomic_test_bit(bt_dev.flags, BT_DEV_READY)) { if (param) { bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN); } bt_le_scan_update(false); } bt_conn_unref(conn); return 0; }
void pthread_testcancel(void) { if (atomic_test_and_clear_bit(0, &pthread_self()->flags)) { pthread_exit(PTHREAD_CANCELED); } }
int bt_smp_auth_pairing_confirm(struct bt_conn *conn) { struct bt_smp *smp; struct nble_sm_pairing_response_req params; BT_DBG(""); smp = smp_chan_get(conn); if (!smp) { return -EINVAL; } if (!atomic_test_and_clear_bit(&smp->flags, SMP_FLAG_USER)) { return -EINVAL; } if (conn->role == BT_CONN_ROLE_MASTER) { /* TODO: handle */ } else { /* TODO: io caps, mitm */ params.conn = conn; params.conn_handle = conn->handle; nble_sm_pairing_response_req(¶ms); } return 0; }
int bt_conn_auth_pincode_entry(struct bt_conn *conn, const char *pin) { size_t len; if (!bt_auth) { return -EINVAL; } if (conn->type != BT_CONN_TYPE_BR) { return -EINVAL; } len = strlen(pin); if (len > 16) { return -EINVAL; } if (conn->required_sec_level == BT_SECURITY_HIGH && len < 16) { BT_WARN("PIN code for %s is not 16 bytes wide", bt_addr_str(&conn->br.dst)); return -EPERM; } /* Allow user send entered PIN to remote, then reset user state. */ if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) { return -EPERM; } if (len == 16) { atomic_set_bit(conn->flags, BT_CONN_BR_LEGACY_SECURE); } return pin_code_reply(conn, pin, len); }
int bt_conn_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) { if (!bt_auth) { return -EINVAL; } #if defined(CONFIG_BLUETOOTH_SMP) if (conn->type == BT_CONN_TYPE_LE) { bt_smp_auth_passkey_entry(conn, passkey); return 0; } #endif /* CONFIG_BLUETOOTH_SMP */ #if defined(CONFIG_BLUETOOTH_BREDR) if (conn->type == BT_CONN_TYPE_BR) { /* User entered passkey, reset user state. */ if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) { return -EPERM; } if (conn->br.pairing_method == PASSKEY_INPUT) { return ssp_passkey_reply(conn, passkey); } } #endif /* CONFIG_BLUETOOTH_BREDR */ return -EINVAL; }
int bt_le_scan_stop(void) { #if NOT_USED_FOR_NOW /* Return if active scanning is already disabled */ if (!atomic_test_and_clear_bit(bt_dev.flags, BT_DEV_EXPLICIT_SCAN)) { return -EALREADY; } #endif scan_dev_found_cb = NULL; #if NOT_USED_FOR_NOW return bt_le_scan_update(false); #else return bt_hci_stop_scanning(); #endif }
int bt_smp_auth_passkey_entry(struct bt_conn *conn, unsigned int passkey) { struct bt_smp *smp; BT_DBG(""); smp = smp_chan_get(conn); if (!smp) { return -EINVAL; } if (!atomic_test_and_clear_bit(&smp->flags, SMP_FLAG_USER)) { return -EINVAL; } if (!atomic_test_bit(&smp->flags, SMP_FLAG_SC)) { legacy_passkey_entry(smp, passkey); return 0; } return 0; }
int bt_conn_auth_passkey_confirm(struct bt_conn *conn) { if (!bt_auth) { return -EINVAL; }; #if defined(CONFIG_BLUETOOTH_SMP) if (conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_passkey_confirm(conn); } #endif /* CONFIG_BLUETOOTH_SMP */ #if defined(CONFIG_BLUETOOTH_BREDR) if (conn->type == BT_CONN_TYPE_BR) { /* Allow user confirm passkey value, then reset user state. */ if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) { return -EPERM; } return ssp_confirm_reply(conn); } #endif /* CONFIG_BLUETOOTH_BREDR */ return -EINVAL; }
int bt_conn_auth_cancel(struct bt_conn *conn) { if (!bt_auth) { return -EINVAL; } #if defined(CONFIG_BLUETOOTH_SMP) if (conn->type == BT_CONN_TYPE_LE) { return bt_smp_auth_cancel(conn); } #endif /* CONFIG_BLUETOOTH_SMP */ #if defined(CONFIG_BLUETOOTH_BREDR) if (conn->type == BT_CONN_TYPE_BR) { /* Allow user cancel authentication, then reset user state. */ if (!atomic_test_and_clear_bit(conn->flags, BT_CONN_USER)) { return -EPERM; } switch (conn->br.pairing_method) { case JUST_WORKS: case PASSKEY_CONFIRM: return ssp_confirm_neg_reply(conn); case PASSKEY_INPUT: return ssp_passkey_neg_reply(conn); case PASSKEY_DISPLAY: return bt_conn_disconnect(conn, BT_HCI_ERR_AUTHENTICATION_FAIL); case LEGACY: return pin_code_neg_reply(&conn->br.dst); default: break; } } #endif /* CONFIG_BLUETOOTH_BREDR */ return -EINVAL; }
void uart_console_isr(struct device *unused) { ARG_UNUSED(unused); while (uart_irq_update(uart_console_dev) && uart_irq_is_pending(uart_console_dev)) { static struct uart_console_input *cmd; uint8_t byte; int rx; if (!uart_irq_rx_ready(uart_console_dev)) { continue; } /* Character(s) have been received */ rx = read_uart(uart_console_dev, &byte, 1); if (rx < 0) { return; } if (uart_irq_input_hook(uart_console_dev, byte) != 0) { /* * The input hook indicates that no further processing * should be done by this handler. */ return; } if (!cmd) { cmd = nano_isr_fifo_get(avail_queue, TICKS_NONE); if (!cmd) return; } /* Handle ANSI escape mode */ if (atomic_test_bit(&esc_state, ESC_ANSI)) { handle_ansi(byte); continue; } /* Handle escape mode */ if (atomic_test_and_clear_bit(&esc_state, ESC_ESC)) { switch (byte) { case ANSI_ESC: atomic_set_bit(&esc_state, ESC_ANSI); atomic_set_bit(&esc_state, ESC_ANSI_FIRST); break; default: break; } continue; } /* Handle special control characters */ if (!isprint(byte)) { switch (byte) { case DEL: if (cur > 0) { del_char(&cmd->line[--cur], end); } break; case ESC: atomic_set_bit(&esc_state, ESC_ESC); break; case '\r': cmd->line[cur + end] = '\0'; uart_poll_out(uart_console_dev, '\r'); uart_poll_out(uart_console_dev, '\n'); cur = 0; end = 0; nano_isr_fifo_put(lines_queue, cmd); cmd = NULL; break; case '\t': if (completion_cb && !end) { cur += completion_cb(cmd->line, cur); } break; default: break; } continue; } /* Ignore characters if there's no more buffer space */ if (cur + end < sizeof(cmd->line) - 1) { insert_char(&cmd->line[cur++], byte, end); } } }
static void handle_ansi(uint8_t byte) { if (atomic_test_and_clear_bit(&esc_state, ESC_ANSI_FIRST)) { if (!isdigit(byte)) { ansi_val = 1; goto ansi_cmd; } atomic_set_bit(&esc_state, ESC_ANSI_VAL); ansi_val = byte - '0'; ansi_val_2 = 0; return; } if (atomic_test_bit(&esc_state, ESC_ANSI_VAL)) { if (isdigit(byte)) { if (atomic_test_bit(&esc_state, ESC_ANSI_VAL_2)) { ansi_val_2 *= 10; ansi_val_2 += byte - '0'; } else { ansi_val *= 10; ansi_val += byte - '0'; } return; } /* Multi value sequence, e.g. Esc[Line;ColumnH */ if (byte == ';' && !atomic_test_and_set_bit(&esc_state, ESC_ANSI_VAL_2)) { return; } atomic_clear_bit(&esc_state, ESC_ANSI_VAL); atomic_clear_bit(&esc_state, ESC_ANSI_VAL_2); } ansi_cmd: switch (byte) { case ANSI_BACKWARD: if (ansi_val > cur) { break; } end += ansi_val; cur -= ansi_val; cursor_backward(ansi_val); break; case ANSI_FORWARD: if (ansi_val > end) { break; } end -= ansi_val; cur += ansi_val; cursor_forward(ansi_val); break; default: break; } atomic_clear_bit(&esc_state, ESC_ANSI); }
void uart_console_isr(struct device *unused) { ARG_UNUSED(unused); while (uart_irq_update(uart_console_dev) && uart_irq_is_pending(uart_console_dev)) { static struct console_input *cmd; u8_t byte; int rx; if (!uart_irq_rx_ready(uart_console_dev)) { continue; } /* Character(s) have been received */ rx = read_uart(uart_console_dev, &byte, 1); if (rx < 0) { return; } #ifdef CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS if (debug_hook_in != NULL && debug_hook_in(byte) != 0) { /* * The input hook indicates that no further processing * should be done by this handler. */ return; } #endif if (!cmd) { cmd = k_fifo_get(avail_queue, K_NO_WAIT); if (!cmd) { return; } } #ifdef CONFIG_UART_CONSOLE_MCUMGR /* Divert this byte from normal console handling if it is part * of an mcumgr frame. */ if (handle_mcumgr(cmd, byte)) { continue; } #endif /* CONFIG_UART_CONSOLE_MCUMGR */ /* Handle ANSI escape mode */ if (atomic_test_bit(&esc_state, ESC_ANSI)) { handle_ansi(byte, cmd->line); continue; } /* Handle escape mode */ if (atomic_test_and_clear_bit(&esc_state, ESC_ESC)) { if (byte == ANSI_ESC) { atomic_set_bit(&esc_state, ESC_ANSI); atomic_set_bit(&esc_state, ESC_ANSI_FIRST); } continue; } /* Handle special control characters */ if (!isprint(byte)) { switch (byte) { case DEL: if (cur > 0) { del_char(&cmd->line[--cur], end); } break; case ESC: atomic_set_bit(&esc_state, ESC_ESC); break; case '\r': cmd->line[cur + end] = '\0'; uart_poll_out(uart_console_dev, '\r'); uart_poll_out(uart_console_dev, '\n'); cur = 0; end = 0; k_fifo_put(lines_queue, cmd); cmd = NULL; break; case '\t': if (completion_cb && !end) { cur += completion_cb(cmd->line, cur); } break; default: break; } continue; } /* Ignore characters if there's no more buffer space */ if (cur + end < sizeof(cmd->line) - 1) { insert_char(&cmd->line[cur++], byte, end); } } }
void atomic_test(void) { int i; atomic_t target, orig; atomic_val_t value; atomic_val_t oldvalue; target = 4; value = 5; oldvalue = 6; /* atomic_cas() */ zassert_true((atomic_cas(&target, oldvalue, value) == 0), "atomic_cas"); target = 6; zassert_true((atomic_cas(&target, oldvalue, value) == 1), "atomic_cas"); zassert_true((target == value), "atomic_cas"); /* atomic_add() */ target = 1; value = 2; zassert_true((atomic_add(&target, value) == 1), "atomic_add"); zassert_true((target == 3), "atomic_add"); /* atomic_sub() */ target = 10; value = 2; zassert_true((atomic_sub(&target, value) == 10), "atomic_sub"); zassert_true((target == 8), "atomic_sub"); /* atomic_inc() */ target = 5; zassert_true((atomic_inc(&target) == 5), "atomic_inc"); zassert_true((target == 6), "atomic_inc"); /* atomic_dec() */ target = 2; zassert_true((atomic_dec(&target) == 2), "atomic_dec"); zassert_true((target == 1), "atomic_dec"); /* atomic_get() */ target = 50; zassert_true((atomic_get(&target) == 50), "atomic_get"); /* atomic_set() */ target = 42; value = 77; zassert_true((atomic_set(&target, value) == 42), "atomic_set"); zassert_true((target == value), "atomic_set"); /* atomic_clear() */ target = 100; zassert_true((atomic_clear(&target) == 100), "atomic_clear"); zassert_true((target == 0), "atomic_clear"); /* atomic_or() */ target = 0xFF00; value = 0x0F0F; zassert_true((atomic_or(&target, value) == 0xFF00), "atomic_or"); zassert_true((target == 0xFF0F), "atomic_or"); /* atomic_xor() */ target = 0xFF00; value = 0x0F0F; zassert_true((atomic_xor(&target, value) == 0xFF00), "atomic_xor"); zassert_true((target == 0xF00F), "atomic_xor"); /* atomic_and() */ target = 0xFF00; value = 0x0F0F; zassert_true((atomic_and(&target, value) == 0xFF00), "atomic_and"); zassert_true((target == 0x0F00), "atomic_and"); /* atomic_nand() */ target = 0xFF00; value = 0x0F0F; zassert_true((atomic_nand(&target, value) == 0xFF00), "atomic_nand"); zassert_true((target == 0xFFFFF0FF), "atomic_nand"); /* atomic_test_bit() */ for (i = 0; i < 32; i++) { target = 0x0F0F0F0F; zassert_true(!!(atomic_test_bit(&target, i) == !!(target & (1 << i))), "atomic_test_bit"); } /* atomic_test_and_clear_bit() */ for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; zassert_true(!!(atomic_test_and_clear_bit(&target, i)) == !!(orig & (1 << i)), "atomic_test_and_clear_bit"); zassert_true(target == (orig & ~(1 << i)), "atomic_test_and_clear_bit"); } /* atomic_test_and_set_bit() */ for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; zassert_true(!!(atomic_test_and_set_bit(&target, i)) == !!(orig & (1 << i)), "atomic_test_and_set_bit"); zassert_true(target == (orig | (1 << i)), "atomic_test_and_set_bit"); } /* atomic_clear_bit() */ for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; atomic_clear_bit(&target, i); zassert_true(target == (orig & ~(1 << i)), "atomic_clear_bit"); } /* atomic_set_bit() */ for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; atomic_set_bit(&target, i); zassert_true(target == (orig | (1 << i)), "atomic_set_bit"); } }
static void handle_ansi(u8_t byte, char *line) { if (atomic_test_and_clear_bit(&esc_state, ESC_ANSI_FIRST)) { if (!isdigit(byte)) { ansi_val = 1U; goto ansi_cmd; } atomic_set_bit(&esc_state, ESC_ANSI_VAL); ansi_val = byte - '0'; ansi_val_2 = 0U; return; } if (atomic_test_bit(&esc_state, ESC_ANSI_VAL)) { if (isdigit(byte)) { if (atomic_test_bit(&esc_state, ESC_ANSI_VAL_2)) { ansi_val_2 *= 10; ansi_val_2 += byte - '0'; } else { ansi_val *= 10; ansi_val += byte - '0'; } return; } /* Multi value sequence, e.g. Esc[Line;ColumnH */ if (byte == ';' && !atomic_test_and_set_bit(&esc_state, ESC_ANSI_VAL_2)) { return; } atomic_clear_bit(&esc_state, ESC_ANSI_VAL); atomic_clear_bit(&esc_state, ESC_ANSI_VAL_2); } ansi_cmd: switch (byte) { case ANSI_BACKWARD: if (ansi_val > cur) { break; } end += ansi_val; cur -= ansi_val; cursor_backward(ansi_val); break; case ANSI_FORWARD: if (ansi_val > end) { break; } end -= ansi_val; cur += ansi_val; cursor_forward(ansi_val); break; case ANSI_HOME: if (!cur) { break; } cursor_backward(cur); end += cur; cur = 0U; break; case ANSI_END: if (!end) { break; } cursor_forward(end); cur += end; end = 0U; break; case ANSI_DEL: if (!end) { break; } cursor_forward(1); del_char(&line[cur], --end); break; default: break; } atomic_clear_bit(&esc_state, ESC_ANSI); }
void main(void) { int failed, rv, i; atomic_t target, orig; atomic_val_t value; atomic_val_t oldvalue; failed = 0; TC_START("Test atomic operation primitives"); TC_PRINT("Test atomic_cas()\n"); target = 4; value = 5; oldvalue = 6; CHECK_OUTPUT(atomic_cas(&target, oldvalue, value), 0); target = 6; CHECK_OUTPUT(atomic_cas(&target, oldvalue, value), 1); CHECK_OUTPUT(target, value); TC_PRINT("Test atomic_add()\n"); target = 1; value = 2; CHECK_OUTPUT(atomic_add(&target, value), 1); CHECK_OUTPUT(target, 3); TC_PRINT("Test atomic_sub()\n"); target = 10; value = 2; CHECK_OUTPUT(atomic_sub(&target, value), 10); CHECK_OUTPUT(target, 8); TC_PRINT("Test atomic_inc()\n"); target = 5; CHECK_OUTPUT(atomic_inc(&target), 5); CHECK_OUTPUT(target, 6); TC_PRINT("Test atomic_dec()\n"); target = 2; CHECK_OUTPUT(atomic_dec(&target), 2); CHECK_OUTPUT(target, 1); TC_PRINT("Test atomic_get()\n"); target = 50; CHECK_OUTPUT(atomic_get(&target), 50); TC_PRINT("Test atomic_set()\n"); target = 42; value = 77; CHECK_OUTPUT(atomic_set(&target, value), 42); CHECK_OUTPUT(target, value); TC_PRINT("Test atomic_clear()\n"); target = 100; CHECK_OUTPUT(atomic_clear(&target), 100); CHECK_OUTPUT(target, 0); TC_PRINT("Test atomic_or()\n"); target = 0xFF00; value = 0x0F0F; CHECK_OUTPUT(atomic_or(&target, value), 0xFF00); CHECK_OUTPUT(target, 0xFF0F); TC_PRINT("Test atomic_xor()\n"); target = 0xFF00; value = 0x0F0F; CHECK_OUTPUT(atomic_xor(&target, value), 0xFF00); CHECK_OUTPUT(target, 0xF00F); TC_PRINT("Test atomic_and()\n"); target = 0xFF00; value = 0x0F0F; CHECK_OUTPUT(atomic_and(&target, value), 0xFF00); CHECK_OUTPUT(target, 0x0F00); TC_PRINT("Test atomic_nand()\n"); target = 0xFF00; value = 0x0F0F; CHECK_OUTPUT(atomic_nand(&target, value), 0xFF00); CHECK_OUTPUT(target, 0xFFFFF0FF); TC_PRINT("Test atomic_test_bit()\n"); for (i = 0; i < 32; i++) { target = 0x0F0F0F0F; CHECK_TRUTH(atomic_test_bit(&target, i), (target & (1 << i))); } TC_PRINT("Test atomic_test_and_clear_bit()\n"); for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; CHECK_TRUTH(atomic_test_and_clear_bit(&target, i), (orig & (1 << i))); CHECK_OUTPUT(target, orig & ~(1 << i)); } TC_PRINT("Test atomic_test_and_set_bit()\n"); for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; CHECK_TRUTH(atomic_test_and_set_bit(&target, i), (orig & (1 << i))); CHECK_OUTPUT(target, orig | (1 << i)); } TC_PRINT("Test atomic_clear_bit()\n"); for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; atomic_clear_bit(&target, i); CHECK_OUTPUT(target, orig & ~(1 << i)); } TC_PRINT("Test atomic_set_bit()\n"); for (i = 0; i < 32; i++) { orig = 0x0F0F0F0F; target = orig; atomic_set_bit(&target, i); CHECK_OUTPUT(target, orig | (1 << i)); } if (failed) { TC_PRINT("%d tests failed\n", failed); rv = TC_FAIL; } else { rv = TC_PASS; } TC_END_RESULT(rv); TC_END_REPORT(rv); }