40#include <sys/stdint.h>
41#include <sys/stddef.h>
46#include <sys/kernel.h>
48#include <sys/module.h>
51#include <sys/condvar.h>
52#include <sys/sysctl.h>
54#include <sys/unistd.h>
55#include <sys/callout.h>
56#include <sys/malloc.h>
61#include <dev/evdev/input.h>
63#include <dev/hid/hid.h>
64#include <dev/hid/hidquirk.h>
74#define USB_DEBUG_VAR usbhid_debug
81static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0,
"USB usbhid");
83SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, enable, CTLFLAG_RWTUN,
84 &
usbhid_enable, 0,
"Enable usbhid and prefer it to other USB HID drivers");
86static int usbhid_debug = 0;
88 &usbhid_debug, 0,
"Debug level");
92#define POLL_XFER(xfer) ((xfer) + USBHID_N_TRANSFER)
186 xfer_ctx->
error = EIO;
188 (void)xfer_ctx->
cb(xfer_ctx);
208 if (xfer_ctx->
cb(xfer_ctx) != 0)
234 bool is_rd = (
req->bmRequestType &
UT_READ) != 0;
238 if (!is_rd &&
len != 0) {
253 if (is_rd &&
len != 0) {
263 xfer_ctx->
error = EIO;
265 (void)xfer_ctx->
cb(xfer_ctx);
297 .flags = {.pipe_bof = 1,.proxy_buffer = 1},
304 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
311 .flags = {.proxy_buffer = 1},
328 if (sc->
sc_xfer[xfer_idx] == NULL)
337 struct hid_rdesc_info *rdesc)
344 nowrite = hid_test_quirk(&sc->
sc_hw, HQ_NOWRITE);
364 DPRINTF(
"xfer %d setup error=%s\n",
n,
386 MAX(rdesc->isize, MAX(rdesc->osize, rdesc->fsize));
395 DPRINTF(
"xfer %d setup error=%s\n",
n,
401 rdesc->srsize = rdesc->grsize;
402 rdesc->wrsize = nowrite ? rdesc->srsize :
405 sc->
sc_intr_buf = malloc(rdesc->rdsize, M_USBDEV, M_ZERO | M_WAITOK);
502 xfer_ctx->
error = ETIMEDOUT;
504 xfer_ctx->
cb_ctx = xfer_ctx;
509 while (timeout > 0 && xfer_ctx->
error == ETIMEDOUT) {
515 msleep_sbt(xfer_ctx, &sc->
sc_mtx, 0,
"usbhid io",
516 SBT_1MS * timeout, 0, C_HARDCLOCK);
530 wakeup_one(&xfer_ctx->
waiters);
552 return (
error == 0 ? 0 : ENXIO);
557 hid_size_t *actlen, uint8_t type, uint8_t
id)
571 req.ctrl.wIndex[1] = 0;
597 req.ctrl.wIndex[1] = 0;
601 __DECONST(
void *, buf)));
636 __DECONST(
void *, buf)));
653 USETW2(
req.ctrl.wValue, (duration + 3) / 4,
id);
655 req.ctrl.wIndex[1] = 0;
676 req.ctrl.wIndex[1] = 0;
734 snprintf(hw->name,
sizeof(hw->name),
"%s %s",
739 iface != NULL && iface->
idesc != NULL) {
750 if (ep == NULL || ep->
methods == NULL)
751 hid_add_dynamic_quirk(hw, HQ_NOWRITE);
802 if (hid_test_quirk(&sc->
sc_hw, HQ_HID_IGNORE))
805 return (BUS_PROBE_GENERIC + 1);
816 DPRINTFN(10,
"sc=%p\n", sc);
829 DPRINTF(
"set idle failed, error=%s (ignored)\n",
832 mtx_init(&sc->
sc_mtx,
"usbhid lock", NULL, MTX_DEF);
834 child = device_add_child(
dev,
"hidbus", -1);
836 device_printf(
dev,
"Could not add hidbus device\n");
844 device_printf(
dev,
"failed to attach child: %d\n",
error);
857 device_delete_children(
dev);
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_interface * iface
struct usb_device * device
struct usb_device_request ucr_request
const struct usb_pipe_methods * methods
struct usb_hid_descriptor::@92 descrs[1]
struct usb_interface_descriptor * idesc
struct usb_xfer_flags_int flags_int
struct usb_xfer * sc_xfer[POLL_XFER(USBHID_N_TRANSFER)]
hid_intr_t * sc_intr_handler
struct hid_device_info sc_hw
struct usbhid_xfer_ctx sc_xfer_ctx[POLL_XFER(USBHID_N_TRANSFER)]
struct usb_config sc_config[USBHID_N_TRANSFER]
struct usb_device * sc_udev
union usbhid_device_request req
struct usb_device_request ctrl
struct usbhid_device_request::@14 intr
#define UISUBCLASS_XBOX360_CONTROLLER
#define UT_READ_CLASS_INTERFACE
#define UIPROTO_XBOX360_GAMEPAD
#define UT_WRITE_CLASS_INTERFACE
#define UIPROTO_BOOT_KEYBOARD
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset, const void *ptr, usb_frlength_t len)
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
struct usb_config_descriptor * usbd_get_config_descriptor(struct usb_device *udev)
const char * usb_get_serial(struct usb_device *udev)
const char * usb_get_product(struct usb_device *udev)
struct usb_endpoint * usbd_get_endpoint(struct usb_device *udev, uint8_t iface_index, const struct usb_config *setup)
const char * usb_get_manufacturer(struct usb_device *udev)
#define USETW2(w, b1, b0)
const char * usbd_errstr(usb_error_t err)
#define USB_IN_POLLING_MODE_FUNC()
struct usb_hid_descriptor * hid_get_descriptor_from_usb(struct usb_config_descriptor *cd, struct usb_interface_descriptor *id)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
uint8_t usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
usb_error_t usbd_req_get_report_descriptor(struct usb_device *udev, struct mtx *mtx, void *d, uint16_t size, uint8_t iface_index)
usb_error_t usbd_req_set_idle(struct usb_device *udev, struct mtx *mtx, uint8_t iface_index, uint8_t duration, uint8_t id)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_transfer_drain(struct usb_xfer *xfer)
void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
int usb_check_request(struct usb_device *, struct usb_device_request *)
#define USB_DEFAULT_TIMEOUT
#define USB_IFACE_SUBCLASS(isc)
#define USB_IFACE_CLASS(ic)
#define USB_ST_TRANSFERRED
#define USB_IFACE_PROTOCOL(ip)
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)
#define USB_DRIVER_INFO(n)
static const STRUCT_USB_HOST_ID usbhid_devs[]
static int usbhid_read(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen)
static driver_t usbhid_driver
MODULE_VERSION(usbhid, 1)
static void usbhid_fill_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
static SYSCTL_NODE(_hw_usb, OID_AUTO, usbhid, CTLFLAG_RW, 0, "USB usbhid")
static usb_callback_t usbhid_intr_out_callback
static void usbhid_intr_setup(device_t dev, hid_intr_t intr, void *context, struct hid_rdesc_info *rdesc)
static usbhid_callback_t usbhid_sync_wakeup_cb
DRIVER_MODULE(usbhid, uhub, usbhid_driver, usbhid_devclass, NULL, 0)
static usb_callback_t usbhid_intr_in_callback
MODULE_DEPEND(usbhid, usb, 1, 1, 1)
USB_PNP_HOST_INFO(usbhid_devs)
static device_detach_t usbhid_detach
static int usbhid_sync_xfer(struct usbhid_softc *sc, int xfer_idx, union usbhid_device_request *req, void *buf)
static int usbhid_set_protocol(device_t dev, uint16_t protocol)
static usb_callback_t usbhid_ctrl_callback
SYSCTL_INT(_hw_usb_usbhid, OID_AUTO, enable, CTLFLAG_RWTUN, &usbhid_enable, 0, "Enable usbhid and prefer it to other USB HID drivers")
static void usbhid_init_device_info(struct usb_attach_arg *uaa, struct hid_device_info *hw)
static void usbhid_intr_poll(device_t dev)
static int usbhid_xfer_check_len(struct usbhid_softc *sc, int xfer_idx, hid_size_t len)
int usbhid_callback_t(struct usbhid_xfer_ctx *xfer_ctx)
static device_attach_t usbhid_attach
static usbhid_callback_t usbhid_intr_handler_cb
static int usbhid_write(device_t dev, const void *buf, hid_size_t len)
static device_method_t usbhid_methods[]
static const struct usb_config usbhid_config[USBHID_N_TRANSFER]
static devclass_t usbhid_devclass
static int usbhid_ioctl(device_t dev, unsigned long cmd, uintptr_t data)
static int usbhid_set_idle(device_t dev, uint16_t duration, uint8_t id)
static device_probe_t usbhid_probe
static int usbhid_get_rdesc(device_t dev, void *buf, hid_size_t len)
static int usbhid_intr_start(device_t dev)
static int usbhid_get_report(device_t dev, void *buf, hid_size_t maxlen, hid_size_t *actlen, uint8_t type, uint8_t id)
static usb_frlength_t usbhid_xfer_max_len(struct usb_xfer *xfer)
static void usbhid_intr_unsetup(device_t dev)
static int usbhid_set_report(device_t dev, const void *buf, hid_size_t len, uint8_t type, uint8_t id)
static int usbhid_intr_stop(device_t dev)