X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=libaltos%2Flibaltos_linux.c;h=255b977347296078d66bf31220cd742e542cbd78;hp=d7cd15cfe79357a92b7f44c680c9b8bb6038ca4a;hb=adf4bec88df1822031e1a8b00422de8b8b0c0cd4;hpb=1594691ea88ca84634eea237ac8137a5bdc19f5c diff --git a/libaltos/libaltos_linux.c b/libaltos/libaltos_linux.c index d7cd15cf..255b9773 100644 --- a/libaltos/libaltos_linux.c +++ b/libaltos/libaltos_linux.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,6 +26,8 @@ #include #include #include +#include +#include static char * cc_fullname (char *dir, char *file) @@ -379,6 +382,30 @@ bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr)) bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags)) #define hci_inquiry altos_hci_inquiry +bt_func(sdp_connect, sdp_session_t *, 0, (const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags), (src, dst, flags)) +#define sdp_connect altos_sdp_connect + +bt_func(sdp_uuid16_create, uuid_t *, 0, (uuid_t *uuid, uint16_t data), (uuid, data)) +#define sdp_uuid16_create altos_sdp_uuid16_create + +bt_func(sdp_list_append, sdp_list_t *, 0, (sdp_list_t *list, void *d), (list, d)) +#define sdp_list_append altos_sdp_list_append + +bt_func(sdp_service_search_attr_req, int, -1, (sdp_session_t *session, const sdp_list_t *search, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list, sdp_list_t **rsp_list), (session, search, reqtype, attrid_list, rsp_list)) +#define sdp_service_search_attr_req altos_sdp_service_search_attr_req + +bt_func(sdp_uuid_to_proto, int, 0, (uuid_t *uuid), (uuid)) +#define sdp_uuid_to_proto altos_sdp_uuid_to_proto + +bt_func(sdp_get_access_protos, int, 0, (const sdp_record_t *rec, sdp_list_t **protos), (rec, protos)) +#define sdp_get_access_protos altos_sdp_get_access_protos + +bt_func(sdp_get_proto_port, int, 0, (const sdp_list_t *list, int proto), (list, proto)) +#define sdp_get_proto_port altos_sdp_get_proto_port + +bt_func(sdp_close, int, 0, (sdp_session_t *session), (session)) +#define sdp_close altos_sdp_close + struct altos_bt_list { inquiry_info *ii; int sock; @@ -477,7 +504,68 @@ altos_bt_open(struct altos_bt_device *device) struct sockaddr_rc addr = { 0 }; int status, i; struct altos_file_posix *file; + sdp_session_t *session = NULL; + int channel = 0; + if (str2ba(device->addr, &addr.rc_bdaddr) < 0) { + altos_set_last_posix_error(); + goto no_file; + } + +#if 0 + /* + * Search for the RFCOMM service to get the right channel + */ + session = sdp_connect(BDADDR_ANY, &addr.rc_bdaddr, SDP_RETRY_IF_BUSY); + + if (session) { + static const uint8_t svc_uuid_int[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x11, 0x01 + }; + int err; + uuid_t svc_uuid; + uint32_t range; + sdp_list_t *search_list, *attrid_list; + sdp_list_t *response_list = NULL, *r; + sdp_uuid16_create(&svc_uuid, PUBLIC_BROWSE_GROUP); + search_list = sdp_list_append(NULL, &svc_uuid); + + range = 0x0000ffff; + attrid_list = sdp_list_append(NULL, &range); + + err = sdp_service_search_attr_req(session, search_list, + SDP_ATTR_REQ_RANGE, attrid_list, &response_list); + + if (err >= 0) { + for (r = response_list; r; r = r->next) { + sdp_record_t *rec = (sdp_record_t*) r->data; + sdp_list_t *proto_list; + sdp_list_t *access = NULL; + int proto; + + proto = sdp_uuid_to_proto(&rec->svclass); + + if (proto == SERIAL_PORT_SVCLASS_ID) { + sdp_get_access_protos(rec, &access); + if (access) { + int this_chan = sdp_get_proto_port(access, RFCOMM_UUID); + if (this_chan) + channel = this_chan; + } + } + } + } + + /* Leave the session open so we don't disconnect from the device before opening + * the RFCOMM channel + */ + } +#endif + if (channel == 0) + channel = altos_bt_port(device); + + /* Connect to the channel */ file = calloc(1, sizeof (struct altos_file_posix)); if (!file) { errno = ENOMEM; @@ -485,11 +573,7 @@ altos_bt_open(struct altos_bt_device *device) goto no_file; } addr.rc_family = AF_BLUETOOTH; - addr.rc_channel = 1; - if (str2ba(device->addr, &addr.rc_bdaddr) < 0) { - altos_set_last_posix_error(); - goto no_sock; - } + addr.rc_channel = channel; for (i = 0; i < 5; i++) { file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); @@ -506,10 +590,16 @@ altos_bt_open(struct altos_bt_device *device) close(file->fd); usleep(100 * 1000); } + + if (status < 0) { altos_set_last_posix_error(); goto no_link; } + + if (session) + sdp_close(session); + usleep(100 * 1000); #ifdef USE_POLL @@ -517,12 +607,14 @@ altos_bt_open(struct altos_bt_device *device) #else file->out_fd = dup(file->fd); #endif - return file; + return &file->file; no_link: close(file->fd); no_sock: free(file); no_file: + if (session) + sdp_close(session); return NULL; }