Example #1
0
int	hci_command_completed(uint8_t *packet, uint16_t size)
{
  
  if (bt_accessor(0)->status == 2 && COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable))
    bt_send_cmd(&l2cap_create_channel, bt_accessor(0)->addr, 0x03);
  if (bt_accessor(0)->status == 1 && COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode))
    {
      printf("Received HCI_COMMAND_COMPLETED, now running next ...\n");
      
    }
  return (0);
}
Example #2
0
/*
 * \brief This function gets the bluetooth device address for a given device number.
 *
 * \param bdaddr         the buffer to store the bluetooth device address
 *
 * \return 0 if successful, -1 otherwise
 */
int bt_device_btstack_get_device_bdaddr(int ignored, bdaddr_t* bdaddr)
{
  int ret;

  ret = btstack_common_send_cmd(&btstack_hci_read_bd_addr);

  while(ret >= 0)
  {
    ret = btstack_common_recv_packet(&recv_data);
    if(ret > 0)
    {
      int type = READ_BT_16(recv_data.buffer, 0);
      unsigned char* packet = recv_data.buffer+sizeof(packet_header_t);
      if(type == HCI_EVENT_PACKET)
      {
        if (COMMAND_COMPLETE_EVENT(packet, btstack_hci_read_bd_addr))
        {
          int i;
          for(i=0; i<sizeof(bdaddr->b); ++i)
          {
            bdaddr->b[i] = packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1 + i];
          }
          break;
        }
      }
    }
  }

  return ret;
}
Example #3
0
// enable LE, setup ADV data
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    if (packet_type != HCI_EVENT_PACKET) return;
    bd_addr_t addr;
    uint8_t adv_data[] = { 02, 01, 05,   03, 02, 0xf0, 0xff }; 
    
    switch (packet[0]) {
        case BTSTACK_EVENT_STATE:
            // bt stack activated, get started - set local name
            if (packet[2] == HCI_STATE_WORKING) {
                printf("Working!\n");
                hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
            }
            break;
            
        case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED:
            if (packet[2]) {
                printf("CONNECTED");
            } else {
                printf("DISCONNECTED");
            }
            break;
            
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            // restart advertising
            hci_send_cmd(&hci_le_set_advertise_enable, 1);
            break;
            
        case HCI_EVENT_COMMAND_COMPLETE:
            if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                bt_flip_addr(addr, &packet[6]);
                printf("BD ADDR: %s\n", bd_addr_to_str(addr));
                break;
            }
            if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){
               hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data);
               break;
            }
            if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){
               hci_send_cmd(&hci_le_set_advertise_enable, 1);
               break;
            }
        default:
            break;
    }
	
}
Example #4
0
/*
 * \brief This function writes the device class for a given device number.
 *
 * \param devclass       the device class to write
 *
 * \return 0 if successful, -1 otherwise
 */
int bt_device_btstack_write_device_class(int ignored, uint32_t devclass)
{
  int ret = btstack_common_send_cmd(&btstack_hci_write_class_of_device, devclass);

  while(ret >= 0)
  {
    ret = btstack_common_recv_packet(&recv_data);
    if(ret > 0)
    {
      int type = READ_BT_16(recv_data.buffer, 0);
      unsigned char* packet = recv_data.buffer+sizeof(packet_header_t);
      if(type == HCI_EVENT_PACKET)
      {
        if ( COMMAND_COMPLETE_EVENT(packet, btstack_hci_write_class_of_device) ) {
          break;
        }
      }
    }
  }

  return ret;
}
Example #5
0
void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
   bd_addr_t event_addr;

   if (packet_type == HCI_EVENT_PACKET)
   {
      switch (packet[0])
      {
         case BTSTACK_EVENT_STATE:
         {
            RARCH_LOG("BTstack: HCI State %d\n", packet[2]);
         
            switch (packet[2])
            {                  
               case HCI_STATE_WORKING:
                  btpad_queue_reset();

                  btpad_queue_hci_read_bd_addr();
                  bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_CONTROL, 672);  // TODO: Where did I get 672 for mtu?
                  bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_INTERRUPT, 672);
                  btpad_queue_hci_inquiry(HCI_INQUIRY_LAP, 3, 1);
               
                  btpad_queue_run(1);
                  break;
                  
               case HCI_STATE_HALTING:
                  btpad_close_all_connections();
                  CFRunLoopStop(CFRunLoopGetCurrent());
                  break;                  
            }
         }
         break;

         case HCI_EVENT_COMMAND_STATUS:
         btpad_queue_run(packet[3]);
         break;

         case HCI_EVENT_COMMAND_COMPLETE:
         {
            btpad_queue_run(packet[2]);

            if (COMMAND_COMPLETE_EVENT(packet, (*hci_read_bd_addr_ptr)))
            {
               bt_flip_addr_ptr(event_addr, &packet[6]);
               if (!packet[5])
                  RARCH_LOG("BTpad: Local address is %s\n", bd_addr_to_str_ptr(event_addr));
               else
                  RARCH_LOG("BTpad: Failed to get local address (Status: %02X)\n", packet[5]);               
            }
         }
         break;

         case HCI_EVENT_INQUIRY_RESULT:
         {
            if (packet[2])
            {
               bt_flip_addr_ptr(event_addr, &packet[3]);

               struct apple_pad_connection* connection = (struct apple_pad_connection*)btpad_find_empty_connection();

               if (connection)
               {
                  RARCH_LOG("BTpad: Inquiry found device\n");
                  memset(connection, 0, sizeof(struct apple_pad_connection));

                  memcpy(connection->address, event_addr, sizeof(bd_addr_t));
                  connection->has_address = true;
                  connection->state = BTPAD_CONNECTING;

                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_CONTROL);
                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_INTERRUPT);
               }
            }
         }
         break;

         case HCI_EVENT_INQUIRY_COMPLETE:
         {
            // This must be turned off during gameplay as it causes a ton of lag
            inquiry_running = !inquiry_off;

            if (inquiry_running)
               btpad_queue_hci_inquiry(HCI_INQUIRY_LAP, 3, 1);
         }
         break;

         case L2CAP_EVENT_CHANNEL_OPENED:
         {
            bt_flip_addr_ptr(event_addr, &packet[3]);
            const uint16_t handle = READ_BT_16(packet, 9);
            const uint16_t psm = READ_BT_16(packet, 11);
            const uint16_t channel_id = READ_BT_16(packet, 13);

            struct apple_pad_connection* connection = (struct apple_pad_connection*)btpad_find_connection_for(handle, event_addr);

            if (!packet[2])
            {
               if (!connection)
               {
                  RARCH_LOG("BTpad: Got L2CAP 'Channel Opened' event for unrecognized device\n");
                  break;
               }

               RARCH_LOG("BTpad: L2CAP channel opened: (PSM: %02X)\n", psm);
               connection->handle = handle;
            
               if (psm == PSM_HID_CONTROL)
                  connection->channels[0] = channel_id;
               else if (psm == PSM_HID_INTERRUPT)
                  connection->channels[1] = channel_id;
               else
                  RARCH_LOG("BTpad: Got unknown L2CAP PSM, ignoring (PSM: %02X)\n", psm);

               if (connection->channels[0] && connection->channels[1])
               {
                  RARCH_LOG("BTpad: Got both L2CAP channels, requesting name\n");
                  btpad_queue_hci_remote_name_request(connection->address, 0, 0, 0);
               }
            }
            else
               RARCH_LOG("BTpad: Got failed L2CAP 'Channel Opened' event (PSM: %02X, Status: %02X)\n", psm, packet[2]);
         }
         break;

         case L2CAP_EVENT_INCOMING_CONNECTION:
         {
            bt_flip_addr_ptr(event_addr, &packet[2]);
            const uint16_t handle = READ_BT_16(packet, 8);
            const uint32_t psm = READ_BT_16(packet, 10);
            const uint32_t channel_id = READ_BT_16(packet, 12);
      
            struct apple_pad_connection* connection = (struct apple_pad_connection*)btpad_find_connection_for(handle, event_addr);

            if (!connection)
            {
               connection = btpad_find_empty_connection();
               if (connection)
               {
                  RARCH_LOG("BTpad: Got new incoming connection\n");

                  memset(connection, 0, sizeof(struct apple_pad_connection));

                  memcpy(connection->address, event_addr, sizeof(bd_addr_t));
                  connection->has_address = true;
                  connection->handle = handle;
                  connection->state = BTPAD_CONNECTING;
               }
               else break;
            }

            RARCH_LOG("BTpad: Incoming L2CAP connection (PSM: %02X)\n", psm);
            bt_send_cmd_ptr(l2cap_accept_connection_ptr, channel_id);
         }
         break;

         case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
         {
            bt_flip_addr_ptr(event_addr, &packet[3]);
            
            struct apple_pad_connection* connection = (struct apple_pad_connection*)btpad_find_connection_for(0, event_addr);

            if (!connection)
            {
               RARCH_LOG("BTpad: Got unexpected remote name, ignoring\n");
               break;
            }

            RARCH_LOG("BTpad: Got %.200s\n", (char*)&packet[9]);
            
            connection->slot = apple_joypad_connect((char*)packet + 9, connection);
            connection->state = BTPAD_CONNECTED;
         }
         break;

         case HCI_EVENT_PIN_CODE_REQUEST:
         RARCH_LOG("BTpad: Sending WiiMote PIN\n");

         bt_flip_addr_ptr(event_addr, &packet[2]);
         btpad_queue_hci_pin_code_request_reply(event_addr, &packet[2]);
         break;

         case HCI_EVENT_DISCONNECTION_COMPLETE:
         {
            const uint32_t handle = READ_BT_16(packet, 3);

            if (!packet[2])
            {
               struct apple_pad_connection* connection = (struct apple_pad_connection*)btpad_find_connection_for(handle, 0);

               if (connection)
               {
                  connection->handle = 0;
               
                  apple_joypad_disconnect(connection->slot);
                  btpad_close_connection(connection);
               }
            }
            else
               RARCH_LOG("BTpad: Got failed 'Disconnection Complete' event (Status: %02X)\n", packet[2]);
         }
         break;

         case L2CAP_EVENT_SERVICE_REGISTERED:
         {
            if (packet[2])
               RARCH_LOG("BTpad: Got failed 'Service Registered' event (PSM: %02X, Status: %02X)\n", READ_BT_16(packet, 3), packet[2]);
         }
         break;
      }
   }
   else if (packet_type == L2CAP_DATA_PACKET)
   {
      int i;
      for (i = 0; i < MAX_PLAYERS; i ++)
      {
         struct apple_pad_connection* connection = (struct apple_pad_connection*)&g_connections[i];
   
         if (connection->state == BTPAD_CONNECTED && (connection->channels[0] == channel || connection->channels[1] == channel))
            apple_joypad_packet(connection->slot, packet, size);
      }
   }
}
Example #6
0
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
	int i,j;
	switch (packet_type) {
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
						printLine("Inquiry");
						state = inquiry;
						hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
						break;
					}
					break;
					
				case HCI_EVENT_INQUIRY_RESULT:
					
					// ignore further results
					if (haveKeyboard) break;
					
					// ignore none keyboards
					if ((packet[12] & 0x40) != 0x40 || packet[13] != 0x25) break;

					// flip addr
					bt_flip_addr(keyboard, &packet[3]);
					
					// show
					printf("Keyboard:\n\r");

					// addr
					j=0;
					for (i=0;i<6;i++){
						lineBuffer[j++] = hexMap[ keyboard[i] >>    4 ];
						lineBuffer[j++] = hexMap[ keyboard[i] &  0x0f ];
						if (i<5) lineBuffer[j++] = ':';
					}
					lineBuffer[j++] = 0;
					printLine(lineBuffer);
					
					haveKeyboard = 1;
					hci_send_cmd(&hci_inquiry_cancel);
					state = w4_inquiry_cmd_complete;
					break;
					
				case HCI_EVENT_INQUIRY_COMPLETE:
					printLine("No keyboard found :(");
					break;
				
				case HCI_EVENT_LINK_KEY_REQUEST:
					// deny link key request
					hci_send_cmd(&hci_link_key_request_negative_reply, &keyboard);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					printLine( "Enter 0000");
					hci_send_cmd(&hci_pin_code_request_reply, &keyboard, 4, "0000");
					break;
					
				case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel) ) {
						// inq successfully cancelled
						// printLine("Connecting");
						l2cap_create_channel_internal(NULL, l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
						break;
					}
			}
	}
}
Example #7
0
static void btpad_packet_handler(uint8_t packet_type,
      uint16_t channel, uint8_t *packet, uint16_t size)
{
   unsigned i;
   bd_addr_t event_addr;
   struct btpad_queue_command* cmd = &commands[insert_position];

   switch (packet_type)
   {
      case L2CAP_DATA_PACKET:
         for (i = 0; i < MAX_USERS; i ++)
         {
            struct btstack_hid_adapter *connection = &g_connections[i];

            if (!connection || connection->state != BTPAD_CONNECTED)
               continue;

            if (     connection->channels[0] == channel 
                  || connection->channels[1] == channel)
               pad_connection_packet(&slots[connection->slot], connection->slot, packet, size);
         }
         break;
      case HCI_EVENT_PACKET:
         switch (packet[0])
         {
            case BTSTACK_EVENT_STATE:
               RARCH_LOG("[BTstack]: HCI State %d.\n", packet[2]);

               switch (packet[2])
               {                  
                  case HCI_STATE_WORKING:
                     btpad_queue_reset();
                     btpad_queue_hci_read_bd_addr(cmd);

                     /* TODO: Where did I get 672 for MTU? */

                     bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_CONTROL,   672);  
                     bt_send_cmd_ptr(l2cap_register_service_ptr, PSM_HID_INTERRUPT, 672);
                     btpad_queue_hci_inquiry(cmd, HCI_INQUIRY_LAP, 3, 1);

                     btpad_queue_run(1);
                     break;

                  case HCI_STATE_HALTING:
                     btpad_close_all_connections();
                     break;                  
               }
               break;

            case HCI_EVENT_COMMAND_STATUS:
               btpad_queue_run(packet[3]);
               break;

            case HCI_EVENT_COMMAND_COMPLETE:
               btpad_queue_run(packet[2]);

               if (COMMAND_COMPLETE_EVENT(packet, (*hci_read_bd_addr_ptr)))
               {
                  bt_flip_addr_ptr(event_addr, &packet[6]);
                  if (!packet[5])
                     RARCH_LOG("[BTpad]: Local address is %s.\n",
                           bd_addr_to_str_ptr(event_addr));
                  else
                     RARCH_LOG("[BTpad]: Failed to get local address (Status: %02X).\n",
                           packet[5]);
               }
               break;

            case HCI_EVENT_INQUIRY_RESULT:
               if (packet[2])
               {
                  struct btstack_hid_adapter* connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  connection = btpad_find_empty_connection();

                  if (!connection)
                     return;

                  RARCH_LOG("[BTpad]: Inquiry found device\n");
                  memset(connection, 0, sizeof(struct btstack_hid_adapter));

                  memcpy(connection->address, event_addr, sizeof(bd_addr_t));
                  connection->has_address = true;
                  connection->state       = BTPAD_CONNECTING;

                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_CONTROL);
                  bt_send_cmd_ptr(l2cap_create_channel_ptr, connection->address, PSM_HID_INTERRUPT);
               }
               break;

            case HCI_EVENT_INQUIRY_COMPLETE:
               /* This must be turned off during gameplay 
                * as it causes a ton of lag. */
               inquiry_running = !inquiry_off;

               if (inquiry_running)
                  btpad_queue_hci_inquiry(cmd, HCI_INQUIRY_LAP, 3, 1);
               break;

            case L2CAP_EVENT_CHANNEL_OPENED:
               {
                  uint16_t handle, psm, channel_id;
                  struct btstack_hid_adapter *connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  handle             = READ_BT_16(packet, 9);
                  psm                = READ_BT_16(packet, 11);
                  channel_id         = READ_BT_16(packet, 13);
                  connection         = btpad_find_connection_for(handle, event_addr);

                  if (!packet[2])
                  {
                     if (!connection)
                     {
                        RARCH_LOG("[BTpad]: Got L2CAP 'Channel Opened' event for unrecognized device.\n");
                        break;
                     }

                     RARCH_LOG("[BTpad]: L2CAP channel opened: (PSM: %02X)\n", psm);
                     connection->handle         = handle;

                     switch (psm)
                     {
                        case PSM_HID_CONTROL:
                           connection->channels[0] = channel_id;
                           break;
                        case PSM_HID_INTERRUPT:
                           connection->channels[1] = channel_id;
                           break;
                        default:
                           RARCH_LOG("[BTpad]: Got unknown L2CAP PSM, ignoring (PSM: %02X).\n", psm);
                           break;
                     }

                     if (connection->channels[0] && connection->channels[1])
                     {
                        RARCH_LOG("[BTpad]: Got both L2CAP channels, requesting name.\n");
                        btpad_queue_hci_remote_name_request(cmd, connection->address, 0, 0, 0);
                     }
                  }
                  else
                     RARCH_LOG("[BTpad]: Got failed L2CAP 'Channel Opened' event (PSM: %02X, Status: %02X).\n", psm, packet[2]);
               }
               break;

            case L2CAP_EVENT_INCOMING_CONNECTION:
               {
                  uint16_t handle, psm, channel_id;
                  struct btstack_hid_adapter* connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[2]);

                  handle     = READ_BT_16(packet, 8);
                  psm        = READ_BT_16(packet, 10);
                  channel_id = READ_BT_16(packet, 12);

                  connection = btpad_find_connection_for(handle, event_addr);

                  if (!connection)
                  {
                     connection = btpad_find_empty_connection();
                     if (!connection)
                        break;

                     RARCH_LOG("[BTpad]: Got new incoming connection\n");

                     memset(connection, 0,
                           sizeof(struct btstack_hid_adapter));

                     memcpy(connection->address, event_addr,
                           sizeof(bd_addr_t));
                     connection->has_address = true;
                     connection->handle = handle;
                     connection->state = BTPAD_CONNECTING;
                  }

                  RARCH_LOG("[BTpad]: Incoming L2CAP connection (PSM: %02X).\n",
                        psm);
                  bt_send_cmd_ptr(l2cap_accept_connection_ptr, channel_id);
               }
               break;

            case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
               {
                  struct btstack_hid_adapter *connection = NULL;

                  bt_flip_addr_ptr(event_addr, &packet[3]);

                  connection = btpad_find_connection_for(0, event_addr);

                  if (!connection)
                  {
                     RARCH_LOG("[BTpad]: Got unexpected remote name, ignoring.\n");
                     break;
                  }

                  RARCH_LOG("[BTpad]: Got %.200s.\n", (char*)&packet[9]);

                  connection->slot  = pad_connection_pad_init(&slots[connection->slot],
                        (char*)packet + 9, 0, 0, connection, &btpad_connection_send_control);
                  connection->state = BTPAD_CONNECTED;
               }
               break;

            case HCI_EVENT_PIN_CODE_REQUEST:
               RARCH_LOG("[BTpad]: Sending Wiimote PIN.\n");

               bt_flip_addr_ptr(event_addr, &packet[2]);
               btpad_queue_hci_pin_code_request_reply(cmd, event_addr, &packet[2]);
               break;

            case HCI_EVENT_DISCONNECTION_COMPLETE:
               {
                  const uint32_t handle = READ_BT_16(packet, 3);

                  if (!packet[2])
                  {
                     struct btstack_hid_adapter* connection = btpad_find_connection_for(handle, 0);

                     if (connection)
                     {
                        connection->handle = 0;

                        pad_connection_pad_deinit(&slots[connection->slot], connection->slot);
                        btpad_close_connection(connection);
                     }
                  }
                  else
                     RARCH_LOG("[BTpad]: Got failed 'Disconnection Complete' event (Status: %02X).\n", packet[2]);
               }
               break;

            case L2CAP_EVENT_SERVICE_REGISTERED:
               if (packet[2])
                  RARCH_LOG("[BTpad]: Got failed 'Service Registered' event (PSM: %02X, Status: %02X).\n",
                        READ_BT_16(packet, 3), packet[2]);
               break;
         }
         break;
   }
}
Example #8
0
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    bd_addr_t event_addr;
    uint8_t   rfcomm_channel_nr;
    uint16_t  mtu;
    int i;

	switch (packet_type) {
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
                        hci_send_cmd(&hci_write_local_name, "BTstack SPP Counter");
					}
					break;
				
				case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(event_addr, &packet[6]);
                        printf("BD-ADDR: %s\n", bd_addr_to_str(event_addr));
                        break;
                    }
                    break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
                    printf("Pin code request - using '0000'\n");
                    bt_flip_addr(event_addr, &packet[2]);
					hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
					break;

                case HCI_EVENT_USER_CONFIRMATION_REQUEST:
                    // inform about user confirmation request
                    printf("SSP User Confirmation Request with numeric value '%06u'\n", READ_BT_32(packet, 8));
                    printf("SSP User Confirmation Auto accept\n");
                    break;

                
                case RFCOMM_EVENT_INCOMING_CONNECTION:
					// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
					bt_flip_addr(event_addr, &packet[2]); 
					rfcomm_channel_nr = packet[8];
					rfcomm_channel_id = READ_BT_16(packet, 9);
					printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr));
                    rfcomm_accept_connection_internal(rfcomm_channel_id);
					break;
					
				case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
					// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
					if (packet[2]) {
						printf("RFCOMM channel open failed, status %u\n", packet[2]);
					} else {
						rfcomm_channel_id = READ_BT_16(packet, 12);
						mtu = READ_BT_16(packet, 14);
						printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu);
					}
					break;
                    
                case RFCOMM_EVENT_CHANNEL_CLOSED:
                    printf("RFCOMM channel closed\n");
                    rfcomm_channel_id = 0;
                    break;
                
                default:
                    break;
			}
            break;
        
        case RFCOMM_DATA_PACKET:
            printf("RCV: '");
            for (i=0;i<size;i++){
                putchar(packet[i]);
            }
            printf("'\n");
            break;

        default:
            break;
	}
}
Example #9
0
void l2cap_event_handler( uint8_t *packet, uint16_t size ){
    
    bd_addr_t address;
    hci_con_handle_t handle;
    l2cap_channel_t * channel;
    linked_item_t *it;
    int hci_con_used;
    
    switch(packet[0]){
            
        // handle connection complete events
        case HCI_EVENT_CONNECTION_COMPLETE:
            bt_flip_addr(address, &packet[5]);
            if (packet[2] == 0){
                handle = READ_BT_16(packet, 3);
                l2cap_handle_connection_success_for_addr(address, handle);
            } else {
                l2cap_handle_connection_failed_for_addr(address, packet[2]);
            }
            break;
            
        // handle successful create connection cancel command
        case HCI_EVENT_COMMAND_COMPLETE:
            if ( COMMAND_COMPLETE_EVENT(packet, hci_create_connection_cancel) ) {
                if (packet[5] == 0){
                    bt_flip_addr(address, &packet[6]);
                    // CONNECTION TERMINATED BY LOCAL HOST (0X16)
                    l2cap_handle_connection_failed_for_addr(address, 0x16);
                }
            }
            l2cap_run();    // try sending signaling packets first
            break;
            
        case HCI_EVENT_COMMAND_STATUS:
            l2cap_run();    // try sending signaling packets first
            break;
            
        // handle disconnection complete events
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            // send l2cap disconnect events for all channels on this handle
            handle = READ_BT_16(packet, 3);
            it = (linked_item_t *) &l2cap_channels;
            while (it->next){
                l2cap_channel_t * channel = (l2cap_channel_t *) it->next;
                if ( channel->handle == handle ){
                    // update prev item before free'ing next element - don't call l2cap_finalize_channel_close
                    it->next = it->next->next;
                    l2cap_emit_channel_closed(channel);
                    btstack_memory_l2cap_channel_free(channel);
                } else {
                    it = it->next;
                }
            }
            break;
            
        case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
            l2cap_run();    // try sending signaling packets first
            l2cap_hand_out_credits();
            break;
            
        // HCI Connection Timeouts
        case L2CAP_EVENT_TIMEOUT_CHECK:
            handle = READ_BT_16(packet, 2);
            if (hci_authentication_active_for_handle(handle)) break;
            hci_con_used = 0;
            for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
                channel = (l2cap_channel_t *) it;
                if (channel->handle == handle) {
                    hci_con_used = 1;
                }
            }
            if (hci_con_used) break;
            if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) break;
            hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection             
            break;

        case DAEMON_EVENT_HCI_PACKET_SENT:
            for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
                channel = (l2cap_channel_t *) it;
                if (channel->packet_handler) {
                    (* (channel->packet_handler))(HCI_EVENT_PACKET, channel->local_cid, packet, size);
                } 
            }
            if (attribute_protocol_packet_handler) {
                (*attribute_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size);
            }
            if (security_protocol_packet_handler) {
                (*security_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size);
            }
            break;
            
        default:
            break;
    }
    
    // pass on
    (*packet_handler)(NULL, HCI_EVENT_PACKET, 0, packet, size);
}
Example #10
0
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
	
	bd_addr_t event_addr;
	uint16_t handle;
	uint16_t psm;
	uint16_t local_cid;
	uint16_t remote_cid;
	char pin[20];
	int i;
	
	switch (packet_type) {
			
		case L2CAP_DATA_PACKET:
			// just dump data for now
			printf("source cid %x -- ", channel);
			hexdump( packet, size );
			break;
			
		case HCI_EVENT_PACKET:
			
			switch (packet[0]) {

				case BTSTACK_EVENT_POWERON_FAILED:
					printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
					exit(1);
					break;
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
						bt_send_cmd(&hci_write_authentication_enable, 0);
					}
					break;
					
				case L2CAP_EVENT_INCOMING_CONNECTION:
					// data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
					bt_flip_addr(event_addr, &packet[2]);
					handle     = READ_BT_16(packet, 8); 
					psm        = READ_BT_16(packet, 10); 
					local_cid  = READ_BT_16(packet, 12); 
					remote_cid = READ_BT_16(packet, 14); 
					printf("L2CAP_EVENT_INCOMING_CONNECTION ");
					print_bd_addr(event_addr);
					printf(", handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
						   handle, psm, local_cid, remote_cid);

					// accept
					bt_send_cmd(&l2cap_accept_connection, local_cid);
					break;
					
				case HCI_EVENT_LINK_KEY_REQUEST:
					// link key request
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					printf("Please enter PIN here: ");
					fgets(pin, 20, stdin);
					i = strlen(pin)-1;
					if( pin[i] == '\n') { 
						pin[i] = '\0';
					}
					printf("PIN = '%s'\n", pin);
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_pin_code_request_reply, &event_addr, strlen(pin), pin);
					break;
					
				case L2CAP_EVENT_CHANNEL_OPENED:
					// inform about new l2cap connection
					bt_flip_addr(event_addr, &packet[3]);
					psm = READ_BT_16(packet, 11); 
					local_cid = READ_BT_16(packet, 13); 
					handle = READ_BT_16(packet, 9);
					if (packet[2] == 0) {
						printf("Channel successfully opened: ");
						print_bd_addr(event_addr);
						printf(", handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
							   handle, psm, local_cid,  READ_BT_16(packet, 15));
						
						if (psm == PSM_HID_CONTROL){
							hid_control = local_cid;
						}
						if (psm == PSM_HID_INTERRUPT){
							hid_interrupt = local_cid;
						}
						if (hid_control && hid_interrupt){
							bt_send_cmd(&hci_switch_role_command, &event_addr, 0);
						}
					} else {
						printf("L2CAP connection to device ");
						print_bd_addr(event_addr);
						printf(" failed. status code %u\n", packet[2]);
						exit(1);
					}
					break;
				
				case HCI_EVENT_ROLE_CHANGE: {
					//HID Control: 0x06 bytes - SET_FEATURE_REPORT [ 53 F4 42 03 00 00 ]
					uint8_t set_feature_report[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00}; 
					bt_send_l2cap(hid_control, (uint8_t*) &set_feature_report, sizeof(set_feature_report));
					break;
				}
										
				case HCI_EVENT_DISCONNECTION_COMPLETE:
					// connection closed -> quit tes app
					printf("Basebank connection closed\n");
					
					// exit(0);
					break;
					
				case HCI_EVENT_COMMAND_COMPLETE:
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
						bt_send_cmd(&hci_write_class_of_device, 0x2540);
					}
				default:
					// other event
					break;
			}
			break;
			
		default:
			// other packet type
			break;
	}
}
Example #11
0
// enable LE, setup ADV data
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    bd_addr_t addr;
    uint8_t adv_data[] = { 02, 01, 05,   03, 02, 0xf0, 0xff }; 
    switch (packet_type) {
            
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
				
                case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
					   printf("Working!\n");
						hci_send_cmd(&hci_read_local_supported_features);
					}
					break;
                
                case DAEMON_EVENT_HCI_PACKET_SENT:
                    att_try_respond();
                    break;
                    
                case HCI_EVENT_LE_META:
                    switch (packet[2]) {
                        case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                            // reset connection MTU
                            att_connection.mtu = 23;
                            break;
                        default:
                            break;
                    }
                    break;

                case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED:
				    if (packet[2]) {
                        printf("Connected.\n");
                    } else {
				        printf("Not connected.\n");
                    }
                    break;
                    
                case HCI_EVENT_DISCONNECTION_COMPLETE:
                    att_response_handle =0;
                    att_response_size = 0;
                    
                    // restart advertising
                    hci_send_cmd(&hci_le_set_advertise_enable, 1);
                    break;
                    
				case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
    					bt_flip_addr(addr, &packet[6]);
					    printf("BD ADDR: %s\n", bd_addr_to_str(addr));
						break;
					}
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_local_supported_features)){
					     printf("Local supported features: %04X%04X\n", READ_BT_32(packet, 10), READ_BT_32(packet, 6));
                        hci_send_cmd(&hci_set_event_mask, 0xffffffff, 0x20001fff);
						break;
					}
					if (COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask)){
                        hci_send_cmd(&hci_write_le_host_supported, 1, 1);
						break;
					}
					if (COMMAND_COMPLETE_EVENT(packet, hci_write_le_host_supported)){
				        hci_send_cmd(&hci_le_set_event_mask, 0xffffffff, 0xffffffff);
                    	break;
					}
					if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_event_mask)){
				        hci_send_cmd(&hci_le_read_buffer_size);
                    	break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_buffer_size)){
					    printf("LE buffer size: %u, count %u\n", READ_BT_16(packet,6), packet[8]);
					   hci_send_cmd(&hci_le_read_supported_states);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_supported_states)){
					   hci_send_cmd(&hci_le_set_advertising_parameters,  0x0400, 0x0800, 0, 0, 0, &addr, 0x07, 0);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){
					   hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){
					   hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){
					   hci_send_cmd(&hci_le_set_advertise_enable, 1);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertise_enable)){
                        hci_discoverable_control(1);
                        break;
					}
                    
			}
	}
}
Example #12
0
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){

	hci_con_handle_t acl_in;
	hci_con_handle_t acl_out;
	
	switch (packet_type){

		case HCI_ACL_DATA_PACKET:
			acl_in = READ_ACL_CONNECTION_HANDLE(packet);
			acl_out = 0;
			if (acl_in == alice_handle) {
				printf("Alice: ");
				hexdump( packet, size );
				printf("\n\n");
				acl_out = bob_handle;
			}
			if (acl_in == bob_handle) {
				printf("Bob: ");
				hexdump( packet, size );
				printf("\n\n");
				acl_out = alice_handle;
			}
			if (acl_out){
				bt_store_16( packet, 0, (READ_BT_16(packet, 0) & 0xf000) | acl_out);
				bt_send_acl(packet, size);
			}
			break;
			
		case HCI_EVENT_PACKET:
			
			switch(packet[0]){
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set COD
					if (packet[2] == HCI_STATE_WORKING) {
						bt_send_cmd(&hci_write_class_of_device, 0x7A020C);  // used on iPhone
					}
					break;
					
				case HCI_EVENT_EXTENDED_INQUIRY_RESPONSE:
					// process EIR responses
					if (packet[17]) {
						bt_flip_addr(temp_addr, &packet[3]); 
						if (BD_ADDR_CMP(temp_addr, bob_addr)) {
							printf("2. Got BOB's EIR. ");
							int i, k;
							bzero(bob_EIR, EIR_LEN);
							for (i=17, k=0;i<EIR_LEN && packet[i]; i += packet[i] + 1, k += bob_EIR[k] + 1){
								if (packet[i+1] == 0x09) {
									// complete name id -- use own
									bob_EIR[k+0] = 1 + strlen(NAME);
									bob_EIR[k+1] = 0x09;
									memcpy(&bob_EIR[k+2], NAME, strlen(NAME));
								} else {
									// vendor specific
									if (packet[i+1] == 0x0ff ) {
										bob_got_EIR = 1;
									}
									memcpy(&bob_EIR[k], &packet[i], packet[i]+1);
								}
							}
							hexdump(&bob_EIR, k);
							printf("\n\n");
							bob_clock_offset = READ_BT_16(packet, 14);
							bob_page_scan_repetition_mode = packet[9];
						}
						
						// stop inquiry
						// bt_send_cmd(&hci_inquiry_cancel);
					}
					break;
					
				case HCI_EVENT_CONNECTION_REQUEST:
					// accept incoming connections
					bt_flip_addr(temp_addr, &packet[2]); 
					if (BD_ADDR_CMP(temp_addr, bob_addr) ){
						printf("-> Connection request from BOB. Denying\n");
						// bt_send_cmd(&hci_accept_connection_request, &temp_addr, 1);
					} else {
						printf("-> Connection request from Alice. Sending Accept\n");
						bt_send_cmd(&hci_accept_connection_request, &temp_addr, 1);
					}
					break;
					
				case HCI_EVENT_CONNECTION_COMPLETE:
					// handle connections
					bt_flip_addr(temp_addr, &packet[5]); 
					if (packet[2] == 0){
						hci_con_handle_t incoming_handle =  READ_BT_16(packet, 3);
						if (BD_ADDR_CMP(temp_addr, bob_addr)){
							bob_handle = incoming_handle;
							printf("7. Connected to BOB (handle %u). Relaying data!\n", bob_handle);
						} else {
							alice_handle = incoming_handle;
							printf("6. Alice connected (handle %u). Connecting to BOB.\n", alice_handle);
							bt_send_cmd(&hci_create_connection, &bob_addr, 0x18, bob_page_scan_repetition_mode, 0, 0x8000 || bob_clock_offset, 0);
						}
					} else {
						printf("Connection complete status %u for connection", packet[2]);
						print_bd_addr(temp_addr);
						printf("\n");
					}
					break;

				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					printf("Please enter PIN 1234 on remote device\n");
					break;

				case HCI_EVENT_DISCONNECTION_COMPLETE:
					// connection closed -> quit test app
					printf("Basebank connection closed, exit.\n");
					exit(0);
					break;

				case HCI_EVENT_COMMAND_COMPLETE:
					
					// use pairing yes/no
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_class_of_device) ) {
						bt_send_cmd(&hci_write_authentication_enable, 0);
					}
					
					// allow Extended Inquiry responses
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
						bt_send_cmd(&hci_write_inquiry_mode, 2);
					}
					
					// get all events, including EIRs
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
						bt_send_cmd(&hci_set_event_mask, 0xffffffff, 0x1fffffff);
					}
					
					// fine with us, too
					if ( COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask) ) {
						bt_send_cmd(&hci_write_simple_pairing_mode, 1);
					}
					
					// start inquiry
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_simple_pairing_mode) ) {
						// enable capure
						bt_send_cmd(&btstack_set_acl_capture_mode, 1);
						
						printf("1. Started inquiry.\n");
						bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, 15, 0);
					}
						// Connect to BOB
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_extended_inquiry_response) ) {
						printf("5. Waiting for Alice!...\n");
						// bt_send_cmd(&hci_write_scan_enable, 3); // 3 inq scan + page scan
						// bt_send_cmd(&hci_create_connection, &addr, 0x18, page_scan_repetition_mode, 0, 0x8000 || clock_offset, 0);
					}
					break;
					
				default:
					// Inquiry done, set EIR
					if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE || COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)){
						if (!inquiry_done){
							inquiry_done = 1;
							printf("3. Inquiry Complete\n");
							if (bob_got_EIR){
								printf("4. Set EIR to Bob's.\n");
								bt_send_cmd(&hci_write_extended_inquiry_response, 0, bob_EIR);	
							} else {
								// failed to get BOB's EIR
							}
						}
					}
				break;
			}

		default:
			break;
	}
	
	
}
Example #13
0
static void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
    bd_addr_t addr;
    int i;
    int numResponses;

    // printf("packet_handler: pt: 0x%02x, packet[0]: 0x%02x\n", packet_type, packet[0]);
    if (packet_type != HCI_EVENT_PACKET) return;

    uint8_t event = packet[0];

    switch(state){

        case INIT: 
            if (packet[2] == HCI_STATE_WORKING) {
                hci_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
                state = W4_INQUIRY_MODE_COMPLETE;
            }
            break;

        case W4_INQUIRY_MODE_COMPLETE:
            if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
                start_scan();
                state = ACTIVE;
            }
            break;
            
        case ACTIVE:
            switch(event){
                case HCI_EVENT_INQUIRY_RESULT:
                case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{
                    numResponses = packet[2];
                    int offset = 3;
                    for (i=0; i<numResponses && deviceCount < MAX_DEVICES;i++){
                        bt_flip_addr(addr, &packet[offset]);
                        offset += 6;
                        int index = getDeviceIndexForAddress(addr);
                        if (index >= 0) continue;   // already in our list
                        memcpy(devices[deviceCount].address, addr, 6);

                        devices[deviceCount].pageScanRepetitionMode = packet[offset];
                        offset += 1;

                        if (event == HCI_EVENT_INQUIRY_RESULT){
                            offset += 2; // Reserved + Reserved
                            devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
                            offset += 3;
                            devices[deviceCount].clockOffset =   READ_BT_16(packet, offset) & 0x7fff;
                            offset += 2;
                            devices[deviceCount].rssi  = 0;
                        } else {
                            offset += 1; // Reserved
                            devices[deviceCount].classOfDevice = READ_BT_24(packet, offset);
                            offset += 3;
                            devices[deviceCount].clockOffset =   READ_BT_16(packet, offset) & 0x7fff;
                            offset += 2;
                            devices[deviceCount].rssi  = packet[offset];
                            offset += 1;
                        }
                        devices[deviceCount].state = BONDING_REQUEST;
                        printf("Device found: %s with COD: 0x%06x, pageScan %d, clock offset 0x%04x, rssi 0x%02x\n", bd_addr_to_str(addr),
                                devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
                                devices[deviceCount].clockOffset, devices[deviceCount].rssi);
                        deviceCount++;
                    }

                    break;
                }   
                case HCI_EVENT_INQUIRY_COMPLETE:
                    continue_bonding();
                    break;

                case GAP_DEDICATED_BONDING_COMPLETED:
                    // data: event(8), len(8), status (8), bd_addr(48)
                    printf("GAP Dedicated Bonding Complete, status %u\n", packet[2]);
                    bt_flip_addr(addr, &packet[3]);
                    int index = getDeviceIndexForAddress(addr);
                    if (index >= 0) {
                        devices[index].state = BONDING_COMPLETED;
                    }
                    continue_bonding();
                    break;

                default:
                    break;
            }
            break;
            
        default:
            break;
    }
}
Example #14
0
static void packet_handler_old (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    bd_addr_t event_addr;
    uint8_t   rfcomm_channel_nr;
    uint16_t  mtu;

    switch (packet_type) {
        case HCI_EVENT_PACKET:

            switch (packet[0]) {
                case BTSTACK_EVENT_STATE:
                    // bt stack activated, get started - set local name
                    if (packet[2] == HCI_STATE_WORKING) {
                            uint8_t des_serviceSearchPattern[5] = {0x35, 0x03, 0x19, 0x10, 0x02};
                            hci_send_cmd(&sdp_client_query_rfcomm_services, host_addr, des_serviceSearchPattern);
                    }
                    break;

                case SDP_QUERY_COMPLETE:
                        // data: event(8), len(8), status(8)
                        printf("SDP_QUERY_COMPLETE, status %u\n", packet[2]);
                        break;

                case SDP_QUERY_RFCOMM_SERVICE:
                        // data: event(8), len(8), rfcomm channel(8), name(var)
                        printf("SDP_QUERY_RFCOMM_SERVICE, rfcomm channel %u, name '%s'\n", packet[2], (const char*)&packet[3]);
                        break;

                case HCI_EVENT_LINK_KEY_REQUEST:
                    printf("HCI_EVENT_LINK_KEY_REQUEST \n");
                    // link key request
                    bt_flip_addr(event_addr, &packet[2]);
                    hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
                    break;

                case HCI_EVENT_PIN_CODE_REQUEST:
                    // inform about pin code request
                    printf("Please enter PIN 0000 on remote device\n");
                    bt_flip_addr(event_addr, &packet[2]);
                    hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
                    break;

                case HCI_EVENT_COMMAND_COMPLETE:
                    if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(event_addr, &packet[6]);
                        printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
                        break;
                    }
//                    if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
//                        hci_send_cmd(&hci_write_class_of_device, 0x38010c);
//                        hci_discoverable_control(1);
//                        break;
//                    }
                    break;

                case RFCOMM_EVENT_INCOMING_CONNECTION:
                    // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
                    bt_flip_addr(event_addr, &packet[2]);
                    rfcomm_channel_nr = packet[8];
                    rfcomm_channel_id = READ_BT_16(packet, 9);
                    //printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
                    if(memcmp(event_addr, host_addr, sizeof(bd_addr_t)) == 0 || true /* TODO: Always accept */) {
                        syslog(LOG_DEBUG, "[bluetooth] Accept RFCOMM connection from host.");
                        rfcomm_accept_connection_internal(rfcomm_channel_id);
                    } else {
                        syslog(LOG_WARNING, "[bluetooth] Decline RFCOMM connection from unknown device %s.", bd_addr_to_str(event_addr));
                        rfcomm_decline_connection_internal(rfcomm_channel_id);
                    }
                    break;

                case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
                    // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
                    if (packet[2]) {
                        printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
                    } else {
                        rfcomm_channel_id = READ_BT_16(packet, 12);
                        mtu = READ_BT_16(packet, 14);
                        printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
                    }
                    break;

                case RFCOMM_EVENT_CHANNEL_CLOSED:
                    rfcomm_channel_id = 0;
                    break;

                default:
                    syslog(LOG_INFO, "Unresolved event packet %d", packet[0]);
                    break;
            }
            break;

        default:
            break;
    }
}
Example #15
0
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    bd_addr_t event_addr;
    uint8_t   rfcomm_channel_nr;
    uint16_t  mtu;
    
	switch (packet_type) {
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
                        hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo");
					}
					break;
				
				case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(event_addr, &packet[6]);
                        printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
                        break;
                    }
					if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
                        hci_discoverable_control(1);
                        break;
                    }
                    break;

				case HCI_EVENT_LINK_KEY_REQUEST:
					// deny link key request
                    printf("Link key request\n\r");
                    bt_flip_addr(event_addr, &packet[2]);
					hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
                    printf("Pin code request - using '0000'\n\r");
                    bt_flip_addr(event_addr, &packet[2]);
					hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
					break;
                
                case RFCOMM_EVENT_INCOMING_CONNECTION:
					// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
					bt_flip_addr(event_addr, &packet[2]); 
					rfcomm_channel_nr = packet[8];
					rfcomm_channel_id = READ_BT_16(packet, 9);
					printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
                    rfcomm_accept_connection_internal(rfcomm_channel_id);
					break;
					
				case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
					// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
					if (packet[2]) {
						printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
					} else {
						rfcomm_channel_id = READ_BT_16(packet, 12);
						mtu = READ_BT_16(packet, 14);
						printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
					}
					break;
                    
                case RFCOMM_EVENT_CHANNEL_CLOSED:
                    rfcomm_channel_id = 0;
                    break;
                
                default:
                    break;
			}
            break;
            
        case RFCOMM_DATA_PACKET:
            // hack: truncate data (we know that the packet is at least on byte bigger
            packet[size] = 0;
            puts( (const char *) packet);
            rfcomm_send_credit = 1;
        default:
            break;
	}
}
Example #16
0
// enable LE, setup ADV data
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    uint8_t adv_data[] = { 02, 01, 05,   03, 02, 0xf0, 0xff }; 

    sm_run();

    switch (packet_type) {
            
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
				
                case BTSTACK_EVENT_STATE:
					// bt stack activated, get started
					if (packet[2] == HCI_STATE_WORKING) {
                        printf("Working!\n");
                        hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
					}
					break;
                
                case DAEMON_EVENT_HCI_PACKET_SENT:
                    att_try_respond();
                    break;
                    
                case HCI_EVENT_LE_META:
                    switch (packet[2]) {
                        case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                            sm_response_handle = READ_BT_16(packet, 4);
                            sm_m_addr_type = packet[7];
                            BD_ADDR_COPY(sm_m_address, &packet[8]);
                            // TODO use non-null TK if appropriate
                            sm_reset_tk();
                            // TODO support private addresses
                            sm_s_addr_type = 0;
                            BD_ADDR_COPY(sm_s_address, hci_local_bd_addr());

                            // request security
                            sm_send_security_request = 1;

                            // reset connection MTU
                            att_connection.mtu = 23;
                            break;

                        case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST:
                            sm_s1(sm_tk, sm_m_random, sm_m_random, sm_s_ltk);
                            hci_send_cmd(&hci_le_long_term_key_request_reply, READ_BT_16(packet, 3), sm_s_ltk);
                            break;

                        default:
                            break;
                    }
                    break;

                case HCI_EVENT_ENCRYPTION_CHANGE:                
                    // distribute keys as requested by initiator
                    // TODO: handle initiator case here
                    if (sm_key_distribution_set & SM_KEYDIST_ENC_KEY)
                        sm_send_encryption_information = 1;
                    sm_send_master_identification = 1;
                    if (sm_key_distribution_set & SM_KEYDIST_ID_KEY)
                        sm_send_identity_information = 1;
                    sm_send_identity_address_information = 1;
                    if (sm_key_distribution_set & SM_KEYDIST_SIGN)
                        sm_send_signing_identification = 1;                
                    break;

                case HCI_EVENT_DISCONNECTION_COMPLETE:
                    att_response_handle = 0;
                    att_response_size = 0;
                    
                    // restart advertising
                    hci_send_cmd(&hci_le_set_advertise_enable, 1);
                    break;
                    
				case HCI_EVENT_COMMAND_COMPLETE:
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){
                        // only needed for BLE Peripheral
                        hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data);
                        break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){
                        // only needed for BLE Peripheral
					   hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data);
					   break;
					}
				    if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){
                        // only needed for BLE Peripheral
					   hci_send_cmd(&hci_le_set_advertise_enable, 1);
					   break;
					}
                    if (COMMAND_COMPLETE_EVENT(packet, hci_le_rand)){
                        switch (sm_state_responding){
                            case SM_STATE_C1_W4_RANDOM_A:
                                memcpy(&sm_s_random[0], &packet[6], 8);
                                hci_send_cmd(&hci_le_rand);
                                sm_state_responding++;
                                break;
                            case SM_STATE_C1_W4_RANDOM_B:
                                memcpy(&sm_s_random[8], &packet[6], 8);

                                // calculate s_confirm
                                sm_c1(sm_tk, sm_s_random, sm_preq, sm_pres, sm_m_addr_type, sm_s_addr_type, sm_m_address, sm_s_address, sm_s_confirm);
                                // send data
                                sm_state_responding = SM_STATE_C1_SEND;
                                break;
                            default:
                                break;
                        }
                        break;
                    }
			}
	}

    sm_run();
}
Example #17
0
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
//static void packet_handler (uint8_t packet_type, uint8_t *packet, uint16_t size){
	bd_addr_t addr;
	int i;
	int numResponses;
	
	// printf("packet_handler: pt: 0x%02x, packet[0]: 0x%02x\n", packet_type, packet[0]);
	if (packet_type != HCI_EVENT_PACKET) return;

	uint8_t event = packet[0];

	switch(state){

		case INIT: 
			if (packet[2] == HCI_STATE_WORKING) {
				bt_send_cmd(&hci_write_inquiry_mode, 0x01); // with RSSI
				state = W4_INQUIRY_MODE_COMPLETE;
			}
			break;

		case W4_INQUIRY_MODE_COMPLETE:
			switch(event){
				case HCI_EVENT_COMMAND_COMPLETE:
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
						start_scan();
						state = ACTIVE;
					}
					break;
				case HCI_EVENT_COMMAND_STATUS:
					if ( COMMAND_STATUS_EVENT(packet, hci_write_inquiry_mode) ) {
						printf("Ignoring error (0x%x) from hci_write_inquiry_mode.\n", packet[2]);
						start_scan();
						state = ACTIVE;
					}
					break;
				default:
					break;
			}

			break;
			
		case ACTIVE:
			switch(event){
				case HCI_EVENT_INQUIRY_RESULT:
				case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
					numResponses = packet[2];
					for (i=0; i<numResponses && deviceCount < MAX_DEVICES;i++){
						bt_flip_addr(addr, &packet[3+i*6]);
						int index = getDeviceIndexForAddress(addr);
						if (index >= 0) continue;
						memcpy(devices[deviceCount].address, addr, 6);
						devices[deviceCount].pageScanRepetitionMode =   packet [3 + numResponses*(6)         + i*1];
						if (event == HCI_EVENT_INQUIRY_RESULT){
							devices[deviceCount].classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1+1)   + i*3);
							devices[deviceCount].clockOffset =   READ_BT_16(packet, 3 + numResponses*(6+1+1+1+3) + i*2) & 0x7fff;
							devices[deviceCount].rssi  = 0;
						} else {
							devices[deviceCount].classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1)     + i*3);
							devices[deviceCount].clockOffset =   READ_BT_16(packet, 3 + numResponses*(6+1+1+3)   + i*2) & 0x7fff;
							devices[deviceCount].rssi  =                    packet [3 + numResponses*(6+1+1+3+2) + i*1];
						}
						devices[deviceCount].state = REMOTE_NAME_REQUEST;
						printf("Device found: %s with COD: 0x%06x, pageScan %u, clock offset 0x%04x, rssi 0x%02x\n", bd_addr_to_str(addr),
				                devices[deviceCount].classOfDevice, devices[deviceCount].pageScanRepetitionMode,
				                devices[deviceCount].clockOffset, devices[deviceCount].rssi);
						deviceCount++;
					}
					break;
					
				case HCI_EVENT_INQUIRY_COMPLETE:
					for (i=0;i<deviceCount;i++) {
						// retry remote name request
						if (devices[i].state == REMOTE_NAME_INQUIRED)
							devices[i].state = REMOTE_NAME_REQUEST;
					}
					if (has_more_remote_name_requests()){
						do_next_remote_name_request();
						break;
					} 
					start_scan();
					break;

				case BTSTACK_EVENT_REMOTE_NAME_CACHED:
					bt_flip_addr(addr, &packet[3]);
					printf("Cached remote name for %s: '%s'\n", bd_addr_to_str(addr), &packet[9]);
					break;

				case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
					bt_flip_addr(addr, &packet[3]);
					int index = getDeviceIndexForAddress(addr);
					if (index >= 0) {
						if (packet[2] == 0) {
							printf("Name: '%s'\n", &packet[9]);
							devices[index].state = REMOTE_NAME_FETCHED;
						} else {
							printf("Failed to get name: page timeout\n");
						}
					}
					if (has_more_remote_name_requests()){
						do_next_remote_name_request();
						break;
					} 
					start_scan();
					break;

				default:
					break;
			}
			break;
			
		default:
			break;
	}
}
Example #18
0
// Bluetooth logic
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    bd_addr_t event_addr;
    uint8_t   rfcomm_channel_nr;
    uint16_t  mtu;
    
    uint8_t event_code;
	// uint8_t channel;
	uint8_t message_id;

	switch (packet_type) {
		case HCI_EVENT_PACKET:
			switch (packet[0]) {
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - set local name
					if (packet[2] == HCI_STATE_WORKING) {
                        hci_send_cmd(&hci_write_local_name, "BlueMSP-Demo");
					}
					break;
				
				case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(event_addr, &packet[6]);
                        printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
                        break;
                    }
					if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
						// start ANT init
						ant_send_cmd(&ant_reset); 
						break;
                    }
                    break;

				case HCI_EVENT_LINK_KEY_REQUEST:
					// deny link key request
                    printf("Link key request\n\r");
                    bt_flip_addr(event_addr, &packet[2]);
					hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
                    printf("Pin code request - using '0000'\n\r");
                    bt_flip_addr(event_addr, &packet[2]);
					hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
					break;
                
                case RFCOMM_EVENT_INCOMING_CONNECTION:
					// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
					bt_flip_addr(event_addr, &packet[2]); 
					rfcomm_channel_nr = packet[8];
					rfcomm_channel_id = READ_BT_16(packet, 9);
					printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
                    rfcomm_accept_connection_internal(rfcomm_channel_id);
					break;
					
				case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
					// data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
					if (packet[2]) {
						printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
					} else {
						rfcomm_channel_id = READ_BT_16(packet, 12);
						mtu = READ_BT_16(packet, 14);
						printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
					}
					break;
                    
                case RFCOMM_EVENT_CHANNEL_CLOSED:
                    rfcomm_channel_id = 0;
                    break;
                

                case 0xff:	// vendor specific -> ANT
                	
                	// vendor specific ant message
                	if (packet[2] != 0x00) break;
                	if (packet[3] != 0x05) break;

					event_code = packet[7];

                	printf("ANT Event: ");
                	printf_hexdump(packet, size);

					switch(event_code){
						
						case MESG_STARTUP_MESG_ID:
							// 2. assign channel
							ant_send_cmd(&ant_assign_channel, 0, 0x00, 0);
							break;

						case MESG_RESPONSE_EVENT_ID:
							// channel    = packet[8];
							message_id = packet[9];
							switch (message_id){
								case MESG_ASSIGN_CHANNEL_ID:
									// 3. set channel ID
									ant_send_cmd(&ant_channel_id, 0, 33, 1, 1);
									break; 
								case MESG_CHANNEL_ID_ID:
									// 4. open channel
									ant_send_cmd(&ant_open_channel, 0);
							}
							break;

						default:
							break;
					}
                	break;

				default:
					break;
			} 
            break;
                        
        default:
            break;
	}
}
Example #19
0
File: commons.c Project: ap4y/iSAP
void process_hci_event(uint8_t* packet)
{
	uint16_t local_cid;
	//char pin[20];
	//int i;
	//CFDataRef cfData;

	switch (packet[0]) {
			
		case BTSTACK_EVENT_POWERON_FAILED:
			printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
			changeState(iSAP_state_error);
			break;
			
		case BTSTACK_EVENT_STATE:
			if (packet[2] == HCI_STATE_WORKING) {
				bt_send_cmd(&hci_write_local_name, device_name);
				changeState(iSAP_state_ready);
			}
			break;
			
		case L2CAP_EVENT_INCOMING_CONNECTION:					
			local_cid  = READ_BT_16(packet, 12); 
			
			// accept
			bt_send_cmd(&l2cap_accept_connection, local_cid);
			changeState(iSAP_state_starting_l2cap);
			break;
			
		case HCI_EVENT_LINK_KEY_NOTIFICATION:
			//implement link key saving
			
			break;
			
		case HCI_EVENT_LINK_KEY_REQUEST:
			// link key request
			bt_flip_addr(event_addr, &packet[2]); 
			
			//unsigned char lk[16] = {0x88, 0xf2, 0x5a, 0x92, 0x5a, 0x9e, 0x00, 0x4b, 0x05, 0xf9, 0xf7, 0x02, 0xd9, 0x1a, 0x43, 0xbb};
			//bt_send_cmd(&hci_link_key_request_reply, &event_addr, lk);
			bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);

			break;
			
		case HCI_EVENT_PIN_CODE_REQUEST:
			// inform about pin code request
			sendMessageToGUI(CFMSG_setPIN, 0, NULL, NULL, CFSTR(_messagePortName_client));
				
			//while (!allowPin) {
			//	sleep(1);
			//}
			//printf("Please enter PIN here: ");
			//fgets(pin, 20, stdin);
			//i = strlen(pin)-1;
			//if( pin[i] == '\n') { 
			//	pin[i] = '\0';
			//}
			//printf("PIN = '%s'\n", pin);
			bt_flip_addr(event_addr, &packet[2]); 
			//bt_send_cmd(&hci_pin_code_request_reply, &event_addr, strlen(pin), pin);
			break;
						
		case L2CAP_EVENT_CHANNEL_OPENED:
			// inform about new l2cap connection			
			source_cid = READ_BT_16(packet, 13);
			con_handle = READ_BT_16(packet, 9);

			break;
			
		case HCI_EVENT_CONNECTION_REQUEST: {
			// accept incoming connections
			bt_flip_addr(event_addr, &packet[2]); 
			bt_send_cmd(&hci_accept_connection_request, &event_addr, 1);
			changeState(iSAP_state_starting_hci);
			
			break;
		}
		case HCI_EVENT_CONNECTION_COMPLETE:
			// handle connections

			break;
			
		case HCI_EVENT_DISCONNECTION_COMPLETE:
			printf("Basebank connection closed\n");
			changeState(iSAP_state_ready);
			break;
			
		case HCI_EVENT_COMMAND_COMPLETE:
			// use pairing yes/no
			if ( COMMAND_COMPLETE_EVENT(packet, hci_write_local_name) ) {
				bt_send_cmd(&hci_write_authentication_enable, 0);
			}
			else if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
				bt_send_cmd(&hci_write_class_of_device, 0x5a020C);
			}
						
			break;
		default:
			// other event
			if (DEBUG) {							
				printf("Unknown packet %02x\n", packet[0]);
			}
			break;
	}
}
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
	
	bd_addr_t event_addr;
	uint16_t handle;
	uint16_t psm;
	uint16_t local_cid;
	char pin[20];
	int i;
	
	switch (packet_type) {
			
		case L2CAP_DATA_PACKET:
			// measure data rate
			break;
			
		case HCI_EVENT_PACKET:
			
			switch (packet[0]) {

				case BTSTACK_EVENT_POWERON_FAILED:
					printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
					exit(1);
					break;
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started
	                if (packet[2] == HCI_STATE_WORKING) {
	                   if (serverMode) {
						   printf("Waiting for incoming L2CAP connection on PSM %04x...\n", PSM_TEST);
						   timer.process = timer_handler;
						   run_loop_set_timer(&timer, 3000);
						   // run_loop_add_timer(&timer);
				        } else {
				        	bt_send_cmd(&hci_write_authentication_enable, 0);
				        }
					}
					break;
                
                case HCI_EVENT_COMMAND_COMPLETE:
					// use pairing yes/no
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
    				    bt_send_cmd(&hci_write_class_of_device, 0x38010c);
					}
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_class_of_device) ) {
    				    bt_send_cmd(&l2cap_create_channel_mtu, addr, PSM_TEST, PACKET_SIZE);
					}
					break;

				case L2CAP_EVENT_INCOMING_CONNECTION:
					// data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16)
					bt_flip_addr(event_addr, &packet[2]);
					handle     = READ_BT_16(packet, 8); 
					psm        = READ_BT_16(packet, 10); 
					local_cid  = READ_BT_16(packet, 12); 
					// remote_cid = READ_BT_16(packet, 14); 
					printf("L2CAP_EVENT_INCOMING_CONNECTION %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x\n", bd_addr_to_str(event_addr), handle, psm, local_cid);
					// accept
					bt_send_cmd(&l2cap_accept_connection, local_cid);
					break;
					
				case HCI_EVENT_LINK_KEY_REQUEST:
					// link key request
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					printf("Please enter PIN here: ");
					fgets(pin, 20, stdin);
					i = strlen(pin);
					if( pin[i-1] == '\n' || pin[i-1] == '\r') { 
						pin[i-1] = '\0';
						i--;
					}
					printf("PIN (%u)= '%s'\n", i, pin);
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_pin_code_request_reply, &event_addr, i, pin);
					break;
					
				case L2CAP_EVENT_CHANNEL_OPENED:
					// inform about new l2cap connection
					bt_flip_addr(event_addr, &packet[3]);
					psm = READ_BT_16(packet, 11); 
					local_cid = READ_BT_16(packet, 13); 
					handle = READ_BT_16(packet, 9);
					if (packet[2] == 0) {
						printf("Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
							   bd_addr_to_str(event_addr), handle, psm, local_cid,  READ_BT_16(packet, 15));
					} else {
						printf("L2CAP connection to device %s failed. status code %u\n", bd_addr_to_str(event_addr), packet[2]);
					}
					break;
				
				case HCI_EVENT_DISCONNECTION_COMPLETE:
					printf("Basebank connection closed\n");
					break;
					
				case L2CAP_EVENT_CREDITS:
					if (!serverMode) {
						// can send! (assuming single credits are handet out)
						update_packet();
						local_cid = READ_BT_16(packet, 2);
						bt_send_l2cap( local_cid, packet, PACKET_SIZE); 
					}
				    break;
				    	
				default:
					// other event
					break;
			}
			break;
			
		default:
			// other packet type
			break;
	}
}
Example #21
0
/*************** PANU client routines *********************/
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
    uint8_t   event;
    bd_addr_t event_addr;
    bd_addr_t src_addr;
    bd_addr_t dst_addr;
    uint16_t  uuid_source;
    uint16_t  uuid_dest;
    uint16_t  mtu;    
    uint16_t  network_type;
    uint8_t   protocol_type;
    uint8_t   icmp_type;
    int       ihl;
    int       payload_offset;

    switch (packet_type) {
		case HCI_EVENT_PACKET:
            event = packet[0];
            switch (event) {            
                case BTSTACK_EVENT_STATE:
                    /* BT Stack activated, get started */ 
                    if (packet[2] == HCI_STATE_WORKING) {
                        printf("BNEP Test ready\n");
                        show_usage();
                    }
                    break;

                case HCI_EVENT_COMMAND_COMPLETE:
					if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
                        bt_flip_addr(local_addr, &packet[6]);
                        printf("BD-ADDR: %s\n", bd_addr_to_str(local_addr));
                        break;
                    }
                    break;

                case HCI_EVENT_USER_CONFIRMATION_REQUEST:
                    // inform about user confirmation request
                    printf("SSP User Confirmation Request with numeric value '%06u'\n", READ_BT_32(packet, 8));
                    printf("SSP User Confirmation Auto accept\n");
                    break;
					
				case BNEP_EVENT_OPEN_CHANNEL_COMPLETE:
                    if (packet[2]) {
                        printf("BNEP channel open failed, status %02x\n", packet[2]);
                    } else {
                        // data: event(8), len(8), status (8), bnep source uuid (16), bnep destination uuid (16), remote_address (48)
                        uuid_source = READ_BT_16(packet, 3);
                        uuid_dest   = READ_BT_16(packet, 5);
                        mtu         = READ_BT_16(packet, 7);
                        bnep_cid    = channel;
                        //bt_flip_addr(event_addr, &packet[9]); 
                        memcpy(&event_addr, &packet[9], sizeof(bd_addr_t));
                        printf("BNEP connection open succeeded to %s source UUID 0x%04x dest UUID: 0x%04x, max frame size %u\n", bd_addr_to_str(event_addr), uuid_source, uuid_dest, mtu);
                    }
					break;
                    
                case BNEP_EVENT_CHANNEL_TIMEOUT:
                    printf("BNEP channel timeout! Channel will be closed\n");
                    break;
                    
                case BNEP_EVENT_CHANNEL_CLOSED:
                    printf("BNEP channel closed\n");
                    break;

                case BNEP_EVENT_READY_TO_SEND:
                    /* Check for parked network packets and send it out now */
                    if (network_buffer_len > 0) {
                        bnep_send(bnep_cid, network_buffer, network_buffer_len);
                        network_buffer_len = 0;
                    }
                    break;
                    
                default:
                    break;
            }
            break;
        case BNEP_DATA_PACKET:
            // show received packet on console

            // TODO: fix BNEP to return BD ADDR in little endian, to use these lines
            // bt_flip_addr(dst_addr, &packet[0]);
            // bt_flip_addr(src_addr, &packet[6]);
            // instead of these
            memcpy(dst_addr, &packet[0], 6);
            memcpy(src_addr, &packet[6], 6);
            // END TOOD

            network_type = READ_NET_16(packet, 12);
            printf("BNEP packet received\n");
            printf("Dst Addr: %s\n", bd_addr_to_str(dst_addr));
            printf("Src Addr: %s\n", bd_addr_to_str(src_addr));
            printf("Net Type: %04x\n", network_type);
            // ignore the next 60 bytes
            // hexdumpf(&packet[74], size - 74);
            switch (network_type){
                case NETWORK_TYPE_IPv4:
                    ihl = packet[14] & 0x0f;
                    payload_offset = 14 + (ihl << 2);
                    // protocol
                    protocol_type = packet[14 + 9]; // offset 9 into IPv4
                    switch (protocol_type){
                        case 0x01:  // ICMP
                            icmp_type = packet[payload_offset];
                            hexdumpf(&packet[payload_offset], size - payload_offset);
                            printf("ICMP packet of type %x\n", icmp_type);
                            switch (icmp_type){
                                case ICMP_V4_TYPE_PING_REQUEST:
                                    printf("IPv4 Ping Request received, sending pong\n");
                                    send_ping_response_ipv4();
                                    break;
                                break;
                            }
                        case 0x11:  // UDP
                            printf("UDP IPv4 packet\n");                        
                            hexdumpf(&packet[payload_offset], size - payload_offset);
                            break;
                        default:
                            printf("Unknown IPv4 protocol type %x", protocol_type);
                            break;
                    }
                    break;
                case NETWORK_TYPE_IPv6:
                    protocol_type = packet[6];
                    switch(protocol_type){
                        case 0x11: // UDP
                            printf("UDP IPv6 packet\n");
                            payload_offset = 40;    // fixed
                            hexdumpf(&packet[payload_offset], size - payload_offset);

                            // send response

                            break;
                        default:
                            printf("IPv6 packet of protocol 0x%02x\n", protocol_type);
                            hexdumpf(&packet[14], size - 14);
                            break;
                    }
                    break;
                default:
                    printf("Unknown network type %x", network_type);
                    break;
            }

            break;            
            
        default:
            break;
    }
}
Example #22
0
static void PacketHandler(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
    bd_addr_t event_addr;
    uint8_t rfcomm_channel_nr;
    uint16_t mtu;

    switch (packet_type) {
    case HCI_EVENT_PACKET:
        switch (packet[0]) {
        case BTSTACK_EVENT_STATE:
            // bt stack activated, get started - set local name
            if (packet[2] == HCI_STATE_WORKING) {
                hci_send_cmd(&hci_write_local_name, local_name);
            }
            break;

        case HCI_EVENT_COMMAND_COMPLETE:
            if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)) {
                bt_flip_addr(event_addr, &packet[6]);
                log_printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
                sprintf(local_name, "IOIO (%02X:%02X)", event_addr[4], event_addr[5]);
                break;
            }
            if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)) {
                hci_discoverable_control(1);
                break;
            }
            break;

        case HCI_EVENT_LINK_KEY_REQUEST:
            // deny link key request
            log_printf("Link key request\n\r");
            bt_flip_addr(event_addr, &packet[2]);
            hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
            break;

        case HCI_EVENT_PIN_CODE_REQUEST:
            // inform about pin code request
            log_printf("Pin code request - using '4545'\n\r");
            bt_flip_addr(event_addr, &packet[2]);
            hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "4545");
            break;

        case RFCOMM_EVENT_INCOMING_CONNECTION:
            // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
            bt_flip_addr(event_addr, &packet[2]);
            rfcomm_channel_nr = packet[8];
            rfcomm_channel_id = READ_BT_16(packet, 9);
            log_printf("RFCOMM channel %u requested for %s\n\r", rfcomm_channel_nr, bd_addr_to_str(event_addr));
            rfcomm_accept_connection_internal(rfcomm_channel_id);
            break;

        case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
            // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16)
            if (packet[2]) {
                log_printf("RFCOMM channel open failed, status %u\n\r", packet[2]);
            } else {
                rfcomm_channel_id = READ_BT_16(packet, 12);
                rfcomm_send_credit = 1;
                mtu = READ_BT_16(packet, 14);
                log_printf("\n\rRFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n\r", rfcomm_channel_id, mtu);
            }
            break;

        case RFCOMM_EVENT_CHANNEL_CLOSED:
            log_printf("RFCOMM channel closed.");
            client_callback(NULL, 0, client_callback_arg);
            client_callback = DummyCallback;
            rfcomm_channel_id = 0;
            break;

        default:
            break;
        }
        break;

    case RFCOMM_DATA_PACKET:
        client_callback(packet, size, client_callback_arg);
        rfcomm_send_credit = 1;

    default:
        break;
    }
}
Example #23
0
File: hci.c Project: ajsb85/ioio
static void event_handler(uint8_t *packet, int size){
    bd_addr_t addr;
    uint8_t link_type;
    hci_con_handle_t handle;
    hci_connection_t * conn;
    int i;
        
    switch (packet[0]) {
                        
        case HCI_EVENT_COMMAND_COMPLETE:
            // get num cmd packets
            // log_info("HCI_EVENT_COMMAND_COMPLETE cmds old %u - new %u\n", hci_stack.num_cmd_packets, packet[2]);
            hci_stack.num_cmd_packets = packet[2];
            
            if (COMMAND_COMPLETE_EVENT(packet, hci_read_buffer_size)){
                // from offset 5
                // status 
                // "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
                hci_stack.acl_data_packet_length = READ_BT_16(packet, 6);
                // ignore: SCO data packet len (8)
                hci_stack.total_num_acl_packets  = packet[9];
                // ignore: total num SCO packets
                if (hci_stack.state == HCI_STATE_INITIALIZING){
                    // determine usable ACL payload size
                    if (HCI_ACL_PAYLOAD_SIZE < hci_stack.acl_data_packet_length){
                        hci_stack.acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
                    }
                    // determine usable ACL packet types
                    hci_stack.packet_types = hci_acl_packet_types_for_buffer_size(hci_stack.acl_data_packet_length);
                    
                    log_error("hci_read_buffer_size: used size %u, count %u, packet types %04x\n",
                             hci_stack.acl_data_packet_length, hci_stack.total_num_acl_packets, hci_stack.packet_types); 
                }
            }
            if (COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
                hci_emit_discoverable_enabled(hci_stack.discoverable);
            }
            break;
            
        case HCI_EVENT_COMMAND_STATUS:
            // get num cmd packets
            // log_info("HCI_EVENT_COMMAND_STATUS cmds - old %u - new %u\n", hci_stack.num_cmd_packets, packet[3]);
            hci_stack.num_cmd_packets = packet[3];
            break;
            
        case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
            for (i=0; i<packet[2];i++){
                handle = READ_BT_16(packet, 3 + 2*i);
                uint16_t num_packets = READ_BT_16(packet, 3 + packet[2]*2 + 2*i);
                conn = connection_for_handle(handle);
                if (!conn){
                    log_error("hci_number_completed_packet lists unused con handle %u\n", handle);
                    continue;
                }
                conn->num_acl_packets_sent -= num_packets;
                // log_info("hci_number_completed_packet %u processed for handle %u, outstanding %u\n", num_packets, handle, conn->num_acl_packets_sent);
            }
            break;
            
        case HCI_EVENT_CONNECTION_REQUEST:
            bt_flip_addr(addr, &packet[2]);
            // TODO: eval COD 8-10
            link_type = packet[11];
            log_info("Connection_incoming: %s, type %u\n", bd_addr_to_str(addr), link_type);
            if (link_type == 1) { // ACL
                conn = connection_for_address(addr);
                if (!conn) {
                    conn = create_connection_for_addr(addr);
                }
                if (!conn) {
                    // CONNECTION REJECTED DUE TO LIMITED RESOURCES (0X0D)
                    hci_stack.decline_reason = 0x0d;
                    BD_ADDR_COPY(hci_stack.decline_addr, addr);
                    break;
                }
                conn->state = RECEIVED_CONNECTION_REQUEST;
                hci_run();
            } else {
                // SYNCHRONOUS CONNECTION LIMIT TO A DEVICE EXCEEDED (0X0A)
                hci_stack.decline_reason = 0x0a;
                BD_ADDR_COPY(hci_stack.decline_addr, addr);
            }
            break;
            
        case HCI_EVENT_CONNECTION_COMPLETE:
            // Connection management
            bt_flip_addr(addr, &packet[5]);
            log_info("Connection_complete (status=%u) %s\n", packet[2], bd_addr_to_str(addr));
            conn = connection_for_address(addr);
            if (conn) {
                if (!packet[2]){
                    conn->state = OPEN;
                    conn->con_handle = READ_BT_16(packet, 3);

#ifdef HAVE_TICK
                    // restart timer
                    run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
                    run_loop_add_timer(&conn->timeout);
#endif
                    
                    log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));
                    
                    hci_emit_nr_connections_changed();
                } else {
                    // connection failed, remove entry
                    linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
                    btstack_memory_hci_connection_free( conn );
                    
                    // if authentication error, also delete link key
                    if (packet[2] == 0x05) {
                        hci_drop_link_key_for_bd_addr(&addr);
                    }
                }
            }
            break;

        case HCI_EVENT_LINK_KEY_REQUEST:
            log_info("HCI_EVENT_LINK_KEY_REQUEST\n");
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_REQUEST);
            if (!hci_stack.remote_device_db) break;
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], HANDLE_LINK_KEY_REQUEST);
            hci_run();
            // request already answered
            return;
            
        case HCI_EVENT_LINK_KEY_NOTIFICATION:
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_NOTIFICATION);
            if (!hci_stack.remote_device_db) break;
            bt_flip_addr(addr, &packet[2]);
            hci_stack.remote_device_db->put_link_key(&addr, (link_key_t *) &packet[8]);
            // still forward event to allow dismiss of pairing dialog
            break;
            
        case HCI_EVENT_PIN_CODE_REQUEST:
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_PIN_CODE_REQUEST);
            break;
            
#ifndef EMBEDDED
        case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
            if (!hci_stack.remote_device_db) break;
            if (packet[2]) break; // status not ok
            bt_flip_addr(addr, &packet[3]);
            // fix for invalid remote names - terminate on 0xff
            for (i=0; i<248;i++){
                if (packet[9+i] == 0xff){
                    packet[9+i] = 0;
                    break;
                }
            }
            memset(&device_name, 0, sizeof(device_name_t));
            strncpy((char*) device_name, (char*) &packet[9], 248);
            hci_stack.remote_device_db->put_name(&addr, &device_name);
            break;
            
        case HCI_EVENT_INQUIRY_RESULT:
        case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
            if (!hci_stack.remote_device_db) break;
            // first send inq result packet
            hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
            // then send cached remote names
            for (i=0; i<packet[2];i++){
                bt_flip_addr(addr, &packet[3+i*6]);
                if (hci_stack.remote_device_db->get_name(&addr, &device_name)){
                    hci_emit_remote_name_cached(&addr, &device_name);
                }
            }
            return;
#endif
            
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            if (!packet[2]){
                handle = READ_BT_16(packet, 3);
                hci_connection_t * conn = connection_for_handle(handle);
                if (conn) {
                    hci_shutdown_connection(conn);
                }
            }
            break;
            
        case HCI_EVENT_HARDWARE_ERROR:
            if(hci_stack.control->hw_error){
                (*hci_stack.control->hw_error)();
            }
            break;

#ifdef HAVE_BLE
        case HCI_EVENT_LE_META:
            switch (packet[2]) {
                case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                    // Connection management
                    bt_flip_addr(addr, &packet[8]);
                    log_info("LE Connection_complete (status=%u) %s\n", packet[3], bd_addr_to_str(addr));
                    // LE connections are auto-accepted, so just create a connection if there isn't one already
                    conn = connection_for_address(addr);
                    if (packet[3]){
                        if (conn){
                            // outgoing connection failed, remove entry
                            linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
                            btstack_memory_hci_connection_free( conn );
                        }
                        // if authentication error, also delete link key
                        if (packet[3] == 0x05) {
                            hci_drop_link_key_for_bd_addr(&addr);
                        }
                        break;
                    }
                    if (!conn){
                        conn = create_connection_for_addr(addr);
                    }
                    if (!conn){
                        // no memory
                        break;
                    }

                    conn->state = OPEN;
                    conn->con_handle = READ_BT_16(packet, 4);

                    // TODO: store - role, peer address type, conn_interval, conn_latency, supervision timeout, master clock
                    // restart timer
                    // run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
                    // run_loop_add_timer(&conn->timeout);

                    log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));

                    hci_emit_nr_connections_changed();
                    break;

        default:
            break;
    }
            break;
#endif

        default:
            break;
    }

    // handle BT initialization
    if (hci_stack.state == HCI_STATE_INITIALIZING){
        // handle H4 synchronization loss on restart
        // if (hci_stack.substate == 1 && packet[0] == HCI_EVENT_HARDWARE_ERROR){
        //    hci_stack.substate = 0;
        // }
        // handle normal init sequence
        if (hci_stack.substate % 2){
            // odd: waiting for event
            if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){
                hci_stack.substate++;
            }
        }
    }
    
    // help with BT sleep
    if (hci_stack.state == HCI_STATE_FALLING_ASLEEP
        && hci_stack.substate == 1
        && COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
        hci_stack.substate++;
    }
    
    hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
	
    // execute main loop
    hci_run();
}
Example #24
0
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
	
	bd_addr_t event_addr;

	switch (packet_type) {
			
		case L2CAP_DATA_PACKET:
			// just dump data for now
			printf("source cid %x -- ", channel);
			hexdump( packet, size );
	
			// HOME => disconnect
			if (packet[0] == 0xA1) {							// Status report
				if (packet[1] == 0x30 || packet[1] == 0x31) {   // type 0x30 or 0x31
					if (packet[3] & 0x080) {                   // homne button pressed
						printf("Disconnect baseband\n");
						bt_send_cmd(&hci_disconnect, con_handle, 0x13); // remote closed connection
					}
				}
			}
			break;
			
		case HCI_EVENT_PACKET:
			
			switch (packet[0]) {

				case BTSTACK_EVENT_POWERON_FAILED:
					printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
					exit(1);
					break;
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - disable pairing
					if (packet[2] == HCI_STATE_WORKING) {
						bt_send_cmd(&hci_write_authentication_enable, 0);
					}
					break;
					
				case HCI_EVENT_LINK_KEY_REQUEST:
					printf("HCI_EVENT_LINK_KEY_REQUEST \n");
					// link key request
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					printf("Please enter PIN 0000 on remote device\n");
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000");
					break;
					
				case L2CAP_EVENT_CHANNEL_OPENED:
					// inform about new l2cap connection
					// inform about new l2cap connection
					bt_flip_addr(event_addr, &packet[3]);
					uint16_t psm = READ_BT_16(packet, 11); 
					uint16_t source_cid = READ_BT_16(packet, 13); 
					con_handle = READ_BT_16(packet, 9);
					if (packet[2] == 0) {
						printf("Channel successfully opened: ");
						print_bd_addr(event_addr);
						printf(", handle 0x%02x, psm 0x%02x, source cid 0x%02x, dest cid 0x%02x\n",
							   con_handle, psm, source_cid,  READ_BT_16(packet, 15));
						
						if (psm == 0x13) {
							source_cid_interrupt = source_cid;
							// interupt channel openedn succesfully, now open control channel, too.
							bt_send_cmd(&l2cap_create_channel, event_addr, 0x11);
						} else {
							source_cid_control = source_cid;
							// request acceleration data..
							// uint8_t setMode31[] = { 0x52, 0x12, 0x00, 0x31 };
							// bt_send_l2cap( source_cid, setMode31, sizeof(setMode31));
							// stop blinking
							// uint8_t setLEDs[] = { 0x52, 0x11, 0x10 };
							// bt_send_l2cap( source_cid, setLEDs, sizeof(setLEDs));
						}
					} else {
						printf("L2CAP connection to device ");
						print_bd_addr(event_addr);
						printf(" failed. status code %u\n", packet[2]);
						exit(1);
					}
					break;
					
				case HCI_EVENT_DISCONNECTION_COMPLETE:
					// connection closed -> quit tes app
					printf("Basebank connection closed, exit.\n");
					exit(0);
					break;
					
				case HCI_EVENT_COMMAND_COMPLETE:
					// connect to HID device (PSM 0x13) at addr
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
						bt_send_cmd(&l2cap_create_channel, addr, 0x13);
						printf("Press 1+2 on WiiMote to make it discoverable - Press HOME to disconnect later :)\n");
					}
					break;
					
				default:
					// other event
					break;
			}
			break;
			
		default:
			// other packet type
			break;
	}
}
Example #25
0
void comm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
	bd_addr_t event_addr;
	
	static uint8_t msc_resp_send = 0;
	static uint8_t msc_resp_received = 0;
	static uint8_t credits_used = 0;
	static uint8_t credits_free = 0;
	uint8_t packet_processed = 0;
	
	switch (packet_type) {
			
		case L2CAP_DATA_PACKET:
			// rfcomm: data[8] = addr
			// rfcomm: data[9] = command
			
			// 	received 1. message BT_RF_COMM_UA
			if (size == 4 && packet[1] == BT_RFCOMM_UA && packet[0] == 0x03){
				packet_processed++;
				printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
				printf("Sending UIH Parameter Negotiation Command\n");
				_bt_rfcomm_send_uih_pn_command(source_cid, 1, RFCOMM_CHANNEL_ID, 100);
			}
			
			//  received UIH Parameter Negotiation Response
			if (size == 14 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_PN_RSP){
				packet_processed++;
				printf("UIH Parameter Negotiation Response\n");
				printf("Sending SABM #%u\n", RFCOMM_CHANNEL_ID);
				_bt_rfcomm_send_sabm(source_cid, 1, RFCOMM_CHANNEL_ID);
			}
			
			// 	received 2. message BT_RF_COMM_UA
			if (size == 4 && packet[1] == BT_RFCOMM_UA && packet[0] == ((RFCOMM_CHANNEL_ID << 3) | 3) ){
				packet_processed++;
				printf("Received RFCOMM unnumbered acknowledgement for channel %u - channel opened\n", RFCOMM_CHANNEL_ID);
				printf("Sending MSC  'I'm ready'\n");
				_bt_rfcomm_send_uih_msc_cmd(source_cid, 1, RFCOMM_CHANNEL_ID, 0x8d);  // ea=1,fc=0,rtc=1,rtr=1,ic=0,dv=1
			}
			
			// received BT_RFCOMM_MSC_CMD
			if (size == 8 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_MSC_CMD){
				packet_processed++;
				printf("Received BT_RFCOMM_MSC_CMD\n");
				printf("Responding to 'I'm ready'\n");
				// fine with this
				uint8_t address = packet[0] | 2; // set response 
				packet[3]  = BT_RFCOMM_MSC_RSP;  //  "      "
				rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0x30, (uint8_t*)&packet[3], 4);
				msc_resp_send = 1;
			}
			
			// received BT_RFCOMM_MSC_RSP
			if (size == 8 && packet[1] == BT_RFCOMM_UIH && packet[3] == BT_RFCOMM_MSC_RSP){
				packet_processed++;
				msc_resp_received = 1;
			}
			
			if (packet[1] == BT_RFCOMM_UIH && packet[0] == ((RFCOMM_CHANNEL_ID<<3)|1)){
				packet_processed++;
				credits_used++;
				if(DEBUG){
					printf("RX: address %02x, control %02x: ", packet[0], packet[1]);
					hexdump( (uint8_t*) &packet[3], size-4);
				}
				int written = 0;
				int length = size-4;
				int start_of_data = 3;
				//write data to fifo
				while (length) {
					if ((written = write(fifo_fd, &packet[start_of_data], length)) == -1) {
						printf("Error writing to FIFO\n");
					} else {
						length -= written;
					}
				}
			}
			
			if (packet[1] == BT_RFCOMM_UIH_PF && packet[0] == ((RFCOMM_CHANNEL_ID<<3)|1)){
				packet_processed++;
				credits_used++;
				if (!credits_free) {
					printf("Got %u credits, can send!\n", packet[2]);
				}
				credits_free = packet[2];
				if(DEBUG){
					printf("RX: address %02x, control %02x: ", packet[0], packet[1]);
					hexdump( (uint8_t *) &packet[4], size-5);				
				}
				int written = 0;
				int length = size-5;
				int start_of_data = 4;
				//write data to fifo
				while (length) {
					if ((written = write(fifo_fd, &packet[start_of_data], length)) == -1) {
						printf("Error writing to FIFO\n");
					} else {
						length -= written;
					}
				}
			}
			
			uint8_t send_credits_packet = 0;
			
			if (credits_used >= NR_CREDITS ) {
				send_credits_packet = 1;
				credits_used -= NR_CREDITS;
			}
			
			if (msc_resp_send && msc_resp_received) {
				send_credits_packet = 1;
				msc_resp_send = msc_resp_received = 0;
				
				printf("RFCOMM up and running!\n");
			}
			
			if (send_credits_packet) {
				// send 0x30 credits
				uint8_t initiator = 1;
				uint8_t address = (1 << 0) | (initiator << 1) |  (initiator << 1) | (RFCOMM_CHANNEL_ID << 3); 
				rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH_PF, NR_CREDITS, NULL, 0);
			}
			
			if (!packet_processed){
				// just dump data for now
				printf("??: address %02x, control %02x: ", packet[0], packet[1]);
				hexdump( packet, size );
			}
			
			break;
			
		case HCI_EVENT_PACKET:
			
			switch (packet[0]) {
					
				case BTSTACK_EVENT_POWERON_FAILED:
					// handle HCI init failure
					printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
					exit(1);
					break;		
					
				case BTSTACK_EVENT_STATE:
					// bt stack activated, get started - use authentication yes/no
					if (packet[2] == HCI_STATE_WORKING) {
						bt_send_cmd(&hci_write_authentication_enable, 1);
					}
					break;
					
				case HCI_EVENT_LINK_KEY_REQUEST:
					// link key request
					bt_flip_addr(event_addr, &packet[2]);
					bt_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
					break;
					
				case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
					bt_flip_addr(event_addr, &packet[2]); 
					bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, PIN);
					printf("Please enter PIN %s on remote device\n", PIN);
					break;
					
				case L2CAP_EVENT_CHANNEL_OPENED:
					// inform about new l2cap connection
					bt_flip_addr(event_addr, &packet[3]);
					uint16_t psm = READ_BT_16(packet, 11); 
					source_cid = READ_BT_16(packet, 13); 
					con_handle = READ_BT_16(packet, 9);
					if (packet[2] == 0) {
						printf("Channel successfully opened: ");
						print_bd_addr(event_addr);
						printf(", handle 0x%02x, psm 0x%02x, source cid 0x%02x, dest cid 0x%02x\n",
							   con_handle, psm, source_cid,  READ_BT_16(packet, 15));
						
						// send SABM command on dlci 0
						printf("Sending SABM #0\n");
						_bt_rfcomm_send_sabm(source_cid, 1, 0);
					} else {
						printf("L2CAP connection to device ");
						print_bd_addr(event_addr);
						printf(" failed. status code %u\n", packet[2]);
						exit(1);
					}
					break;
					
				case HCI_EVENT_DISCONNECTION_COMPLETE:
					// connection closed -> quit test app
					printf("Basebank connection closed, exit.\n");
					exit(0);
					break;
					
				case HCI_EVENT_COMMAND_COMPLETE:
					// connect to RFCOMM device (PSM 0x03) at addr
					if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
						bt_send_cmd(&l2cap_create_channel, addr, 0x03);
					}
					break;
					
				default:
					// unhandled event
					if(DEBUG) printf("unhandled event : %02x\n", packet[0]);
					break;
			}
			break;
		default:
			// unhandled packet type
			if(DEBUG) printf("unhandled packet type : %02x\n", packet_type);
			break;
	}
}
Example #26
0
static void bt_packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
	switch (packet_type)
	{
	case HCI_EVENT_PACKET:
		// hexdump( packet, size ); // not needed?
		switch (packet[0])
		{
		case BTSTACK_EVENT_POWERON_FAILED:
			printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n");
			exit(1);
			break;

		case BTSTACK_EVENT_STATE:
			// bt stack activated, get started - set local name
			if (packet[2] == HCI_STATE_WORKING)
			{
				hci_send_cmd(&hci_write_local_name, "RASP BT");
			}
			break;

		case HCI_EVENT_COMMAND_COMPLETE:
			if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr))
			{
				bt_flip_addr(event_addr, &packet[6]);
				printf("BD-ADDR: %s\n\r", bd_addr_to_str(event_addr));
				break;
			}
			if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name))
			{
				hci_discoverable_control(1);
				break;
			}
			break;

		case HCI_EVENT_LINK_KEY_REQUEST:
			// deny link key request
			printf("Link key request\n\r");
			bt_flip_addr(event_addr, &packet[2]);
			hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
			break;

		case HCI_EVENT_PIN_CODE_REQUEST:
			// inform about pin code request
			printf("Pin code request using '0943'\n\r");
			bt_flip_addr(event_addr, &packet[2]);
			hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0943");
			break;

		case HCI_EVENT_DISCONNECTION_COMPLETE:
			// connection closed -> quit tes app
			printf("Basebank connection closed\n");

			// exit(0);
			break;

		default:
			break;
		}
		break;

	default:
		break;
	}
}