summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/device/bluetoth/bluez.c
Side-by-side diff
Diffstat (limited to 'gammu/emb/common/device/bluetoth/bluez.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/device/bluetoth/bluez.c207
1 files changed, 207 insertions, 0 deletions
diff --git a/gammu/emb/common/device/bluetoth/bluez.c b/gammu/emb/common/device/bluetoth/bluez.c
new file mode 100644
index 0000000..8a4807e
--- a/dev/null
+++ b/gammu/emb/common/device/bluetoth/bluez.c
@@ -0,0 +1,207 @@
+/* Based on work by Marcel Holtmann and other authors of Bluez */
+
+#include "../../gsmstate.h"
+
+#ifdef GSM_ENABLE_BLUETOOTHDEVICE
+#ifdef GSM_ENABLE_BLUEZ
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#include "../../gsmcomon.h"
+#include "../devfunc.h"
+#include "bluetoth.h"
+
+GSM_Error bluetooth_connect(GSM_StateMachine *s, int port, char *device)
+{
+ GSM_Device_BlueToothData *d = &s->Device.Data.BlueTooth;
+ struct sockaddr_rc laddr, raddr;
+ bdaddr_t bdaddr;
+ int fd;
+
+ smprintf(s, "Connecting to RF channel %i\n",port);
+
+ fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (fd < 0) {
+ dbgprintf("Can't create socket\n");
+ return ERR_DEVICENODRIVER;
+ }
+
+ bacpy(&laddr.rc_bdaddr, BDADDR_ANY);
+ laddr.rc_family = AF_BLUETOOTH;
+ laddr.rc_channel = 0;
+
+ if (bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
+ dbgprintf("Can't bind socket\n");
+ close(fd);
+ return ERR_DEVICEOPENERROR;
+ }
+
+ str2ba(device, &bdaddr);
+ bacpy(&raddr.rc_bdaddr, &bdaddr);
+ raddr.rc_family = AF_BLUETOOTH;
+ raddr.rc_channel = port;
+
+ if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) {
+ dbgprintf("Can't connect\n");
+ close(fd);
+ return ERR_DEVICEOPENERROR;
+ }
+
+ d->hPhone = fd;
+ return ERR_NONE;
+}
+
+#ifdef BLUETOOTH_RF_SEARCHING
+
+struct search_context {
+ char *svc;
+ uuid_t group;
+ int tree;
+ uint32_t handle;
+};
+
+static void print_service_desc(void *value, void *user)
+{
+ sdp_data_t *p = (sdp_data_t *)value;
+ int i = 0, proto = 0, *channel = (int *)user;
+
+ for (; p; p = p->next, i++) {
+ switch (p->dtd) {
+ case SDP_UUID16:
+ case SDP_UUID32:
+ case SDP_UUID128:
+ proto = 1;//sdp_uuid_to_proto(&p->val.uuid);
+ break;
+ case SDP_UINT8:
+ if (proto == RFCOMM_UUID) {
+ (*channel) = p->val.uint8;
+ return;
+ }
+ break;
+ }
+ }
+}
+
+void print_access_protos(value, user)
+{
+ sdp_list_t *protDescSeq = (sdp_list_t *)value;
+ int *channel = (int *)user;
+
+ sdp_list_foreach(protDescSeq,print_service_desc,channel);
+}
+
+static GSM_Error bluetooth_checkdevice(GSM_StateMachine *s, bdaddr_t *bdaddr, struct search_context *context)
+{
+ sdp_session_t *sess;
+ sdp_list_t *attrid, *search, *seq, *next, *proto = 0;
+ uint32_t range = 0x0000ffff;
+ char str[20];
+ sdp_record_t *rec;
+ sdp_data_t *d;
+ bdaddr_t interface;
+ struct search_context subcontext;
+ int channel,channel2;
+
+ bacpy(&interface,BDADDR_ANY);
+
+ ba2str(bdaddr, str);
+ smprintf(s,"%s\n", str);
+
+ sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY);
+ if (!sess) {
+ dbgprintf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno));
+ return ERR_UNKNOWN;
+ }
+
+ attrid = sdp_list_append(0, &range);
+ search = sdp_list_append(0, &context->group);
+ if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) {
+ dbgprintf("Service Search failed: %s\n", strerror(errno));
+ sdp_close(sess);
+ return ERR_UNKNOWN;
+ }
+ sdp_list_free(attrid, 0);
+ sdp_list_free(search, 0);
+
+ channel2 = -1;
+ for (; seq; seq = next) {
+ rec = (sdp_record_t *) seq->data;
+
+ if (channel2 == -1) {
+ if (!context->tree) {
+ d = sdp_data_get(rec,SDP_ATTR_SVCNAME_PRIMARY);
+
+ if (false) {
+ channel = -1;
+ sdp_list_foreach(proto,print_access_protos,&channel);
+ //sdp_list_free(proto,(sdp_free_func_t)sdp_data_free);
+ }
+ smprintf(s,"Channel %i",channel);
+ if (d) smprintf(s," - \"%s\"",d->val.str);
+ smprintf(s,"\n");
+ if (channel2 == -1 && bluetooth_checkservicename(s, d->val.str) == ERR_NONE) {
+ channel2 = channel;
+ }
+ }
+ if (sdp_get_group_id(rec,&subcontext.group) != -1) {
+ memcpy(&subcontext, context, sizeof(struct search_context));
+ if (subcontext.group.value.uuid16 != context->group.value.uuid16) bluetooth_checkdevice(s,bdaddr,&subcontext);
+ }
+ }
+
+ next = seq->next;
+ free(seq);
+ //sdp_record_free(rec);
+ }
+ sdp_close(sess);
+
+ if (channel2 != -1) return bluetooth_connect(s, channel2, str);
+
+ return ERR_UNKNOWN;
+}
+
+GSM_Error bluetooth_findchannel(GSM_StateMachine *s)
+{
+ inquiry_info ii[20];
+ uint8_t count = 0;
+ int i;
+ struct search_context context;
+ GSM_Error error = ERR_NOTSUPPORTED;
+
+ memset(&context, '\0', sizeof(struct search_context));
+ //sdp_uuid16_create(&(context.group),PUBLIC_BROWSE_GROUP);
+
+ if (!strcmp(s->CurrentConfig->Device,"/dev/ttyS1")) {
+ dbgprintf("Searching for devices\n");
+ if (sdp_general_inquiry(ii, 20, 8, &count) < 0) {
+ return ERR_UNKNOWN;
+ }
+ } else {
+ count = 1;
+ str2ba(s->CurrentConfig->Device,&ii[0].bdaddr);
+ }
+ for (i=0;i<count;i++) {
+ error = bluetooth_checkdevice(s,&ii[i].bdaddr,&context);
+ if (error == ERR_NONE) return error;
+ }
+ return error;
+}
+
+#endif
+#endif
+#endif
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */