int32_t kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len) { vkbd_status_t st; uint8_t leds, report_id; hid_device_p hid_device; hid_data_t d; hid_item_t h; assert(s != NULL); assert(len == sizeof(vkbd_status_t)); memcpy(&st, data, sizeof(st)); leds = 0; report_id = NO_REPORT_ID; hid_device = get_hid_device(&s->bdaddr); assert(hid_device != NULL); for (d = hid_start_parse(hid_device->desc, 1 << hid_output, -1); hid_get_item(d, &h) > 0; ) { if (HID_PAGE(h.usage) == HUP_LEDS) { if (report_id == NO_REPORT_ID) report_id = h.report_ID; else if (h.report_ID != report_id) syslog(LOG_WARNING, "Output HID report IDs " \ "for %s do not match: %d vs. %d. " \ "Please report", bt_ntoa(&s->bdaddr, NULL), h.report_ID, report_id); switch(HID_USAGE(h.usage)) { case 0x01: /* Num Lock LED */ if (st.leds & LED_NUM) hid_set_data(&leds, &h, 1); break; case 0x02: /* Caps Lock LED */ if (st.leds & LED_CAP) hid_set_data(&leds, &h, 1); break; case 0x03: /* Scroll Lock LED */ if (st.leds & LED_SCR) hid_set_data(&leds, &h, 1); break; /* XXX add other LEDs ? */ } } } hid_end_parse(d); data[0] = 0xa2; /* DATA output (HID output report) */ if (report_id != NO_REPORT_ID) { data[1] = report_id; data[2] = leds; len = 3; } else { data[1] = leds; len = 2; } write(s->intr, data, len); return (0); }
static void writedata(int f, report_desc_t rd) { struct variable *var; int dlen, i, r, rid; u_char *dbuf; enum hid_kind kind; kind = 0; rid = 0; for (kind = 0; kind < 3; kind ++) { for (rid = 0; rid < 256; rid ++) { for (var = vars; var; var = var->next) { if (rid == var->h.report_ID && kind == var->h.kind) break; } if (var == NULL) continue; dlen = hid_report_size(rd, kind, rid); if (dlen <= 0) continue; dbuf = malloc(dlen); memset(dbuf, 0, dlen); dbuf[0] = rid; if (!zflag && hid_get_report(f, kind, dbuf, dlen) == 0) { if (verbose) { printf("Got %s report %d (%d bytes):", kind == hid_input ? "input" : kind == hid_output ? "output" : "feature", rid, dlen); for (i = 0; i < dlen; i++) printf(" %02x", dbuf[i]); printf("\n"); } } else if (!zflag) { warn("hid_get_report(rid %d)", rid); if (verbose) { printf("Can't get %s report %d (%d bytes). " "Will be initialized with zeros.\n", kind == hid_input ? "input" : kind == hid_output ? "output" : "feature", rid, dlen); } } for (var = vars; var; var = var->next) { if (rid != var->h.report_ID || kind != var->h.kind) continue; hid_set_data(dbuf, &var->h, var->val); } if (verbose) { printf("Setting %s report %d (%d bytes):", kind == hid_output ? "output" : kind == hid_feature ? "feature" : "input", rid, dlen); for (i = 0; i < dlen; i++) printf(" %02x", dbuf[i]); printf("\n"); } r = hid_set_report(f, kind, dbuf, dlen); if (r != 0) warn("hid_set_report(rid %d)", rid); free(dbuf); } } }