From owner-freebsd-current@FreeBSD.ORG Thu Feb 14 11:33:50 2013 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id A4294507 for ; Thu, 14 Feb 2013 11:33:50 +0000 (UTC) (envelope-from mattblists@icritical.com) Received: from mail1.icritical.com (mail1.icritical.com [93.95.13.41]) by mx1.freebsd.org (Postfix) with SMTP id AF7D0A8C for ; Thu, 14 Feb 2013 11:33:49 +0000 (UTC) Received: (qmail 31952 invoked from network); 14 Feb 2013 11:33:48 -0000 Received: from localhost (127.0.0.1) by mail1.icritical.com with SMTP; 14 Feb 2013 11:33:48 -0000 Received: (qmail 31943 invoked by uid 599); 14 Feb 2013 11:33:48 -0000 Received: from unknown (HELO PDC002.icritical.int) (212.57.254.146) by mail1.icritical.com (qpsmtpd/0.28) with ESMTP; Thu, 14 Feb 2013 11:33:48 +0000 Message-ID: <511CCB99.40101@icritical.com> Date: Thu, 14 Feb 2013 11:33:45 +0000 From: Matt Burke User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:17.0) Gecko/20130122 Thunderbird/17.0.2 MIME-Version: 1.0 To: Subject: [PATCH] USB power usage reporting Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-TLS-Incoming: YES X-Virus-Scanned: by iCritical at mail1.icritical.com X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Feb 2013 11:33:50 -0000 The following patch adds the ability to read power draw on usb devices. I have used ioctl 135. I don't know what the protocol is for assigning numbers, so this may be unacceptable? ugen is patched to export the data via ioctl libusb20 and usbconfig are patched to make use of it (end-of-line): [mattb@falcon ~]$ usbconfig ugen0.1: at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA) ugen1.1: at usbus1, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA) ugen2.1: at usbus2, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA) ugen3.1: at usbus3, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA) ugen0.2: at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA) ugen3.2: at usbus3, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA) ugen3.3: at usbus3, cfg=0 md=HOST spd=LOW (1.5Mbps) pwr=ON (70mA) ugen3.4: at usbus3, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (98mA) ugen3.5: at usbus3, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (0mA) ugen3.6: at usbus3, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (100mA) diff --git a/lib/libusb/libusb20.3 b/lib/libusb/libusb20.3 index af80c6c..8753e06 100644 --- a/lib/libusb/libusb20.3 +++ b/lib/libusb/libusb20.3 @@ -149,6 +149,8 @@ USB access library (libusb -lusb) .Fn libusb20_dev_set_power_mode "struct libusb20_device *pdev" "uint8_t power_mode" .Ft uint8_t .Fn libusb20_dev_get_power_mode "struct libusb20_device *pdev" +.Ft uint16_t +.Fn libusb20_dev_get_power_usage "struct libusb20_device *pdev" .Ft int .Fn libusb20_dev_set_alt_index "struct libusb20_device *pdev" "uint8_t iface_index" "uint8_t alt_index" .Ft struct LIBUSB20_DEVICE_DESC_DECODED * @@ -740,6 +742,11 @@ USB device. . .Pp . +.Fn libusb20_dev_get_power_usage +returns the reported power usage in milliamps for the given USB device. +. +.Pp +. .Fn libusb20_dev_set_alt_index will try to set the given alternate index for the given USB interface index. diff --git a/lib/libusb/libusb20.c b/lib/libusb/libusb20.c index aa45991..ce75511 100644 --- a/lib/libusb/libusb20.c +++ b/lib/libusb/libusb20.c @@ -71,6 +71,7 @@ dummy_callback(struct libusb20_transfer *xfer) #define dummy_check_connected (void *)dummy_int #define dummy_set_power_mode (void *)dummy_int #define dummy_get_power_mode (void *)dummy_int +#define dummy_get_power_usage (void *)dummy_int #define dummy_kernel_driver_active (void *)dummy_int #define dummy_detach_kernel_driver (void *)dummy_int #define dummy_do_request_sync (void *)dummy_int @@ -717,6 +718,18 @@ libusb20_dev_get_power_mode(struct libusb20_device *pdev) return (power_mode); } +uint16_t +libusb20_dev_get_power_usage(struct libusb20_device *pdev) +{ + int error; + uint16_t power_usage; + + error = pdev->methods->get_power_usage(pdev, &power_usage); + if (error) + power_usage = 0; + return (power_usage); +} + int libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex) { diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h index 87e0572..81928b1 100644 --- a/lib/libusb/libusb20.h +++ b/lib/libusb/libusb20.h @@ -255,6 +255,7 @@ int libusb20_dev_reset(struct libusb20_device *pdev); int libusb20_dev_check_connected(struct libusb20_device *pdev); int libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode); uint8_t libusb20_dev_get_power_mode(struct libusb20_device *pdev); +uint16_t libusb20_dev_get_power_usage(struct libusb20_device *pdev); int libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index); int libusb20_dev_get_info(struct libusb20_device *pdev, struct usb_device_info *pinfo); int libusb20_dev_get_iface_desc(struct libusb20_device *pdev, uint8_t iface_index, char *buf, uint8_t len); diff --git a/lib/libusb/libusb20_int.h b/lib/libusb/libusb20_int.h index 0251c5f..6705c63 100644 --- a/lib/libusb/libusb20_int.h +++ b/lib/libusb/libusb20_int.h @@ -105,6 +105,7 @@ typedef int (libusb20_process_t)(struct libusb20_device *pdev); typedef int (libusb20_reset_device_t)(struct libusb20_device *pdev); typedef int (libusb20_set_power_mode_t)(struct libusb20_device *pdev, uint8_t power_mode); typedef int (libusb20_get_power_mode_t)(struct libusb20_device *pdev, uint8_t *power_mode); +typedef int (libusb20_get_power_usage_t)(struct libusb20_device *pdev, uint16_t *power_usage); typedef int (libusb20_set_alt_index_t)(struct libusb20_device *pdev, uint8_t iface_index, uint8_t alt_index); typedef int (libusb20_set_config_index_t)(struct libusb20_device *pdev, uint8_t index); typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev); @@ -127,6 +128,7 @@ typedef void (libusb20_tr_cancel_async_t)(struct libusb20_transfer *xfer); m(n, check_connected) \ m(n, set_power_mode) \ m(n, get_power_mode) \ + m(n, get_power_usage) \ m(n, set_alt_index) \ m(n, set_config_index) \ m(n, tr_cancel_async) \ diff --git a/lib/libusb/libusb20_ugen20.c b/lib/libusb/libusb20_ugen20.c index 2c67778..bff8e02 100644 --- a/lib/libusb/libusb20_ugen20.c +++ b/lib/libusb/libusb20_ugen20.c @@ -69,6 +69,7 @@ static libusb20_reset_device_t ugen20_reset_device; static libusb20_check_connected_t ugen20_check_connected; static libusb20_set_power_mode_t ugen20_set_power_mode; static libusb20_get_power_mode_t ugen20_get_power_mode; +static libusb20_get_power_usage_t ugen20_get_power_usage; static libusb20_kernel_driver_active_t ugen20_kernel_driver_active; static libusb20_detach_kernel_driver_t ugen20_detach_kernel_driver; static libusb20_do_request_sync_t ugen20_do_request_sync; @@ -639,6 +640,18 @@ ugen20_get_power_mode(struct libusb20_device *pdev, uint8_t *power_mode) } static int +ugen20_get_power_usage(struct libusb20_device *pdev, uint16_t *power_usage) +{ + int temp; + + if (ioctl(pdev->file_ctrl, USB_GET_POWER_USAGE, &temp)) { + return (LIBUSB20_ERROR_OTHER); + } + *power_usage = temp; + return (0); /* success */ +} + +static int ugen20_kernel_driver_active(struct libusb20_device *pdev, uint8_t iface_index) { diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c index 13f5bd6..ff1c47d 100644 --- a/sys/dev/usb/usb_generic.c +++ b/sys/dev/usb/usb_generic.c @@ -1834,6 +1834,17 @@ ugen_get_power_mode(struct usb_fifo *f) } static int +ugen_get_power_usage(struct usb_fifo *f) +{ + struct usb_device *udev = f->udev; + + if (udev == NULL) + return (0); + + return (udev->power); +} + +static int ugen_do_port_feature(struct usb_fifo *f, uint8_t port_no, uint8_t set, uint16_t feature) { @@ -2195,6 +2206,10 @@ ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) *u.pint = ugen_get_power_mode(f); break; + case USB_GET_POWER_USAGE: + *u.pint = ugen_get_power_usage(f); + break; + case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); diff --git a/sys/dev/usb/usb_ioctl.h b/sys/dev/usb/usb_ioctl.h index 1d9b223..979240f 100644 --- a/sys/dev/usb/usb_ioctl.h +++ b/sys/dev/usb/usb_ioctl.h @@ -277,7 +277,8 @@ struct usb_gen_quirk { #define USB_IFACE_DRIVER_DETACH _IOW ('U', 125, int) #define USB_GET_PLUGTIME _IOR ('U', 126, uint32_t) #define USB_READ_DIR _IOW ('U', 127, struct usb_read_dir) -/* 128 - 135 unused */ +/* 128 - 134 unused */ +#define USB_GET_POWER_USAGE _IOR ('U', 135, int) #define USB_SET_TX_FORCE_SHORT _IOW ('U', 136, int) #define USB_SET_TX_TIMEOUT _IOW ('U', 137, int) #define USB_GET_TX_FRAME_SIZE _IOR ('U', 138, int) diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c index 7ee89da..467c0de 100644 --- a/usr.sbin/usbconfig/dump.c +++ b/usr.sbin/usbconfig/dump.c @@ -226,12 +226,13 @@ dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv) char buf[128]; uint8_t n; - printf("%s, cfg=%u md=%s spd=%s pwr=%s\n", + printf("%s, cfg=%u md=%s spd=%s pwr=%s (%dmA)\n", libusb20_dev_get_desc(pdev), libusb20_dev_get_config_index(pdev), dump_mode(libusb20_dev_get_mode(pdev)), dump_speed(libusb20_dev_get_speed(pdev)), - dump_power_mode(libusb20_dev_get_power_mode(pdev))); + dump_power_mode(libusb20_dev_get_power_mode(pdev)), + libusb20_dev_get_power_usage(pdev)); if (!show_ifdrv) return; -- Sorry for the following... The information contained in this message is confidential and intended for the addressee only. If you have received this message in error, or there are any problems with its content, please contact the sender. iCritical is a trading name of Critical Software Ltd. Registered in England: 04909220. Registered Office: IC2, Keele Science Park, Keele, Staffordshire, ST5 5NH. This message has been scanned for security threats by iCritical. www.icritical.com