From e1c5b199f6c3e3749cf76b3e6a7bb5475658f43f Mon Sep 17 00:00:00 2001 From: Maximilian von Tschirschnitz Date: Thu, 4 Jun 2020 12:18:24 +0000 Subject: [PATCH 1/4] Added function to libusb interface that allows addressing of devices via their direct device id (result of `lsusb`) Signed-off-by: Maximilian von Tschirschnitz --- platform/libusb/hci_transport_h2_libusb.c | 38 ++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/platform/libusb/hci_transport_h2_libusb.c b/platform/libusb/hci_transport_h2_libusb.c index 314a3fa21c..dcf819eb16 100644 --- a/platform/libusb/hci_transport_h2_libusb.c +++ b/platform/libusb/hci_transport_h2_libusb.c @@ -225,6 +225,7 @@ static int sco_out_addr; // device path static int usb_path_len; +static uint8_t dev_addr; static uint8_t usb_path[USB_MAX_PATH_LEN]; // transport interface state @@ -245,11 +246,15 @@ void hci_transport_usb_set_path(int len, uint8_t * port_numbers){ if (len > USB_MAX_PATH_LEN || !port_numbers){ log_error("hci_transport_usb_set_path: len or port numbers invalid"); return; - } + } usb_path_len = len; memcpy(usb_path, port_numbers, len); } +void hci_transport_usb_set_address(uint8_t _dev_addr){ + dev_addr = _dev_addr; +} + // static void queue_transfer(struct libusb_transfer *transfer){ @@ -1019,6 +1024,37 @@ static int usb_open(void){ printf("USB device with given path not found\n"); return -1; } + } else if(dev_addr) { + + for (int i=0;i Date: Mon, 22 Jun 2020 18:23:21 +0200 Subject: [PATCH 2/4] python server testing --- platform/daemon/binding/python/cli.py | 98 +++++++++++ platform/daemon/src/daemon.c | 233 ++++++++++++++------------ src/hci_transport.h | 5 + 3 files changed, 230 insertions(+), 106 deletions(-) create mode 100755 platform/daemon/binding/python/cli.py diff --git a/platform/daemon/binding/python/cli.py b/platform/daemon/binding/python/cli.py new file mode 100755 index 0000000000..866db2d68a --- /dev/null +++ b/platform/daemon/binding/python/cli.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 + +from btstack import btstack_client, event_factory, btstack_types +#import btstack.command_builder as cb +import sys +import time +import struct +from enum import Enum + +class STATE(Enum): + w4_btstack_working = 0 + w4_query_result = 1 + w4_connected = 2 + active = 3 + +btstack = None +state = -1 +testHandle = -1 + +remote = btstack_types.BD_ADDR("84:CF:BF:8D:D8:F7") +rfcommServiceUUID = 0x1002 +btIncomingChannelNr = 3 + +rfcommChannelID = 0 +mtu = 0 + +services = [] +counter = -1 + +def service_search_pattern(uuid): + return struct.pack("BBBBB", 0x35, 0x03, 0x19, (uuid >> 8), (uuid & 0xff)) + +def packet_handler(packet): + global state + global btstack_client + if isinstance(packet, event_factory.HCIEventDisconnectionComplete): + event = packet + testHandle = event.get_connection_handle() + print("Received disconnect, status" + str(event.get_status()) + ", handle" + str(testHandle)) + #return + + # this is a switch statement + if state == STATE.w4_btstack_working: + if isinstance(packet, event_factory.BTstackEventState): + event = packet + if event.get_state() == 2: + print("BTstack working. Start SDP inquiry.") + state = STATE.w4_query_result + serviceSearchPattern = service_search_pattern(rfcommServiceUUID) + btstack_client.sdp_client_query_rfcomm_services(remote, serviceSearchPattern) + elif state == STATE.w4_query_result: + if isinstance(packet, event_factory.SDPEventQueryRFCOMMService): + service = packet + services.append(service.get_rfcomm_channel()) + if isinstance(packet, event_factory.SDPEventQueryComplete): + for channel_nr in services: + print("Found rfcomm channel nr: " + str(channel_nr)) + if channel_nr == btIncomingChannelNr: + state = STATE.w4_connected + print("Connect to channel nr " + str(channel_nr)) + btstack_client.rfcomm_create_channel(remote, 3) + elif state == STATE.w4_connected: + if isinstance(packet, event_factory.RFCOMMEventChannelOpened): + e = packet + print("RFCOMMEventChannelOpened with status " + str(e.get_status())) + if e.get_status(): + print("RFCOMM channel open failed, status " + str(e.get_status())) + else: + state = STATE.active + rfcommChannelID = e.get_rfcomm_cid() + mtu = e.get_max_frame_size() + print("RFCOMM channel open succeeded. New RFCOMM Channel ID %s, max frame size %s" % (str(rfcommChannelID), str(mtu))) + counter = 0 + while state == STATE.active: + time.sleep(1) + data = ("BTstack SPP Counter %d\n" % counter).encode() + print("would send now") + #btstack_client.rfcomm_send_data(rfcommChannelID, data) + elif state == STATE.active: + if isinstance(packet, event_factory.RFCOMM_Data_Packet): + print("Received RFCOMM data packet: " + packet.toString()) + +# check version +if sys.version_info < (3, 0): + print('BTstack Server Client library, requires Python 3.x or higher.\n') + sys.exit(10) + +# Client for BTstack Server +btstack_client = btstack_client.BTstackClient() + +# connect to slient, register for HCI packets and power up +ok = btstack_client.connect() +if ok: + btstack_client.register_packet_handler(packet_handler) + state = STATE.w4_btstack_working + btstack_client.btstack_set_power_mode(1) + btstack_client.run() + diff --git a/platform/daemon/src/daemon.c b/platform/daemon/src/daemon.c index 2402b884c7..ac9463088f 100644 --- a/platform/daemon/src/daemon.c +++ b/platform/daemon/src/daemon.c @@ -30,7 +30,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Please inquire about commercial licensing options at + * Please inquire about commercial licensing options at * contact@bluekitchen-gmbh.com * */ @@ -55,6 +55,9 @@ #include #include +/* ... ?? */ +#include "bluetooth_comapny_id.h" + #ifdef _WIN32 #include "Winsock2.h" #endif @@ -124,7 +127,7 @@ const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void); // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT #ifndef BTSTACK_LOG_TYPE -#define BTSTACK_LOG_TYPE HCI_DUMP_PACKETLOGGER +#define BTSTACK_LOG_TYPE HCI_DUMP_PACKETLOGGER #endif #define DAEMON_NO_ACTIVE_CLIENT_TIMEOUT 10000 @@ -146,7 +149,7 @@ const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void); typedef struct { // linked list - assert: first field btstack_linked_item_t item; - + // connection connection_t * connection; @@ -159,10 +162,10 @@ typedef struct { // power mode HCI_POWER_MODE power_mode; - + // discoverable uint8_t discoverable; - + } client_state_t; typedef struct btstack_linked_list_uint32 { @@ -268,41 +271,41 @@ static void daemon_no_connections_timeout(struct btstack_timer_source *ts){ static void add_uint32_to_list(btstack_linked_list_t *list, uint32_t value){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); if ( item->value == value) return; // already in list - } + } btstack_linked_list_uint32_t * item = malloc(sizeof(btstack_linked_list_uint32_t)); - if (!item) return; + if (!item) return; memset(item, 0, sizeof(btstack_linked_list_uint32_t)); item->value = value; btstack_linked_list_add(list, (btstack_linked_item_t *) item); } static void remove_and_free_uint32_from_list(btstack_linked_list_t *list, uint32_t value){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); if ( item->value != value) continue; btstack_linked_list_remove(list, (btstack_linked_item_t *) item); free(item); - } + } } static void daemon_add_client_rfcomm_service(connection_t * connection, uint16_t service_channel){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - add_uint32_to_list(&client_state->rfcomm_services, service_channel); + add_uint32_to_list(&client_state->rfcomm_services, service_channel); } static void daemon_remove_client_rfcomm_service(connection_t * connection, uint16_t service_channel){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - remove_and_free_uint32_from_list(&client_state->rfcomm_services, service_channel); + remove_and_free_uint32_from_list(&client_state->rfcomm_services, service_channel); } static void daemon_add_client_rfcomm_channel(connection_t * connection, uint16_t cid){ @@ -344,27 +347,27 @@ static void daemon_remove_client_l2cap_channel(connection_t * connection, uint16 static void daemon_add_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - add_uint32_to_list(&client_state->sdp_record_handles, handle); + add_uint32_to_list(&client_state->sdp_record_handles, handle); } static void daemon_remove_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - remove_and_free_uint32_from_list(&client_state->sdp_record_handles, handle); + remove_and_free_uint32_from_list(&client_state->sdp_record_handles, handle); } #ifdef ENABLE_BLE static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - + // check if handle already exists in the gatt_con_handles list btstack_linked_list_iterator_t it; int handle_found = 0; btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); - if (item->value == handle){ + if (item->value == handle){ handle_found = 1; break; } @@ -373,7 +376,7 @@ static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t ha if (!handle_found){ add_uint32_to_list(&client_state->gatt_con_handles, handle); } - + // check if there is a helper with given handle btstack_linked_list_gatt_client_helper_t * gatt_helper = NULL; btstack_linked_list_iterator_init(&it, &gatt_client_helpers); @@ -388,7 +391,7 @@ static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t ha // if gatt_helper doesn't exist, create it and add it to gatt_client_helpers list if (!gatt_helper){ gatt_helper = calloc(sizeof(btstack_linked_list_gatt_client_helper_t), 1); - if (!gatt_helper) return; + if (!gatt_helper) return; gatt_helper->con_handle = handle; btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) gatt_helper); } @@ -419,8 +422,8 @@ static void daemon_remove_gatt_client_handle(connection_t * connection, uint32_t // might be extracted or vanish totally client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - - btstack_linked_list_iterator_t it; + + btstack_linked_list_iterator_t it; // remove handle from gatt_con_handles list btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ @@ -469,7 +472,7 @@ static void daemon_remove_gatt_client_handle(connection_t * connection, uint32_t static void daemon_remove_gatt_client_helper(uint32_t con_handle){ log_info("daemon_remove_gatt_client_helper for con_handle 0x%04x", con_handle); - btstack_linked_list_iterator_t it, cl; + btstack_linked_list_iterator_t it, cl; // find helper with given handle btstack_linked_list_gatt_client_helper_t * helper = NULL; btstack_linked_list_iterator_init(&it, &gatt_client_helpers); @@ -482,7 +485,7 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ } if (!helper) return; - + // remove all connection from helper btstack_linked_list_iterator_init(&it, &helper->all_connections); while (btstack_linked_list_iterator_has_next(&it)){ @@ -493,7 +496,7 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ btstack_linked_list_remove(&gatt_client_helpers, (btstack_linked_item_t *) helper); free(helper); - + btstack_linked_list_iterator_init(&cl, &clients); while (btstack_linked_list_iterator_has_next(&cl)){ client_state_t * client_state = (client_state_t *) btstack_linked_list_iterator_next(&cl); @@ -510,10 +513,10 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ #endif static void daemon_rfcomm_close_connection(client_state_t * daemon_client){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_t *rfcomm_services = &daemon_client->rfcomm_services; btstack_linked_list_t *rfcomm_cids = &daemon_client->rfcomm_cids; - + btstack_linked_list_iterator_init(&it, rfcomm_services); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -533,10 +536,10 @@ static void daemon_rfcomm_close_connection(client_state_t * daemon_client){ static void daemon_l2cap_close_connection(client_state_t * daemon_client){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_t *l2cap_psms = &daemon_client->l2cap_psms; btstack_linked_list_t *l2cap_cids = &daemon_client->l2cap_cids; - + btstack_linked_list_iterator_init(&it, l2cap_psms); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -556,7 +559,7 @@ static void daemon_l2cap_close_connection(client_state_t * daemon_client){ static void daemon_sdp_close_connection(client_state_t * daemon_client){ btstack_linked_list_t * list = &daemon_client->sdp_record_handles; - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -590,28 +593,28 @@ static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, // pre: ServiceRecordHandle is first attribute and is not already registered in database // @returns status static uint32_t daemon_sdp_create_and_register_service(uint8_t * record){ - + // create new handle uint32_t record_handle = sdp_create_service_record_handle(); - - // calculate size of new service record: DES (2 byte len) + + // calculate size of new service record: DES (2 byte len) // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record); - + // alloc memory for new service record uint8_t * newRecord = malloc(recordSize); if (!newRecord) return 0; - + // create DES for new record de_create_sequence(newRecord); - + // set service record handle de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0); de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle); - + // add other attributes sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord); - + uint8_t status = sdp_register_service(newRecord); if (status) { @@ -644,7 +647,7 @@ static void daemon_gatt_client_close_connection(connection_t * connection){ client_state_t * client = client_for_connection(connection); if (!client) return; - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, &client->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ @@ -670,7 +673,7 @@ static void daemon_disconnect_client(connection_t * connection){ #endif btstack_linked_list_remove(&clients, (btstack_linked_item_t *) client); - free(client); + free(client); } static void hci_emit_btstack_version(void){ @@ -707,8 +710,8 @@ static void send_l2cap_connection_open_failed(connection_t * connection, bd_addr // little_endian_store_16(event, 13, channel->local_cid); // little_endian_store_16(event, 15, channel->remote_cid); // little_endian_store_16(event, 17, channel->local_mtu); - // little_endian_store_16(event, 19, channel->remote_mtu); - // little_endian_store_16(event, 21, channel->flush_timeout); + // little_endian_store_16(event, 19, channel->remote_mtu); + // little_endian_store_16(event, 21, channel->flush_timeout); hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event)); } @@ -764,10 +767,10 @@ static void sdp_emit_service_registered(void *connection, uint32_t handle, uint8 #ifdef ENABLE_BLE btstack_linked_list_gatt_client_helper_t * daemon_get_gatt_client_helper(hci_con_handle_t con_handle) { - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; if (!gatt_client_helpers) return NULL; log_debug("daemon_get_gatt_client_helper for handle 0x%02x", con_handle); - + btstack_linked_list_iterator_init(&it, &gatt_client_helpers); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it); @@ -804,7 +807,7 @@ static void send_gatt_mtu_event(connection_t * connection, hci_con_handle_t con_ } btstack_linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(connection_t *connection, uint8_t *packet, int track_active_connection) { - hci_con_handle_t con_handle = little_endian_read_16(packet, 3); + hci_con_handle_t con_handle = little_endian_read_16(packet, 3); log_info("daemon_setup_gatt_client_request for handle 0x%02x", con_handle); hci_connection_t * hci_con = hci_connection_for_handle(con_handle); if ((hci_con == NULL) || (hci_con->state != OPEN)){ @@ -817,18 +820,18 @@ btstack_linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(conn if (!helper){ log_info("helper does not exist"); helper = calloc(sizeof(btstack_linked_list_gatt_client_helper_t), 1); - if (!helper) return NULL; + if (!helper) return NULL; helper->con_handle = con_handle; btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) helper); - } - + } + if (track_active_connection && helper->active_connection){ send_gatt_query_complete(connection, con_handle, GATT_CLIENT_BUSY); return NULL; } daemon_add_gatt_client_handle(connection, con_handle); - + if (track_active_connection){ // remember connection responsible for this request helper->active_connection = connection; @@ -871,7 +874,7 @@ static void btstack_server_intel_firmware_done(int result){ #endif static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){ - + bd_addr_t addr; #ifdef ENABLE_BLE bd_addr_type_t addr_type; @@ -933,14 +936,14 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui case BTSTACK_GET_VERSION: log_info("BTSTACK_GET_VERSION"); hci_emit_btstack_version(); - break; + break; #ifdef HAVE_PLATFORM_IPHONE_OS case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED %u", packet[3]); btstack_control_iphone_bt_set_enabled(packet[3]); hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled()); break; - + case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED"); hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled()); @@ -1072,7 +1075,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui cid = little_endian_read_16(packet, 3); reason = packet[7]; rfcomm_decline_connection(cid); - break; + break; case RFCOMM_GRANT_CREDITS: cid = little_endian_read_16(packet, 3); rfcomm_credits = packet[5]; @@ -1112,7 +1115,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui free(data); } break; - case SDP_CLIENT_QUERY_RFCOMM_SERVICES: + case SDP_CLIENT_QUERY_RFCOMM_SERVICES: reverse_bd_addr(&packet[3], addr); serviceSearchPatternLen = de_get_len(&packet[9]); @@ -1128,10 +1131,10 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); - - attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); + + attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); memcpy(attributeIDList, &packet[9+serviceSearchPatternLen], attributeIDListLen); - + sdp_client_query(&handle_sdp_client_query_result, addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]); break; #ifdef ENABLE_BLE @@ -1180,7 +1183,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_service(packet, 5, &service); gatt_client_find_included_services_for_service(&handle_gatt_client_event, gatt_helper->con_handle, &service); break; - + case GATT_DISCOVER_CHARACTERISTICS_FOR_SERVICE: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1); if (!gatt_helper) break; @@ -1200,7 +1203,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_characteristic(packet, 5, &characteristic); gatt_client_discover_characteristic_descriptors(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic); break; - + case GATT_READ_VALUE_OF_CHARACTERISTIC: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1); if (!gatt_helper) break; @@ -1213,7 +1216,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_characteristic(packet, 5, &characteristic); gatt_client_read_long_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic); break; - + case GATT_WRITE_VALUE_OF_CHARACTERISTIC_WITHOUT_RESPONSE: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 0); // note: don't track active connection if (!gatt_helper) break; @@ -1313,7 +1316,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui sm_just_works_confirm(little_endian_read_16(packet, 3)); break; case SM_NUMERIC_COMPARISON_CONFIRM: - sm_numeric_comparison_confirm(little_endian_read_16(packet, 3)); + sm_numeric_comparison_confirm(little_endian_read_16(packet, 3)); break; case SM_PASSKEY_INPUT: sm_passkey_input(little_endian_read_16(packet, 3), little_endian_read_32(packet, 5)); @@ -1323,18 +1326,18 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui log_error("Error: command %u not implemented:", READ_CMD_OCF(packet)); break; } - + return 0; } static int daemon_client_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){ - + int err = 0; client_state_t * client; - + switch (packet_type){ case HCI_COMMAND_DATA_PACKET: - if (READ_CMD_OGF(data) != OGF_BTSTACK) { + if (READ_CMD_OGF(data) != OGF_BTSTACK) { // HCI Command hci_send_cmd_packet(data, length); } else { @@ -1438,9 +1441,9 @@ static void preferences_changed_callback(void){ #endif static void deamon_status_event_handler(uint8_t *packet, uint16_t size){ - + uint8_t update_status = 0; - + // handle state event switch (hci_event_packet_get_type(packet)) { case BTSTACK_EVENT_STATE: @@ -1456,23 +1459,23 @@ static void deamon_status_event_handler(uint8_t *packet, uint16_t size){ default: break; } - - // choose full bluetooth state + + // choose full bluetooth state if (update_status) { update_ui_status(); } } static void daemon_retry_parked(void){ - + // socket_connection_retry_parked is not reentrant static int retry_mutex = 0; // lock mutex if (retry_mutex) return; retry_mutex = 1; - - // ... try sending again + + // ... try sending again socket_connection_retry_parked(); // unlock mutex @@ -1558,11 +1561,11 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 packet[9+248] = 0; btstack_device_name_db->put_name(addr, (device_name_t *)&packet[9]); break; - + case HCI_EVENT_INQUIRY_RESULT: case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{ if (!btstack_device_name_db) break; - + // first send inq result packet daemon_emit_packet(connection, packet_type, channel, packet, size); @@ -1575,22 +1578,22 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 remote_name_event[1] = sizeof(remote_name_event) - 2 - 1; remote_name_event[2] = 0; // just to be compatible with HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE reverse_bd_addr(addr, &remote_name_event[3]); - + remote_name_event[9+248] = 0; // assert \0 for log_info log_info("DAEMON_EVENT_REMOTE_NAME_CACHED %s = '%s'", bd_addr_to_str(addr), &remote_name_event[9]); hci_dump_packet(HCI_EVENT_PACKET, 0, remote_name_event, sizeof(remote_name_event)-1); daemon_emit_packet(connection, HCI_EVENT_PACKET, channel, remote_name_event, sizeof(remote_name_event) -1); } - offset += 14; // 6 + 1 + 1 + 1 + 3 + 2; + offset += 14; // 6 + 1 + 1 + 1 + 3 + 2; } return; } - + case DAEMON_EVENT_RFCOMM_CREDITS: // RFCOMM CREDITS received... daemon_retry_parked(); break; - + case RFCOMM_EVENT_CHANNEL_OPENED: cid = little_endian_read_16(packet, 13); connection = connection_for_rfcomm_cid(cid); @@ -1640,14 +1643,14 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 connection = connection_for_l2cap_cid(channel); if (!connection) return; break; - case RFCOMM_DATA_PACKET: + case RFCOMM_DATA_PACKET: connection = connection_for_l2cap_cid(channel); if (!connection) return; break; default: break; } - + daemon_emit_packet(connection, packet_type, channel, packet, size); } @@ -1663,7 +1666,7 @@ static void handle_sdp_rfcomm_service_result(uint8_t packet_type, uint16_t chann hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); socket_connection_send_packet(sdp_client_query_connection, HCI_EVENT_PACKET, 0, packet, size); break; - default: + default: break; } } @@ -1685,7 +1688,7 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)){ log_info_hexdump(attribute_value, sdp_event_query_attribute_byte_get_attribute_length(packet)); - int event_len = 1 + 3 * 2 + sdp_event_query_attribute_byte_get_attribute_length(packet); + int event_len = 1 + 3 * 2 + sdp_event_query_attribute_byte_get_attribute_length(packet); uint8_t event[event_len]; event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE; little_endian_store_16(event, 1, sdp_event_query_attribute_byte_get_record_id(packet)); @@ -1724,13 +1727,13 @@ static void power_notification_callback(POWER_NOTIFICATION_t notification){ } static void daemon_sigint_handler(int param){ - + #ifdef HAVE_PLATFORM_IPHONE_OS // notify daemons notify_post("ch.ringwald.btstack.stopped"); #endif - - log_info(" <= SIGINT received, shutting down..\n"); + + log_info(" <= SIGINT received, shutting down..\n"); int send_power_off = 1; #ifdef HAVE_INTEL_USB @@ -1742,9 +1745,9 @@ static void daemon_sigint_handler(int param){ hci_power_control( HCI_POWER_OFF); hci_close(); } - - log_info("Good bye, see you.\n"); - + + log_info("Good bye, see you.\n"); + exit(0); } @@ -1762,7 +1765,7 @@ static void stop_power_off_timer(void){ } static void start_power_off_timer(void){ -#ifdef USE_POWER_OFF_TIMER +#ifdef USE_POWER_OFF_TIMER stop_power_off_timer(); btstack_run_loop_set_timer(&timeout, DAEMON_NO_ACTIVE_CLIENT_TIMEOUT); btstack_run_loop_add_timer(&timeout); @@ -1795,9 +1798,9 @@ static void clients_clear_power_request(void){ } static int clients_require_power_on(void){ - + if (global_enable) return 1; - + btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) clients; it ; it = it->next){ client_state_t * client_state = (client_state_t *) it; @@ -1819,6 +1822,7 @@ static int clients_require_discoverable(void){ return 0; } +/* static void usage(const char * name) { printf("%s, BTstack background daemon\n", name); printf("usage: %s [--help] [--tcp]\n", name); @@ -1826,8 +1830,9 @@ static void usage(const char * name) { printf(" --tcp use TCP server on port %u\n", BTSTACK_PORT); printf("Without the --tcp option, BTstack Server is listening on unix domain socket %s\n\n", BTSTACK_UNIX); } +*/ -#ifdef HAVE_PLATFORM_IPHONE_OS +#ifdef HAVE_PLATFORM_IPHONE_OS static void * btstack_run_loop_thread(void *context){ btstack_run_loop_execute(); return NULL; @@ -1861,7 +1866,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint if (!gatt_client_helper){ log_info("daemon handle_gatt_client_event: gc helper for handle 0x%2x is NULL.", con_handle); return; - } + } connection_t *connection = NULL; @@ -1870,7 +1875,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint case GATT_EVENT_NOTIFICATION: case GATT_EVENT_INDICATION:{ hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); - + btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) clients; it ; it = it->next){ client_state_t * client_state = (client_state_t *) it; @@ -1900,7 +1905,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, packet, size); break; - + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: case GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT: offset = little_endian_read_16(packet, 6); @@ -1972,7 +1977,7 @@ static void btstack_server_configure_stack(void){ log_info("config.h: ENABLE_RFCOMM\n"); rfcomm_init(); #endif - + #ifdef ENABLE_SDP sdp_init(); #endif @@ -1982,14 +1987,14 @@ static void btstack_server_configure_stack(void){ sm_event_callback_registration.callback = &stack_packet_handler; sm_add_event_handler(&sm_event_callback_registration); // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); - // sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); + // sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); // GATT Client gatt_client_init(); gatt_client_listen_for_characteristic_value_updates(&daemon_gatt_client_notifications, &handle_gatt_client_event, GATT_CLIENT_ANY_CONNECTION, GATT_CLIENT_ANY_VALUE_HANDLE); // GATT Server - empty attribute database - att_server_init(NULL, NULL, NULL); + att_server_init(NULL, NULL, NULL); #endif } @@ -2024,7 +2029,7 @@ int btstack_server_run(int tcp_flag){ btstack_control_t * control = NULL; const btstack_uart_block_t * uart_block_implementation = NULL; (void) uart_block_implementation; - + #ifdef HAVE_TRANSPORT_H4 hci_transport_config_uart.type = HCI_TRANSPORT_CONFIG_UART; hci_transport_config_uart.baudrate_init = UART_SPEED; @@ -2039,7 +2044,7 @@ int btstack_server_run(int tcp_flag){ uart_block_implementation = btstack_uart_block_posix_instance(); #endif #endif - + #ifdef HAVE_PLATFORM_IPHONE_OS // use default (max) UART baudrate over netgraph interface hci_transport_config_uart.baudrate_init = 0; @@ -2086,14 +2091,14 @@ int btstack_server_run(int tcp_flag){ newLoggingEnabled = platform_iphone_logging_enabled(); #endif daemon_set_logging_enabled(newLoggingEnabled); - + // dump version log_info("BTStack Server started\n"); log_info("version %s, build %s", BTSTACK_VERSION, BTSTACK_DATE); #ifndef HAVE_INTEL_USB btstack_server_configure_stack(); -#endif +#endif #ifdef USE_LAUNCHD socket_connection_create_launchd(); @@ -2108,8 +2113,8 @@ int btstack_server_run(int tcp_flag){ } #endif socket_connection_register_packet_callback(&daemon_client_handler); - -#ifdef HAVE_PLATFORM_IPHONE_OS + +#ifdef HAVE_PLATFORM_IPHONE_OS // notify daemons notify_post("ch.ringwald.btstack.started"); @@ -2130,20 +2135,21 @@ int btstack_server_run_tcp(void){ } int main (int argc, char * const * argv){ - + + /* int tcp_flag = 0; struct option long_options[] = { { "tcp", no_argument, &tcp_flag, 1 }, { "help", no_argument, 0, 0 }, { 0,0,0,0 } // This is a filler for -1 }; - + while (true) { int c; int option_index = -1; c = getopt_long(argc, argv, "h", long_options, &option_index); if (c == -1) break; // no more option - + // treat long parameter first if (option_index == -1) { switch (c) { @@ -2162,7 +2168,22 @@ int main (int argc, char * const * argv){ } } } - + */ + uint8_t initiator_usb_device_id; + int tcp_flag = 0; + + /* Parse arguments */ + if(argc < 3) + { + printf("Too few arguments provided\n"); + printf("Usage:./%s device_id port\n", argv[0]); + exit(0); + } + + initiator_usb_device_id = strtol(argv[1], 0, 10); + tcp_flag = strtol(argv[2], 0, 10); + hci_transport_usb_set_address(initiator_usb_device_id); + #ifndef HAVE_UNIX_SOCKETS // TCP is default if there are no unix sockets tcp_flag = 1; diff --git a/src/hci_transport.h b/src/hci_transport.h index 8767e124ad..8586370cb4 100644 --- a/src/hci_transport.h +++ b/src/hci_transport.h @@ -172,6 +172,11 @@ const hci_transport_t * hci_transport_usb_instance(void); */ void hci_transport_usb_set_path(int len, uint8_t * port_numbers); +/** + * @brief Specify USB Bluetooth device via device address + */ +void hci_transport_usb_set_address(uint8_t _dev_addr); + /* API_END */ #if defined __cplusplus From eb867b266f8edf3a228cfe9091ff3b3b9f04ec21 Mon Sep 17 00:00:00 2001 From: Ludwig Peuckert Date: Tue, 23 Jun 2020 11:03:57 +0200 Subject: [PATCH 3/4] Revert "python server testing" This reverts commit 482618cb78e889ea4e5969f2af91018807f33693. Moved to a new branch --- platform/daemon/binding/python/cli.py | 98 ----------- platform/daemon/src/daemon.c | 233 ++++++++++++-------------- src/hci_transport.h | 5 - 3 files changed, 106 insertions(+), 230 deletions(-) delete mode 100755 platform/daemon/binding/python/cli.py diff --git a/platform/daemon/binding/python/cli.py b/platform/daemon/binding/python/cli.py deleted file mode 100755 index 866db2d68a..0000000000 --- a/platform/daemon/binding/python/cli.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 - -from btstack import btstack_client, event_factory, btstack_types -#import btstack.command_builder as cb -import sys -import time -import struct -from enum import Enum - -class STATE(Enum): - w4_btstack_working = 0 - w4_query_result = 1 - w4_connected = 2 - active = 3 - -btstack = None -state = -1 -testHandle = -1 - -remote = btstack_types.BD_ADDR("84:CF:BF:8D:D8:F7") -rfcommServiceUUID = 0x1002 -btIncomingChannelNr = 3 - -rfcommChannelID = 0 -mtu = 0 - -services = [] -counter = -1 - -def service_search_pattern(uuid): - return struct.pack("BBBBB", 0x35, 0x03, 0x19, (uuid >> 8), (uuid & 0xff)) - -def packet_handler(packet): - global state - global btstack_client - if isinstance(packet, event_factory.HCIEventDisconnectionComplete): - event = packet - testHandle = event.get_connection_handle() - print("Received disconnect, status" + str(event.get_status()) + ", handle" + str(testHandle)) - #return - - # this is a switch statement - if state == STATE.w4_btstack_working: - if isinstance(packet, event_factory.BTstackEventState): - event = packet - if event.get_state() == 2: - print("BTstack working. Start SDP inquiry.") - state = STATE.w4_query_result - serviceSearchPattern = service_search_pattern(rfcommServiceUUID) - btstack_client.sdp_client_query_rfcomm_services(remote, serviceSearchPattern) - elif state == STATE.w4_query_result: - if isinstance(packet, event_factory.SDPEventQueryRFCOMMService): - service = packet - services.append(service.get_rfcomm_channel()) - if isinstance(packet, event_factory.SDPEventQueryComplete): - for channel_nr in services: - print("Found rfcomm channel nr: " + str(channel_nr)) - if channel_nr == btIncomingChannelNr: - state = STATE.w4_connected - print("Connect to channel nr " + str(channel_nr)) - btstack_client.rfcomm_create_channel(remote, 3) - elif state == STATE.w4_connected: - if isinstance(packet, event_factory.RFCOMMEventChannelOpened): - e = packet - print("RFCOMMEventChannelOpened with status " + str(e.get_status())) - if e.get_status(): - print("RFCOMM channel open failed, status " + str(e.get_status())) - else: - state = STATE.active - rfcommChannelID = e.get_rfcomm_cid() - mtu = e.get_max_frame_size() - print("RFCOMM channel open succeeded. New RFCOMM Channel ID %s, max frame size %s" % (str(rfcommChannelID), str(mtu))) - counter = 0 - while state == STATE.active: - time.sleep(1) - data = ("BTstack SPP Counter %d\n" % counter).encode() - print("would send now") - #btstack_client.rfcomm_send_data(rfcommChannelID, data) - elif state == STATE.active: - if isinstance(packet, event_factory.RFCOMM_Data_Packet): - print("Received RFCOMM data packet: " + packet.toString()) - -# check version -if sys.version_info < (3, 0): - print('BTstack Server Client library, requires Python 3.x or higher.\n') - sys.exit(10) - -# Client for BTstack Server -btstack_client = btstack_client.BTstackClient() - -# connect to slient, register for HCI packets and power up -ok = btstack_client.connect() -if ok: - btstack_client.register_packet_handler(packet_handler) - state = STATE.w4_btstack_working - btstack_client.btstack_set_power_mode(1) - btstack_client.run() - diff --git a/platform/daemon/src/daemon.c b/platform/daemon/src/daemon.c index ac9463088f..2402b884c7 100644 --- a/platform/daemon/src/daemon.c +++ b/platform/daemon/src/daemon.c @@ -30,7 +30,7 @@ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Please inquire about commercial licensing options at + * Please inquire about commercial licensing options at * contact@bluekitchen-gmbh.com * */ @@ -55,9 +55,6 @@ #include #include -/* ... ?? */ -#include "bluetooth_comapny_id.h" - #ifdef _WIN32 #include "Winsock2.h" #endif @@ -127,7 +124,7 @@ const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void); // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT #ifndef BTSTACK_LOG_TYPE -#define BTSTACK_LOG_TYPE HCI_DUMP_PACKETLOGGER +#define BTSTACK_LOG_TYPE HCI_DUMP_PACKETLOGGER #endif #define DAEMON_NO_ACTIVE_CLIENT_TIMEOUT 10000 @@ -149,7 +146,7 @@ const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void); typedef struct { // linked list - assert: first field btstack_linked_item_t item; - + // connection connection_t * connection; @@ -162,10 +159,10 @@ typedef struct { // power mode HCI_POWER_MODE power_mode; - + // discoverable uint8_t discoverable; - + } client_state_t; typedef struct btstack_linked_list_uint32 { @@ -271,41 +268,41 @@ static void daemon_no_connections_timeout(struct btstack_timer_source *ts){ static void add_uint32_to_list(btstack_linked_list_t *list, uint32_t value){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); if ( item->value == value) return; // already in list - } + } btstack_linked_list_uint32_t * item = malloc(sizeof(btstack_linked_list_uint32_t)); - if (!item) return; + if (!item) return; memset(item, 0, sizeof(btstack_linked_list_uint32_t)); item->value = value; btstack_linked_list_add(list, (btstack_linked_item_t *) item); } static void remove_and_free_uint32_from_list(btstack_linked_list_t *list, uint32_t value){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); if ( item->value != value) continue; btstack_linked_list_remove(list, (btstack_linked_item_t *) item); free(item); - } + } } static void daemon_add_client_rfcomm_service(connection_t * connection, uint16_t service_channel){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - add_uint32_to_list(&client_state->rfcomm_services, service_channel); + add_uint32_to_list(&client_state->rfcomm_services, service_channel); } static void daemon_remove_client_rfcomm_service(connection_t * connection, uint16_t service_channel){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - remove_and_free_uint32_from_list(&client_state->rfcomm_services, service_channel); + remove_and_free_uint32_from_list(&client_state->rfcomm_services, service_channel); } static void daemon_add_client_rfcomm_channel(connection_t * connection, uint16_t cid){ @@ -347,27 +344,27 @@ static void daemon_remove_client_l2cap_channel(connection_t * connection, uint16 static void daemon_add_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - add_uint32_to_list(&client_state->sdp_record_handles, handle); + add_uint32_to_list(&client_state->sdp_record_handles, handle); } static void daemon_remove_client_sdp_service_record_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - remove_and_free_uint32_from_list(&client_state->sdp_record_handles, handle); + remove_and_free_uint32_from_list(&client_state->sdp_record_handles, handle); } #ifdef ENABLE_BLE static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t handle){ client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - + // check if handle already exists in the gatt_con_handles list btstack_linked_list_iterator_t it; int handle_found = 0; btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); - if (item->value == handle){ + if (item->value == handle){ handle_found = 1; break; } @@ -376,7 +373,7 @@ static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t ha if (!handle_found){ add_uint32_to_list(&client_state->gatt_con_handles, handle); } - + // check if there is a helper with given handle btstack_linked_list_gatt_client_helper_t * gatt_helper = NULL; btstack_linked_list_iterator_init(&it, &gatt_client_helpers); @@ -391,7 +388,7 @@ static void daemon_add_gatt_client_handle(connection_t * connection, uint32_t ha // if gatt_helper doesn't exist, create it and add it to gatt_client_helpers list if (!gatt_helper){ gatt_helper = calloc(sizeof(btstack_linked_list_gatt_client_helper_t), 1); - if (!gatt_helper) return; + if (!gatt_helper) return; gatt_helper->con_handle = handle; btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) gatt_helper); } @@ -422,8 +419,8 @@ static void daemon_remove_gatt_client_handle(connection_t * connection, uint32_t // might be extracted or vanish totally client_state_t * client_state = client_for_connection(connection); if (!client_state) return; - - btstack_linked_list_iterator_t it; + + btstack_linked_list_iterator_t it; // remove handle from gatt_con_handles list btstack_linked_list_iterator_init(&it, &client_state->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ @@ -472,7 +469,7 @@ static void daemon_remove_gatt_client_handle(connection_t * connection, uint32_t static void daemon_remove_gatt_client_helper(uint32_t con_handle){ log_info("daemon_remove_gatt_client_helper for con_handle 0x%04x", con_handle); - btstack_linked_list_iterator_t it, cl; + btstack_linked_list_iterator_t it, cl; // find helper with given handle btstack_linked_list_gatt_client_helper_t * helper = NULL; btstack_linked_list_iterator_init(&it, &gatt_client_helpers); @@ -485,7 +482,7 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ } if (!helper) return; - + // remove all connection from helper btstack_linked_list_iterator_init(&it, &helper->all_connections); while (btstack_linked_list_iterator_has_next(&it)){ @@ -496,7 +493,7 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ btstack_linked_list_remove(&gatt_client_helpers, (btstack_linked_item_t *) helper); free(helper); - + btstack_linked_list_iterator_init(&cl, &clients); while (btstack_linked_list_iterator_has_next(&cl)){ client_state_t * client_state = (client_state_t *) btstack_linked_list_iterator_next(&cl); @@ -513,10 +510,10 @@ static void daemon_remove_gatt_client_helper(uint32_t con_handle){ #endif static void daemon_rfcomm_close_connection(client_state_t * daemon_client){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_t *rfcomm_services = &daemon_client->rfcomm_services; btstack_linked_list_t *rfcomm_cids = &daemon_client->rfcomm_cids; - + btstack_linked_list_iterator_init(&it, rfcomm_services); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -536,10 +533,10 @@ static void daemon_rfcomm_close_connection(client_state_t * daemon_client){ static void daemon_l2cap_close_connection(client_state_t * daemon_client){ - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_t *l2cap_psms = &daemon_client->l2cap_psms; btstack_linked_list_t *l2cap_cids = &daemon_client->l2cap_cids; - + btstack_linked_list_iterator_init(&it, l2cap_psms); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -559,7 +556,7 @@ static void daemon_l2cap_close_connection(client_state_t * daemon_client){ static void daemon_sdp_close_connection(client_state_t * daemon_client){ btstack_linked_list_t * list = &daemon_client->sdp_record_handles; - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, list); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_uint32_t * item = (btstack_linked_list_uint32_t*) btstack_linked_list_iterator_next(&it); @@ -593,28 +590,28 @@ static const uint8_t removeServiceRecordHandleAttributeIDList[] = { 0x36, 0x00, // pre: ServiceRecordHandle is first attribute and is not already registered in database // @returns status static uint32_t daemon_sdp_create_and_register_service(uint8_t * record){ - + // create new handle uint32_t record_handle = sdp_create_service_record_handle(); - - // calculate size of new service record: DES (2 byte len) + + // calculate size of new service record: DES (2 byte len) // + ServiceRecordHandle attribute (UINT16 UINT32) + size of existing attributes uint16_t recordSize = 3 + (3 + 5) + de_get_data_size(record); - + // alloc memory for new service record uint8_t * newRecord = malloc(recordSize); if (!newRecord) return 0; - + // create DES for new record de_create_sequence(newRecord); - + // set service record handle de_add_number(newRecord, DE_UINT, DE_SIZE_16, 0); de_add_number(newRecord, DE_UINT, DE_SIZE_32, record_handle); - + // add other attributes sdp_append_attributes_in_attributeIDList(record, (uint8_t *) removeServiceRecordHandleAttributeIDList, 0, recordSize, newRecord); - + uint8_t status = sdp_register_service(newRecord); if (status) { @@ -647,7 +644,7 @@ static void daemon_gatt_client_close_connection(connection_t * connection){ client_state_t * client = client_for_connection(connection); if (!client) return; - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; btstack_linked_list_iterator_init(&it, &client->gatt_con_handles); while (btstack_linked_list_iterator_has_next(&it)){ @@ -673,7 +670,7 @@ static void daemon_disconnect_client(connection_t * connection){ #endif btstack_linked_list_remove(&clients, (btstack_linked_item_t *) client); - free(client); + free(client); } static void hci_emit_btstack_version(void){ @@ -710,8 +707,8 @@ static void send_l2cap_connection_open_failed(connection_t * connection, bd_addr // little_endian_store_16(event, 13, channel->local_cid); // little_endian_store_16(event, 15, channel->remote_cid); // little_endian_store_16(event, 17, channel->local_mtu); - // little_endian_store_16(event, 19, channel->remote_mtu); - // little_endian_store_16(event, 21, channel->flush_timeout); + // little_endian_store_16(event, 19, channel->remote_mtu); + // little_endian_store_16(event, 21, channel->flush_timeout); hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event)); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event)); } @@ -767,10 +764,10 @@ static void sdp_emit_service_registered(void *connection, uint32_t handle, uint8 #ifdef ENABLE_BLE btstack_linked_list_gatt_client_helper_t * daemon_get_gatt_client_helper(hci_con_handle_t con_handle) { - btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_t it; if (!gatt_client_helpers) return NULL; log_debug("daemon_get_gatt_client_helper for handle 0x%02x", con_handle); - + btstack_linked_list_iterator_init(&it, &gatt_client_helpers); while (btstack_linked_list_iterator_has_next(&it)){ btstack_linked_list_gatt_client_helper_t * item = (btstack_linked_list_gatt_client_helper_t*) btstack_linked_list_iterator_next(&it); @@ -807,7 +804,7 @@ static void send_gatt_mtu_event(connection_t * connection, hci_con_handle_t con_ } btstack_linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(connection_t *connection, uint8_t *packet, int track_active_connection) { - hci_con_handle_t con_handle = little_endian_read_16(packet, 3); + hci_con_handle_t con_handle = little_endian_read_16(packet, 3); log_info("daemon_setup_gatt_client_request for handle 0x%02x", con_handle); hci_connection_t * hci_con = hci_connection_for_handle(con_handle); if ((hci_con == NULL) || (hci_con->state != OPEN)){ @@ -820,18 +817,18 @@ btstack_linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(conn if (!helper){ log_info("helper does not exist"); helper = calloc(sizeof(btstack_linked_list_gatt_client_helper_t), 1); - if (!helper) return NULL; + if (!helper) return NULL; helper->con_handle = con_handle; btstack_linked_list_add(&gatt_client_helpers, (btstack_linked_item_t *) helper); - } - + } + if (track_active_connection && helper->active_connection){ send_gatt_query_complete(connection, con_handle, GATT_CLIENT_BUSY); return NULL; } daemon_add_gatt_client_handle(connection, con_handle); - + if (track_active_connection){ // remember connection responsible for this request helper->active_connection = connection; @@ -874,7 +871,7 @@ static void btstack_server_intel_firmware_done(int result){ #endif static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){ - + bd_addr_t addr; #ifdef ENABLE_BLE bd_addr_type_t addr_type; @@ -936,14 +933,14 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui case BTSTACK_GET_VERSION: log_info("BTSTACK_GET_VERSION"); hci_emit_btstack_version(); - break; + break; #ifdef HAVE_PLATFORM_IPHONE_OS case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED %u", packet[3]); btstack_control_iphone_bt_set_enabled(packet[3]); hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled()); break; - + case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED"); hci_emit_system_bluetooth_enabled(btstack_control_iphone_bt_enabled()); @@ -1075,7 +1072,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui cid = little_endian_read_16(packet, 3); reason = packet[7]; rfcomm_decline_connection(cid); - break; + break; case RFCOMM_GRANT_CREDITS: cid = little_endian_read_16(packet, 3); rfcomm_credits = packet[5]; @@ -1115,7 +1112,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui free(data); } break; - case SDP_CLIENT_QUERY_RFCOMM_SERVICES: + case SDP_CLIENT_QUERY_RFCOMM_SERVICES: reverse_bd_addr(&packet[3], addr); serviceSearchPatternLen = de_get_len(&packet[9]); @@ -1131,10 +1128,10 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); - - attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); + + attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); memcpy(attributeIDList, &packet[9+serviceSearchPatternLen], attributeIDListLen); - + sdp_client_query(&handle_sdp_client_query_result, addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]); break; #ifdef ENABLE_BLE @@ -1183,7 +1180,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_service(packet, 5, &service); gatt_client_find_included_services_for_service(&handle_gatt_client_event, gatt_helper->con_handle, &service); break; - + case GATT_DISCOVER_CHARACTERISTICS_FOR_SERVICE: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1); if (!gatt_helper) break; @@ -1203,7 +1200,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_characteristic(packet, 5, &characteristic); gatt_client_discover_characteristic_descriptors(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic); break; - + case GATT_READ_VALUE_OF_CHARACTERISTIC: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 1); if (!gatt_helper) break; @@ -1216,7 +1213,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui gatt_client_deserialize_characteristic(packet, 5, &characteristic); gatt_client_read_long_value_of_characteristic(&handle_gatt_client_event, gatt_helper->con_handle, &characteristic); break; - + case GATT_WRITE_VALUE_OF_CHARACTERISTIC_WITHOUT_RESPONSE: gatt_helper = daemon_setup_gatt_client_request(connection, packet, 0); // note: don't track active connection if (!gatt_helper) break; @@ -1316,7 +1313,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui sm_just_works_confirm(little_endian_read_16(packet, 3)); break; case SM_NUMERIC_COMPARISON_CONFIRM: - sm_numeric_comparison_confirm(little_endian_read_16(packet, 3)); + sm_numeric_comparison_confirm(little_endian_read_16(packet, 3)); break; case SM_PASSKEY_INPUT: sm_passkey_input(little_endian_read_16(packet, 3), little_endian_read_32(packet, 5)); @@ -1326,18 +1323,18 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui log_error("Error: command %u not implemented:", READ_CMD_OCF(packet)); break; } - + return 0; } static int daemon_client_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length){ - + int err = 0; client_state_t * client; - + switch (packet_type){ case HCI_COMMAND_DATA_PACKET: - if (READ_CMD_OGF(data) != OGF_BTSTACK) { + if (READ_CMD_OGF(data) != OGF_BTSTACK) { // HCI Command hci_send_cmd_packet(data, length); } else { @@ -1441,9 +1438,9 @@ static void preferences_changed_callback(void){ #endif static void deamon_status_event_handler(uint8_t *packet, uint16_t size){ - + uint8_t update_status = 0; - + // handle state event switch (hci_event_packet_get_type(packet)) { case BTSTACK_EVENT_STATE: @@ -1459,23 +1456,23 @@ static void deamon_status_event_handler(uint8_t *packet, uint16_t size){ default: break; } - - // choose full bluetooth state + + // choose full bluetooth state if (update_status) { update_ui_status(); } } static void daemon_retry_parked(void){ - + // socket_connection_retry_parked is not reentrant static int retry_mutex = 0; // lock mutex if (retry_mutex) return; retry_mutex = 1; - - // ... try sending again + + // ... try sending again socket_connection_retry_parked(); // unlock mutex @@ -1561,11 +1558,11 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 packet[9+248] = 0; btstack_device_name_db->put_name(addr, (device_name_t *)&packet[9]); break; - + case HCI_EVENT_INQUIRY_RESULT: case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:{ if (!btstack_device_name_db) break; - + // first send inq result packet daemon_emit_packet(connection, packet_type, channel, packet, size); @@ -1578,22 +1575,22 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 remote_name_event[1] = sizeof(remote_name_event) - 2 - 1; remote_name_event[2] = 0; // just to be compatible with HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE reverse_bd_addr(addr, &remote_name_event[3]); - + remote_name_event[9+248] = 0; // assert \0 for log_info log_info("DAEMON_EVENT_REMOTE_NAME_CACHED %s = '%s'", bd_addr_to_str(addr), &remote_name_event[9]); hci_dump_packet(HCI_EVENT_PACKET, 0, remote_name_event, sizeof(remote_name_event)-1); daemon_emit_packet(connection, HCI_EVENT_PACKET, channel, remote_name_event, sizeof(remote_name_event) -1); } - offset += 14; // 6 + 1 + 1 + 1 + 3 + 2; + offset += 14; // 6 + 1 + 1 + 1 + 3 + 2; } return; } - + case DAEMON_EVENT_RFCOMM_CREDITS: // RFCOMM CREDITS received... daemon_retry_parked(); break; - + case RFCOMM_EVENT_CHANNEL_OPENED: cid = little_endian_read_16(packet, 13); connection = connection_for_rfcomm_cid(cid); @@ -1643,14 +1640,14 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16 connection = connection_for_l2cap_cid(channel); if (!connection) return; break; - case RFCOMM_DATA_PACKET: + case RFCOMM_DATA_PACKET: connection = connection_for_l2cap_cid(channel); if (!connection) return; break; default: break; } - + daemon_emit_packet(connection, packet_type, channel, packet, size); } @@ -1666,7 +1663,7 @@ static void handle_sdp_rfcomm_service_result(uint8_t packet_type, uint16_t chann hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); socket_connection_send_packet(sdp_client_query_connection, HCI_EVENT_PACKET, 0, packet, size); break; - default: + default: break; } } @@ -1688,7 +1685,7 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)){ log_info_hexdump(attribute_value, sdp_event_query_attribute_byte_get_attribute_length(packet)); - int event_len = 1 + 3 * 2 + sdp_event_query_attribute_byte_get_attribute_length(packet); + int event_len = 1 + 3 * 2 + sdp_event_query_attribute_byte_get_attribute_length(packet); uint8_t event[event_len]; event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE; little_endian_store_16(event, 1, sdp_event_query_attribute_byte_get_record_id(packet)); @@ -1727,13 +1724,13 @@ static void power_notification_callback(POWER_NOTIFICATION_t notification){ } static void daemon_sigint_handler(int param){ - + #ifdef HAVE_PLATFORM_IPHONE_OS // notify daemons notify_post("ch.ringwald.btstack.stopped"); #endif - - log_info(" <= SIGINT received, shutting down..\n"); + + log_info(" <= SIGINT received, shutting down..\n"); int send_power_off = 1; #ifdef HAVE_INTEL_USB @@ -1745,9 +1742,9 @@ static void daemon_sigint_handler(int param){ hci_power_control( HCI_POWER_OFF); hci_close(); } - - log_info("Good bye, see you.\n"); - + + log_info("Good bye, see you.\n"); + exit(0); } @@ -1765,7 +1762,7 @@ static void stop_power_off_timer(void){ } static void start_power_off_timer(void){ -#ifdef USE_POWER_OFF_TIMER +#ifdef USE_POWER_OFF_TIMER stop_power_off_timer(); btstack_run_loop_set_timer(&timeout, DAEMON_NO_ACTIVE_CLIENT_TIMEOUT); btstack_run_loop_add_timer(&timeout); @@ -1798,9 +1795,9 @@ static void clients_clear_power_request(void){ } static int clients_require_power_on(void){ - + if (global_enable) return 1; - + btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) clients; it ; it = it->next){ client_state_t * client_state = (client_state_t *) it; @@ -1822,7 +1819,6 @@ static int clients_require_discoverable(void){ return 0; } -/* static void usage(const char * name) { printf("%s, BTstack background daemon\n", name); printf("usage: %s [--help] [--tcp]\n", name); @@ -1830,9 +1826,8 @@ static void usage(const char * name) { printf(" --tcp use TCP server on port %u\n", BTSTACK_PORT); printf("Without the --tcp option, BTstack Server is listening on unix domain socket %s\n\n", BTSTACK_UNIX); } -*/ -#ifdef HAVE_PLATFORM_IPHONE_OS +#ifdef HAVE_PLATFORM_IPHONE_OS static void * btstack_run_loop_thread(void *context){ btstack_run_loop_execute(); return NULL; @@ -1866,7 +1861,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint if (!gatt_client_helper){ log_info("daemon handle_gatt_client_event: gc helper for handle 0x%2x is NULL.", con_handle); return; - } + } connection_t *connection = NULL; @@ -1875,7 +1870,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint case GATT_EVENT_NOTIFICATION: case GATT_EVENT_INDICATION:{ hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); - + btstack_linked_item_t *it; for (it = (btstack_linked_item_t *) clients; it ; it = it->next){ client_state_t * client_state = (client_state_t *) it; @@ -1905,7 +1900,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, packet, size); break; - + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: case GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT: offset = little_endian_read_16(packet, 6); @@ -1977,7 +1972,7 @@ static void btstack_server_configure_stack(void){ log_info("config.h: ENABLE_RFCOMM\n"); rfcomm_init(); #endif - + #ifdef ENABLE_SDP sdp_init(); #endif @@ -1987,14 +1982,14 @@ static void btstack_server_configure_stack(void){ sm_event_callback_registration.callback = &stack_packet_handler; sm_add_event_handler(&sm_event_callback_registration); // sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); - // sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); + // sm_set_authentication_requirements( SM_AUTHREQ_BONDING | SM_AUTHREQ_MITM_PROTECTION); // GATT Client gatt_client_init(); gatt_client_listen_for_characteristic_value_updates(&daemon_gatt_client_notifications, &handle_gatt_client_event, GATT_CLIENT_ANY_CONNECTION, GATT_CLIENT_ANY_VALUE_HANDLE); // GATT Server - empty attribute database - att_server_init(NULL, NULL, NULL); + att_server_init(NULL, NULL, NULL); #endif } @@ -2029,7 +2024,7 @@ int btstack_server_run(int tcp_flag){ btstack_control_t * control = NULL; const btstack_uart_block_t * uart_block_implementation = NULL; (void) uart_block_implementation; - + #ifdef HAVE_TRANSPORT_H4 hci_transport_config_uart.type = HCI_TRANSPORT_CONFIG_UART; hci_transport_config_uart.baudrate_init = UART_SPEED; @@ -2044,7 +2039,7 @@ int btstack_server_run(int tcp_flag){ uart_block_implementation = btstack_uart_block_posix_instance(); #endif #endif - + #ifdef HAVE_PLATFORM_IPHONE_OS // use default (max) UART baudrate over netgraph interface hci_transport_config_uart.baudrate_init = 0; @@ -2091,14 +2086,14 @@ int btstack_server_run(int tcp_flag){ newLoggingEnabled = platform_iphone_logging_enabled(); #endif daemon_set_logging_enabled(newLoggingEnabled); - + // dump version log_info("BTStack Server started\n"); log_info("version %s, build %s", BTSTACK_VERSION, BTSTACK_DATE); #ifndef HAVE_INTEL_USB btstack_server_configure_stack(); -#endif +#endif #ifdef USE_LAUNCHD socket_connection_create_launchd(); @@ -2113,8 +2108,8 @@ int btstack_server_run(int tcp_flag){ } #endif socket_connection_register_packet_callback(&daemon_client_handler); - -#ifdef HAVE_PLATFORM_IPHONE_OS + +#ifdef HAVE_PLATFORM_IPHONE_OS // notify daemons notify_post("ch.ringwald.btstack.started"); @@ -2135,21 +2130,20 @@ int btstack_server_run_tcp(void){ } int main (int argc, char * const * argv){ - - /* + int tcp_flag = 0; struct option long_options[] = { { "tcp", no_argument, &tcp_flag, 1 }, { "help", no_argument, 0, 0 }, { 0,0,0,0 } // This is a filler for -1 }; - + while (true) { int c; int option_index = -1; c = getopt_long(argc, argv, "h", long_options, &option_index); if (c == -1) break; // no more option - + // treat long parameter first if (option_index == -1) { switch (c) { @@ -2168,22 +2162,7 @@ int main (int argc, char * const * argv){ } } } - */ - uint8_t initiator_usb_device_id; - int tcp_flag = 0; - - /* Parse arguments */ - if(argc < 3) - { - printf("Too few arguments provided\n"); - printf("Usage:./%s device_id port\n", argv[0]); - exit(0); - } - - initiator_usb_device_id = strtol(argv[1], 0, 10); - tcp_flag = strtol(argv[2], 0, 10); - hci_transport_usb_set_address(initiator_usb_device_id); - + #ifndef HAVE_UNIX_SOCKETS // TCP is default if there are no unix sockets tcp_flag = 1; diff --git a/src/hci_transport.h b/src/hci_transport.h index 8586370cb4..8767e124ad 100644 --- a/src/hci_transport.h +++ b/src/hci_transport.h @@ -172,11 +172,6 @@ const hci_transport_t * hci_transport_usb_instance(void); */ void hci_transport_usb_set_path(int len, uint8_t * port_numbers); -/** - * @brief Specify USB Bluetooth device via device address - */ -void hci_transport_usb_set_address(uint8_t _dev_addr); - /* API_END */ #if defined __cplusplus From 3cd6ef39dcd068eca2d4cb5bf1f364449fb844a0 Mon Sep 17 00:00:00 2001 From: Maximilian von Tschirschnitz Date: Tue, 23 Jun 2020 11:42:08 +0200 Subject: [PATCH 4/4] forgot to also edit .h file now its complete Signed-off-by: Maximilian von Tschirschnitz --- src/hci_transport.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hci_transport.h b/src/hci_transport.h index 8767e124ad..acbf7dce49 100644 --- a/src/hci_transport.h +++ b/src/hci_transport.h @@ -172,6 +172,11 @@ const hci_transport_t * hci_transport_usb_instance(void); */ void hci_transport_usb_set_path(int len, uint8_t * port_numbers); +/** + * @brief Specify USB Bluetooth device via device address + */ +void hci_transport_usb_set_address(uint8_t _dev_addr); + /* API_END */ #if defined __cplusplus