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); }
/* * \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; }
// 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; } }
/* * \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; }
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); } } }
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; } } } }
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; } }
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; } }
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); }
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; } }
// 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; } } } }
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; } }
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; } }
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; } }
// 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; } }
// 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(); }
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; } }
// 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; } }
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; } }
/*************** 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; } }
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; } }
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(); }
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; } }
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; } }
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; } }