Пример #1
0
int l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t len){
    
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_prepared_to_handle cid %u, cannot send\n", cid);
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    log_debug("l2cap_send_prepared_to_handle cid %u, handle %u\n", cid, handle);
    
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();
    
    // 0 - Connection handle : PB=10 : BC=00 
    bt_store_16(acl_buffer, 0, handle | (2 << 12) | (0 << 14));
    // 2 - ACL length
    bt_store_16(acl_buffer, 2,  len + 4);
    // 4 - L2CAP packet length
    bt_store_16(acl_buffer, 4,  len + 0);
    // 6 - L2CAP channel DEST
    bt_store_16(acl_buffer, 6, cid);    
    // send
    int err = hci_send_acl_packet(acl_buffer, len+8);
    
    l2cap_hand_out_credits();

    return err;
}
Пример #2
0
int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){

    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_signaling_packet, cannot send\n");
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    // log_info("l2cap_send_signaling_packet type %u\n", cmd);
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();
    va_list argptr;
    va_start(argptr, identifier);
    uint16_t len = l2cap_create_signaling_internal(acl_buffer, handle, cmd, identifier, argptr);
    va_end(argptr);
    // log_info("l2cap_send_signaling_packet con %u!\n", handle);
    return hci_send_acl_packet(acl_buffer, len);
}
Пример #3
0
int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
    
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_internal cid %u, cannot send\n", local_cid);
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
    if (!channel) {
        log_error("l2cap_send_internal no channel for cid %u\n", local_cid);
        return -1;   // TODO: define error
    }

    if (channel->packets_granted == 0){
        log_error("l2cap_send_internal cid %u, no credits!\n", local_cid);
        return -1;  // TODO: define error
    }
    
    --channel->packets_granted;

    log_debug("l2cap_send_internal cid %u, handle %u, 1 credit used, credits left %u;\n",
                  local_cid, channel->handle, channel->packets_granted);
    
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();

    // 0 - Connection handle : PB=10 : BC=00 
    bt_store_16(acl_buffer, 0, channel->handle | (2 << 12) | (0 << 14));
    // 2 - ACL length
    bt_store_16(acl_buffer, 2,  len + 4);
    // 4 - L2CAP packet length
    bt_store_16(acl_buffer, 4,  len + 0);
    // 6 - L2CAP channel DEST
    bt_store_16(acl_buffer, 6, channel->remote_cid);    
    // send
    int err = hci_send_acl_packet(acl_buffer, len+8);
    
    l2cap_hand_out_credits();
    
    return err;
}
Пример #4
0
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;
}