Centralize USB device mode bus power reporting, and add

hw.usb.template_power sysctl to control it.

Reviewed by:	hselasky@ (earlier version)
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Edward Tomasz Napierala 2018-05-23 20:06:04 +00:00
parent 95104040a3
commit d008c0d75f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=334115
13 changed files with 65 additions and 31 deletions

View File

@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd May 17, 2018
.Dd May 23, 2018
.Dt USB_TEMPLATE 4
.Os
.
@ -100,6 +100,11 @@ tunables:
.It Va hw.usb.template
Currently selected template.
Set to -1 to make the device disappear from the USB host point of view.
.It Va hw.usb.template_power
USB bus power consumption in mA.
Must be between 0 and 500.
Setting to 0 marks the device as self-powered.
Defaults to 500mA.
.It Va hw.usb.templates.N
Configuration for template number
.Va N .

View File

@ -76,14 +76,12 @@
#include <dev/usb/template/usb_template.h>
#endif /* USB_GLOBAL_INCLUDE_FILE */
SYSCTL_NODE(_hw_usb, OID_AUTO, templates, CTLFLAG_RW, 0,
"USB device side templates");
MODULE_DEPEND(usb_template, usb, 1, 1, 1);
MODULE_VERSION(usb_template, 1);
/* function prototypes */
static int sysctl_hw_usb_template_power(SYSCTL_HANDLER_ARGS);
static void usb_make_raw_desc(struct usb_temp_setup *, const uint8_t *);
static void usb_make_endpoint_desc(struct usb_temp_setup *,
const struct usb_temp_endpoint_desc *);
@ -117,6 +115,33 @@ static usb_error_t usb_temp_setup_by_index(struct usb_device *,
uint16_t index);
static void usb_temp_init(void *);
SYSCTL_NODE(_hw_usb, OID_AUTO, templates, CTLFLAG_RW, 0,
"USB device side templates");
SYSCTL_PROC(_hw_usb, OID_AUTO, template_power,
CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
NULL, 0, sysctl_hw_usb_template_power,
"I", "USB bus power consumption in mA");
static int usb_template_power = 500; /* 500mA */
static int
sysctl_hw_usb_template_power(SYSCTL_HANDLER_ARGS)
{
int error, val;
val = usb_template_power;
error = sysctl_handle_int(oidp, &val, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (val < 0 || val > 500)
return (EINVAL);
usb_template_power = val;
return (0);
}
/*------------------------------------------------------------------------*
* usb_decode_str_desc
*
@ -426,6 +451,7 @@ usb_make_config_desc(struct usb_temp_setup *temp,
struct usb_config_descriptor *cd;
const struct usb_temp_interface_desc **tid;
uint16_t old_size;
int power;
/* Reserve memory */
@ -463,13 +489,16 @@ usb_make_config_desc(struct usb_temp_setup *temp,
cd->bConfigurationValue = temp->bConfigurationValue;
cd->iConfiguration = tcd->iConfiguration;
cd->bmAttributes = tcd->bmAttributes;
cd->bMaxPower = tcd->bMaxPower;
cd->bmAttributes |= (UC_REMOTE_WAKEUP | UC_BUS_POWERED);
if (temp->self_powered) {
cd->bmAttributes |= UC_SELF_POWERED;
} else {
power = usb_template_power;
cd->bMaxPower = power / 2; /* 2 mA units */
cd->bmAttributes |= UC_REMOTE_WAKEUP;
if (power > 0) {
cd->bmAttributes |= UC_BUS_POWERED;
cd->bmAttributes &= ~UC_SELF_POWERED;
} else {
cd->bmAttributes &= ~UC_BUS_POWERED;
cd->bmAttributes |= UC_SELF_POWERED;
}
}
}

View File

@ -351,8 +351,8 @@ static const struct usb_temp_interface_desc *audio_interfaces[] = {
static const struct usb_temp_config_desc audio_config_desc = {
.ppIfaceDesc = audio_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = AUDIO_PRODUCT_INDEX,
};

View File

@ -219,8 +219,8 @@ static const struct usb_temp_interface_desc *eth_interfaces[] = {
static const struct usb_temp_config_desc eth_config_desc = {
.ppIfaceDesc = eth_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = ETH_CONFIGURATION_INDEX,
};

View File

@ -157,8 +157,8 @@ static const struct usb_temp_interface_desc *keyboard_interfaces[] = {
static const struct usb_temp_config_desc keyboard_config_desc = {
.ppIfaceDesc = keyboard_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = KBD_PRODUCT_INDEX,
};

View File

@ -199,8 +199,8 @@ static const struct usb_temp_interface_desc *midi_interfaces[] = {
static const struct usb_temp_config_desc midi_config_desc = {
.ppIfaceDesc = midi_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MIDI_PRODUCT_INDEX,
};

View File

@ -198,8 +198,8 @@ static const struct usb_temp_interface_desc *modem_interfaces[] = {
static const struct usb_temp_config_desc modem_config_desc = {
.ppIfaceDesc = modem_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MODEM_PRODUCT_INDEX,
};

View File

@ -155,8 +155,8 @@ static const struct usb_temp_interface_desc *mouse_interfaces[] = {
static const struct usb_temp_config_desc mouse_config_desc = {
.ppIfaceDesc = mouse_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MOUSE_INTERFACE_INDEX,
};

View File

@ -142,8 +142,8 @@ static const struct usb_temp_interface_desc *msc_interfaces[] = {
static const struct usb_temp_config_desc msc_config_desc = {
.ppIfaceDesc = msc_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MSC_CONFIGURATION_INDEX,
};

View File

@ -164,8 +164,8 @@ static const struct usb_temp_interface_desc *mtp_interfaces[] = {
static const struct usb_temp_config_desc mtp_config_desc = {
.ppIfaceDesc = mtp_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MTP_CONFIGURATION_INDEX,
};

View File

@ -370,8 +370,8 @@ static const struct usb_temp_interface_desc *multi_interfaces[] = {
static const struct usb_temp_config_desc multi_config_desc = {
.ppIfaceDesc = multi_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = MULTI_CONFIGURATION_INDEX,
};
static const struct usb_temp_config_desc *multi_configs[] = {

View File

@ -347,8 +347,8 @@ static const struct usb_temp_interface_desc *phone_interfaces[] = {
static const struct usb_temp_config_desc phone_config_desc = {
.ppIfaceDesc = phone_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = PHONE_PRODUCT_INDEX,
};

View File

@ -327,8 +327,8 @@ static const struct usb_temp_interface_desc *serialnet_interfaces[] = {
static const struct usb_temp_config_desc serialnet_config_desc = {
.ppIfaceDesc = serialnet_interfaces,
.bmAttributes = UC_BUS_POWERED,
.bMaxPower = 25, /* 50 mA */
.bmAttributes = 0,
.bMaxPower = 0,
.iConfiguration = SERIALNET_CONFIGURATION_INDEX,
};
static const struct usb_temp_config_desc *serialnet_configs[] = {