hci.c (e90f848d38bf2709345848319b77042d6031fad6) hci.c (30199e24c811081e34846cfb3b6c82e682b38b47)
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 97 unchanged lines hidden (view full) ---

106// Names are arbitrarily shortened to 32 bytes if not requested otherwise
107#ifndef GAP_INQUIRY_MAX_NAME_LEN
108#define GAP_INQUIRY_MAX_NAME_LEN 32
109#endif
110
111// GAP inquiry state: 0 = off, 0x01 - 0x30 = requested duration, 0xfe = active, 0xff = stop requested
112#define GAP_INQUIRY_DURATION_MIN 0x01
113#define GAP_INQUIRY_DURATION_MAX 0x30
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 97 unchanged lines hidden (view full) ---

106// Names are arbitrarily shortened to 32 bytes if not requested otherwise
107#ifndef GAP_INQUIRY_MAX_NAME_LEN
108#define GAP_INQUIRY_MAX_NAME_LEN 32
109#endif
110
111// GAP inquiry state: 0 = off, 0x01 - 0x30 = requested duration, 0xfe = active, 0xff = stop requested
112#define GAP_INQUIRY_DURATION_MIN 0x01
113#define GAP_INQUIRY_DURATION_MAX 0x30
114#define GAP_INQUIRY_MIN_PERIODIC_LEN_MIN 0x02
115#define GAP_INQUIRY_MAX_PERIODIC_LEN_MIN 0x03
114#define GAP_INQUIRY_STATE_IDLE 0x00
115#define GAP_INQUIRY_STATE_W4_ACTIVE 0x80
116#define GAP_INQUIRY_STATE_ACTIVE 0x81
117#define GAP_INQUIRY_STATE_W2_CANCEL 0x82
118#define GAP_INQUIRY_STATE_W4_CANCELLED 0x83
116#define GAP_INQUIRY_STATE_IDLE 0x00
117#define GAP_INQUIRY_STATE_W4_ACTIVE 0x80
118#define GAP_INQUIRY_STATE_ACTIVE 0x81
119#define GAP_INQUIRY_STATE_W2_CANCEL 0x82
120#define GAP_INQUIRY_STATE_W4_CANCELLED 0x83
121#define GAP_INQUIRY_STATE_PERIODIC 0x84
122#define GAP_INQUIRY_STATE_W2_EXIT_PERIODIC 0x85
123#define GAP_INQUIRY_STATE_W4_EXIT_PERIODIC_COMPLETE 0x86
119
120// GAP Remote Name Request
121#define GAP_REMOTE_NAME_STATE_IDLE 0
122#define GAP_REMOTE_NAME_STATE_W2_SEND 1
123#define GAP_REMOTE_NAME_STATE_W4_COMPLETE 2
124
125// GAP Pairing
126#define GAP_PAIRING_STATE_IDLE 0

--- 2401 unchanged lines hidden (view full) ---

2528 }
2529#endif
2530 break;
2531#ifdef ENABLE_CLASSIC
2532 case HCI_OPCODE_HCI_WRITE_SCAN_ENABLE:
2533 hci_emit_discoverable_enabled(hci_stack->discoverable);
2534 break;
2535 case HCI_OPCODE_HCI_INQUIRY_CANCEL:
124
125// GAP Remote Name Request
126#define GAP_REMOTE_NAME_STATE_IDLE 0
127#define GAP_REMOTE_NAME_STATE_W2_SEND 1
128#define GAP_REMOTE_NAME_STATE_W4_COMPLETE 2
129
130// GAP Pairing
131#define GAP_PAIRING_STATE_IDLE 0

--- 2401 unchanged lines hidden (view full) ---

2533 }
2534#endif
2535 break;
2536#ifdef ENABLE_CLASSIC
2537 case HCI_OPCODE_HCI_WRITE_SCAN_ENABLE:
2538 hci_emit_discoverable_enabled(hci_stack->discoverable);
2539 break;
2540 case HCI_OPCODE_HCI_INQUIRY_CANCEL:
2541 case HCI_OPCODE_HCI_EXIT_PERIODIC_INQUIRY_MODE:
2536 if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W4_CANCELLED){
2537 hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
2538 uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
2539 hci_emit_event(event, sizeof(event), 1);
2540 }
2541 break;
2542#endif
2543 case HCI_OPCODE_HCI_READ_LOCAL_SUPPORTED_FEATURES:

--- 359 unchanged lines hidden (view full) ---

2903 // error => outgoing connection failed
2904 if (conn != NULL){
2905 hci_handle_connection_failed(conn, status);
2906 }
2907 }
2908 }
2909
2910#ifdef ENABLE_CLASSIC
2542 if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W4_CANCELLED){
2543 hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
2544 uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
2545 hci_emit_event(event, sizeof(event), 1);
2546 }
2547 break;
2548#endif
2549 case HCI_OPCODE_HCI_READ_LOCAL_SUPPORTED_FEATURES:

--- 359 unchanged lines hidden (view full) ---

2909 // error => outgoing connection failed
2910 if (conn != NULL){
2911 hci_handle_connection_failed(conn, status);
2912 }
2913 }
2914 }
2915
2916#ifdef ENABLE_CLASSIC
2911 if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_inquiry)) {
2917 if (HCI_EVENT_IS_COMMAND_STATUS(packet, hci_inquiry)){
2912 uint8_t status = hci_event_command_status_get_status(packet);
2913 log_info("command status (inquiry), status %x", status);
2914 if (status == ERROR_CODE_SUCCESS) {
2915 hci_stack->inquiry_state = GAP_INQUIRY_STATE_ACTIVE;
2916 } else {
2917 hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
2918 }
2919 }
2918 uint8_t status = hci_event_command_status_get_status(packet);
2919 log_info("command status (inquiry), status %x", status);
2920 if (status == ERROR_CODE_SUCCESS) {
2921 hci_stack->inquiry_state = GAP_INQUIRY_STATE_ACTIVE;
2922 } else {
2923 hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
2924 }
2925 }
2926 if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_periodic_inquiry_mode)) {
2927 uint8_t status = hci_event_command_status_get_status(packet);
2928 log_info("command status (inquiry), status %x", status);
2929 if (status == ERROR_CODE_SUCCESS) {
2930 hci_stack->inquiry_state = GAP_INQUIRY_STATE_PERIODIC;
2931 } else {
2932 hci_stack->inquiry_state = GAP_INQUIRY_STATE_IDLE;
2933 }
2934 }
2920#endif
2921 break;
2922
2923 case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:{
2924 if (size < 3) return;
2925 uint16_t num_handles = packet[2];
2926 if (size != (3u + num_handles * 4u)) return;
2927 uint16_t offset = 3;

--- 1824 unchanged lines hidden (view full) ---

4752 // start/stop inquiry
4753 if ((hci_stack->inquiry_state >= GAP_INQUIRY_DURATION_MIN) && (hci_stack->inquiry_state <= GAP_INQUIRY_DURATION_MAX)){
4754#ifdef ENABLE_HCI_SERIALIZED_CONTROLLER_OPERATIONS
4755 if (hci_classic_operation_active() == false)
4756#endif
4757 {
4758 uint8_t duration = hci_stack->inquiry_state;
4759 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W4_ACTIVE;
2935#endif
2936 break;
2937
2938 case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:{
2939 if (size < 3) return;
2940 uint16_t num_handles = packet[2];
2941 if (size != (3u + num_handles * 4u)) return;
2942 uint16_t offset = 3;

--- 1824 unchanged lines hidden (view full) ---

4767 // start/stop inquiry
4768 if ((hci_stack->inquiry_state >= GAP_INQUIRY_DURATION_MIN) && (hci_stack->inquiry_state <= GAP_INQUIRY_DURATION_MAX)){
4769#ifdef ENABLE_HCI_SERIALIZED_CONTROLLER_OPERATIONS
4770 if (hci_classic_operation_active() == false)
4771#endif
4772 {
4773 uint8_t duration = hci_stack->inquiry_state;
4774 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W4_ACTIVE;
4760 hci_send_cmd(&hci_inquiry, hci_stack->inquiry_lap, duration, 0);
4775 if (hci_stack->inquiry_max_period_length != 0){
4776 hci_send_cmd(&hci_periodic_inquiry_mode, hci_stack->inquiry_max_period_length, hci_stack->inquiry_min_period_length, hci_stack->inquiry_lap, duration, 0);
4777 } else {
4778 hci_send_cmd(&hci_inquiry, hci_stack->inquiry_lap, duration, 0);
4779 }
4761 return true;
4762 }
4763 }
4764 if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W2_CANCEL){
4765 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W4_CANCELLED;
4766 hci_send_cmd(&hci_inquiry_cancel);
4767 return true;
4768 }
4780 return true;
4781 }
4782 }
4783 if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W2_CANCEL){
4784 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W4_CANCELLED;
4785 hci_send_cmd(&hci_inquiry_cancel);
4786 return true;
4787 }
4788
4789 if (hci_stack->inquiry_state == GAP_INQUIRY_STATE_W2_EXIT_PERIODIC){
4790 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W4_EXIT_PERIODIC_COMPLETE;
4791 hci_send_cmd(&hci_exit_periodic_inquiry_mode);
4792 return true;
4793 }
4794
4769 // remote name request
4770 if (hci_stack->remote_name_state == GAP_REMOTE_NAME_STATE_W2_SEND){
4771#ifdef ENABLE_HCI_SERIALIZED_CONTROLLER_OPERATIONS
4772 if (hci_classic_operation_active() == false)
4773#endif
4774 {
4775 hci_stack->remote_name_state = GAP_REMOTE_NAME_STATE_W4_COMPLETE;
4776 hci_send_cmd(&hci_remote_name_request, hci_stack->remote_name_addr,

--- 2745 unchanged lines hidden (view full) ---

7522 */
7523int gap_inquiry_start(uint8_t duration_in_1280ms_units){
7524 if (hci_stack->state != HCI_STATE_WORKING) return ERROR_CODE_COMMAND_DISALLOWED;
7525 if (hci_stack->inquiry_state != GAP_INQUIRY_STATE_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
7526 if ((duration_in_1280ms_units < GAP_INQUIRY_DURATION_MIN) || (duration_in_1280ms_units > GAP_INQUIRY_DURATION_MAX)){
7527 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
7528 }
7529 hci_stack->inquiry_state = duration_in_1280ms_units;
4795 // remote name request
4796 if (hci_stack->remote_name_state == GAP_REMOTE_NAME_STATE_W2_SEND){
4797#ifdef ENABLE_HCI_SERIALIZED_CONTROLLER_OPERATIONS
4798 if (hci_classic_operation_active() == false)
4799#endif
4800 {
4801 hci_stack->remote_name_state = GAP_REMOTE_NAME_STATE_W4_COMPLETE;
4802 hci_send_cmd(&hci_remote_name_request, hci_stack->remote_name_addr,

--- 2745 unchanged lines hidden (view full) ---

7548 */
7549int gap_inquiry_start(uint8_t duration_in_1280ms_units){
7550 if (hci_stack->state != HCI_STATE_WORKING) return ERROR_CODE_COMMAND_DISALLOWED;
7551 if (hci_stack->inquiry_state != GAP_INQUIRY_STATE_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
7552 if ((duration_in_1280ms_units < GAP_INQUIRY_DURATION_MIN) || (duration_in_1280ms_units > GAP_INQUIRY_DURATION_MAX)){
7553 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
7554 }
7555 hci_stack->inquiry_state = duration_in_1280ms_units;
7556 hci_stack->inquiry_max_period_length = 0;
7557 hci_stack->inquiry_min_period_length = 0;
7530 hci_run();
7531 return 0;
7532}
7533
7558 hci_run();
7559 return 0;
7560}
7561
7562uint8_t gap_inquiry_periodic_start(uint8_t duration, uint16_t max_period_length, uint16_t min_period_length){
7563 if (hci_stack->state != HCI_STATE_WORKING) return ERROR_CODE_COMMAND_DISALLOWED;
7564 if (hci_stack->inquiry_state != GAP_INQUIRY_STATE_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
7565 if (duration < GAP_INQUIRY_DURATION_MIN) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
7566 if (duration > GAP_INQUIRY_DURATION_MAX) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
7567 if (max_period_length < GAP_INQUIRY_MAX_PERIODIC_LEN_MIN) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;;
7568 if (min_period_length < GAP_INQUIRY_MIN_PERIODIC_LEN_MIN) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;;
7569
7570 hci_stack->inquiry_state = duration;
7571 hci_stack->inquiry_max_period_length = max_period_length;
7572 hci_stack->inquiry_min_period_length = min_period_length;
7573 hci_run();
7574 return 0;
7575}
7576
7534/**
7535 * @brief Stop GAP Classic Inquiry
7536 * @return 0 if ok
7537 */
7538int gap_inquiry_stop(void){
7539 if ((hci_stack->inquiry_state >= GAP_INQUIRY_DURATION_MIN) && (hci_stack->inquiry_state <= GAP_INQUIRY_DURATION_MAX)) {
7540 // emit inquiry complete event, before it even started
7541 uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
7542 hci_emit_event(event, sizeof(event), 1);
7543 return 0;
7544 }
7577/**
7578 * @brief Stop GAP Classic Inquiry
7579 * @return 0 if ok
7580 */
7581int gap_inquiry_stop(void){
7582 if ((hci_stack->inquiry_state >= GAP_INQUIRY_DURATION_MIN) && (hci_stack->inquiry_state <= GAP_INQUIRY_DURATION_MAX)) {
7583 // emit inquiry complete event, before it even started
7584 uint8_t event[] = { GAP_EVENT_INQUIRY_COMPLETE, 1, 0};
7585 hci_emit_event(event, sizeof(event), 1);
7586 return 0;
7587 }
7545 if (hci_stack->inquiry_state != GAP_INQUIRY_STATE_ACTIVE) return ERROR_CODE_COMMAND_DISALLOWED;
7546 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W2_CANCEL;
7547 hci_run();
7548 return 0;
7588 switch (hci_stack->inquiry_state){
7589 case GAP_INQUIRY_STATE_ACTIVE:
7590 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W2_CANCEL;
7591 hci_run();
7592 return ERROR_CODE_SUCCESS;
7593 case GAP_INQUIRY_STATE_PERIODIC:
7594 hci_stack->inquiry_state = GAP_INQUIRY_STATE_W2_EXIT_PERIODIC;
7595 hci_run();
7596 return ERROR_CODE_SUCCESS;
7597 default:
7598 return ERROR_CODE_COMMAND_DISALLOWED;
7599 }
7549}
7550
7551void gap_inquiry_set_lap(uint32_t lap){
7552 hci_stack->inquiry_lap = lap;
7553}
7554
7555void gap_inquiry_set_scan_activity(uint16_t inquiry_scan_interval, uint16_t inquiry_scan_window){
7556 hci_stack->inquiry_scan_interval = inquiry_scan_interval;

--- 735 unchanged lines hidden ---
7600}
7601
7602void gap_inquiry_set_lap(uint32_t lap){
7603 hci_stack->inquiry_lap = lap;
7604}
7605
7606void gap_inquiry_set_scan_activity(uint16_t inquiry_scan_interval, uint16_t inquiry_scan_window){
7607 hci_stack->inquiry_scan_interval = inquiry_scan_interval;

--- 735 unchanged lines hidden ---