#define _Bool bool extern "C" { #include } #include #include #include #include "ReportDescriptor.h" using namespace std; using namespace HID; void printDataItem(const InputOutputFeature* item) { cout << "Main item: "; for(int i = 1; i < 10; i++) { if(item->hasFlag((InputOutputFeature::BitFlagEnum) i)) { cout << item->BitFlag.stringForValue(i) << "|"; } if(item->hasFlag((InputOutputFeature::BitFlagEnum) -i)) { cout << item->BitFlag.stringForValue(-i) << "|"; } } cout << endl; ostringstream unsetList; if(item->isReportSizeSet()) cout << "Report Size: " << item->reportSize() << endl; else unsetList << " Report Size | "; if(item->isReportCountSet()) cout << "Report Count: " << item->reportCount() << endl; else unsetList << " Report Count | "; if(item->isLogicalMinSet()) cout << "Logical Min: " << item->logicalMin() << endl; else unsetList << " Logical Min | "; if(item->isLogicalMaxSet()) cout << "Logical Max: " << item->logicalMax() << endl; else unsetList << " Logical Max | "; if(item->isPhysicalMinSet()) cout << "Physical Min: " << item->physicalMin() << endl; else unsetList << " Physical Min | "; if(item->isPhysicalMaxSet()) cout << "Physical Max: " << item->physicalMax() << endl; else unsetList << " Physical Max | "; if(item->isUnitSet()) cout << "Unit: " << item->unit() << endl; else unsetList << " Unit | "; if(item->isUnitExponentSet()) cout << "Unit: " << item->unitExponent() << endl; else unsetList << " Unit Exponent | "; if(item->isReportIdSet()) cout << "Report ID: " << item->reportId() << endl; else unsetList << " Report ID | "; cout << "Unset globals: " << unsetList.str(); cout << endl << "Number of fields: " << item->numberOfFields() << endl; cout << "Parent usages: "; Collection * parent = item->parent(); while(parent != NULL) { if(parent->usage().isValid()) cout << "[usage '" << parent->usage().usageName() << "' (" << parent->usage().usage() << ") page '" << parent->usage().usagePageName() << "' (" << parent->usage().usagePage() << ")]"; parent = parent->parent(); } const LocalItems& locals = item->localItems(); int numSets = locals.alternateSetsCount() + 1; for(int set = 0; set < numSets; set++) { cout << endl << "Local item set " << set; if(numSets = 1) cout << " (no alternative sets defined)"; cout << endl; for(int field = 0; field < item->numberOfFields(); field++) { cout << "[Field " << field; Usage u = locals.usageForSetAndIndex(set, field); StringIndex si = locals.stringIndexForSetAndIndex(set, field); Designator d = locals.designatorForSetAndIndex(set, field); if(u.isValid()) { cout << " usage '" << u.usageName() << "' (" << u.usage() << ") page '" << u.usagePageName() << "' (" << u.usagePage() << ")"; } if(si.isValid()) cout << " string index " << si.value(); if(d.isValid()) cout << " designator " << d.value(); cout << "]"; } } cout << endl << endl; } int inputNum(char *in) { int result; if(sscanf(in, "0x%x", &result)) return result; return atoi(in); } int main(int argc, char** argv) { HIDInterface* hid; hid_return ret; /* How to use a custom matcher function: * * The third member of the HIDInterfaceMatcher is a function pointer, and * the forth member will be passed to it on invocation, together with the * USB device handle. The fifth member holds the length of the buffer * passed. See above. This can be used to do custom selection e.g. if you * have multiple identical devices which differ in the serial number. * * char const* const serial = "01518"; * HIDInterfaceMatcher matcher = { * 0x06c2, // vendor ID * 0x0038, // product ID * match_serial_number, // custom matcher function pointer * (void*)serial, // custom matching data * strlen(serial)+1 // length of custom data * }; * * If you do not want to use this, set the third member to NULL. * Then the match will only be on vendor and product ID. */ // HIDInterfaceMatcher matcher = { 0x0925, 0x1237, NULL, NULL, 0 }; //HIDInterfaceMatcher matcher = { 0x4242, 0xe131, NULL, NULL, 0 }; int vendor = 0x046e; int product = 0x520a; if(argc > 2) { vendor = inputNum(argv[1]); product = inputNum(argv[2]); } else { cout << "You must specify a vendor id and product id for the device you want to dump (in hex with 0x???? or decimal" << endl; exit(0); } HIDInterfaceMatcher matcher = { vendor, product, NULL, NULL, 0 }; /* see include/debug.h for possible values */ hid_set_debug(HID_DEBUG_ALL); hid_set_debug_stream(stderr); /* passed directly to libusb */ hid_set_usb_debug(0); ret = hid_init(); if (ret != HID_RET_SUCCESS) { fprintf(stderr, "hid_init failed with return code %d\n", ret); return 1; } hid = hid_new_HIDInterface(); if (hid == 0) { fprintf(stderr, "hid_new_HIDInterface() failed, out of memory?\n"); return 1; } /* How to detach a device from the kernel HID driver: * * The hid.o or usbhid.ko kernel modules claim a HID device on insertion, * usually. To be able to use it with libhid, you need to blacklist the * device (which requires a kernel recompilation), or simply tell libhid to * detach it for you. hid_open just opens the device, hid_force_open will * try n times to detach the device before failing. * In the following, n == 3. * * To open the HID, you need permission to the file in the /proc usbfs * (which must be mounted -- most distros do that by default): * mount -t usbfs none /proc/bus/usb * You can use hotplug to automatically give permissions to the device on * connection. Please see * http://cvs.ailab.ch/cgi-bin/viewcvs.cgi/external/libphidgets/hotplug/ * for an example. Try NOT to work as root! */ ret = hid_force_open(hid, 0, &matcher, 3); if (ret != HID_RET_SUCCESS) { fprintf(stderr, "hid_force_open failed with return code %d\n", ret); return 1; } ret = hid_write_identification(stdout, hid); if (ret != HID_RET_SUCCESS) { fprintf(stderr, "hid_write_identification failed with return code %d\n", ret); return 1; } HIDParser* parser = hid->hid_parser; ReportDescriptor myDesc(parser->ReportDesc, parser->ReportDescSize); cout << "I found " << myDesc.reports().size() << " reports available." << endl; map::const_iterator i = myDesc.reports().begin(); while(i != myDesc.reports().end()) { const Report& report = i->second; if(report.reportId() == Report::UNSET_REPORT_ID) { cout << "Details for unnumbered report" << endl; } else { cout << "Details for report " << (int) report.reportId() << endl; } vector::const_iterator item; cout << report.inputs().size() << " input items " << "(length " << report.inputLength() << " bits)" << endl; for(item = report.inputs().begin(); item != report.inputs().end(); item++) { printDataItem(*item); } cout << report.outputsAndFeatures().size() << " output/feature items " << "(length " << report.outputLength() << " bits)" << endl; for(item = report.outputsAndFeatures().begin(); item != report.outputsAndFeatures().end(); item++) { printDataItem(*item); } i++; } ret = hid_close(hid); if (ret != HID_RET_SUCCESS) { fprintf(stderr, "hid_close failed with return code %d\n", ret); return 1; } hid_delete_HIDInterface(&hid); ret = hid_cleanup(); if (ret != HID_RET_SUCCESS) { fprintf(stderr, "hid_cleanup failed with return code %d\n", ret); return 1; } return 0; } /* COPYRIGHT -- * * This file is part of libhid, a user-space HID access library. * libhid is (c) 2003-2005 * Martin F. Krafft * Charles Lepple * Arnaud Quette && * and distributed under the terms of the GNU General Public License. * See the file ./COPYING in the source distribution for more information. * * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES * OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */