Exemple #1
0
void hci_run(){
        
    hci_connection_t * connection;
    linked_item_t * it;
    
    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

    // global/non-connection oriented commands
    
    // decline incoming connections
    if (hci_stack.decline_reason){
        uint8_t reason = hci_stack.decline_reason;
        hci_stack.decline_reason = 0;
        hci_send_cmd(&hci_reject_connection_request, hci_stack.decline_addr, reason);
    }

    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

    // send scan enable
    if (hci_stack.new_scan_enable_value != 0xff){
        hci_send_cmd(&hci_write_scan_enable, hci_stack.new_scan_enable_value);
        hci_stack.new_scan_enable_value = 0xff;
    }
    
    // send pending HCI commands
    for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){

        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

        connection = (hci_connection_t *) it;
        
        if (connection->state == RECEIVED_CONNECTION_REQUEST){
            log_info("sending hci_accept_connection_request\n");
            hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
            connection->state = ACCEPTED_CONNECTION_REQUEST;
        }

        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
        
        if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
            link_key_t link_key;
            log_info("responding to link key request\n");
            if ( hci_stack.remote_device_db->get_link_key( &connection->address, &link_key)){
               hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
            } else {
               hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
            }
            connectionClearAuthenticationFlags(connection, HANDLE_LINK_KEY_REQUEST);
        }
    }

    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
        
    switch (hci_stack.state){
        case HCI_STATE_INITIALIZING:
            // log_info("hci_init: substate %u\n", hci_stack.substate);
            if (hci_stack.substate % 2) {
                // odd: waiting for command completion
                return;
            }
            switch (hci_stack.substate >> 1){
                case 0: // RESET
                    hci_send_cmd(&hci_reset);
                    if (hci_stack.config == 0 || ((hci_uart_config_t *)hci_stack.config)->baudrate_main == 0){
                        // skip baud change
                        hci_stack.substate = 4; // >> 1 = 2
                    }
                    break;
                case 1: // SEND BAUD CHANGE
                    hci_stack.control->baudrate_cmd(hci_stack.config, ((hci_uart_config_t *)hci_stack.config)->baudrate_main, hci_stack.hci_packet_buffer);
                    hci_send_cmd_packet(hci_stack.hci_packet_buffer, 3 + hci_stack.hci_packet_buffer[2]);
                    break;
                case 2: // LOCAL BAUD CHANGE
                    hci_stack.hci_transport->set_baudrate(((hci_uart_config_t *)hci_stack.config)->baudrate_main);
                    hci_stack.substate += 2;
                    // break missing here for fall through
                    
                case 3:
                    // custom initialization
                    if (hci_stack.control && hci_stack.control->next_cmd){
                        int valid_cmd = (*hci_stack.control->next_cmd)(hci_stack.config, hci_stack.hci_packet_buffer);
                        if (valid_cmd){
                            int size = 3 + hci_stack.hci_packet_buffer[2];
                            hci_stack.hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, hci_stack.hci_packet_buffer, size);
                            hci_stack.substate = 4; // more init commands
                            break;
                        }
                        log_info("hci_run: init script done\n\r");
                    }
                    // otherwise continue
					hci_send_cmd(&hci_read_bd_addr);
					break;
				case 4:
					hci_send_cmd(&hci_read_buffer_size);
					break;
                case 5:
                    // ca. 15 sec
                    hci_send_cmd(&hci_write_page_timeout, 0x6000);
                    break;
				case 6:
					hci_send_cmd(&hci_write_scan_enable, (hci_stack.connectable << 1) | hci_stack.discoverable); // page scan
					break;
                case 7:
#ifndef EMBEDDED
                {
                    char hostname[30];
                    gethostname(hostname, 30);
                    hostname[29] = '\0';
                    hci_send_cmd(&hci_write_local_name, hostname);
                    break;
                }
                case 8:
#ifdef USE_BLUETOOL
                    hci_send_cmd(&hci_write_class_of_device, 0x007a020c); // Smartphone
                    break;
                    
                case 9:
#endif
#endif
                    // done.
                    hci_stack.state = HCI_STATE_WORKING;
                    hci_emit_state();
                    break;
                default:
                    break;
            }
            hci_stack.substate++;
            break;
            
        case HCI_STATE_HALTING:

            log_info("HCI_STATE_HALTING\n");
            // close all open connections
            connection =  (hci_connection_t *) hci_stack.connections;
            if (connection){
                
                // send disconnect
                if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
                
                log_info("HCI_STATE_HALTING, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
                hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // remote closed connection

                // send disconnected event right away - causes higher layer connections to get closed, too.
                hci_shutdown_connection(connection);
                return;
            }
            log_info("HCI_STATE_HALTING, calling off\n");
            
            // switch mode
            hci_power_control_off();
            
            log_info("HCI_STATE_HALTING, emitting state\n");
            hci_emit_state();
            log_info("HCI_STATE_HALTING, done\n");
            break;
            
        case HCI_STATE_FALLING_ASLEEP:
            switch(hci_stack.substate) {
                case 0:
                    log_info("HCI_STATE_FALLING_ASLEEP\n");
                    // close all open connections
                    connection =  (hci_connection_t *) hci_stack.connections;

#if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
                    // don't close connections, if H4 supports power management
                    if (bt_control_iphone_power_management_enabled()){
                        connection = NULL;
                    }
#endif
                    if (connection){
                        
                        // send disconnect
                        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

                        log_info("HCI_STATE_FALLING_ASLEEP, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
                        hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // remote closed connection
                        
                        // send disconnected event right away - causes higher layer connections to get closed, too.
                        hci_shutdown_connection(connection);
                        return;
                    }
                    
                    // disable page and inquiry scan
                    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
                    
                    log_info("HCI_STATE_HALTING, disabling inq cans\n");
                    hci_send_cmd(&hci_write_scan_enable, hci_stack.connectable << 1); // drop inquiry scan but keep page scan
                    
                    // continue in next sub state
                    hci_stack.substate++;
                    break;
                case 1:
                    // wait for command complete "hci_write_scan_enable" in event_handler();
                    break;
                case 2:
                    log_info("HCI_STATE_HALTING, calling sleep\n");
#if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
                    // don't actually go to sleep, if H4 supports power management
                    if (bt_control_iphone_power_management_enabled()){
                        // SLEEP MODE reached
                        hci_stack.state = HCI_STATE_SLEEPING; 
                        hci_emit_state();
                        break;
                    }
#endif
                    // switch mode
                    hci_power_control_sleep();  // changes hci_stack.state to SLEEP
                    hci_emit_state();
                    break;
                    
                default:
                    break;
            }
            break;
            
        default:
            break;
    }
}
Exemple #2
0
uint8_t test_ble(uint8_t ev, uint16_t lparam, void* rparam)
{
	switch(ev)
	{
		case EVENT_WINDOW_CREATED:
		onoff = 0;
		data = 0;
		ble_advertise(0);
		hci_send_cmd_packet((uint8_t*)HCI_VS_Set_LE_Test_Mode_Parameters, sizeof(HCI_VS_Set_LE_Test_Mode_Parameters));
		break;

		case EVENT_KEY_PRESSED:
		{
			if (lparam == KEY_ENTER)
			{
				onoff++;
				if (onoff == 9) onoff = 0;
			}

			if (lparam == KEY_UP && data < 37)
			{
				data++;
			}

			if (lparam == KEY_DOWN && data >= 0)
			{
				data--;
			}

			if (onoff == 0)
			{
				//switch off
				hci_send_cmd(&hci_le_test_end);
			}
			else
			{
				hci_send_cmd(&hci_le_transmitter_test, data, 0x25, onoff - 1);
			}
			
			window_invalid(NULL);
			break;
		}
		case EVENT_WINDOW_PAINT:
		{
		  tContext *pContext = (tContext*)rparam;
		  const char *text;
		  GrContextForegroundSet(pContext, ClrBlack);
		  GrRectFill(pContext, &client_clip);

		  GrContextForegroundSet(pContext, ClrWhite);
      GrContextFontSet(pContext, (tFont*)&g_sFontGothic18);
      switch(onoff)
      {
 		  	case 0:
 		  	text = "BLE TX is off";
 		  	break;

 		  	case 1:
 		  	text = "PRBS 9";
 		  	break;

 		  	case 2:
 		  	text = "FOFO";
 		  	break;

 		  	case 3:
 		  	text = "ZOZO";
 		  	break;

 		  	case 4:
 		  	text = "PRBS 15";
 		  	break;

 		  	case 5:
 		  	text = "All Ones";
 		  	break;
 		  
 		  	case 6:
 		  	text = "All Zeros";
 		  	break;

 		  	case 7:
 		  	text = "OFOF";
 		  	break;

 		  	case 8:
 		  	text = "OZOZ";
 		  	break;
			}
			GrStringDraw(pContext, text, -1, 32, 50, 0);

 		  if (data >= 0)
 		  {
	 		  char buf[32];
			  sprintf(buf, "Freqency: %dMhz", data < 40 ? 
			  									2402 + data * 2:
			  									2403 + (data - 40) * 2);
	 		  GrStringDraw(pContext, buf, -1, 5, 70, 0);
			}
			else
			{
	 		  GrStringDraw(pContext, "Hoping mode", -1, 5, 70, 0);
			}

 		  window_button(pContext, KEY_UP, "+");
 		  window_button(pContext, KEY_DOWN, "-");
	  	window_button(pContext, KEY_ENTER, "Switch");
 		  break;
 		}
 		case EVENT_WINDOW_CLOSING:
 		if (onoff)
		{
			hci_send_cmd(&hci_le_test_end);
 		}
 		break;

 		default:
 		return 0;
	}

	return 1;
}
Exemple #3
0
uint8_t test_bluetooth(uint8_t ev, uint16_t lparam, void* rparam)
{
	uint8_t buf[sizeof(HCI_VS_DRPb_Tester_Packet_TX_RX_Cmd)];
	switch(ev)
	{
		case EVENT_WINDOW_CREATED:
		onoff = 0;
		data = 0;
		break;

		case EVENT_KEY_PRESSED:
		{
			if (lparam == KEY_ENTER)
			{
				onoff++;
				if (onoff == 10) onoff = 0;
			}

			if (lparam == KEY_UP && data <= 78)
			{
				data++;
			}

			if (lparam == KEY_DOWN && data >= -1)
			{
				data--;
			}

			switch(onoff)
			{
				case 0:
				buf[0] = 0x88;
				buf[1] = 0xFD;
				buf[2] = 0;
				hci_send_cmd_packet(buf, 3);
				break;

				default:
				memcpy(buf, HCI_VS_DRPb_Tester_Packet_TX_RX_Cmd, sizeof(HCI_VS_DRPb_Tester_Packet_TX_RX_Cmd));
				if (data == -1)
				{
					buf[3] = 0x00; //hoping mode
				}
				else
				{
					buf[4] = data;
				}
				if (onoff != 0x09)
					buf[6] = onoff - 1;
				else
					buf[6] = onoff;

				switch(onoff)
				{
					case 1:
					buf[9] = 17;
					break;
					case 2:
					buf[9] = 27;
					break;
					case 3:
					buf[9] = 121;
					break;
					case 4:
					buf[9] = 183;
					break;
					case 5:
					buf[9] = 224;
					break;
					case 6:
					buf[9] = 255;
					break;
					case 7:
					buf[9] = 54;
					break;
					case 8:
					buf[9] = 255;
					break;
					case 9:
					buf[9] = 83;
					break;
				}

				hci_send_cmd_packet(buf, sizeof(HCI_VS_DRPb_Tester_Packet_TX_RX_Cmd));
				break;
			}

			window_invalid(NULL);
			break;
		}
		case EVENT_WINDOW_PAINT:
		{
		  tContext *pContext = (tContext*)rparam;
		  const char *text;
		  GrContextForegroundSet(pContext, ClrBlack);
		  GrRectFill(pContext, &client_clip);

		  GrContextForegroundSet(pContext, ClrWhite);
      GrContextFontSet(pContext, (tFont*)&g_sFontGothic18);
      switch(onoff)
      {
 		  	case 0:
 		  	text = "BT RX/TX is off";
 		  	break;

 		  	case 1:
 		  	text = "DM1";
 		  	break;

 		  	case 2:
 		  	text = "DH1";
 		  	break;

 		  	case 3:
 		  	text = "DM3";
 		  	break;

 		  	case 4:
 		  	text = "DH3";
 		  	break;

 		  	case 5:
 		  	text = "DM5";
 		  	break;
 		  
 		  	case 6:
 		  	text = "DH5";
 		  	break;

 		  	case 7:
 		  	text = "2-DH1";
 		  	break;

 		  	case 8:
 		  	text = "2-DH3";
 		  	break;

 		  	case 9:
 		  	text = "3-DH1";
 		  	break;
			}
			GrStringDraw(pContext, text, -1, 32, 50, 0);

 		  if (data >= 0)
 		  {
	 		  char buf[32];
			  sprintf(buf, "Freqency: %dMhz", data < 40 ? 
			  									2402 + data * 2:
			  									2403 + (data - 40) * 2);
	 		  GrStringDraw(pContext, buf, -1, 5, 70, 0);
			}
			else
			{
	 		  GrStringDraw(pContext, "Hoping mode", -1, 5, 70, 0);
			}
 		  window_button(pContext, KEY_UP, "+");
 		  window_button(pContext, KEY_DOWN, "-");
	  	window_button(pContext, KEY_ENTER, "Switch");
 		  break;
 		}
 		case EVENT_WINDOW_CLOSING:
 		if (onoff)
		{
			uint8_t buf[3];
			buf[0] = 0x88;
			buf[1] = 0xFD;
			buf[2] = 0;
			hci_send_cmd_packet(buf, 3);
 		}
 		break;

 		default:
 		return 0;
	}

	return 1;
}
Exemple #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:
            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:
            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;
}