static void extract_hid_record(sdp_record_t *rec, struct hidp_connadd_req *req) { sdp_data_t *pdlist, *pdlist2; uint8_t attr_val; pdlist = sdp_data_get(rec, 0x0101); pdlist2 = sdp_data_get(rec, 0x0102); if (pdlist) { if (pdlist2) { if (strncmp(pdlist->val.str, pdlist2->val.str, 5)) { strncpy(req->name, pdlist2->val.str, 127); strcat(req->name, " "); } strncat(req->name, pdlist->val.str, 127 - strlen(req->name)); } else strncpy(req->name, pdlist->val.str, 127); } else { pdlist2 = sdp_data_get(rec, 0x0100); if (pdlist2) strncpy(req->name, pdlist2->val.str, 127); } pdlist = sdp_data_get(rec, SDP_ATTR_HID_PARSER_VERSION); req->parser = pdlist ? pdlist->val.uint16 : 0x0100; pdlist = sdp_data_get(rec, SDP_ATTR_HID_DEVICE_SUBCLASS); req->subclass = pdlist ? pdlist->val.uint8 : 0; pdlist = sdp_data_get(rec, SDP_ATTR_HID_COUNTRY_CODE); req->country = pdlist ? pdlist->val.uint8 : 0; pdlist = sdp_data_get(rec, SDP_ATTR_HID_VIRTUAL_CABLE); attr_val = pdlist ? pdlist->val.uint8 : 0; if (attr_val) req->flags |= (1 << HIDP_VIRTUAL_CABLE_UNPLUG); pdlist = sdp_data_get(rec, SDP_ATTR_HID_BOOT_DEVICE); attr_val = pdlist ? pdlist->val.uint8 : 0; if (attr_val) req->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE); pdlist = sdp_data_get(rec, SDP_ATTR_HID_DESCRIPTOR_LIST); if (pdlist) { pdlist = pdlist->val.dataseq; pdlist = pdlist->val.dataseq; pdlist = pdlist->next; req->rd_data = g_try_malloc0(pdlist->unitSize); if (req->rd_data) { memcpy(req->rd_data, (unsigned char *) pdlist->val.str, pdlist->unitSize); req->rd_size = pdlist->unitSize; epox_endian_quirk(req->rd_data, req->rd_size); } } }
/* See HID profile specification v1.0, "7.11.6 HIDDescriptorList" for details * on the attribute format. */ static int extract_hid_desc_data(sdp_record_t *rec, struct hidp_connadd_req *req) { sdp_data_t *d; d = sdp_data_get(rec, SDP_ATTR_HID_DESCRIPTOR_LIST); if (!d) goto invalid_desc; if (!SDP_IS_SEQ(d->dtd)) goto invalid_desc; /* First HIDDescriptor */ d = d->val.dataseq; if (!SDP_IS_SEQ(d->dtd)) goto invalid_desc; /* ClassDescriptorType */ d = d->val.dataseq; if (d->dtd != SDP_UINT8) goto invalid_desc; /* ClassDescriptorData */ d = d->next; if (!d || !SDP_IS_TEXT_STR(d->dtd)) goto invalid_desc; req->rd_data = g_try_malloc0(d->unitSize); if (req->rd_data) { memcpy(req->rd_data, d->val.str, d->unitSize); req->rd_size = d->unitSize; epox_endian_quirk(req->rd_data, req->rd_size); } return 0; invalid_desc: error("Missing or invalid HIDDescriptorList SDP attribute"); return -EINVAL; }