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: ...@@ -55,14 +55,6 @@ Description:
Indicates the maximum USB speed supported by this port. Indicates the maximum USB speed supported by this port.
Users: 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 What: /sys/class/udc/<udc>/soft_connect
Date: June 2011 Date: June 2011
KernelVersion: 3.1 KernelVersion: 3.1
...@@ -91,3 +83,11 @@ Description: ...@@ -91,3 +83,11 @@ Description:
'configured', and 'suspended'; however not all USB Device 'configured', and 'suspended'; however not all USB Device
Controllers support reporting all states. Controllers support reporting all states.
Users: 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 What: /config/usb-gadget/gadget/functions/uac1.name
Date: Sep 2014 Date: June 2017
KernelVersion: 3.18 KernelVersion: 4.14
Description: Description:
The attributes: The attributes:
audio_buf_size - audio buffer size c_chmask - capture channel mask
fn_cap - capture pcm device file name c_srate - capture sampling rate
fn_cntl - control device file name c_ssize - capture sample size (bytes)
fn_play - playback pcm device file name p_chmask - playback channel mask
req_buf_size - ISO OUT endpoint request buffer size p_srate - playback sampling rate
req_count - ISO OUT endpoint request count 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: ...@@ -45,6 +45,8 @@ Optional properties:
a free-running PHY clock. a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY power - snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
from P0 to P1/P2/P3 without delay. 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 - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold - 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 ...@@ -16,7 +16,10 @@ Linux USB API
persist persist
error-codes error-codes
writing_usb_driver writing_usb_driver
dwc3
writing_musb_glue_layer writing_musb_glue_layer
typec
usb3-debug-port
.. only:: subproject and html .. only:: subproject and html
......
...@@ -16,10 +16,11 @@ provided by gadgets. ...@@ -16,10 +16,11 @@ provided by gadgets.
13. RNDIS function 13. RNDIS function
14. SERIAL function 14. SERIAL function
15. SOURCESINK function 15. SOURCESINK function
16. UAC1 function 16. UAC1 function (legacy implementation)
17. UAC2 function 17. UAC2 function
18. UVC function 18. UVC function
19. PRINTER function 19. PRINTER function
20. UAC1 function (new API)
1. ACM function 1. ACM function
...@@ -589,15 +590,16 @@ device: run the gadget ...@@ -589,15 +590,16 @@ device: run the gadget
host: test-usb (tools/usb/testusb.c) 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 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: The uac1 function provides these attributes in its function directory:
audio_buf_size - audio buffer size audio_buf_size - audio buffer size
...@@ -772,3 +774,46 @@ host: ...@@ -772,3 +774,46 @@ host:
More advanced testing can be done with the prn_example More advanced testing can be done with the prn_example
described in Documentation/usb/gadget-printer.txt. 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) ...@@ -151,11 +151,24 @@ static void __dwc3_set_mode(struct work_struct *work)
switch (dwc->desired_dr_role) { switch (dwc->desired_dr_role) {
case DWC3_GCTL_PRTCAP_HOST: case DWC3_GCTL_PRTCAP_HOST:
ret = dwc3_host_init(dwc); ret = dwc3_host_init(dwc);
if (ret) if (ret) {
dev_err(dwc->dev, "failed to initialize host\n"); 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; break;
case DWC3_GCTL_PRTCAP_DEVICE: case DWC3_GCTL_PRTCAP_DEVICE:
dwc3_event_buffers_setup(dwc); 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); ret = dwc3_gadget_init(dwc);
if (ret) if (ret)
dev_err(dwc->dev, "failed to initialize peripheral\n"); dev_err(dwc->dev, "failed to initialize peripheral\n");
...@@ -721,6 +734,8 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) ...@@ -721,6 +734,8 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GCTL, reg); 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 * dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure * @dwc: Pointer to our controller context structure
...@@ -759,6 +774,10 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -759,6 +774,10 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (ret) if (ret)
goto err0; goto err0;
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
dwc3_core_setup_global_control(dwc); dwc3_core_setup_global_control(dwc);
dwc3_core_num_eps(dwc); dwc3_core_num_eps(dwc);
...@@ -796,13 +815,19 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -796,13 +815,19 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 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 * Enable hardware control of sending remote wakeup
* the device is in the L1 state. * in HS when the device is in the L1 state.
*/ */
if (dwc->revision >= DWC3_REVISION_290A) { if (dwc->revision >= DWC3_REVISION_290A)
reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; 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); dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
} }
...@@ -903,6 +928,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) ...@@ -903,6 +928,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
switch (dwc->dr_mode) { switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL: case USB_DR_MODE_PERIPHERAL:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 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); ret = dwc3_gadget_init(dwc);
if (ret) { if (ret) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
...@@ -912,6 +943,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) ...@@ -912,6 +943,12 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
break; break;
case USB_DR_MODE_HOST: case USB_DR_MODE_HOST:
dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_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); ret = dwc3_host_init(dwc);
if (ret) { if (ret) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
...@@ -1023,6 +1060,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) ...@@ -1023,6 +1060,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
"snps,dis-u2-freeclk-exists-quirk"); "snps,dis-u2-freeclk-exists-quirk");
dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,dis-del-phy-power-chg-quirk"); "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, dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk"); "snps,tx_de_emphasis_quirk");
...@@ -1148,10 +1187,6 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -1148,10 +1187,6 @@ static int dwc3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dwc); platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc); dwc3_cache_hwparams(dwc);
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
spin_lock_init(&dwc->lock); spin_lock_init(&dwc->lock);
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
......
/** /*
* core.h - DesignWare USB3 DRD Core Header * core.h - DesignWare USB3 DRD Core Header
* *
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
...@@ -204,6 +204,7 @@ ...@@ -204,6 +204,7 @@
#define DWC3_GCTL_DSBLCLKGTNG BIT(0) #define DWC3_GCTL_DSBLCLKGTNG BIT(0)
/* Global User Control 1 Register */ /* Global User Control 1 Register */
#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
#define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24)
/* Global USB2 PHY Configuration Register */ /* Global USB2 PHY Configuration Register */
...@@ -522,7 +523,6 @@ struct dwc3_event_buffer { ...@@ -522,7 +523,6 @@ struct dwc3_event_buffer {
* @trb_pool_dma: dma address of @trb_pool * @trb_pool_dma: dma address of @trb_pool
* @trb_enqueue: enqueue 'pointer' into TRB array * @trb_enqueue: enqueue 'pointer' into TRB array
* @trb_dequeue: dequeue 'pointer' into TRB array * @trb_dequeue: dequeue 'pointer' into TRB array
* @desc: usb_endpoint_descriptor pointer
* @dwc: pointer to DWC controller * @dwc: pointer to DWC controller
* @saved_state: ep state saved during hibernation * @saved_state: ep state saved during hibernation
* @flags: endpoint flags (wedged, stalled, ...) * @flags: endpoint flags (wedged, stalled, ...)
...@@ -664,7 +664,7 @@ enum dwc3_link_state { ...@@ -664,7 +664,7 @@ enum dwc3_link_state {
* @bpl: DW0-3 * @bpl: DW0-3
* @bph: DW4-7 * @bph: DW4-7
* @size: DW8-B * @size: DW8-B
* @trl: DWC-F * @ctrl: DWC-F
*/ */
struct dwc3_trb { struct dwc3_trb {
u32 bpl; u32 bpl;
...@@ -674,16 +674,16 @@ struct dwc3_trb { ...@@ -674,16 +674,16 @@ struct dwc3_trb {
} __packed; } __packed;
/** /**
* dwc3_hwparams - copy of HWPARAMS registers * struct dwc3_hwparams - copy of HWPARAMS registers
* @hwparams0 - GHWPARAMS0 * @hwparams0: GHWPARAMS0
* @hwparams1 - GHWPARAMS1 * @hwparams1: GHWPARAMS1
* @hwparams2 - GHWPARAMS2 * @hwparams2: GHWPARAMS2
* @hwparams3 - GHWPARAMS3 * @hwparams3: GHWPARAMS3
* @hwparams4 - GHWPARAMS4 * @hwparams4: GHWPARAMS4
* @hwparams5 - GHWPARAMS5 * @hwparams5: GHWPARAMS5
* @hwparams6 - GHWPARAMS6 * @hwparams6: GHWPARAMS6
* @hwparams7 - GHWPARAMS7 * @hwparams7: GHWPARAMS7
* @hwparams8 - GHWPARAMS8 * @hwparams8: GHWPARAMS8
*/ */
struct dwc3_hwparams { struct dwc3_hwparams {
u32 hwparams0; u32 hwparams0;
...@@ -730,7 +730,8 @@ struct dwc3_hwparams { ...@@ -730,7 +730,8 @@ struct dwc3_hwparams {
* @unaligned: true for OUT endpoints with length not divisible by maxp * @unaligned: true for OUT endpoints with length not divisible by maxp
* @direction: IN or OUT direction flag * @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped * @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 dwc3_request {
struct usb_request request; struct usb_request request;
...@@ -761,17 +762,23 @@ struct dwc3_scratchpad_array { ...@@ -761,17 +762,23 @@ struct dwc3_scratchpad_array {
/** /**
* struct dwc3 - representation of our controller * 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 * @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 * @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 * @ep0_usb_req: dummy req used while handling STD USB requests
* @scratch_addr: dma address of scratchbuf * @scratch_addr: dma address of scratchbuf
* @ep0_in_setup: one control transfer is completed and enter setup phase * @ep0_in_setup: one control transfer is completed and enter setup phase
* @lock: for synchronizing * @lock: for synchronizing
* @dev: pointer to our struct device * @dev: pointer to our struct device
* @sysdev: pointer to the DMA-capable device
* @xhci: pointer to our xHCI child * @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: device side representation of the peripheral controller
* @gadget_driver: pointer to the gadget driver * @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers * @regs: base address for our registers
...@@ -795,8 +802,6 @@ struct dwc3_scratchpad_array { ...@@ -795,8 +802,6 @@ struct dwc3_scratchpad_array {
* @usb2_generic_phy: pointer to USB2 PHY * @usb2_generic_phy: pointer to USB2 PHY
* @usb3_generic_phy: pointer to USB3 PHY * @usb3_generic_phy: pointer to USB3 PHY
* @ulpi: pointer to ulpi interface * @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; * @isoch_delay: wValue from Set Isochronous Delay request;
* @u2sel: parameter from Set SEL request. * @u2sel: parameter from Set SEL request.
* @u2pel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request.
...@@ -830,7 +835,6 @@ struct dwc3_scratchpad_array { ...@@ -830,7 +835,6 @@ struct dwc3_scratchpad_array {
* @pending_events: true when we have pending IRQs to be handled * @pending_events: true when we have pending IRQs to be handled
* @pullups_connected: true when Run/Stop bit is set * @pullups_connected: true when Run/Stop bit is set
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround * @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 * @three_stage_setup: set if we perform a three phase setup
* @usb3_lpm_capable: set if hadrware supports Link Power Management * @usb3_lpm_capable: set if hadrware supports Link Power Management
* @disable_scramble_quirk: set if we enable the disable scramble quirk * @disable_scramble_quirk: set if we enable the disable scramble quirk
...@@ -845,11 +849,14 @@ struct dwc3_scratchpad_array { ...@@ -845,11 +849,14 @@ struct dwc3_scratchpad_array {
* @dis_u2_susphy_quirk: set if we disable usb2 suspend phy * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
* @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG, * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
* disabling the suspend signal to the PHY. * 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 * @dis_u2_freeclk_exists_quirk : set if we clear u2_freeclk_exists
* in GUSB2PHYCFG, specify that USB2 PHY doesn't * in GUSB2PHYCFG, specify that USB2 PHY doesn't
* provide a free-running PHY clock. * provide a free-running PHY clock.
* @dis_del_phy_power_chg_quirk: set if we disable delay phy power * @dis_del_phy_power_chg_quirk: set if we disable delay phy power
* change quirk. * 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_quirk: set if we enable Tx de-emphasis quirk
* @tx_de_emphasis: Tx de-emphasis value * @tx_de_emphasis: Tx de-emphasis value
* 0 - -6dB de-emphasis * 0 - -6dB de-emphasis
...@@ -1004,6 +1011,7 @@ struct dwc3 { ...@@ -1004,6 +1011,7 @@ struct dwc3 {
unsigned dis_rxdet_inp3_quirk:1; unsigned dis_rxdet_inp3_quirk:1;
unsigned dis_u2_freeclk_exists_quirk:1; unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_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_quirk:1;
unsigned tx_de_emphasis:2; unsigned tx_de_emphasis:2;
......
...@@ -173,9 +173,8 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) ...@@ -173,9 +173,8 @@ static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
* @event: the event code * @event: the event code
*/ */
static inline const char * 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; enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) { switch (event->type) {
...@@ -223,15 +222,249 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event) ...@@ -223,15 +222,249 @@ dwc3_gadget_event_string(const struct dwc3_event_devt *event)
return str; 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 * dwc3_ep_event_string - returns event name
* @event: then event code * @event: then event code
*/ */
static inline const char * 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; u8 epnum = event->endpoint_number;
static char str[256];
size_t len; size_t len;
int status; int status;
int ret; int ret;
...@@ -332,14 +565,14 @@ static inline const char *dwc3_gadget_event_type_string(u8 event) ...@@ -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; const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec) if (evt.type.is_devspec)
return dwc3_gadget_event_string(&evt.devt); return dwc3_gadget_event_string(str, &evt.devt);
else 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) 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) ...@@ -653,16 +653,13 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
goto out; 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"); seq_printf(s, "buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo\n");
for (i = 0; i < DWC3_TRB_NUM; i++) { for (i = 0; i < DWC3_TRB_NUM; i++) {
struct dwc3_trb *trb = &dep->trb_pool[i]; struct dwc3_trb *trb = &dep->trb_pool[i];
unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl); 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, trb->bph, trb->bpl, trb->size,
dwc3_trb_type_string(type), dwc3_trb_type_string(type),
!!(trb->ctrl & DWC3_TRB_CTRL_IOC), !!(trb->ctrl & DWC3_TRB_CTRL_IOC),
...@@ -670,7 +667,9 @@ static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused) ...@@ -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_CSP),
!!(trb->ctrl & DWC3_TRB_CTRL_CHN), !!(trb->ctrl & DWC3_TRB_CTRL_CHN),
!!(trb->ctrl & DWC3_TRB_CTRL_LST), !!(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: out:
......
...@@ -125,12 +125,16 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -125,12 +125,16 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
dev_err(dev, "couldn't get clock\n"); dev_err(dev, "couldn't get clock\n");
return -EINVAL; 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"); exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk)) if (IS_ERR(exynos->susp_clk))
exynos->susp_clk = NULL; 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")) { if (of_device_is_compatible(node, "samsung,exynos7-dwusb3")) {
exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk"); exynos->axius_clk = devm_clk_get(dev, "usbdrd30_axius_clk");
...@@ -139,7 +143,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -139,7 +143,9 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
ret = -ENODEV; ret = -ENODEV;
goto axius_clk_err; goto axius_clk_err;
} }
clk_prepare_enable(exynos->axius_clk); ret = clk_prepare_enable(exynos->axius_clk);
if (ret)
goto axius_clk_err;
} else { } else {
exynos->axius_clk = NULL; exynos->axius_clk = NULL;
} }
...@@ -197,6 +203,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -197,6 +203,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
clk_disable_unprepare(exynos->axius_clk); clk_disable_unprepare(exynos->axius_clk);
axius_clk_err: axius_clk_err:
clk_disable_unprepare(exynos->susp_clk); clk_disable_unprepare(exynos->susp_clk);
susp_clk_err:
clk_disable_unprepare(exynos->clk); clk_disable_unprepare(exynos->clk);
return ret; return ret;
} }
......
...@@ -230,7 +230,7 @@ static int st_dwc3_probe(struct platform_device *pdev) ...@@ -230,7 +230,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
dwc3_data->syscfg_reg_off = res->start; 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->glue_base, dwc3_data->syscfg_reg_off);
dwc3_data->rstc_pwrdn = dwc3_data->rstc_pwrdn =
......
/** /*
* ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling
* *
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
...@@ -319,10 +319,16 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, ...@@ -319,10 +319,16 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
{ {
struct dwc3_ep *dep; struct dwc3_ep *dep;
u32 recip; u32 recip;
u32 value;
u32 reg; u32 reg;
u16 usb_status = 0; u16 usb_status = 0;
__le16 *response_pkt; __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; recip = ctrl->bRequestType & USB_RECIP_MASK;
switch (recip) { switch (recip) {
case USB_RECIP_DEVICE: case USB_RECIP_DEVICE:
......
This diff is collapsed.
/** /*
* gadget.h - DesignWare USB3 DRD Gadget Header * gadget.h - DesignWare USB3 DRD Gadget Header
* *
* Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com
...@@ -60,11 +60,25 @@ struct dwc3; ...@@ -60,11 +60,25 @@ struct dwc3;
#define to_dwc3_request(r) (container_of(r, struct dwc3_request, request)) #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) static inline struct dwc3_request *next_request(struct list_head *list)
{ {
return list_first_entry_or_null(list, struct dwc3_request, 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) static inline void dwc3_gadget_move_started_request(struct dwc3_request *req)
{ {
struct dwc3_ep *dep = req->dep; struct dwc3_ep *dep = req->dep;
...@@ -87,10 +101,10 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); ...@@ -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 * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
* @dwc: DesignWare USB3 Pointer * @dep: dwc3 endpoint
* @number: DWC endpoint number
* *
* 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) static inline u32 dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
{ {
......
...@@ -60,13 +60,15 @@ DECLARE_EVENT_CLASS(dwc3_log_event, ...@@ -60,13 +60,15 @@ DECLARE_EVENT_CLASS(dwc3_log_event,
TP_STRUCT__entry( TP_STRUCT__entry(
__field(u32, event) __field(u32, event)
__field(u32, ep0state) __field(u32, ep0state)
__dynamic_array(char, str, DWC3_MSG_MAX)
), ),
TP_fast_assign( TP_fast_assign(
__entry->event = event; __entry->event = event;
__entry->ep0state = dwc->ep0state; __entry->ep0state = dwc->ep0state;
), ),
TP_printk("event (%08x): %s", __entry->event, 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, DEFINE_EVENT(dwc3_log_event, dwc3_event,
...@@ -83,6 +85,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, ...@@ -83,6 +85,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__field(__u16, wValue) __field(__u16, wValue)
__field(__u16, wIndex) __field(__u16, wIndex)
__field(__u16, wLength) __field(__u16, wLength)
__dynamic_array(char, str, DWC3_MSG_MAX)
), ),
TP_fast_assign( TP_fast_assign(
__entry->bRequestType = ctrl->bRequestType; __entry->bRequestType = ctrl->bRequestType;
...@@ -91,10 +94,9 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, ...@@ -91,10 +94,9 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
__entry->wIndex = le16_to_cpu(ctrl->wIndex); __entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength); __entry->wLength = le16_to_cpu(ctrl->wLength);
), ),
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d", TP_printk("%s", dwc3_decode_ctrl(__get_str(str), __entry->bRequestType,
__entry->bRequestType, __entry->bRequest, __entry->bRequest, __entry->wValue,
__entry->wValue, __entry->wIndex, __entry->wIndex, __entry->wLength)
__entry->wLength
) )
); );
...@@ -107,7 +109,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request, ...@@ -107,7 +109,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
TP_PROTO(struct dwc3_request *req), TP_PROTO(struct dwc3_request *req),
TP_ARGS(req), TP_ARGS(req),
TP_STRUCT__entry( TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX) __string(name, req->dep->name)
__field(struct dwc3_request *, req) __field(struct dwc3_request *, req)
__field(unsigned, actual) __field(unsigned, actual)
__field(unsigned, length) __field(unsigned, length)
...@@ -117,7 +119,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request, ...@@ -117,7 +119,7 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
__field(int, no_interrupt) __field(int, no_interrupt)
), ),
TP_fast_assign( TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name); __assign_str(name, req->dep->name);
__entry->req = req; __entry->req = req;
__entry->actual = req->request.actual; __entry->actual = req->request.actual;
__entry->length = req->request.length; __entry->length = req->request.length;
...@@ -190,7 +192,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, ...@@ -190,7 +192,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
struct dwc3_gadget_ep_cmd_params *params, int cmd_status), struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status), TP_ARGS(dep, cmd, params, cmd_status),
TP_STRUCT__entry( TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX) __string(name, dep->name)
__field(unsigned int, cmd) __field(unsigned int, cmd)
__field(u32, param0) __field(u32, param0)
__field(u32, param1) __field(u32, param1)
...@@ -198,7 +200,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, ...@@ -198,7 +200,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
__field(int, cmd_status) __field(int, cmd_status)
), ),
TP_fast_assign( TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); __assign_str(name, dep->name);
__entry->cmd = cmd; __entry->cmd = cmd;
__entry->param0 = params->param0; __entry->param0 = params->param0;
__entry->param1 = params->param1; __entry->param1 = params->param1;
...@@ -223,7 +225,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, ...@@ -223,7 +225,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb), TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb), TP_ARGS(dep, trb),
TP_STRUCT__entry( TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX) __string(name, dep->name)
__field(struct dwc3_trb *, trb) __field(struct dwc3_trb *, trb)
__field(u32, allocated) __field(u32, allocated)
__field(u32, queued) __field(u32, queued)
...@@ -234,7 +236,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, ...@@ -234,7 +236,7 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
__field(u32, type) __field(u32, type)
), ),
TP_fast_assign( TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name); __assign_str(name, dep->name);
__entry->trb = trb; __entry->trb = trb;
__entry->allocated = dep->allocated_requests; __entry->allocated = dep->allocated_requests;
__entry->queued = dep->queued_requests; __entry->queued = dep->queued_requests;
...@@ -291,7 +293,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, ...@@ -291,7 +293,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
TP_PROTO(struct dwc3_ep *dep), TP_PROTO(struct dwc3_ep *dep),
TP_ARGS(dep), TP_ARGS(dep),
TP_STRUCT__entry( TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX) __string(name, dep->name)
__field(unsigned, maxpacket) __field(unsigned, maxpacket)
__field(unsigned, maxpacket_limit) __field(unsigned, maxpacket_limit)
__field(unsigned, max_streams) __field(unsigned, max_streams)
...@@ -302,7 +304,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep, ...@@ -302,7 +304,7 @@ DECLARE_EVENT_CLASS(dwc3_log_ep,
__field(u8, trb_dequeue) __field(u8, trb_dequeue)
), ),
TP_fast_assign( 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 = dep->endpoint.maxpacket;
__entry->maxpacket_limit = dep->endpoint.maxpacket_limit; __entry->maxpacket_limit = dep->endpoint.maxpacket_limit;
__entry->max_streams = dep->endpoint.max_streams; __entry->max_streams = dep->endpoint.max_streams;
......
...@@ -41,6 +41,12 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr) ...@@ -41,6 +41,12 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr)
u32 reg; u32 reg;
int ret; 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); reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
...@@ -58,6 +64,12 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val) ...@@ -58,6 +64,12 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val)
struct dwc3 *dwc = dev_get_drvdata(dev); struct dwc3 *dwc = dev_get_drvdata(dev);
u32 reg; 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_NEWREGREQ | DWC3_ULPI_ADDR(addr);
reg |= DWC3_GUSB2PHYACC_WRITE | val; reg |= DWC3_GUSB2PHYACC_WRITE | val;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
......
...@@ -41,7 +41,7 @@ menuconfig USB_GADGET ...@@ -41,7 +41,7 @@ menuconfig USB_GADGET
don't have this kind of hardware (except maybe inside Linux PDAs). don't have this kind of hardware (except maybe inside Linux PDAs).
For more information, see <http://www.linux-usb.org/gadget> and 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 if USB_GADGET
...@@ -158,6 +158,9 @@ config USB_U_SERIAL ...@@ -158,6 +158,9 @@ config USB_U_SERIAL
config USB_U_ETHER config USB_U_ETHER
tristate tristate
config USB_U_AUDIO
tristate
config USB_F_SERIAL config USB_F_SERIAL
tristate tristate
...@@ -191,6 +194,9 @@ config USB_F_FS ...@@ -191,6 +194,9 @@ config USB_F_FS
config USB_F_UAC1 config USB_F_UAC1
tristate tristate
config USB_F_UAC1_LEGACY
tristate
config USB_F_UAC2 config USB_F_UAC2
tristate tristate
...@@ -368,12 +374,30 @@ config USB_CONFIGFS_F_UAC1 ...@@ -368,12 +374,30 @@ config USB_CONFIGFS_F_UAC1
depends on SND depends on SND
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select SND_PCM select SND_PCM
select USB_U_AUDIO
select USB_F_UAC1 select USB_F_UAC1
help help
This Audio function implements 1 AudioControl interface, This Audio function implements 1 AudioControl interface,
1 AudioStreaming Interface each for USB-OUT and USB-IN. 1 AudioStreaming Interface each for USB-OUT and USB-IN.
This driver requires a real Audio codec to be present This driver doesn't expect any real Audio codec to be present
on the device. 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 config USB_CONFIGFS_F_UAC2
bool "Audio Class 2.0" bool "Audio Class 2.0"
...@@ -381,6 +405,7 @@ config USB_CONFIGFS_F_UAC2 ...@@ -381,6 +405,7 @@ config USB_CONFIGFS_F_UAC2
depends on SND depends on SND
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select SND_PCM select SND_PCM
select USB_U_AUDIO
select USB_F_UAC2 select USB_F_UAC2
help help
This Audio function is compatible with USB Audio Class This Audio function is compatible with USB Audio Class
......
...@@ -610,7 +610,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type) ...@@ -610,7 +610,6 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
static int bos_desc(struct usb_composite_dev *cdev) static int bos_desc(struct usb_composite_dev *cdev)
{ {
struct usb_ext_cap_descriptor *usb_ext; struct usb_ext_cap_descriptor *usb_ext;
struct usb_ss_cap_descriptor *ss_cap;
struct usb_dcd_config_params dcd_config_params; struct usb_dcd_config_params dcd_config_params;
struct usb_bos_descriptor *bos = cdev->req->buf; struct usb_bos_descriptor *bos = cdev->req->buf;
...@@ -636,6 +635,9 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -636,6 +635,9 @@ static int bos_desc(struct usb_composite_dev *cdev)
* The Superspeed USB Capability descriptor shall be implemented by all * The Superspeed USB Capability descriptor shall be implemented by all
* SuperSpeed devices. * 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); ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
bos->bNumDeviceCaps++; bos->bNumDeviceCaps++;
le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE); le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
...@@ -650,15 +652,18 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -650,15 +652,18 @@ static int bos_desc(struct usb_composite_dev *cdev)
ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION; ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
/* Get Controller configuration */ /* Get Controller configuration */
if (cdev->gadget->ops->get_config_params) if (cdev->gadget->ops->get_config_params) {
cdev->gadget->ops->get_config_params(&dcd_config_params); cdev->gadget->ops->get_config_params(
else { &dcd_config_params);
dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT; } else {
dcd_config_params.bU1devExitLat =
USB_DEFAULT_U1_DEV_EXIT_LAT;
dcd_config_params.bU2DevExitLat = dcd_config_params.bU2DevExitLat =
cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
} }
ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
}
/* The SuperSpeedPlus USB Device Capability descriptor */ /* The SuperSpeedPlus USB Device Capability descriptor */
if (gadget_is_superspeed_plus(cdev->gadget)) { if (gadget_is_superspeed_plus(cdev->gadget)) {
...@@ -1602,6 +1607,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1602,6 +1607,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
cdev->desc.bcdUSB = cpu_to_le16(0x0210); cdev->desc.bcdUSB = cpu_to_le16(0x0210);
} }
} else { } else {
if (gadget->lpm_capable)
cdev->desc.bcdUSB = cpu_to_le16(0x0201);
else
cdev->desc.bcdUSB = cpu_to_le16(0x0200); cdev->desc.bcdUSB = cpu_to_le16(0x0200);
} }
...@@ -1633,7 +1641,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1633,7 +1641,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value); value = min(w_length, (u16) value);
break; break;
case USB_DT_BOS: case USB_DT_BOS:
if (gadget_is_superspeed(gadget)) { if (gadget_is_superspeed(gadget) ||
gadget->lpm_capable) {
value = bos_desc(cdev); value = bos_desc(cdev);
value = min(w_length, (u16) value); value = min(w_length, (u16) value);
} }
......
...@@ -738,7 +738,7 @@ static inline struct gadget_info *os_desc_item_to_gadget_info( ...@@ -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) 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); 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, ...@@ -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) 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); 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, ...@@ -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) 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); 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 res;
return OS_STRING_QW_SIGN_LEN;
} }
static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page, 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 ...@@ -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) 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, 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 ...@@ -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 obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_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 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 usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_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 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 { ...@@ -127,7 +127,6 @@ struct ffs_ep {
struct ffs_epfile { struct ffs_epfile {
/* Protects ep->ep and ep->req. */ /* Protects ep->ep and ep->req. */
struct mutex mutex; struct mutex mutex;
wait_queue_head_t wait;
struct ffs_data *ffs; struct ffs_data *ffs;
struct ffs_ep *ep; /* P: ffs->eps_lock */ 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) ...@@ -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) if (file->f_flags & O_NONBLOCK)
return -EAGAIN; return -EAGAIN;
ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); ret = wait_event_interruptible(
epfile->ffs->wait, (ep = epfile->ep));
if (ret) if (ret)
return -EINTR; return -EINTR;
} }
...@@ -1189,6 +1189,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ...@@ -1189,6 +1189,7 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
unsigned long value) unsigned long value)
{ {
struct ffs_epfile *epfile = file->private_data; struct ffs_epfile *epfile = file->private_data;
struct ffs_ep *ep;
int ret; int ret;
ENTER(); ENTER();
...@@ -1196,8 +1197,26 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ...@@ -1196,8 +1197,26 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
return -ENODEV; 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); 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) { switch (code) {
case FUNCTIONFS_FIFO_STATUS: case FUNCTIONFS_FIFO_STATUS:
ret = usb_ep_fifo_status(epfile->ep->ep); ret = usb_ep_fifo_status(epfile->ep->ep);
...@@ -1238,9 +1257,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code, ...@@ -1238,9 +1257,6 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
default: default:
ret = -ENOTTY; ret = -ENOTTY;
} }
} else {
ret = -ENODEV;
}
spin_unlock_irq(&epfile->ffs->eps_lock); spin_unlock_irq(&epfile->ffs->eps_lock);
return ret; return ret;
...@@ -1593,7 +1609,8 @@ static void ffs_data_put(struct ffs_data *ffs) ...@@ -1593,7 +1609,8 @@ static void ffs_data_put(struct ffs_data *ffs)
pr_info("%s(): freeing\n", __func__); pr_info("%s(): freeing\n", __func__);
ffs_data_clear(ffs); ffs_data_clear(ffs);
BUG_ON(waitqueue_active(&ffs->ev.waitq) || 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->dev_name);
kfree(ffs); kfree(ffs);
} }
...@@ -1640,6 +1657,7 @@ static struct ffs_data *ffs_data_new(void) ...@@ -1640,6 +1657,7 @@ static struct ffs_data *ffs_data_new(void)
mutex_init(&ffs->mutex); mutex_init(&ffs->mutex);
spin_lock_init(&ffs->eps_lock); spin_lock_init(&ffs->eps_lock);
init_waitqueue_head(&ffs->ev.waitq); init_waitqueue_head(&ffs->ev.waitq);
init_waitqueue_head(&ffs->wait);
init_completion(&ffs->ep0req_completion); init_completion(&ffs->ep0req_completion);
/* XXX REVISIT need to update it in some places, or do we? */ /* 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) ...@@ -1761,7 +1779,6 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
for (i = 1; i <= count; ++i, ++epfile) { for (i = 1; i <= count; ++i, ++epfile) {
epfile->ffs = ffs; epfile->ffs = ffs;
mutex_init(&epfile->mutex); mutex_init(&epfile->mutex);
init_waitqueue_head(&epfile->wait);
if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) if (ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR)
sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]); sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]);
else else
...@@ -1786,8 +1803,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) ...@@ -1786,8 +1803,7 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
ENTER(); ENTER();
for (; count; --count, ++epfile) { for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex) || BUG_ON(mutex_is_locked(&epfile->mutex));
waitqueue_active(&epfile->wait));
if (epfile->dentry) { if (epfile->dentry) {
d_delete(epfile->dentry); d_delete(epfile->dentry);
dput(epfile->dentry); dput(epfile->dentry);
...@@ -1874,11 +1890,11 @@ static int ffs_func_eps_enable(struct ffs_function *func) ...@@ -1874,11 +1890,11 @@ static int ffs_func_eps_enable(struct ffs_function *func)
break; break;
} }
wake_up(&epfile->wait);
++ep; ++ep;
++epfile; ++epfile;
} }
wake_up_interruptible(&ffs->wait);
spin_unlock_irqrestore(&func->ffs->eps_lock, flags); spin_unlock_irqrestore(&func->ffs->eps_lock, flags);
return ret; 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) ...@@ -133,9 +133,10 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_MAX_LUNS 16 #define FSG_MAX_LUNS 16
enum fsg_buffer_state { enum fsg_buffer_state {
BUF_STATE_SENDING = -2,
BUF_STATE_RECEIVING,
BUF_STATE_EMPTY = 0, BUF_STATE_EMPTY = 0,
BUF_STATE_FULL, BUF_STATE_FULL
BUF_STATE_BUSY
}; };
struct fsg_buffhd { struct fsg_buffhd {
...@@ -151,23 +152,14 @@ struct fsg_buffhd { ...@@ -151,23 +152,14 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length; unsigned int bulk_out_intended_length;
struct usb_request *inreq; struct usb_request *inreq;
int inreq_busy;
struct usb_request *outreq; struct usb_request *outreq;
int outreq_busy;
}; };
enum fsg_state { enum fsg_state {
/* This one isn't used anywhere */ FSG_STATE_NORMAL,
FSG_STATE_COMMAND_PHASE = -10,
FSG_STATE_DATA_PHASE,
FSG_STATE_STATUS_PHASE,
FSG_STATE_IDLE = 0,
FSG_STATE_ABORT_BULK_OUT, FSG_STATE_ABORT_BULK_OUT,
FSG_STATE_RESET, FSG_STATE_PROTOCOL_RESET,
FSG_STATE_INTERFACE_CHANGE,
FSG_STATE_CONFIG_CHANGE, FSG_STATE_CONFIG_CHANGE,
FSG_STATE_DISCONNECT,
FSG_STATE_EXIT, FSG_STATE_EXIT,
FSG_STATE_TERMINATED 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 { ...@@ -216,6 +216,9 @@ struct ffs_data {
#define FFS_FL_CALL_CLOSED_CALLBACK 0 #define FFS_FL_CALL_CLOSED_CALLBACK 0
#define FFS_FL_BOUND 1 #define FFS_FL_BOUND 1
/* For waking up blocked threads when function is enabled. */
wait_queue_head_t wait;
/* Active function */ /* Active function */
struct ffs_function *func; struct ffs_function *func;
......
This diff is collapsed.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include "u_uac1.h" #include "u_uac1_legacy.h"
/* /*
* This component encapsulates the ALSA devices for USB audio gadget * This component encapsulates the ALSA devices for USB audio gadget
...@@ -205,10 +205,11 @@ static int gaudio_open_snd_dev(struct gaudio *card) ...@@ -205,10 +205,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
{ {
struct snd_pcm_file *pcm_file; struct snd_pcm_file *pcm_file;
struct gaudio_snd_dev *snd; struct gaudio_snd_dev *snd;
struct f_uac1_opts *opts; struct f_uac1_legacy_opts *opts;
char *fn_play, *fn_cap, *fn_cntl; 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_play = opts->fn_play;
fn_cap = opts->fn_cap; fn_cap = opts->fn_cap;
fn_cntl = opts->fn_cntl; 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