static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint8_t rfcomm_channel_nr; uint16_t mtu; int i; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter"); } break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ bt_flip_addr(event_addr, &packet[6]); printf("BD-ADDR: %s\n", bd_addr_to_str(event_addr)); break; } break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Pin code request - using '0000'\n"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case HCI_EVENT_USER_CONFIRMATION_REQUEST: // inform about user confirmation request printf("SSP User Confirmation Request with numeric value '%06u'\n", READ_BT_32(packet, 8)); printf("SSP User Confirmation Auto accept\n"); break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_channel_id); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: printf("RFCOMM channel closed\n"); rfcomm_channel_id = 0; break; default: break; } break; case RFCOMM_DATA_PACKET: printf("RCV: '"); for (i=0;i<size;i++){ putchar(packet[i]); } printf("'\n"); break; default: break; } }
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){ bd_addr_t addr; uint16_t cid; uint16_t psm; uint16_t service_channel; uint16_t mtu; uint8_t reason; uint8_t rfcomm_channel; uint8_t rfcomm_credits; uint32_t service_record_handle; client_state_t *client; uint16_t serviceSearchPatternLen; uint16_t attributeIDListLen; // BTstack internal commands - 16 Bit OpCode, 8 Bit ParamLen, Params... switch (READ_CMD_OCF(packet)){ case BTSTACK_GET_STATE: log_info("BTSTACK_GET_STATE"); hci_emit_state(); break; case BTSTACK_SET_POWER_MODE: log_info("BTSTACK_SET_POWER_MODE %u", packet[3]); // track client power requests client = client_for_connection(connection); if (!client) break; client->power_mode = packet[3]; // handle merged state if (!clients_require_power_on()){ start_power_off_timer(); } else if (!power_management_sleep) { stop_power_off_timer(); hci_power_control(HCI_POWER_ON); } break; case BTSTACK_GET_VERSION: log_info("BTSTACK_GET_VERSION"); hci_emit_btstack_version(); break; #ifdef USE_BLUETOOL case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED %u", packet[3]); iphone_system_bt_set_enabled(packet[3]); hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled()); break; case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED"); hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled()); break; #else case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: hci_emit_system_bluetooth_enabled(0); break; #endif case BTSTACK_SET_DISCOVERABLE: log_info("BTSTACK_SET_DISCOVERABLE discoverable %u)", packet[3]); // track client discoverable requests client = client_for_connection(connection); if (!client) break; client->discoverable = packet[3]; // merge state hci_discoverable_control(clients_require_discoverable()); break; case BTSTACK_SET_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_BLUETOOTH_ENABLED: %u\n", packet[3]); if (packet[3]) { // global enable global_enable = 1; hci_power_control(HCI_POWER_ON); } else { global_enable = 0; clients_clear_power_request(); hci_power_control(HCI_POWER_OFF); } break; case L2CAP_CREATE_CHANNEL_MTU: bt_flip_addr(addr, &packet[3]); psm = READ_BT_16(packet, 9); mtu = READ_BT_16(packet, 11); l2cap_create_channel_internal( connection, NULL, addr, psm, mtu); break; case L2CAP_CREATE_CHANNEL: bt_flip_addr(addr, &packet[3]); psm = READ_BT_16(packet, 9); l2cap_create_channel_internal( connection, NULL, addr, psm, 150); // until r865 break; case L2CAP_DISCONNECT: cid = READ_BT_16(packet, 3); reason = packet[5]; l2cap_disconnect_internal(cid, reason); break; case L2CAP_REGISTER_SERVICE: psm = READ_BT_16(packet, 3); mtu = READ_BT_16(packet, 5); l2cap_register_service_internal(connection, NULL, psm, mtu); break; case L2CAP_UNREGISTER_SERVICE: psm = READ_BT_16(packet, 3); l2cap_unregister_service_internal(connection, psm); break; case L2CAP_ACCEPT_CONNECTION: cid = READ_BT_16(packet, 3); l2cap_accept_connection_internal(cid); break; case L2CAP_DECLINE_CONNECTION: cid = READ_BT_16(packet, 3); reason = packet[7]; l2cap_decline_connection_internal(cid, reason); break; case RFCOMM_CREATE_CHANNEL: bt_flip_addr(addr, &packet[3]); rfcomm_channel = packet[9]; rfcomm_create_channel_internal( connection, &addr, rfcomm_channel ); break; case RFCOMM_CREATE_CHANNEL_WITH_CREDITS: bt_flip_addr(addr, &packet[3]); rfcomm_channel = packet[9]; rfcomm_credits = packet[10]; rfcomm_create_channel_with_initial_credits_internal( connection, &addr, rfcomm_channel, rfcomm_credits ); break; case RFCOMM_DISCONNECT: cid = READ_BT_16(packet, 3); reason = packet[5]; rfcomm_disconnect_internal(cid); break; case RFCOMM_REGISTER_SERVICE: rfcomm_channel = packet[3]; mtu = READ_BT_16(packet, 4); rfcomm_register_service_internal(connection, rfcomm_channel, mtu); break; case RFCOMM_REGISTER_SERVICE_WITH_CREDITS: rfcomm_channel = packet[3]; mtu = READ_BT_16(packet, 4); rfcomm_credits = packet[6]; rfcomm_register_service_with_initial_credits_internal(connection, rfcomm_channel, mtu, rfcomm_credits); break; case RFCOMM_UNREGISTER_SERVICE: service_channel = READ_BT_16(packet, 3); rfcomm_unregister_service_internal(service_channel); break; case RFCOMM_ACCEPT_CONNECTION: cid = READ_BT_16(packet, 3); rfcomm_accept_connection_internal(cid); break; case RFCOMM_DECLINE_CONNECTION: cid = READ_BT_16(packet, 3); reason = packet[7]; rfcomm_decline_connection_internal(cid); break; case RFCOMM_GRANT_CREDITS: cid = READ_BT_16(packet, 3); rfcomm_credits = packet[5]; rfcomm_grant_credits(cid, rfcomm_credits); break; case RFCOMM_PERSISTENT_CHANNEL: { if (remote_device_db) { // enforce \0 packet[3+248] = 0; rfcomm_channel = remote_device_db->persistent_rfcomm_channel((char*)&packet[3]); } else { // NOTE: hack for non-iOS platforms rfcomm_channel = rfcomm_channel_generator++; } log_info("RFCOMM_EVENT_PERSISTENT_CHANNEL %u", rfcomm_channel); uint8_t event[4]; event[0] = RFCOMM_EVENT_PERSISTENT_CHANNEL; event[1] = sizeof(event) - 2; event[2] = 0; event[3] = rfcomm_channel; hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); break; } case SDP_REGISTER_SERVICE_RECORD: log_info("SDP_REGISTER_SERVICE_RECORD size %u\n", size); sdp_register_service_internal(connection, &packet[3]); break; case SDP_UNREGISTER_SERVICE_RECORD: service_record_handle = READ_BT_32(packet, 3); log_info("SDP_UNREGISTER_SERVICE_RECORD handle 0x%x ", service_record_handle); sdp_unregister_service_internal(connection, service_record_handle); break; case SDP_CLIENT_QUERY_RFCOMM_SERVICES: bt_flip_addr(addr, &packet[3]); serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); sdp_query_rfcomm_register_callback(handle_sdp_rfcomm_service_result, connection); sdp_query_rfcomm_channel_and_name_for_search_pattern(addr, serviceSearchPattern); break; case SDP_CLIENT_QUERY_SERVICES: bt_flip_addr(addr, &packet[3]); sdp_parser_init(); sdp_parser_register_callback(handle_sdp_client_query_result); serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); memcpy(attributeIDList, &packet[9+serviceSearchPatternLen], attributeIDListLen); sdp_client_query(addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]); // sdp_general_query_for_uuid(addr, 0x1002); break; default: log_error("Error: command %u not implemented\n:", READ_CMD_OCF(packet)); break; } // verbose log info on command before dumped command unknown to PacketLogger or Wireshark hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size); return 0; }
// Bluetooth logic static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint8_t rfcomm_channel_nr; uint16_t mtu; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo"); } break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ bt_flip_addr(event_addr, &packet[6]); printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ hci_discoverable_control(1); break; } break; case HCI_EVENT_LINK_KEY_REQUEST: // deny link key request printf("Link key request\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr); break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Pin code request - using '0000'\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_channel_id); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n\r", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: rfcomm_channel_id = 0; break; default: break; } break; case RFCOMM_DATA_PACKET: // hack: truncate data (we know that the packet is at least on byte bigger packet[size] = 0; puts( (const char *) packet); rfcomm_send_credit = 1; default: break; } }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ //printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); if (packet_type == RFCOMM_DATA_PACKET){ // skip over leading newline while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){ size--; packet++; } if (strncmp((char *)packet, HSP_AG_RING, strlen(HSP_AG_RING)) == 0){ emit_ring_event(); } else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){ wait_ok = 0; } else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]); emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain); } else if (strncmp((char *)packet, HSP_SPEAKER_GAIN, strlen(HSP_SPEAKER_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_SPEAKER_GAIN)]); emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain); } else { if (!hsp_hs_callback) return; // strip trailing newline while (size > 0 && (packet[size-1] == '\n' || packet[size-1] == '\r')){ size--; } // add trailing \0 packet[size] = 0; // re-use incoming buffer to avoid reserving large buffers - ugly but efficient uint8_t * event = packet - 4; event[0] = HCI_EVENT_HSP_META; event[1] = size + 2; event[2] = HSP_SUBEVENT_AG_INDICATION; event[3] = size; (*hsp_hs_callback)(event, size+4); } hsp_run(); return; } if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; bd_addr_t event_addr; uint16_t handle; switch (event) { case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED) return; int index = 2; uint8_t status = packet[index++]; sco_handle = READ_BT_16(packet, index); index+=2; bd_addr_t address; memcpy(address, &packet[index], 6); index+=6; uint8_t link_type = packet[index++]; uint8_t transmission_interval = packet[index++]; // measured in slots uint8_t retransmission_interval = packet[index++];// measured in slots uint16_t rx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint16_t tx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint8_t air_mode = packet[index]; if (status != 0){ log_error("(e)SCO Connection failed, status %u", status); emit_event_audio_connected(status, sco_handle); hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED ; break; } switch (link_type){ case 0x00: log_info("SCO Connection established."); if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval); if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval); if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length); if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length); break; case 0x02: log_info("eSCO Connection established."); break; default: log_error("(e)SCO reserved link_type 0x%2x", link_type); break; } log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle, bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode); // forward event to app hsp_hs_callback(packet, size); hsp_state = HSP_AUDIO_CONNECTION_ESTABLISHED; emit_event_audio_connected(status, sco_handle); break; } case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) if (hsp_state != HSP_IDLE) return; bt_flip_addr(event_addr, &packet[2]); rfcomm_cid = READ_BT_16(packet, 9); log_info("RFCOMM channel %u requested for %s", packet[8], bd_addr_to_str(event_addr)); hsp_state = HSP_W4_RFCOMM_CONNECTED; rfcomm_accept_connection_internal(rfcomm_cid); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) if (hsp_state != HSP_W4_RFCOMM_CONNECTED) return; if (packet[2]) { log_info("RFCOMM channel open failed, status %u", packet[2]); hsp_state = HSP_IDLE; hsp_hs_reset_state(); } else { // data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) rfcomm_handle = READ_BT_16(packet, 9); rfcomm_cid = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u, handle %02x", rfcomm_cid, mtu, rfcomm_handle); hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED; } emit_event(HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE, packet[2]); break; case BTSTACK_EVENT_STATE: case DAEMON_EVENT_HCI_PACKET_SENT: case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS: case RFCOMM_EVENT_CREDITS: hsp_hs_callback(packet, size); break; case HCI_EVENT_DISCONNECTION_COMPLETE: handle = READ_BT_16(packet,3); if (handle == sco_handle){ sco_handle = 0; hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED; emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0); break; } if (handle == rfcomm_handle) { rfcomm_handle = 0; hsp_state = HSP_IDLE; emit_event(HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE,0); hsp_hs_reset_state(); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: hsp_hs_reset_state(); hsp_hs_callback(packet, size); break; default: break; } hsp_run(); }
static void PacketHandler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { bd_addr_t event_addr; uint8_t rfcomm_channel_nr; uint16_t mtu; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { hci_send_cmd(&hci_write_local_name, local_name); } break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) { bt_flip_addr(event_addr, &packet[6]); log_printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); sprintf(local_name, "IOIO (%02X:%02X)", event_addr[4], event_addr[5]); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)) { hci_discoverable_control(1); break; } break; case HCI_EVENT_LINK_KEY_REQUEST: // deny link key request log_printf("Link key request\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr); break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request log_printf("Pin code request - using '4545'\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "4545"); break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); log_printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_channel_id); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { log_printf("RFCOMM channel open failed, status %u\n\r", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); rfcomm_send_credit = 1; mtu = READ_BT_16(packet, 14); log_printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: log_printf("RFCOMM channel closed."); client_callback(NULL, 0, client_callback_arg); client_callback = DummyCallback; rfcomm_channel_id = 0; break; default: break; } break; case RFCOMM_DATA_PACKET: client_callback(packet, size, client_callback_arg); rfcomm_send_credit = 1; default: break; } }
void hfp_handle_hci_event(hfp_callback_t callback, uint8_t packet_type, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint16_t rfcomm_cid, handle; hfp_connection_t * context = NULL; switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ printf("BTstack activated, get started .\n"); } break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Pin code request - using '0000'\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); context = get_hfp_connection_context_for_bd_addr(event_addr); if (!context || context->state != HFP_IDLE) return; context->rfcomm_cid = READ_BT_16(packet, 9); context->state = HFP_W4_RFCOMM_CONNECTED; printf("RFCOMM channel %u requested for %s\n", context->rfcomm_cid, bd_addr_to_str(context->remote_addr)); rfcomm_accept_connection_internal(context->rfcomm_cid); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); bt_flip_addr(event_addr, &packet[3]); context = get_hfp_connection_context_for_bd_addr(event_addr); if (!context || context->state != HFP_W4_RFCOMM_CONNECTED) return; if (packet[2]) { hfp_emit_event(callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, packet[2]); remove_hfp_connection_context(context); } else { context->con_handle = READ_BT_16(packet, 9); context->rfcomm_cid = READ_BT_16(packet, 12); uint16_t mtu = READ_BT_16(packet, 14); printf("RFCOMM channel open succeeded. Context %p, RFCOMM Channel ID 0x%02x, max frame size %u\n", context, context->rfcomm_cid, mtu); switch (context->state){ case HFP_W4_RFCOMM_CONNECTED: context->state = HFP_EXCHANGE_SUPPORTED_FEATURES; break; case HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: context->state = HFP_W2_DISCONNECT_RFCOMM; printf("Shutting down RFCOMM.\n"); break; default: break; } } break; case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ int index = 2; uint8_t status = packet[index++]; uint16_t sco_handle = READ_BT_16(packet, index); index+=2; bd_addr_t address; memcpy(address, &packet[index], 6); index+=6; uint8_t link_type = packet[index++]; uint8_t transmission_interval = packet[index++]; // measured in slots uint8_t retransmission_interval = packet[index++];// measured in slots uint16_t rx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint16_t tx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint8_t air_mode = packet[index]; if (status != 0){ log_error("(e)SCO Connection is not established, status %u", status); break; } switch (link_type){ case 0x00: printf("SCO Connection established. \n"); if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval); if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval); if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length); if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length); break; case 0x02: printf("eSCO Connection established. \n"); break; default: log_error("(e)SCO reserved link_type 0x%2x", link_type); break; } log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle, bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode); context = get_hfp_connection_context_for_bd_addr(address); if (context->state == HFP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){ context->state = HFP_W2_DISCONNECT_SCO; break; } context->sco_handle = sco_handle; context->state = HFP_AUDIO_CONNECTION_ESTABLISHED; hfp_emit_event(callback, HFP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, packet[2]); break; } case RFCOMM_EVENT_CHANNEL_CLOSED: rfcomm_cid = READ_BT_16(packet,2); context = get_hfp_connection_context_for_rfcomm_cid(rfcomm_cid); if (!context) break; if (context->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ context->state = HFP_IDLE; hfp_establish_service_level_connection(context->remote_addr, context->service_uuid); break; } remove_hfp_connection_context(context); hfp_emit_event(callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, 0); break; case HCI_EVENT_DISCONNECTION_COMPLETE: handle = READ_BT_16(packet,3); context = get_hfp_connection_context_for_handle(handle); if (!context) break; if (context->state == HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART){ context->state = HFP_IDLE; hfp_establish_service_level_connection(context->remote_addr, context->service_uuid); break; } hfp_emit_event(callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED, packet[2]); remove_hfp_connection_context(context); break; default: break; } }
// Bluetooth logic static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint8_t rfcomm_channel_nr; uint16_t mtu; uint8_t event_code; // uint8_t channel; uint8_t message_id; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo"); } break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ bt_flip_addr(event_addr, &packet[6]); printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ // start ANT init ant_send_cmd(&ant_reset); break; } break; case HCI_EVENT_LINK_KEY_REQUEST: // deny link key request printf("Link key request\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr); break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Pin code request - using '0000'\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_channel_id); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n\r", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: rfcomm_channel_id = 0; break; case 0xff: // vendor specific -> ANT // vendor specific ant message if (packet[2] != 0x00) break; if (packet[3] != 0x05) break; event_code = packet[7]; printf("ANT Event: "); printf_hexdump(packet, size); switch(event_code){ case MESG_STARTUP_MESG_ID: // 2. assign channel ant_send_cmd(&ant_assign_channel, 0, 0x00, 0); break; case MESG_RESPONSE_EVENT_ID: // channel = packet[8]; message_id = packet[9]; switch (message_id){ case MESG_ASSIGN_CHANNEL_ID: // 3. set channel ID ant_send_cmd(&ant_channel_id, 0, 33, 1, 1); break; case MESG_CHANNEL_ID_ID: // 4. open channel ant_send_cmd(&ant_open_channel, 0); } break; default: break; } break; default: break; } break; default: break; } }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ // printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); if (packet_type == RFCOMM_DATA_PACKET){ while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){ size--; packet++; } if (strncmp((char *)packet, HSP_AG_RING, strlen(HSP_AG_RING)) == 0){ hs_ring_received = 1; } if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){ hs_ok_received = 1; switch (hsp_state){ case HSP_W4_RFCOMM_CONNECTED: hsp_state = HSP_W2_CONNECT_SCO; break; case HSP_W4_USER_ACTION: hsp_state = HSP_W2_DISCONNECT_SCO; break; default: break; } } else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]); emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain); } else if (strncmp((char *)packet, HSP_SPEAKER_GAIN, strlen(HSP_SPEAKER_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_SPEAKER_GAIN)]); emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain); } else { if (!hsp_hs_callback) return; // re-use incoming buffer to avoid reserving large buffers - ugly but efficient uint8_t * event = packet - 3; event[0] = HCI_EVENT_HSP_META; event[1] = size + 1; event[2] = HSP_SUBEVENT_AG_INDICATION; (*hsp_hs_callback)(event, size+3); } hsp_run(); return; } if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; bd_addr_t event_addr; uint16_t handle; switch (event) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ printf("BTstack activated, get started .\n"); } break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Pin code request - using '0000'\n\r"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ int index = 2; uint8_t status = packet[index++]; sco_handle = READ_BT_16(packet, index); index+=2; bd_addr_t address; memcpy(address, &packet[index], 6); index+=6; uint8_t link_type = packet[index++]; uint8_t transmission_interval = packet[index++]; // measured in slots uint8_t retransmission_interval = packet[index++];// measured in slots uint16_t rx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint16_t tx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint8_t air_mode = packet[index]; if (status != 0){ log_error("(e)SCO Connection is not established, status %u", status); exit(0); break; } switch (link_type){ case 0x00: printf("SCO Connection established. \n"); if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval); if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval); if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length); if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length); break; case 0x02: printf("eSCO Connection established. \n"); break; default: log_error("(e)SCO reserved link_type 0x%2x", link_type); break; } log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle, bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode); if (hsp_state == HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){ hsp_state = HSP_W2_DISCONNECT_SCO; break; } hsp_state = HSP_ACTIVE; emit_event(HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, 0); break; } case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) if (hsp_state != HSP_IDLE) return; bt_flip_addr(event_addr, &packet[2]); rfcomm_cid = READ_BT_16(packet, 9); printf("RFCOMM channel %u requested for %s\n", packet[8], bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_cid); hsp_state = HSP_W4_RFCOMM_CONNECTED; hs_send_button_press = 1; break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n", packet[2]); hsp_hs_reset_state(); emit_event(HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, packet[2]); } else { // data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) rfcomm_handle = READ_BT_16(packet, 9); rfcomm_cid = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_cid, mtu); switch (hsp_state){ case HSP_W4_RFCOMM_CONNECTED: hsp_state = HSP_W2_CONNECT_SCO; hs_send_button_press = 1; break; case HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: hsp_state = HSP_W2_DISCONNECT_RFCOMM; break; default: break; } } break; case DAEMON_EVENT_HCI_PACKET_SENT: case RFCOMM_EVENT_CREDITS: break; case HCI_EVENT_DISCONNECTION_COMPLETE: printf("HCI_EVENT_DISCONNECTION_COMPLETE \n"); if (hsp_state != HSP_W4_SCO_DISCONNECTED){ printf("received gap disconnect in wrong hsp state"); } handle = READ_BT_16(packet,3); if (handle == sco_handle){ sco_handle = 0; hsp_state = HSP_W2_DISCONNECT_RFCOMM; printf(" HSP_W2_DISCONNECT_RFCOMM\n"); break; } break; case RFCOMM_EVENT_CHANNEL_CLOSED: printf(" RFCOMM_EVENT_CHANNEL_CLOSED\n"); if (hsp_state != HSP_W4_RFCOMM_DISCONNECTED){ printf("received RFCOMM disconnect in wrong hsp state"); } printf("RFCOMM channel closed\n"); hsp_hs_reset_state(); emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0); break; default: break; } hsp_run(); }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ // log_info("packet_handler type %u, packet[0] %x", packet_type, packet[0]); if (packet_type == RFCOMM_DATA_PACKET){ while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){ size--; packet++; } if (strncmp((char *)packet, HSP_HS_BUTTON_PRESS, strlen(HSP_HS_BUTTON_PRESS)) == 0){ log_info("Received button press %s", HSP_HS_BUTTON_PRESS); ag_num_button_press_received++; ag_send_ok = 1; if (hsp_state == HSP_ACTIVE && ag_num_button_press_received >=2){ ag_num_button_press_received = 0; hsp_state = HSP_W2_DISCONNECT_SCO; } } else if (strncmp((char *)packet, HSP_HS_MICROPHONE_GAIN, strlen(HSP_HS_MICROPHONE_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_HS_MICROPHONE_GAIN)]); ag_send_ok = 1; emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain); } else if (strncmp((char *)packet, HSP_HS_SPEAKER_GAIN, strlen(HSP_HS_SPEAKER_GAIN)) == 0){ uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_HS_SPEAKER_GAIN)]); ag_send_ok = 1; emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain); } else if (strncmp((char *)packet, "AT+", 3) == 0){ ag_send_error = 1; if (!hsp_ag_callback) return; // re-use incoming buffer to avoid reserving large buffers - ugly but efficient uint8_t * event = packet - 4; event[0] = HCI_EVENT_HSP_META; event[1] = size + 2; event[2] = HSP_SUBEVENT_HS_COMMAND; event[3] = size; (*hsp_ag_callback)(event, size+4); } hsp_run(); return; } if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; bd_addr_t event_addr; uint16_t handle; switch (event) { case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ int index = 2; uint8_t status = packet[index++]; sco_handle = READ_BT_16(packet, index); index+=2; bd_addr_t address; memcpy(address, &packet[index], 6); index+=6; uint8_t link_type = packet[index++]; uint8_t transmission_interval = packet[index++]; // measured in slots uint8_t retransmission_interval = packet[index++];// measured in slots uint16_t rx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint16_t tx_packet_length = READ_BT_16(packet, index); // measured in bytes index+=2; uint8_t air_mode = packet[index]; if (status != 0){ log_error("(e)SCO Connection failed, status %u", status); emit_event_audio_connected(status, sco_handle); break; } switch (link_type){ case 0x00: log_info("SCO Connection established."); if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval); if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval); if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length); if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length); break; case 0x02: log_info("eSCO Connection established."); break; default: log_error("(e)SCO reserved link_type 0x%2x", link_type); break; } log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle, bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode); if (hsp_state == HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){ hsp_state = HSP_W2_DISCONNECT_SCO; break; } hsp_state = HSP_ACTIVE; emit_event_audio_connected(status, sco_handle); break; } case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) if (hsp_state != HSP_IDLE) return; bt_flip_addr(event_addr, &packet[2]); rfcomm_cid = READ_BT_16(packet, 9); log_info("RFCOMM channel %u requested for %s", packet[8], bd_addr_to_str(event_addr)); rfcomm_accept_connection_internal(rfcomm_cid); hsp_state = HSP_W4_RFCOMM_CONNECTED; break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: log_info("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x", packet_type, packet[0]); // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { log_info("RFCOMM channel open failed, status %u§", packet[2]); hsp_ag_reset_state(); emit_event(HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, packet[2]); } else { // data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) rfcomm_handle = READ_BT_16(packet, 9); rfcomm_cid = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u, state %d", rfcomm_cid, mtu, hsp_state); switch (hsp_state){ case HSP_W4_RFCOMM_CONNECTED: ag_num_button_press_received = 0; hsp_state = HSP_W2_CONNECT_SCO; break; case HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN: hsp_state = HSP_W2_DISCONNECT_RFCOMM; break; default: log_error("no valid state"); break; } } break; case DAEMON_EVENT_HCI_PACKET_SENT: case RFCOMM_EVENT_CREDITS: break; case HCI_EVENT_DISCONNECTION_COMPLETE: handle = READ_BT_16(packet,3); if (handle == sco_handle){ log_info("SCO disconnected, w2 disconnect RFCOMM"); sco_handle = 0; hsp_state = HSP_W2_DISCONNECT_RFCOMM; break; } break; case RFCOMM_EVENT_CHANNEL_CLOSED: log_info("RFCOMM channel closed"); hsp_ag_reset_state(); emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0); break; default: break; } hsp_run(); }
static void packet_handler_old (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t event_addr; uint8_t rfcomm_channel_nr; uint16_t mtu; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { uint8_t des_serviceSearchPattern[5] = {0x35, 0x03, 0x19, 0x10, 0x02}; hci_send_cmd(&sdp_client_query_rfcomm_services, host_addr, des_serviceSearchPattern); } break; case SDP_QUERY_COMPLETE: // data: event(8), len(8), status(8) printf("SDP_QUERY_COMPLETE, status %u\n", packet[2]); break; case SDP_QUERY_RFCOMM_SERVICE: // data: event(8), len(8), rfcomm channel(8), name(var) printf("SDP_QUERY_RFCOMM_SERVICE, rfcomm channel %u, name '%s'\n", packet[2], (const char*)&packet[3]); break; case HCI_EVENT_LINK_KEY_REQUEST: printf("HCI_EVENT_LINK_KEY_REQUEST \n"); // link key request bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr); break; case HCI_EVENT_PIN_CODE_REQUEST: // inform about pin code request printf("Please enter PIN 0000 on remote device\n"); bt_flip_addr(event_addr, &packet[2]); hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ bt_flip_addr(event_addr, &packet[6]); printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr)); break; } // if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){ // hci_send_cmd(&hci_write_class_of_device, 0x38010c); // hci_discoverable_control(1); // break; // } break; case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(event_addr, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); //printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr)); if(memcmp(event_addr, host_addr, sizeof(bd_addr_t)) == 0 || true /* TODO: Always accept */) { syslog(LOG_DEBUG, "[bluetooth] Accept RFCOMM connection from host."); rfcomm_accept_connection_internal(rfcomm_channel_id); } else { syslog(LOG_WARNING, "[bluetooth] Decline RFCOMM connection from unknown device %s.", bd_addr_to_str(event_addr)); rfcomm_decline_connection_internal(rfcomm_channel_id); } break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n\r", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: rfcomm_channel_id = 0; break; default: syslog(LOG_INFO, "Unresolved event packet %d", packet[0]); break; } break; default: break; } }
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ uint16_t psm; uint32_t passkey; if (packet_type == UCD_DATA_PACKET){ printf("UCD Data for PSM %04x received, size %u\n", READ_BT_16(packet, 0), size - 2); } if (packet_type != HCI_EVENT_PACKET) return; switch (packet[0]) { case HCI_EVENT_INQUIRY_RESULT: case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI: case HCI_EVENT_INQUIRY_COMPLETE: case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: inquiry_packet_handler(packet_type, packet, size); break; case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ printf("BTstack Bluetooth Classic Test Ready\n"); hci_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI show_usage(); } break; case GAP_DEDICATED_BONDING_COMPLETED: printf("GAP Dedicated Bonding Complete, status %u\n", packet[2]); break; case HCI_EVENT_CONNECTION_COMPLETE: if (!packet[2]){ handle = READ_BT_16(packet, 3); bt_flip_addr(remote, &packet[5]); printf("HCI_EVENT_CONNECTION_COMPLETE: handle 0x%04x\n", handle); } break; case HCI_EVENT_USER_PASSKEY_REQUEST: bt_flip_addr(remote, &packet[2]); printf("GAP User Passkey Request for %s\nPasskey:", bd_addr_to_str(remote)); fflush(stdout); ui_digits_for_passkey = 6; break; case HCI_EVENT_USER_CONFIRMATION_REQUEST: bt_flip_addr(remote, &packet[2]); passkey = READ_BT_32(packet, 8); printf("GAP User Confirmation Request for %s, number '%06u'\n", bd_addr_to_str(remote),passkey); break; case HCI_EVENT_PIN_CODE_REQUEST: bt_flip_addr(remote, &packet[2]); printf("GAP Legacy PIN Request for %s (press ENTER to send)\nPasskey:", bd_addr_to_str(remote)); fflush(stdout); ui_chars_for_pin = 1; break; case L2CAP_EVENT_CHANNEL_OPENED: // inform about new l2cap connection bt_flip_addr(remote, &packet[3]); psm = READ_BT_16(packet, 11); local_cid = READ_BT_16(packet, 13); handle = READ_BT_16(packet, 9); if (packet[2] == 0) { printf("L2CAP Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n", bd_addr_to_str(remote), handle, psm, local_cid, READ_BT_16(packet, 15)); } else { printf("L2CAP connection to device %s failed. status code %u\n", bd_addr_to_str(remote), packet[2]); } break; case L2CAP_EVENT_INCOMING_CONNECTION: { // data: event (8), len(8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16) psm = READ_BT_16(packet, 10); // uint16_t l2cap_cid = READ_BT_16(packet, 12); printf("L2CAP incoming connection request on PSM %u\n", psm); // l2cap_accept_connection_internal(l2cap_cid); break; } case RFCOMM_EVENT_INCOMING_CONNECTION: // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) bt_flip_addr(remote, &packet[2]); rfcomm_channel_nr = packet[8]; rfcomm_channel_id = READ_BT_16(packet, 9); printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(remote)); rfcomm_accept_connection_internal(rfcomm_channel_id); break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n\r", packet[2]); } else { rfcomm_channel_id = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); if (mtu > 60){ printf("BTstack libusb hack: using reduced MTU for sending instead of %u\n", mtu); mtu = 60; } printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu); } break; case RFCOMM_EVENT_CHANNEL_CLOSED: rfcomm_channel_id = 0; break; default: break; } }