Commit 24040a58 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'usb-for-v4.13' of...

Merge tag 'usb-for-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-testing

Felipe writes:

usb: changes for v4.13 merge window

This time around we have a total of 57 non-merge commits. A list of
most important changes follows:

- Improvements to dwc3 tracing interface
- Initial dual-role support for dwc3
- Improvements to how we handle DMA resources in dwc3
- A new f_uac1 implementation which much more flexible
- Removal of AVR32 bits
- Improvements to f_mass_storage driver
parents 571949a4 0591bc23
......@@ -55,14 +55,6 @@ Description:
Indicates the maximum USB speed supported by this port.
Users:
What: /sys/class/udc/<udc>/maximum_speed
Date: June 2011
KernelVersion: 3.1
Contact: Felipe Balbi <balbi@kernel.org>
Description:
Indicates the maximum USB speed supported by this port.
Users:
What: /sys/class/udc/<udc>/soft_connect
Date: June 2011
KernelVersion: 3.1
......@@ -91,3 +83,11 @@ Description:
'configured', and 'suspended'; however not all USB Device
Controllers support reporting all states.
Users:
What: /sys/class/udc/<udc>/function
Date: June 2017
KernelVersion: 4.13
Contact: Felipe Balbi <balbi@kernel.org>
Description:
Prints out name of currently running USB Gadget Driver.
Users:
What: /config/usb-gadget/gadget/functions/uac1.name
Date: Sep 2014
KernelVersion: 3.18
Date: June 2017
KernelVersion: 4.14
Description:
The attributes:
audio_buf_size - audio buffer size
fn_cap - capture pcm device file name
fn_cntl - control device file name
fn_play - playback pcm device file name
req_buf_size - ISO OUT endpoint request buffer size
req_count - ISO OUT endpoint request count
c_chmask - capture channel mask
c_srate - capture sampling rate
c_ssize - capture sample size (bytes)
p_chmask - playback channel mask
p_srate - playback sampling rate
p_ssize - playback sample size (bytes)
req_number - the number of pre-allocated request
for both capture and playback
What: /config/usb-gadget/gadget/functions/uac1_legacy.name
Date: Sep 2014
KernelVersion: 3.18
Description:
The attributes:
audio_buf_size - audio buffer size
fn_cap - capture pcm device file name
fn_cntl - control device file name
fn_play - playback pcm device file name
req_buf_size - ISO OUT endpoint request buffer size
req_count - ISO OUT endpoint request count
......@@ -45,6 +45,8 @@ Optional properties:
a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
from P0 to P1/P2/P3 without delay.
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
during HS transmit.
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold
......
Broadcom IPROC USB Device controller.
The device node is used for UDCs integrated into Broadcom's
iProc family (Northstar2, Cygnus) of SoCs'. The UDC is based
on Synopsys Designware Cores AHB Subsystem Device Controller
IP.
Required properties:
- compatible: Add the compatibility strings for supported platforms.
For Broadcom NS2 platform, add "brcm,ns2-udc","brcm,iproc-udc".
For Broadcom Cygnus platform, add "brcm,cygnus-udc", "brcm,iproc-udc".
- reg: Offset and length of UDC register set
- interrupts: description of interrupt line
- phys: phandle to phy node.
Example:
udc_dwc: usb@664e0000 {
compatible = "brcm,ns2-udc", "brcm,iproc-udc";
reg = <0x664e0000 0x2000>;
interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usbdrd_phy>;
This diff is collapsed.
......@@ -16,7 +16,10 @@ Linux USB API
persist
error-codes
writing_usb_driver
dwc3
writing_musb_glue_layer
typec
usb3-debug-port
.. only:: subproject and html
......
......@@ -16,10 +16,11 @@ provided by gadgets.
13. RNDIS function
14. SERIAL function
15. SOURCESINK function
16. UAC1 function
16. UAC1 function (legacy implementation)
17. UAC2 function
18. UVC function
19. PRINTER function
20. UAC1 function (new API)
1. ACM function
......@@ -589,15 +590,16 @@ device: run the gadget
host: test-usb (tools/usb/testusb.c)
16. UAC1 function
16. UAC1 function (legacy implementation)
=================
The function is provided by usb_f_uac1.ko module.
The function is provided by usb_f_uac1_legacy.ko module.
Function-specific configfs interface
------------------------------------
The function name to use when creating the function directory is "uac1".
The function name to use when creating the function directory
is "uac1_legacy".
The uac1 function provides these attributes in its function directory:
audio_buf_size - audio buffer size
......@@ -772,3 +774,46 @@ host:
More advanced testing can be done with the prn_example
described in Documentation/usb/gadget-printer.txt.
20. UAC1 function (virtual ALSA card, using u_audio API)
=================
The function is provided by usb_f_uac1.ko module.
It will create a virtual ALSA card and the audio streams are simply
sinked to and sourced from it.
Function-specific configfs interface
------------------------------------
The function name to use when creating the function directory is "uac1".
The uac1 function provides these attributes in its function directory:
c_chmask - capture channel mask
c_srate - capture sampling rate
c_ssize - capture sample size (bytes)
p_chmask - playback channel mask
p_srate - playback sampling rate
p_ssize - playback sample size (bytes)
req_number - the number of pre-allocated request for both capture
and playback
The attributes have sane default values.
Testing the UAC1 function
-------------------------
device: run the gadget
host: aplay -l # should list our USB Audio Gadget
This function does not require real hardware support, it just
sends a stream of audio data to/from the host. In order to
actually hear something at the device side, a command similar
to this must be used at the device side:
$ arecord -f dat -t wav -D hw:2,0 | aplay -D hw:0,0 &
e.g.:
$ arecord -f dat -t wav -D hw:CARD=UAC1Gadget,DEV=0 | \
aplay -D default:CARD=OdroidU3
......@@ -151,11 +151,24 @@ static void __dwc3_set_mode(struct work_struct *work)
switch (dwc->desired_dr_role) {
case DWC3_GCTL_PRTCAP_HOST:
ret = dwc3_host_init(dwc);
if (ret)
if (ret) {
dev_err(dwc->dev, "failed to initialize host\n");
} else {
if (dwc->usb2_phy)
otg_set_vbus(dwc->usb2_phy->otg, true);
if (dwc->usb2_generic_phy)
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
}
break;
case DWC3_GCTL_PRTCAP_DEVICE:
dwc3_event_buffers_setup(dwc);
if (dwc->usb2_phy)
otg_set_vbus(dwc->usb2_phy->otg, false);
if (dwc->usb2_generic_phy)
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret)
dev_err(dwc->dev, "failed to initialize peripheral\n");
......@@ -721,6 +734,8 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}
static int dwc3_core_get_phy(struct dwc3 *dwc);
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
......@@ -759,6 +774,10 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (ret)
goto err0;
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc);
......@@ -796,13 +815,19 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
}
if (dwc->revision >= DWC3_REVISION_250A) {
reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
/*
* Enable hardware control of sending remote wakeup in HS when
* the device is in the L1 state.
* Enable hardware control of sending remote wakeup
* in HS when the device is in the L1 state.
*/
if (dwc->revision >= DWC3_REVISION_290A) {
reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
if (dwc->revision >= DWC3_REVISION_290A)
reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
if (dwc->dis_tx_ipgap_linecheck_quirk)
reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}
......@@ -903,6 +928,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
if (dwc->usb2_phy)
otg_set_vbus(dwc->usb2_phy->otg, false);
if (dwc->usb2_generic_phy)
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret) {
if (ret != -EPROBE_DEFER)
......@@ -912,6 +943,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
break;
case USB_DR_MODE_HOST:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
if (dwc->usb2_phy)
otg_set_vbus(dwc->usb2_phy->otg, true);
if (dwc->usb2_generic_phy)
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
ret = dwc3_host_init(dwc);
if (ret) {
if (ret != -EPROBE_DEFER)
......@@ -1023,6 +1060,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
"snps,dis-u2-freeclk-exists-quirk");
dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,dis-del-phy-power-chg-quirk");
dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev,
"snps,dis-tx-ipgap-linecheck-quirk");
dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk");
......@@ -1148,10 +1187,6 @@ static int dwc3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
spin_lock_init(&dwc->lock);
pm_runtime_set_active(dev);
......
/**
/*
* core.h - DesignWare USB3 DRD Core Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
......@@ -204,6 +204,7 @@
#define DWC3_GCTL_DSBLCLKGTNG BIT(0)
/* Global User Control 1 Register */
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
/* Global USB2 PHY Configuration Register */
......@@ -522,7 +523,6 @@ struct dwc3_event_buffer {
* @trb_pool_dma: dma address of @trb_pool
* @trb_enqueue: enqueue 'pointer' into TRB array
* @trb_dequeue: dequeue 'pointer' into TRB array
* @desc: usb_endpoint_descriptor pointer
* @dwc: pointer to DWC controller
* @saved_state: ep state saved during hibernation
* @flags: endpoint flags (wedged, stalled, ...)
......@@ -664,7 +664,7 @@ enum dwc3_link_state {
* @bpl: DW0-3
* @bph: DW4-7
* @size: DW8-B
* @trl: DWC-F
* @ctrl: DWC-F
*/
struct dwc3_trb {
u32 bpl;
......@@ -674,16 +674,16 @@ struct dwc3_trb {
} __packed;
/**
* dwc3_hwparams - copy of HWPARAMS registers
* @hwparams0 - GHWPARAMS0
* @hwparams1 - GHWPARAMS1
* @hwparams2 - GHWPARAMS2
* @hwparams3 - GHWPARAMS3
* @hwparams4 - GHWPARAMS4
* @hwparams5 - GHWPARAMS5
* @hwparams6 - GHWPARAMS6
* @hwparams7 - GHWPARAMS7
* @hwparams8 - GHWPARAMS8
* struct dwc3_hwparams - copy of HWPARAMS registers
* @hwparams0: GHWPARAMS0
* @hwparams1: GHWPARAMS1
* @hwparams2: GHWPARAMS2
* @hwparams3: GHWPARAMS3
* @hwparams4: GHWPARAMS4
* @hwparams5: GHWPARAMS5
* @hwparams6: GHWPARAMS6
* @hwparams7: GHWPARAMS7
* @hwparams8: GHWPARAMS8
*/
struct dwc3_hwparams {
u32 hwparams0;
......@@ -730,7 +730,8 @@ struct dwc3_hwparams {
* @unaligned: true for OUT endpoints with length not divisible by maxp
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
* @queued: true when request has been queued to HW
* @started: request is started
* @zero: wants a ZLP
*/
struct dwc3_request {
struct usb_request request;
......@@ -761,17 +762,23 @@ struct dwc3_scratchpad_array {
/**
* struct dwc3 - representation of our controller
* @drd_work - workqueue used for role swapping
* @drd_work: workqueue used for role swapping
* @ep0_trb: trb which is used for the ctrl_req
* @bounce: address of bounce buffer
* @scratchbuf: address of scratch buffer
* @setup_buf: used while precessing STD USB requests
* @ep0_trb: dma address of ep0_trb
* @ep0_trb_addr: dma address of @ep0_trb
* @bounce_addr: dma address of @bounce
* @ep0_usb_req: dummy req used while handling STD USB requests
* @scratch_addr: dma address of scratchbuf
* @ep0_in_setup: one control transfer is completed and enter setup phase
* @lock: for synchronizing
* @dev: pointer to our struct device
* @sysdev: pointer to the DMA-capable device
* @xhci: pointer to our xHCI child
* @event_buffer_list: a list of event buffers
* @xhci_resources: struct resources for our @xhci child
* @ev_buf: struct dwc3_event_buffer pointer
* @eps: endpoint array
* @gadget: device side representation of the peripheral controller
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
......@@ -795,8 +802,6 @@ struct dwc3_scratchpad_array {
* @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY
* @ulpi: pointer to ulpi interface
* @dcfg: saved contents of DCFG register
* @gctl: saved contents of GCTL register
* @isoch_delay: wValue from Set Isochronous Delay request;
* @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request.
......@@ -830,7 +835,6 @@ struct dwc3_scratchpad_array {
* @pending_events: true when we have pending IRQs to be handled
* @pullups_connected: true when Run/Stop bit is set
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
* @usb3_lpm_capable: set if hadrware supports Link Power Management
* @disable_scramble_quirk: set if we enable the disable scramble quirk
......@@ -845,11 +849,14 @@ struct dwc3_scratchpad_array {
* @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
* @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
* disabling the suspend signal to the PHY.
* @dis_rxdet_inp3_quirk: set if we disable Rx.Detect in P3
* @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists
* in GUSB2PHYCFG, specify that USB2 PHY doesn't
* provide a free-running PHY clock.
* @dis_del_phy_power_chg_quirk: set if we disable delay phy power
* change quirk.
* @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate
* check during HS transmit.
* @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
* @tx_de_emphasis: Tx de-emphasis value
* 0 - -6dB de-emphasis
......@@ -1004,6 +1011,7 @@ struct dwc3 {
unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
unsigned dis_tx_ipgap_linecheck_quirk:1;
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
......
......@@ -173,9 +173,8 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
* @event: the event code
*/
static inline const char *
dwc3_gadget_event_string(const struct dwc3_event_devt *event)
dwc3_gadget_event_string(char *str, const struct dwc3_event_devt *event)
{
static char str[256];
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) {
......@@ -223,15 +222,249 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event)
return str;
}
static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str)
{
switch (t & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
sprintf(str, "Get Interface Status(Intf = %d, Length = %d)",
i, l);
break;
case USB_RECIP_ENDPOINT:
sprintf(str, "Get Endpoint Status(ep%d%s)",
i & ~USB_DIR_IN,
i & USB_DIR_IN ? "in" : "out");
break;
}
}
static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
__u16 i, char *str)
{
switch (t & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
sprintf(str, "%s Device Feature(%s%s)",
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
({char *s;
switch (v) {
case USB_DEVICE_SELF_POWERED:
s = "Self Powered";
break;
case USB_DEVICE_REMOTE_WAKEUP:
s = "Remote Wakeup";
break;
case USB_DEVICE_TEST_MODE:
s = "Test Mode";
break;
default:
s = "UNKNOWN";
} s; }),
v == USB_DEVICE_TEST_MODE ?
({ char *s;
switch (i) {
case TEST_J:
s = ": TEST_J";
break;
case TEST_K:
s = ": TEST_K";
break;
case TEST_SE0_NAK:
s = ": TEST_SE0_NAK";
break;
case TEST_PACKET:
s = ": TEST_PACKET";
break;
case TEST_FORCE_EN:
s = ": TEST_FORCE_EN";
break;
default:
s = ": UNKNOWN";
} s; }) : "");
break;
case USB_RECIP_INTERFACE:
sprintf(str, "%s Interface Feature(%s)",
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
v == USB_INTRF_FUNC_SUSPEND ?
"Function Suspend" : "UNKNOWN");
break;
case USB_RECIP_ENDPOINT:
sprintf(str, "%s Endpoint Feature(%s ep%d%s)",
b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
i & ~USB_DIR_IN,
i & USB_DIR_IN ? "in" : "out");
break;
}
}
static inline void dwc3_decode_set_address(__u16 v, char *str)
{
sprintf(str, "Set Address(Addr = %02x)", v);
}
static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
__u16 i, __u16 l, char *str)
{
sprintf(str, "%s %s Descriptor(Index = %d, Length = %d)",
b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
({ char *s;
switch (v >> 8) {
case USB_DT_DEVICE:
s = "Device";
break;
case USB_DT_CONFIG:
s = "Configuration";
break;
case USB_DT_STRING:
s = "String";
break;
case USB_DT_INTERFACE:
s = "Interface";
break;
case USB_DT_ENDPOINT:
s = "Endpoint";
break;
case USB_DT_DEVICE_QUALIFIER:
s = "Device Qualifier";
break;
case USB_DT_OTHER_SPEED_CONFIG:
s = "Other Speed Config";
break;
case USB_DT_INTERFACE_POWER:
s = "Interface Power";
break;
case USB_DT_OTG:
s = "OTG";
break;
case USB_DT_DEBUG:
s = "Debug";
break;
case USB_DT_INTERFACE_ASSOCIATION:
s = "Interface Association";
break;
case USB_DT_BOS:
s = "BOS";
break;
case USB_DT_DEVICE_CAPABILITY:
s = "Device Capability";
break;
case USB_DT_PIPE_USAGE:
s = "Pipe Usage";
break;
case USB_DT_SS_ENDPOINT_COMP:
s = "SS Endpoint Companion";
break;
case USB_DT_SSP_ISOC_ENDPOINT_COMP:
s = "SSP Isochronous Endpoint Companion";
break;
default:
s = "UNKNOWN";
break;
} s; }), v & 0xff, l);
}
static inline void dwc3_decode_get_configuration(__u16 l, char *str)
{
sprintf(str, "Get Configuration(Length = %d)", l);
}
static inline void dwc3_decode_set_configuration(__u8 v, char *str)
{
sprintf(str, "Set Configuration(Config = %d)", v);
}
static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str)
{
sprintf(str, "Get Interface(Intf = %d, Length = %d)", i, l);
}
static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str)
{
sprintf(str, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
}
static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str)
{
sprintf(str, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
}
static inline void dwc3_decode_set_sel(__u16 l, char *str)
{
sprintf(str, "Set SEL(Length = %d)", l);
}
static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str)
{
sprintf(str, "Set Isochronous Delay(Delay = %d ns)", v);
}
/**
* dwc3_decode_ctrl - returns a string represetion of ctrl request
*/
static inline const char *dwc3_decode_ctrl(char *str, __u8 bRequestType,
__u8 bRequest, __u16 wValue, __u16 wIndex, __u16 wLength)
{
switch (bRequest) {
case USB_REQ_GET_STATUS:
dwc3_decode_get_status(bRequestType, wIndex, wLength, str);
break;
case USB_REQ_CLEAR_FEATURE:
case USB_REQ_SET_FEATURE:
dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
wIndex, str);
break;
case USB_REQ_SET_ADDRESS:
dwc3_decode_set_address(wValue, str);
break;
case USB_REQ_GET_DESCRIPTOR:
case USB_REQ_SET_DESCRIPTOR:
dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
wIndex, wLength, str);
break;
case USB_REQ_GET_CONFIGURATION:
dwc3_decode_get_configuration(wLength, str);
break;
case USB_REQ_SET_CONFIGURATION:
dwc3_decode_set_configuration(wValue, str);
break;
case USB_REQ_GET_INTERFACE:
dwc3_decode_get_intf(wIndex, wLength, str);
break;
case USB_REQ_SET_INTERFACE:
dwc3_decode_set_intf(wValue, wIndex, str);
break;
case USB_REQ_SYNCH_FRAME:
dwc3_decode_synch_frame(wIndex, wLength, str);
break;
case USB_REQ_SET_SEL:
dwc3_decode_set_sel(wLength, str);
break;
case USB_REQ_SET_ISOCH_DELAY:
dwc3_decode_set_isoch_delay(wValue, str);
break;
default:
sprintf(str, "%02x %02x %02x %02x %02x %02x %02x %02x",
bRequestType, bRequest,
cpu_to_le16(wValue) & 0xff,
cpu_to_le16(wValue) >> 8,
cpu_to_le16(wIndex) & 0xff,
cpu_to_le16(wIndex) >> 8,
cpu_to_le16(wLength) & 0xff,
cpu_to_le16(wLength) >> 8);
}
return str;
}
/**
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
static inline const char *
dwc3_ep_event_string(const struct dwc3_event_depevt *event, u32 ep0state)
dwc3_ep_event_string(char *str, const struct dwc3_event_depevt *event,
u32 ep0state)
{
u8 epnum = event->endpoint_number;
static char str[256];
size_t len;
int status;
int ret;
......@@ -332,14 +565,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event)
}
}
static inline const char *dwc3_decode_event(u32 event, u32 ep0state)
static inline const char *dwc3_decode_event(char *str, u32 event, u32 ep0state)
{
const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec)
return dwc3_gadget_event_string(&evt.devt);
return dwc3_gadget_event_string(str, &evt.devt);
else
return dwc3_ep_event_string(&evt.depevt, ep0state);
return dwc3_ep_event_string(str, &evt.depevt, ep0state);
}
static inline const char *dwc3_ep_cmd_status_string(int status)
......
......@@ -653,16 +653,13 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
goto out;
}
seq_printf(s, "enqueue pointer %d\n", dep->trb_enqueue);
seq_printf(s, "dequeue pointer %d\n", dep->trb_dequeue);
seq_printf(s, "\n--------------------------------------------------\n\n");
seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n");
for (i = 0; i < DWC3_TRB_NUM; i++) {
struct dwc3_trb *trb = &dep->trb_pool[i];
unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl);
seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n",
seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d %c%c\n",
trb->bph, trb->bpl, trb->size,
dwc3_trb_type_string(type),
!!(trb->ctrl & DWC3_TRB_CTRL_IOC),
......@@ -670,7 +667,9 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
!!(trb->ctrl & DWC3_TRB_CTRL_CSP),
!!(trb->ctrl & DWC3_TRB_CTRL_CHN),
!!(trb->ctrl & DWC3_TRB_CTRL_LST),
!!(trb->ctrl & DWC3_TRB_CTRL_HWO));
!!(trb->ctrl & DWC3_TRB_CTRL_HWO),
dep->trb_enqueue == i ? 'E' : ' ',
dep->trb_dequeue == i ? 'D' : ' ');
}
out:
......
......@@ -125,12 +125,16 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
dev_err(dev, "couldn't get clock\n");
return -EINVAL;
}
clk_prepare_enable(exynos->clk);
ret = clk_prepare_enable(exynos->clk);
if (ret)
return ret;
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk))
exynos->susp_clk = NULL;
clk_prepare_enable(exynos->susp_clk);
ret = clk_prepare_enable(exynos->susp_clk);
if (ret)
goto susp_clk_err;
if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
......@@ -139,7 +143,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
ret = -ENODEV;
goto axius_clk_err;
}
clk_prepare_enable(exynos->axius_clk);
ret = clk_prepare_enable(exynos->axius_clk);
if (ret)
goto axius_clk_err;
} else {
exynos->axius_clk = NULL;
}
......@@ -197,6 +203,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
clk_disable_unprepare(exynos->axius_clk);
axius_clk_err:
clk_disable_unprepare(exynos->susp_clk);
susp_clk_err:
clk_disable_unprepare(exynos->clk);
return ret;
}
......
......@@ -230,7 +230,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
dwc3_data->syscfg_reg_off = res->start;
dev_vdbg(&pdev->dev, "glue-logic addr 0x%p, syscfg-reg offset 0x%x\n",
dev_vdbg(&pdev->dev, "glue-logic addr 0x%pK, syscfg-reg offset 0x%x\n",
dwc3_data->glue_base, dwc3_data->syscfg_reg_off);
dwc3_data->rstc_pwrdn =
......
/**
/*
* ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
......@@ -319,10 +319,16 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{
struct dwc3_ep *dep;
u32 recip;
u32 value;
u32 reg;
u16 usb_status = 0;
__le16 *response_pkt;
/* We don't support PTM_STATUS */
value = le16_to_cpu(ctrl->wValue);
if (value != 0)
return -EINVAL;
recip = ctrl->bRequestType & USB_RECIP_MASK;
switch (recip) {
case USB_RECIP_DEVICE:
......
This diff is collapsed.
/**
/*
* gadget.h - DesignWare USB3 DRD Gadget Header
*
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
......@@ -60,11 +60,25 @@ struct dwc3;
#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request))
/**
* next_request - gets the next request on the given list
* @list: the request list to operate on
*
* Caller should take care of locking. This function return %NULL or the first
* request available on @list.
*/
static inline struct dwc3_request *next_request(struct list_head *list)
{
return list_first_entry_or_null(list, struct dwc3_request, list);
}
/**
* dwc3_gadget_move_started_request - move @req to the started_list
* @req: the request to be moved
*
* Caller should take care of locking. This function will move @req from its
* current list to the endpoint's started_list.
*/
static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{
struct dwc3_ep *dep = req->dep;
......@@ -87,10 +101,10 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
/**
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
* @dwc: DesignWare USB3 Pointer
* @number: DWC endpoint number
* @dep: dwc3 endpoint
*
* Caller should take care of locking
* Caller should take care of locking. Returns the transfer resource
* index for a given endpoint.
*/
static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
{
......
......@@ -60,13 +60,15 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
TP_STRUCT__entry(
__field(u32, event)
__field(u32, ep0state)
__dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->event = event;
__entry->ep0state = dwc->ep0state;
),
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
dwc3_decode_event(__get_str(str), __entry->event,
__entry->ep0state))
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
......@@ -83,6 +85,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__field(__u16, wValue)
__field(__u16, wIndex)
__field(__u16, wLength)
__dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->bRequestType = ctrl->bRequestType;
......@@ -91,10 +94,9 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength);
),
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
__entry->bRequestType, __entry->bRequest,
__entry->wValue, __entry->wIndex,
__entry->wLength
TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
);
......@@ -107,7 +109,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__string(name, req->dep->name)
__field(struct dwc3_request *, req)
__field(unsigned, actual)
__field(unsigned, length)
......@@ -117,7 +119,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
__field(int, no_interrupt)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
__assign_str(name, req->dep->name);
__entry->req = req;
__entry->actual = req->request.actual;
__entry->length = req->request.length;
......@@ -190,7 +192,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__string(name, dep->name)
__field(unsigned int, cmd)
__field(u32, param0)
__field(u32, param1)
......@@ -198,7 +200,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
__field(int, cmd_status)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__assign_str(name, dep->name);
__entry->cmd = cmd;
__entry->param0 = params->param0;
__entry->param1 = params->param1;
......@@ -223,7 +225,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__string(name, dep->name)
__field(struct dwc3_trb *, trb)
__field(u32, allocated)
__field(u32, queued)
......@@ -234,7 +236,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
__field(u32, type)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__assign_str(name, dep->name);
__entry->trb = trb;
__entry->allocated = dep->allocated_requests;
__entry->queued = dep->queued_requests;
......@@ -291,7 +293,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep),
TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__string(name, dep->name)
__field(unsigned, maxpacket)
__field(unsigned, maxpacket_limit)
__field(unsigned, max_streams)
......@@ -302,7 +304,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__field(u8, trb_dequeue)
),
TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__assign_str(name, dep->name);
__entry->maxpacket = dep->endpoint.maxpacket;
__entry->maxpacket_limit = dep->endpoint.maxpacket_limit;
__entry->max_streams = dep->endpoint.max_streams;
......
......@@ -41,6 +41,12 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr)
u32 reg;
int ret;
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
}
reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
......@@ -58,6 +64,12 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
struct dwc3 *dwc = dev_get_drvdata(dev);
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
}
reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
reg |= DWC3_GUSB2PHYACC_WRITE | val;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
......
......@@ -41,7 +41,7 @@ menuconfig USB_GADGET
don't have this kind of hardware (except maybe inside Linux PDAs).
For more information, see <http://www.linux-usb.org/gadget> and
the kernel DocBook documentation for this API.
the kernel documentation for this API.
if USB_GADGET
......@@ -158,6 +158,9 @@ config USB_U_SERIAL
config USB_U_ETHER
tristate
config USB_U_AUDIO
tristate
config USB_F_SERIAL
tristate
......@@ -191,6 +194,9 @@ config USB_F_FS
config USB_F_UAC1
tristate
config USB_F_UAC1_LEGACY
tristate
config USB_F_UAC2
tristate
......@@ -368,12 +374,30 @@ config USB_CONFIGFS_F_UAC1
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
select USB_U_AUDIO
select USB_F_UAC1
help
This Audio function implements 1 AudioControl interface,
1 AudioStreaming Interface each for USB-OUT and USB-IN.
This driver requires a real Audio codec to be present
on the device.
This driver doesn't expect any real Audio codec to be present
on the device - the audio streams are simply sinked to and
sourced from a virtual ALSA sound card created. The user-space
application may choose to do whatever it wants with the data
received from the USB Host and choose to provide whatever it
wants as audio data to the USB Host.
config USB_CONFIGFS_F_UAC1_LEGACY
bool "Audio Class 1.0 (legacy implementation)"
depends on USB_CONFIGFS
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
select USB_F_UAC1_LEGACY
help
This Audio function implements 1 AudioControl interface,
1 AudioStreaming Interface each for USB-OUT and USB-IN.
This is a legacy driver and requires a real Audio codec
to be present on the device.
config USB_CONFIGFS_F_UAC2
bool "Audio Class 2.0"
......@@ -381,6 +405,7 @@ config USB_CONFIGFS_F_UAC2
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
select USB_U_AUDIO
select USB_F_UAC2
help
This Audio function is compatible with USB Audio Class
......
......@@ -610,7 +610,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
static int bos_desc(struct usb_composite_dev *cdev)
{
struct usb_ext_cap_descriptor *usb_ext;
struct usb_ss_cap_descriptor *ss_cap;
struct usb_dcd_config_params dcd_config_params;
struct usb_bos_descriptor *bos = cdev->req->buf;
......@@ -636,6 +635,9 @@ static int bos_desc(struct usb_composite_dev *cdev)
* The Superspeed USB Capability descriptor shall be implemented by all
* SuperSpeed devices.
*/
if (gadget_is_superspeed(cdev->gadget)) {
struct usb_ss_cap_descriptor *ss_cap;
ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
bos->bNumDeviceCaps++;
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
......@@ -650,15 +652,18 @@ static int bos_desc(struct usb_composite_dev *cdev)
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
/* Get Controller configuration */
if (cdev->gadget->ops->get_config_params)
cdev->gadget->ops->get_config_params(&dcd_config_params);
else {
dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
if (cdev->gadget->ops->get_config_params) {
cdev->gadget->ops->get_config_params(
&dcd_config_params);
} else {
dcd_config_params.bU1devExitLat =
USB_DEFAULT_U1_DEV_EXIT_LAT;
dcd_config_params.bU2DevExitLat =
cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
}
ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
}
/* The SuperSpeedPlus USB Device Capability descriptor */
if (gadget_is_superspeed_plus(cdev->gadget)) {
......@@ -1602,6 +1607,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
cdev->desc.bcdUSB = cpu_to_le16(0x0210);
}
} else {
if (gadget->lpm_capable)
cdev->desc.bcdUSB = cpu_to_le16(0x0201);
else
cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
......@@ -1633,7 +1641,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value);
break;
case USB_DT_BOS:
if (gadget_is_superspeed(gadget)) {
if (gadget_is_superspeed(gadget) ||
gadget->lpm_capable) {
value = bos_desc(cdev);
value = min(w_length, (u16) value);
}
......
......@@ -738,7 +738,7 @@ static inline struct gadget_info *os_desc_item_to_gadget_info(
static ssize_t os_desc_use_show(struct config_item *item, char *page)
{
return sprintf(page, "%d",
return sprintf(page, "%d\n",
os_desc_item_to_gadget_info(item)->use_os_desc);
}
......@@ -762,7 +762,7 @@ static ssize_t os_desc_use_store(struct config_item *item, const char *page,
static ssize_t os_desc_b_vendor_code_show(struct config_item *item, char *page)
{
return sprintf(page, "%d",
return sprintf(page, "0x%02x\n",
os_desc_item_to_gadget_info(item)->b_vendor_code);
}
......@@ -787,9 +787,13 @@ static ssize_t os_desc_b_vendor_code_store(struct config_item *item,
static ssize_t os_desc_qw_sign_show(struct config_item *item, char *page)
{
struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int res;
res = utf16s_to_utf8s((wchar_t *) gi->qw_sign, OS_STRING_QW_SIGN_LEN,
UTF16_LITTLE_ENDIAN, page, PAGE_SIZE - 1);
page[res++] = '\n';
memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
return OS_STRING_QW_SIGN_LEN;
return res;
}
static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
......@@ -900,7 +904,7 @@ static inline struct usb_os_desc_ext_prop
static ssize_t ext_prop_type_show(struct config_item *item, char *page)
{
return sprintf(page, "%d", to_usb_os_desc_ext_prop(item)->type);
return sprintf(page, "%d\n", to_usb_os_desc_ext_prop(item)->type);
}
static ssize_t ext_prop_type_store(struct config_item *item,
......
......@@ -32,8 +32,11 @@ usb_f_mass_storage-y := f_mass_storage.o storage_common.o
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
usb_f_uac1-y := f_uac1.o u_uac1.o
obj-$(CONFIG_USB_U_AUDIO) += u_audio.o
usb_f_uac1-y := f_uac1.o
obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o
usb_f_uac1_legacy-y := f_uac1_legacy.o u_uac1_legacy.o
obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
......
......@@ -127,7 +127,6 @@ struct ffs_ep {
struct ffs_epfile {
/* Protects ep->ep and ep->req. */
struct mutex mutex;
wait_queue_head_t wait;
struct ffs_data *ffs;
struct ffs_ep *ep; /* P: ffs->eps_lock */
......@@ -889,7 +888,8 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep));
ret = wait_event_interruptible(
epfile->ffs->wait, (ep = epfile->ep));
if (ret)
return -EINTR;
}
......@@ -1189,6 +1189,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
unsigned long value)
{
struct ffs_epfile *epfile = file->private_data;
struct ffs_ep *ep;
int ret;
ENTER();
......@@ -1196,8 +1197,26 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV;
/* Wait for endpoint to be enabled */
ep = epfile->ep;
if (!ep) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(
epfile->ffs->wait, (ep = epfile->ep));
if (ret)
return -EINTR;
}
spin_lock_irq(&epfile->ffs->eps_lock);
if (likely(epfile->ep)) {
/* In the meantime, endpoint got disabled or changed. */
if (epfile->ep != ep) {
spin_unlock_irq(&epfile->ffs->eps_lock);
return -ESHUTDOWN;
}
switch (code) {
case FUNCTIONFS_FIFO_STATUS:
ret = usb_ep_fifo_status(epfile->ep->ep);
......@@ -1238,9 +1257,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
default:
ret = -ENOTTY;
}
} else {
ret = -ENODEV;
}
spin_unlock_irq(&epfile->ffs->eps_lock);
return ret;
......@@ -1593,7 +1609,8 @@ static void ffs_data_put(struct ffs_data *ffs)
pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
waitqueue_active(&ffs->ep0req_completion.wait));
waitqueue_active(&ffs->ep0req_completion.wait) ||
waitqueue_active(&ffs->wait));
kfree(ffs->dev_name);
kfree(ffs);
}
......@@ -1640,6 +1657,7 @@ static struct ffs_data *ffs_data_new(void)
mutex_init(&ffs->mutex);
spin_lock_init(&ffs->eps_lock);
init_waitqueue_head(&ffs->ev.waitq);
init_waitqueue_head(&ffs->wait);
init_completion(&ffs->ep0req_completion);
/* XXX REVISIT need to update it in some places, or do we? */
......@@ -1761,7 +1779,6 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
for (i = 1; i <= count; ++i, ++epfile) {
epfile->ffs = ffs;
mutex_init(&epfile->mutex);
init_waitqueue_head(&epfile->wait);
if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
else
......@@ -1786,8 +1803,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER();
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) ||
waitqueue_active(&epfile->wait));
BUG_ON(mutex_is_locked(&epfile->mutex));
if (epfile->dentry) {
d_delete(epfile->dentry);
dput(epfile->dentry);
......@@ -1874,11 +1890,11 @@ static int ffs_func_eps_enable(struct ffs_function *func)
break;
}
wake_up(&epfile->wait);
++ep;
++epfile;
}
wake_up_interruptible(&ffs->wait);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
return ret;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_MAX_LUNS 16
enum fsg_buffer_state {
BUF_STATE_SENDING = -2,
BUF_STATE_RECEIVING,
BUF_STATE_EMPTY = 0,
BUF_STATE_FULL,
BUF_STATE_BUSY
BUF_STATE_FULL
};
struct fsg_buffhd {
......@@ -151,23 +152,14 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length;
struct usb_request *inreq;
int inreq_busy;
struct usb_request *outreq;
int outreq_busy;
};
enum fsg_state {
/* This one isn't used anywhere */
FSG_STATE_COMMAND_PHASE = -10,
FSG_STATE_DATA_PHASE,
FSG_STATE_STATUS_PHASE,
FSG_STATE_IDLE = 0,
FSG_STATE_NORMAL,
FSG_STATE_ABORT_BULK_OUT,
FSG_STATE_RESET,
FSG_STATE_INTERFACE_CHANGE,
FSG_STATE_PROTOCOL_RESET,
FSG_STATE_CONFIG_CHANGE,
FSG_STATE_DISCONNECT,
FSG_STATE_EXIT,
FSG_STATE_TERMINATED
};
......
This diff is collapsed.
/*
* u_audio.h -- interface to USB gadget "ALSA sound card" utilities
*
* Copyright (C) 2016
* Author: Ruslan Bilovol <ruslan.bilovol@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __U_AUDIO_H
#define __U_AUDIO_H
#include <linux/usb/composite.h>
struct uac_params {
/* playback */
int p_chmask; /* channel mask */
int p_srate; /* rate in Hz */
int p_ssize; /* sample size */
/* capture */
int c_chmask; /* channel mask */
int c_srate; /* rate in Hz */
int c_ssize; /* sample size */
int req_number; /* number of preallocated requests */
};
struct g_audio {
struct usb_function func;
struct usb_gadget *gadget;
struct usb_ep *in_ep;
struct usb_ep *out_ep;
/* Max packet size for all in_ep possible speeds */
unsigned int in_ep_maxpsize;
/* Max packet size for all out_ep possible speeds */
unsigned int out_ep_maxpsize;
/* The ALSA Sound Card it represents on the USB-Client side */
struct snd_uac_chip *uac;
struct uac_params params;
};
static inline struct g_audio *func_to_g_audio(struct usb_function *f)
{
return container_of(f, struct g_audio, func);
}
static inline uint num_channels(uint chanmask)
{
uint num = 0;
while (chanmask) {
num += (chanmask & 1);
chanmask >>= 1;
}
return num;
}
/*
* g_audio_setup - initialize one virtual ALSA sound card
* @g_audio: struct with filled params, in_ep_maxpsize, out_ep_maxpsize
* @pcm_name: the id string for a PCM instance of this sound card
* @card_name: name of this soundcard
*
* This sets up the single virtual ALSA sound card that may be exported by a
* gadget driver using this framework.
*
* Context: may sleep
*
* Returns zero on success, or a negative error on failure.
*/
int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
const char *card_name);
void g_audio_cleanup(struct g_audio *g_audio);
int u_audio_start_capture(struct g_audio *g_audio);
void u_audio_stop_capture(struct g_audio *g_audio);
int u_audio_start_playback(struct g_audio *g_audio);
void u_audio_stop_playback(struct g_audio *g_audio);
#endif /* __U_AUDIO_H */
......@@ -216,6 +216,9 @@ struct ffs_data {
#define FFS_FL_CALL_CLOSED_CALLBACK 0
#define FFS_FL_BOUND 1
/* For waking up blocked threads when function is enabled. */
wait_queue_head_t wait;
/* Active function */
struct ffs_function *func;
......
This diff is collapsed.
......@@ -18,7 +18,7 @@
#include <linux/random.h>
#include <linux/syscalls.h>
#include "u_uac1.h"
#include "u_uac1_legacy.h"
/*
* This component encapsulates the ALSA devices for USB audio gadget
......@@ -205,10 +205,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
{
struct snd_pcm_file *pcm_file;
struct gaudio_snd_dev *snd;
struct f_uac1_opts *opts;
struct f_uac1_legacy_opts *opts;
char *fn_play, *fn_cap, *fn_cntl;
opts = container_of(card->func.fi, struct f_uac1_opts, func_inst);
opts = container_of(card->func.fi, struct f_uac1_legacy_opts,
func_inst);
fn_play = opts->fn_play;
fn_cap = opts->fn_cap;
fn_cntl = opts->fn_cntl;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment