diff options
Diffstat (limited to 'cups/sdp.c')
-rw-r--r-- | cups/sdp.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/cups/sdp.c b/cups/sdp.c new file mode 100644 index 00000000..7491ab1f --- /dev/null +++ b/cups/sdp.c @@ -0,0 +1,155 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * 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 OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> +#include <sys/socket.h> + +#include <bluetooth/bluetooth.h> +#include <bluetooth/sdp.h> +#include <bluetooth/sdp_lib.h> + +#define HCRP_CTRL_UUID 0x0012 +#define HCRP_DATA_UUID 0x0014 + +#define HCR_PROFILE_ID 0x1125 +#define HCR_PRINT_SVCLASS_ID 0x1126 + +#define SDP_ATTR_ADD_PROTO_DESC_LIST 0x000d + +static int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap) +{ + sdp_data_t *pdlist, *curr; + sdp_list_t *ap = 0; + + pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); + if (pdlist == NULL) { + errno = ENODATA; + return -1; + } + + pdlist = pdlist->val.dataseq; + + for (; pdlist; pdlist = pdlist->next) { + sdp_list_t *pds = 0; + for (curr = pdlist->val.dataseq; curr; curr = curr->next) + pds = sdp_list_append(pds, curr->val.dataseq); + ap = sdp_list_append(ap, pds); + } + + *pap = ap; + + return 0; +} + +int sdp_search_hcrp(sdp_session_t *sdp, unsigned short *ctrl_psm, unsigned short *data_psm) +{ + sdp_list_t *srch, *attrs, *rsp; + uuid_t svclass; + uint16_t attr1, attr2; + int err; + + if (!sdp) + return -1; + + sdp_uuid16_create(&svclass, HCR_PRINT_SVCLASS_ID); + srch = sdp_list_append(NULL, &svclass); + + attr1 = SDP_ATTR_PROTO_DESC_LIST; + attrs = sdp_list_append(NULL, &attr1); + attr2 = SDP_ATTR_ADD_PROTO_DESC_LIST; + attrs = sdp_list_append(attrs, &attr2); + + err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp); + if (err) + return -1; + + for (; rsp; rsp = rsp->next) { + sdp_record_t *rec = (sdp_record_t *) rsp->data; + sdp_list_t *protos; + + if (!sdp_get_access_protos(rec, &protos)) { + unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID); + if (psm > 0) { + *ctrl_psm = psm; + } + } + + if (!sdp_get_add_access_protos(rec, &protos)) { + unsigned short psm = sdp_get_proto_port(protos, L2CAP_UUID); + if (psm > 0 && *ctrl_psm > 0) { + *data_psm = psm; + return 0; + } + } + } + + return -1; +} + +int sdp_search_spp(sdp_session_t *sdp, uint8_t *channel) +{ + sdp_list_t *srch, *attrs, *rsp; + uuid_t svclass; + uint16_t attr; + int err; + + if (!sdp) + return -1; + + sdp_uuid16_create(&svclass, SERIAL_PORT_SVCLASS_ID); + srch = sdp_list_append(NULL, &svclass); + + attr = SDP_ATTR_PROTO_DESC_LIST; + attrs = sdp_list_append(NULL, &attr); + + err = sdp_service_search_attr_req(sdp, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp); + if (err) + return -1; + + for (; rsp; rsp = rsp->next) { + sdp_record_t *rec = (sdp_record_t *) rsp->data; + sdp_list_t *protos; + + if (!sdp_get_access_protos(rec, &protos)) { + uint8_t ch = sdp_get_proto_port(protos, RFCOMM_UUID); + if (ch > 0) { + *channel = ch; + return 0; + } + } + } + + return -1; +} |