#include #include #include #include #include #include #include /* To compile this, use the following Bash command: * gcc -I/usr/include/glib-2.0/ -I/usr/lib/glib-2.0/include -o server-with-haskell server-with-haskell.c -lbluetooth * * Adapted from http://www.btessentials.com/examples/examples.html, under the following license: * * Copyright (c) 2007 Albert Huang & Larry Rudolph * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* Allows this service to be discovered when running sdptool. For example, you can find this service * after starting it by running * * $ sdptool browse local * * (Adapted from http://www.btessentials.com/examples/bluez/sdp-register.c) * */ sdp_session_t *register_service(uint8_t rfcomm_channel) { /* A 128-bit number used to identify this service. The words are ordered from most to least * significant, but within each word, the octets are ordered from least to most significant. * For example, the UUID represneted by this array is 00001101-0000-1000-8000-00805F9B34FB. (The * hyphenation is a convention specified by the Service Discovery Protocol of the Bluetooth Core * Specification, but is not particularly important for this program.) * * This UUID is the Bluetooth Base UUID and is commonly used for simple Bluetooth applications. * Regardless of the UUID used, it must match the one that the Armatus Android app is searching * for. */ uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F }; const char *service_name = "Armatus Bluetooth server"; const char *svc_dsc = "A HERMIT server that interfaces with the Armatus Android app"; const char *service_prov = "Armatus"; uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class_uuid; sdp_list_t *l2cap_list = 0, *rfcomm_list = 0, *root_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_class_list = 0, *profile_list = 0; sdp_data_t *channel = 0; sdp_profile_desc_t profile; sdp_record_t record = { 0 }; sdp_session_t *session = 0; // set the general service ID sdp_uuid128_create(&svc_uuid, &svc_uuid_int); sdp_set_service_id(&record, svc_uuid); char str[256] = ""; sdp_uuid2strn(&svc_uuid, str, 256); printf("Registering UUID %s\n", str); // set the service class sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID); svc_class_list = sdp_list_append(0, &svc_class_uuid); sdp_set_service_classes(&record, svc_class_list); // set the Bluetooth profile information sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profile_list = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, profile_list); // make the service record publicly browsable sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root_list = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root_list); // set l2cap information sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); l2cap_list = sdp_list_append(0, &l2cap_uuid); proto_list = sdp_list_append(0, l2cap_list); // register the RFCOMM channel for RFCOMM sockets sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel); rfcomm_list = sdp_list_append(0, &rfcomm_uuid); sdp_list_append(rfcomm_list, channel); sdp_list_append(proto_list, rfcomm_list); access_proto_list = sdp_list_append(0, proto_list); sdp_set_access_protos(&record, access_proto_list); // set the name, provider, and description sdp_set_info_attr(&record, service_name, service_prov, svc_dsc); // connect to the local SDP server, register the service record, // and disconnect session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); sdp_record_register(session, &record, 0); // cleanup sdp_data_free(channel); sdp_list_free(l2cap_list, 0); sdp_list_free(rfcomm_list, 0); sdp_list_free(root_list, 0); sdp_list_free(access_proto_list, 0); sdp_list_free(svc_class_list, 0); sdp_list_free(profile_list, 0); return session; } int init_server() { int port = 3, result, sock, client, bytes_read, bytes_sent; struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 }; char buffer[1024] = { 0 }; socklen_t opt = sizeof(rem_addr); // local bluetooth adapter loc_addr.rc_family = AF_BLUETOOTH; loc_addr.rc_bdaddr = *BDADDR_ANY; loc_addr.rc_channel = (uint8_t) port; // register service sdp_session_t *session = register_service(port); // allocate socket sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); printf("socket() returned %d\n", sock); // bind socket to port 3 of the first available result = bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr)); printf("bind() on channel %d returned %d\n", port, result); // put socket into listening mode result = listen(sock, 1); printf("listen() returned %d\n", result); //sdpRegisterL2cap(port); // accept one connection printf("calling accept()\n"); client = accept(sock, (struct sockaddr *)&rem_addr, &opt); printf("accept() returned %d\n", client); ba2str(&rem_addr.rc_bdaddr, buffer); fprintf(stderr, "accepted connection from %s\n", buffer); memset(buffer, 0, sizeof(buffer)); return client; } char *read_server(int client) { // read data from the client char input[1024] = { 0 }; int bytes_read; bytes_read = read(client, input, sizeof(input)); if (bytes_read > 0) { printf("received [%s]\n", input); return input; } else { return ""; } } void write_server(int client, char *message) { // send data to the client char messageArr[1024] = { 0 }; int bytes_sent; sprintf(messageArr, message); bytes_sent = write(client, messageArr, sizeof(messageArr)); if (bytes_sent > 0) { printf("sent [%s]\n", messageArr); } }