static int blacklist_contains(bd_addr_t addr){ int i; for (i=0; i<blacklist_size(); i++){ if (bd_addr_cmp(addr, blacklist[i]) == 0) return 1; } return 0; }
static int getDeviceIndexForAddress( bd_addr_t addr){ int j; for (j=0; j< deviceCount; j++){ if (bd_addr_cmp(addr, devices[j].address) == 0){ return j; } } return -1; }
static btstack_link_key_db_memory_entry_t * get_item(btstack_linked_list_t list, bd_addr_t bd_addr) { btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) list; it ; it = it->next){ btstack_link_key_db_memory_entry_t * item = (btstack_link_key_db_memory_entry_t *) it; if (bd_addr_cmp(item->bd_addr, bd_addr) == 0) { return item; } } return NULL; }
void l2cap_input(struct pbuf *p, struct bd_addr *bdaddr) { struct l2cap_seg *inseg; struct hci_acl_hdr *aclhdr; struct pbuf *data; err_t ret; pbuf_header(p, HCI_ACL_HDR_LEN); aclhdr = p->payload; pbuf_header(p, -HCI_ACL_HDR_LEN); pbuf_realloc(p, aclhdr->len); for(inseg = l2cap_insegs; inseg != NULL; inseg = inseg->next) { if(bd_addr_cmp(bdaddr, &(inseg->bdaddr))) { break; } } /* Reassembly procedures */ /* Check if continuing fragment or start of L2CAP packet */ if(((aclhdr->conhdl_pb_bc >> 12) & 0x03)== L2CAP_ACL_CONT) { /* Continuing fragment */ if(inseg == NULL) { /* Discard packet */ LWIP_DEBUGF(L2CAP_DEBUG, ("l2cap_input: Continuing fragment. Discard packet\n")); pbuf_free(p); return; } else if(inseg->p->tot_len + p->tot_len > inseg->len) { /* Check if length of segment exceeds l2cap header length */ /* Discard packet */ LWIP_DEBUGF(L2CAP_DEBUG, ("l2cap_input: Continuing fragment. Length exceeds L2CAP hdr length. Discard packet\n")); pbuf_free(inseg->p); L2CAP_SEG_RMV(&(l2cap_insegs), inseg); lwbt_memp_free(MEMP_L2CAP_SEG, inseg); pbuf_free(p); return; } /* Add pbuf to segement */ pbuf_chain(inseg->p, p); pbuf_free(p); } else if(((aclhdr->conhdl_pb_bc >> 12) & 0x03) == L2CAP_ACL_START) { /* Start of L2CAP packet */
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); // ok: no channel for HCI_EVENT_PACKET and only single active RFCOMM channel if (packet_type == RFCOMM_DATA_PACKET){ // printf("packet_handler type RFCOMM_DATA_PACKET %u, packet[0] %x\n", packet_type, packet[0]); // 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)btstack_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)btstack_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)(HCI_EVENT_PACKET, 0, event, size+4); } hsp_run(); return; } if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = hci_event_packet_get_type(packet); bd_addr_t event_addr; uint16_t handle; // printf("packet_handler HCI_EVENT_PACKET type %u, packet[0] %x\n", packet_type, packet[0]); switch (event) { case HCI_EVENT_CONNECTION_REQUEST: switch(hci_event_connection_request_get_link_type(packet)){ case 0: // SCO case 2: // eSCO hci_event_connection_request_get_bd_addr(packet, event_addr); printf("remote device %s\n", bd_addr_to_str(remote)); printf("accept sco for device %s\n", bd_addr_to_str(event_addr)); if (bd_addr_cmp(event_addr, remote) == 0){ printf("hs_accept_sco_connection \n"); hs_accept_sco_connection = 1; } break; default: break; } break; case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{ if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED) return; int index = 2; uint8_t status = packet[index++]; sco_handle = little_endian_read_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 = little_endian_read_16(packet, index); // measured in bytes index+=2; uint16_t tx_packet_length = little_endian_read_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); 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; reverse_bd_addr(&packet[2], event_addr); rfcomm_cid = little_endian_read_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(rfcomm_cid); break; case RFCOMM_EVENT_CHANNEL_OPENED: // printf("RFCOMM_EVENT_CHANNEL_OPENED 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 = little_endian_read_16(packet, 9); rfcomm_cid = little_endian_read_16(packet, 12); mtu = little_endian_read_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 RFCOMM_EVENT_CAN_SEND_NOW: hsp_run(); break; case HCI_EVENT_DISCONNECTION_COMPLETE: handle = little_endian_read_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(HCI_EVENT_PACKET, 0, packet, size); break; default: break; } hsp_run(); }