static void test_get_channel(struct context *cxt, gconstpointer unused) { GIOChannel *chan; chan = g_attrib_get_channel(cxt->att); g_assert(chan == cxt->att_io); }
static void update_char_desc(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; INFO("%s",chr->path); if (status == 0) { g_free(chr->desc); chr->desc = g_malloc(len); memcpy(chr->desc, pdu + 1, len - 1); chr->desc[len - 1] = '\0'; store_attribute(gatt, current->handle, GATT_CHARAC_USER_DESC_UUID, (void *) chr->desc, len); } else if (status == ATT_ECODE_INSUFF_ENC) { GIOChannel *io = g_attrib_get_channel(gatt->attrib); BtIOSecLevel level = BT_IO_SEC_HIGH; bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_SEC_LEVEL, &level, BT_IO_OPT_INVALID); if (level < BT_IO_SEC_HIGH) level++; if (bt_io_set(io, BT_IO_L2CAP, NULL, BT_IO_OPT_SEC_LEVEL, level, BT_IO_OPT_INVALID)) { gatt_read_char(gatt->attrib, current->handle, 0, update_char_desc, current); return; } } add_characteristic_descriptor(current, GATT_CHARAC_USER_DESC_UUID); query_list_remove(gatt, current); g_free(current); }
static void update_char_value(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct query_data *current = user_data; struct gatt_service *gatt = current->gatt; struct characteristic *chr = current->chr; if (status == 0) characteristic_set_value(chr, pdu + 1, len - 1); else if (status == ATT_ECODE_INSUFF_ENC) { GIOChannel *io = g_attrib_get_channel(gatt->attrib); if (bt_io_set(io, BT_IO_L2CAP, NULL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH, BT_IO_OPT_INVALID)) { gatt_read_char(gatt->attrib, chr->handle, 0, update_char_value, current); return; } } query_list_remove(gatt, current); g_free(current); }
static void report_map_read_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct bt_hog *hog = user_data; uint8_t value[HOG_REPORT_MAP_MAX_SIZE]; struct uhid_event ev; ssize_t vlen; char itemstr[20]; /* 5x3 (data) + 4 (continuation) + 1 (null) */ int i, err; GError *gerr = NULL; if (status != 0) { error("Report Map read failed: %s", att_ecode2str(status)); return; } vlen = dec_read_resp(pdu, plen, value, sizeof(value)); if (vlen < 0) { error("ATT protocol error"); return; } DBG("Report MAP:"); for (i = 0; i < vlen;) { ssize_t ilen = 0; bool long_item = false; if (get_descriptor_item_info(&value[i], vlen - i, &ilen, &long_item)) { /* Report ID is short item with prefix 100001xx */ if (!long_item && (value[i] & 0xfc) == 0x84) hog->has_report_id = TRUE; DBG("\t%s", item2string(itemstr, &value[i], ilen)); i += ilen; } else { error("Report Map parsing failed at %d", i); /* Just print remaining items at once and break */ DBG("\t%s", item2string(itemstr, &value[i], vlen - i)); break; } } /* create uHID device */ memset(&ev, 0, sizeof(ev)); ev.type = UHID_CREATE; bt_io_get(g_attrib_get_channel(hog->attrib), &gerr, BT_IO_OPT_SOURCE, ev.u.create.phys, BT_IO_OPT_DEST, ev.u.create.uniq, BT_IO_OPT_INVALID); if (gerr) { error("Failed to connection details: %s", gerr->message); g_error_free(gerr); return; } strcpy((char *) ev.u.create.name, hog->name); ev.u.create.vendor = hog->vendor; ev.u.create.product = hog->product; ev.u.create.version = hog->version; ev.u.create.country = hog->bcountrycode; ev.u.create.bus = BUS_BLUETOOTH; ev.u.create.rd_data = value; ev.u.create.rd_size = vlen; err = bt_uhid_send(hog->uhid, &ev); if (err < 0) { error("bt_uhid_send: %s", strerror(-err)); return; } bt_uhid_register(hog->uhid, UHID_OUTPUT, forward_report, hog); bt_uhid_register(hog->uhid, UHID_FEATURE, forward_report, hog); }