#define HID_INTERNAL
#include <hid.h>
#include <hid_helpers.h>
#include <constants.h>
#include <debug.h>
#include <assert.h>
/*! @todo This code does not seem to properly retrieve descriptors for devices
* with multiple interfaces. We probably need to parse each interface a little
* more to determine which endpoints we want to talk to with usb_control_msg
* (EP1IN can't be right for everything).
*/
static hid_return hid_prepare_hid_descriptor(HIDInterface* const hidif)
{
ASSERT(hid_is_opened(hidif));
ASSERT(hidif->hid_parser);
TRACE("initialising the HID descriptor for USB device %s...", hidif->id);
/* TODO: BUFLEN seems to depend on the device, so we need to do something
* about the following.
*/
byte const BUFLEN = 9;
byte buffer[BUFLEN];
TRACE("retrieving HID descriptor for USB device %s...", hidif->id);
int len = usb_control_msg(hidif->dev_handle,
USB_ENDPOINT_IN+1,
USB_REQ_GET_DESCRIPTOR,
(USB_DT_HID << 8) + 0, hidif->interface,
(char*)buffer, BUFLEN,
USB_TIMEOUT);
if (len < 0) {
WARNING("failed to get HID descriptor for USB device %s:%s", hidif->id, usb_strerror());
return HID_RET_NOT_HID_DEVICE;
}
if (len < BUFLEN) {
WARNING("HID descriptor for USB device %s is too short; "
"expected: %d bytes; got: %d bytes.\n", hidif->id, BUFLEN, len);
return HID_RET_HID_DESC_SHORT;
}
/* TODO:
* the constants 7 and 8 should be exported.
*/
hidif->hid_parser->ReportDescSize = buffer[7] | (buffer[8] << 8);
NOTICE("successfully initialised HID descriptor for USB device %s (%d bytes).",
hidif->id, hidif->hid_parser->ReportDescSize);
return HID_RET_SUCCESS;
}
static hid_return hid_prepare_report_descriptor(HIDInterface* const hidif)
{
ASSERT(hid_is_opened(hidif));
ASSERT(hidif->hid_parser);
TRACE("initialising the report descriptor for USB device %s...", hidif->id);
if (hidif->hid_parser->ReportDescSize > REPORT_DSC_SIZE) {
ERROR("report descriptor size for USB device %s exceeds maximum size: "
"%d > %d.\n", hidif->id, hidif->hid_parser->ReportDescSize,
REPORT_DSC_SIZE);
return HID_RET_REPORT_DESC_LONG;
}
TRACE("retrieving report descriptor for USB device %s...", hidif->id);
int len = usb_control_msg(hidif->dev_handle,
USB_ENDPOINT_IN+1,
USB_REQ_GET_DESCRIPTOR,
(USB_DT_REPORT << 8) + 0, hidif->interface,
(char*)hidif->hid_parser->ReportDesc, hidif->hid_parser->ReportDescSize,
USB_TIMEOUT);
if (len < 0) {
WARNING("failed to get report descriptor for USB device %s...", hidif->id);
NOTICE("Error from libusb: %s", usb_strerror());
return HID_RET_FAIL_GET_REPORT;
}
if (len < hidif->hid_parser->ReportDescSize) {
WARNING("HID report descriptor for USB device %s is too short; "
"expected: %d bytes; got: %d bytes.\n", hidif->id,
hidif->hid_parser->ReportDescSize, len);
return HID_RET_REPORT_DESC_SHORT;
}
NOTICE("successfully initialised report descriptor for USB device %s.",
hidif->id);
return HID_RET_SUCCESS;
}
hid_return hid_prepare_interface(HIDInterface* const hidif)
{
if (!hid_is_opened(hidif)) {
ERROR("cannot prepare unopened HIDinterface.");
return HID_RET_DEVICE_NOT_OPENED;
}
hid_return ret = hid_init_parser(hidif);
if (ret != HID_RET_SUCCESS) {
hid_close(hidif);
return ret;
}
ret = hid_prepare_hid_descriptor(hidif);
if (ret != HID_RET_SUCCESS) {
hid_close(hidif);
return ret;
}
ret = hid_prepare_report_descriptor(hidif);
if (ret != HID_RET_SUCCESS) {
hid_close(hidif);
return ret;
}
ret = hid_prepare_parser(hidif);
if (ret != HID_RET_SUCCESS) {
hid_close(hidif);
return ret;
}
return HID_RET_SUCCESS;
}
/* COPYRIGHT --
*
* This file is part of libhid, a user-space HID access library.
* libhid is (c) 2003-2005
* Martin F. Krafft <libhid@pobox.madduck.net>
* Charles Lepple <clepple@ghz.cc>
* Arnaud Quette <arnaud.quette@free.fr> && <arnaud.quette@mgeups.com>
* 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.
*/
syntax highlighted by Code2HTML, v. 0.9.1