usbhid(4): Implement USB_GET_DEVICEINFO ioctl
With factoring out of supporting code from ugen(4) driver. The ioctl is used in FIDO/U2F security key drivers to get USB product and manufacturer strings. PR: 264843 Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D51609
This commit is contained in:
@@ -707,6 +707,10 @@ usbhid_ioctl(device_t dev, device_t child __unused, unsigned long cmd,
|
||||
if (error == 0)
|
||||
ucr->ucr_actlen = UGETW(req.ctrl.wLength);
|
||||
break;
|
||||
case USB_GET_DEVICEINFO:
|
||||
error = usbd_fill_deviceinfo(sc->sc_udev,
|
||||
(struct usb_device_info *)data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
@@ -3111,3 +3111,51 @@ usbd_get_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep)
|
||||
{
|
||||
return (ep->ep_mode);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_fill_deviceinfo
|
||||
*
|
||||
* This function dumps information about an USB device to the
|
||||
* structure pointed to by the "di" argument.
|
||||
*
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* Else: Failure
|
||||
*------------------------------------------------------------------------*/
|
||||
int
|
||||
usbd_fill_deviceinfo(struct usb_device *udev, struct usb_device_info *di)
|
||||
{
|
||||
struct usb_device *hub;
|
||||
|
||||
bzero(di, sizeof(di[0]));
|
||||
|
||||
di->udi_bus = device_get_unit(udev->bus->bdev);
|
||||
di->udi_addr = udev->address;
|
||||
di->udi_index = udev->device_index;
|
||||
strlcpy(di->udi_serial, usb_get_serial(udev), sizeof(di->udi_serial));
|
||||
strlcpy(di->udi_vendor, usb_get_manufacturer(udev), sizeof(di->udi_vendor));
|
||||
strlcpy(di->udi_product, usb_get_product(udev), sizeof(di->udi_product));
|
||||
usb_printbcd(di->udi_release, sizeof(di->udi_release),
|
||||
UGETW(udev->ddesc.bcdDevice));
|
||||
di->udi_vendorNo = UGETW(udev->ddesc.idVendor);
|
||||
di->udi_productNo = UGETW(udev->ddesc.idProduct);
|
||||
di->udi_releaseNo = UGETW(udev->ddesc.bcdDevice);
|
||||
di->udi_class = udev->ddesc.bDeviceClass;
|
||||
di->udi_subclass = udev->ddesc.bDeviceSubClass;
|
||||
di->udi_protocol = udev->ddesc.bDeviceProtocol;
|
||||
di->udi_config_no = udev->curr_config_no;
|
||||
di->udi_config_index = udev->curr_config_index;
|
||||
di->udi_power = udev->flags.self_powered ? 0 : udev->power;
|
||||
di->udi_speed = udev->speed;
|
||||
di->udi_mode = udev->flags.usb_mode;
|
||||
di->udi_power_mode = udev->power_mode;
|
||||
di->udi_suspended = udev->flags.peer_suspended;
|
||||
|
||||
hub = udev->parent_hub;
|
||||
if (hub) {
|
||||
di->udi_hubaddr = hub->address;
|
||||
di->udi_hubindex = hub->device_index;
|
||||
di->udi_hubport = udev->port_no;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -831,42 +831,7 @@ ugen_get_iface_driver(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
|
||||
int
|
||||
ugen_fill_deviceinfo(struct usb_fifo *f, struct usb_device_info *di)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
struct usb_device *hub;
|
||||
|
||||
udev = f->udev;
|
||||
|
||||
bzero(di, sizeof(di[0]));
|
||||
|
||||
di->udi_bus = device_get_unit(udev->bus->bdev);
|
||||
di->udi_addr = udev->address;
|
||||
di->udi_index = udev->device_index;
|
||||
strlcpy(di->udi_serial, usb_get_serial(udev), sizeof(di->udi_serial));
|
||||
strlcpy(di->udi_vendor, usb_get_manufacturer(udev), sizeof(di->udi_vendor));
|
||||
strlcpy(di->udi_product, usb_get_product(udev), sizeof(di->udi_product));
|
||||
usb_printbcd(di->udi_release, sizeof(di->udi_release),
|
||||
UGETW(udev->ddesc.bcdDevice));
|
||||
di->udi_vendorNo = UGETW(udev->ddesc.idVendor);
|
||||
di->udi_productNo = UGETW(udev->ddesc.idProduct);
|
||||
di->udi_releaseNo = UGETW(udev->ddesc.bcdDevice);
|
||||
di->udi_class = udev->ddesc.bDeviceClass;
|
||||
di->udi_subclass = udev->ddesc.bDeviceSubClass;
|
||||
di->udi_protocol = udev->ddesc.bDeviceProtocol;
|
||||
di->udi_config_no = udev->curr_config_no;
|
||||
di->udi_config_index = udev->curr_config_index;
|
||||
di->udi_power = udev->flags.self_powered ? 0 : udev->power;
|
||||
di->udi_speed = udev->speed;
|
||||
di->udi_mode = udev->flags.usb_mode;
|
||||
di->udi_power_mode = udev->power_mode;
|
||||
di->udi_suspended = udev->flags.peer_suspended;
|
||||
|
||||
hub = udev->parent_hub;
|
||||
if (hub) {
|
||||
di->udi_hubaddr = hub->address;
|
||||
di->udi_hubindex = hub->device_index;
|
||||
di->udi_hubport = udev->port_no;
|
||||
}
|
||||
return (0);
|
||||
return (usbd_fill_deviceinfo(f->udev, di));
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -38,6 +38,7 @@ struct usb_process;
|
||||
struct usb_proc_msg;
|
||||
struct usb_mbuf;
|
||||
struct usb_fs_privdata;
|
||||
struct usb_device_info;
|
||||
struct mbuf;
|
||||
|
||||
typedef enum { /* keep in sync with usb_errstr_table */
|
||||
@@ -587,6 +588,8 @@ usb_error_t usbd_set_endpoint_mode(struct usb_device *udev,
|
||||
struct usb_endpoint *ep, uint8_t ep_mode);
|
||||
uint8_t usbd_get_endpoint_mode(struct usb_device *udev,
|
||||
struct usb_endpoint *ep);
|
||||
int usbd_fill_deviceinfo(struct usb_device *udev,
|
||||
struct usb_device_info *di);
|
||||
|
||||
const struct usb_device_id *usbd_lookup_id_by_info(
|
||||
const struct usb_device_id *id, usb_size_t sizeof_id,
|
||||
|
||||
Reference in New Issue
Block a user