/**
 * send HCI packet to all connections 
 */
void socket_connection_send_packet_all(uint16_t type, uint16_t channel, uint8_t *packet, uint16_t size){
    linked_item_t *next;
    linked_item_t *it;
    for (it = (linked_item_t *) connections; it ; it = next){
        next = it->next; // cache pointer to next connection_t to allow for removal
        socket_connection_send_packet( (connection_t *) linked_item_get_user(it), type, channel, packet, size);
    }
}
int socket_connection_hci_process(struct data_source *ds) {
    connection_t *conn = (connection_t *) ds;
    
    int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
    if (bytes_read <= 0){
        // connection broken (no particular channel, no date yet)
        socket_connection_emit_connection_closed(conn);
        
        // free connection
        socket_connection_free_connection(linked_item_get_user(&conn->item));
        
        socket_connection_emit_nr_connections();
        return 0;
    }
    conn->bytes_read += bytes_read;
    conn->bytes_to_read -= bytes_read;
    // hexdump( conn->buffer, conn->bytes_read);
    if (conn->bytes_to_read > 0) {
        return 0;
    }
    
    int dispatch = 0;
    switch (conn->state){
        case SOCKET_W4_HEADER:
            conn->state = SOCKET_W4_DATA;
            conn->bytes_to_read = READ_BT_16( conn->buffer, 4);
            if (conn->bytes_to_read == 0){
                dispatch = 1;
            }
            break;
        case SOCKET_W4_DATA:
            dispatch = 1;
            break;
        default:
            break;
    }
    
    if (dispatch){
        // dispatch packet !!! connection, type, channel, data, size
        int dispatch_err = (*socket_connection_packet_callback)(conn, READ_BT_16( conn->buffer, 0), READ_BT_16( conn->buffer, 2),
                                                            &conn->buffer[sizeof(packet_header_t)], READ_BT_16( conn->buffer, 4));
        
        // reset state machine
        socket_connection_init_statemachine(conn);
        
        // "park" if dispatch failed
        if (dispatch_err) {
            log_info("socket_connection_hci_process dispatch failed -> park connection\n");
            run_loop_remove_data_source(ds);
            linked_list_add_tail(&parked, (linked_item_t *) ds);
        }
    }
	return 0;
}
Example #3
0
static void hci_connection_timeout_handler(timer_source_t *timer){
    hci_connection_t * connection = (hci_connection_t *) linked_item_get_user(&timer->item);
#ifdef HAVE_TIME
    struct timeval tv;
    gettimeofday(&tv, NULL);
    if (tv.tv_sec >= connection->timestamp.tv_sec + HCI_CONNECTION_TIMEOUT_MS/1000) {
        // connections might be timed out
        hci_emit_l2cap_check_timeout(connection);
    }
#endif
#ifdef HAVE_TICK
    if (embedded_get_ticks() > connection->timestamp + embedded_ticks_for_ms(HCI_CONNECTION_TIMEOUT_MS)){
        // connections might be timed out
        hci_emit_l2cap_check_timeout(connection);
    }
#endif
    run_loop_set_timer(timer, HCI_CONNECTION_TIMEOUT_MS);
    run_loop_add_timer(timer);
}