static int daemon_client_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){ int err = 0; client_state_t * client; switch (packet_type){ case HCI_COMMAND_DATA_PACKET: if (READ_CMD_OGF(data) != OGF_BTSTACK) { // HCI Command hci_send_cmd_packet(data, length); } else { // BTstack command btstack_command_handler(connection, data, length); } break; case HCI_ACL_DATA_PACKET: err = hci_send_acl_packet(data, length); break; case L2CAP_DATA_PACKET: // process l2cap packet... err = l2cap_send_internal(channel, data, length); if (err == BTSTACK_ACL_BUFFERS_FULL) { l2cap_block_new_credits(1); } break; case RFCOMM_DATA_PACKET: // process l2cap packet... err = rfcomm_send_internal(channel, data, length); break; case DAEMON_EVENT_PACKET: switch (data[0]) { case DAEMON_EVENT_CONNECTION_OPENED: log_info("DAEMON_EVENT_CONNECTION_OPENED %p\n",connection); client = malloc(sizeof(client_state_t)); if (!client) break; // fail client->connection = connection; client->power_mode = HCI_POWER_OFF; client->discoverable = 0; linked_list_add(&clients, (linked_item_t *) client); break; case DAEMON_EVENT_CONNECTION_CLOSED: log_info("DAEMON_EVENT_CONNECTION_CLOSED %p\n",connection); sdp_unregister_services_for_connection(connection); rfcomm_close_connection(connection); l2cap_close_connection(connection); client = client_for_connection(connection); if (!client) break; linked_list_remove(&clients, (linked_item_t *) client); free(client); // update discoverable mode hci_discoverable_control(clients_require_discoverable()); // start power off, if last active client if (!clients_require_power_on()){ start_power_off_timer(); } break; case DAEMON_NR_CONNECTIONS_CHANGED: log_info("Nr Connections changed, new %u\n",data[1]); break; default: break; } break; } if (err) { log_info("Daemon Handler: err %d\n", err); } return err; }
/* parse the sdp record: type DES (6), element len 26 type DES (6), element len 24 type UINT (1), element len 3 , value: 0x00000004 type DES (6), element len 19 type DES (6), element len 5 type UUID (3), element len 3 , value: 0x00000100 type DES (6), element len 7 type UUID (3), element len 3 , value: 0x00000003 type UINT (1), element len 2 , value: 0x00000002 type DES (6), element len 5 type UUID (3), element len 3 , value: 0x00000008 */ static void sdpc_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { if (packet_type == HCI_EVENT_PACKET) { switch(packet[0]){ case L2CAP_EVENT_CHANNEL_OPENED: { if (packet[2]) { log_info("Connection failed\n"); return; } log_info("Connected\n"); state = SENDING; current_server = 0; l2cap_cid = READ_BT_16(packet, 13); sdpc_trysend(); break; } case DAEMON_EVENT_HCI_PACKET_SENT: case L2CAP_EVENT_CREDITS: { sdpc_trysend(); break; } case L2CAP_EVENT_CHANNEL_CLOSED: if (channel == l2cap_cid){ // reset l2cap_cid = 0; } break; } } if (packet_type == L2CAP_DATA_PACKET){ log_info("SDP Respone %d \n", READ_NET_16(packet, 5)); //de_dump_data_element(&packet[7]); //check if valid answer returns if (READ_NET_16(packet, 5) > 2) { switch(current_server) { case 0: { hfp_port = sdp_get_parameters_for_uuid(&packet[7], 0x0003);; log_info("hfp port: %d\n", hfp_port); break; } case 1: break; case 2: { mas_port = sdp_get_parameters_for_uuid(&packet[7], 0x0003);; log_info("MAP port: %d\n", mas_port ); break; } } } current_server++; if (current_server == 3) { state = DONE; l2cap_close_connection(¤t_server); if (hfp_port != 0) hfp_open(&addr, hfp_port); // if (mas_port != 0) // mas_open(&addr, mas_port); } else { state = SENDING; sdpc_trysend(); } } }