mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
USB merge for 3.7-rc1
Here is the big USB pull request for 3.7-rc1
There are lots of gadget driver changes (including copying a bunch of
files into the drivers/staging/ccg/ directory so that the other gadget
drivers can be fixed up properly without breaking that driver), and we
remove the old obsolete ub.c driver from the tree. There are also the
usual XHCI set of updates, and other various driver changes and updates.
We also are trying hard to remove the old dbg() macro, but the final
bits of that removal will be coming in through the networking tree
before we can delete it for good.
All of these patches have been in the linux-next tree.
Signed-off-by: Greg Kroah-Hartman <[email protected]>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
iEYEABECAAYFAlBp3+AACgkQMUfUDdst+ym5vwCfe93FyJyXn/RDkGz7iBemvWFd
vrwAoIxjaOa4/yWZWcgrWc5bP4aO3ssc
=jYDr
-----END PGP SIGNATURE-----
Merge tag 'usb-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB changes from Greg Kroah-Hartman:
"Here is the big USB pull request for 3.7-rc1
There are lots of gadget driver changes (including copying a bunch of
files into the drivers/staging/ccg/ directory so that the other gadget
drivers can be fixed up properly without breaking that driver), and we
remove the old obsolete ub.c driver from the tree.
There are also the usual XHCI set of updates, and other various driver
changes and updates. We also are trying hard to remove the old dbg()
macro, but the final bits of that removal will be coming in through
the networking tree before we can delete it for good.
All of these patches have been in the linux-next tree.
Signed-off-by: Greg Kroah-Hartman <[email protected]>"
Fix up several annoying - but fairly mindless - conflicts due to the
termios structure having moved into the tty device, and often clashing
with dbg -> dev_dbg conversion.
* tag 'usb-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (339 commits)
USB: ezusb: move ezusb.c from drivers/usb/serial to drivers/usb/misc
USB: uas: fix gcc warning
USB: uas: fix locking
USB: Fix race condition when removing host controllers
USB: uas: add locking
USB: uas: fix abort
USB: uas: remove aborted field, replace with status bit.
USB: uas: fix task management
USB: uas: keep track of command urbs
xhci: Intel Panther Point BEI quirk.
powerpc/usb: remove checking PHY_CLK_VALID for UTMI PHY
USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support
Revert "usb : Add sysfs files to control port power."
USB: serial: remove vizzini driver
usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems
Increase XHCI suspend timeout to 16ms
USB: ohci-at91: fix null pointer in ohci_hcd_at91_overcurrent_irq
USB: sierra_ms: don't keep unused variable
fsl/usb: Add support for USB controller version 2.4
USB: qcaux: add Pantech vendor class match
...
This commit is contained in:
commit
d9a807461f
333 changed files with 25607 additions and 9056 deletions
|
|
@ -48,6 +48,7 @@ config USB_ARCH_HAS_EHCI
|
|||
default y if SPARC_LEON
|
||||
default y if ARCH_MMP
|
||||
default y if MACH_LOONGSON1
|
||||
default y if PLAT_ORION
|
||||
default PCI
|
||||
|
||||
# some non-PCI HCDs implement xHCI
|
||||
|
|
|
|||
|
|
@ -307,6 +307,34 @@ enum {
|
|||
#define FW_GET_BYTE(p) (*((__u8 *) (p)))
|
||||
|
||||
#define FW_DIR "ueagle-atm/"
|
||||
#define EAGLE_FIRMWARE FW_DIR "eagle.fw"
|
||||
#define ADI930_FIRMWARE FW_DIR "adi930.fw"
|
||||
#define EAGLE_I_FIRMWARE FW_DIR "eagleI.fw"
|
||||
#define EAGLE_II_FIRMWARE FW_DIR "eagleII.fw"
|
||||
#define EAGLE_III_FIRMWARE FW_DIR "eagleIII.fw"
|
||||
#define EAGLE_IV_FIRMWARE FW_DIR "eagleIV.fw"
|
||||
|
||||
#define DSP4I_FIRMWARE FW_DIR "DSP4i.bin"
|
||||
#define DSP4P_FIRMWARE FW_DIR "DSP4p.bin"
|
||||
#define DSP9I_FIRMWARE FW_DIR "DSP9i.bin"
|
||||
#define DSP9P_FIRMWARE FW_DIR "DSP9p.bin"
|
||||
#define DSPEI_FIRMWARE FW_DIR "DSPei.bin"
|
||||
#define DSPEP_FIRMWARE FW_DIR "DSPep.bin"
|
||||
#define FPGA930_FIRMWARE FW_DIR "930-fpga.bin"
|
||||
|
||||
#define CMV4P_FIRMWARE FW_DIR "CMV4p.bin"
|
||||
#define CMV4PV2_FIRMWARE FW_DIR "CMV4p.bin.v2"
|
||||
#define CMV4I_FIRMWARE FW_DIR "CMV4i.bin"
|
||||
#define CMV4IV2_FIRMWARE FW_DIR "CMV4i.bin.v2"
|
||||
#define CMV9P_FIRMWARE FW_DIR "CMV9p.bin"
|
||||
#define CMV9PV2_FIRMWARE FW_DIR "CMV9p.bin.v2"
|
||||
#define CMV9I_FIRMWARE FW_DIR "CMV9i.bin"
|
||||
#define CMV9IV2_FIRMWARE FW_DIR "CMV9i.bin.v2"
|
||||
#define CMVEP_FIRMWARE FW_DIR "CMVep.bin"
|
||||
#define CMVEPV2_FIRMWARE FW_DIR "CMVep.bin.v2"
|
||||
#define CMVEI_FIRMWARE FW_DIR "CMVei.bin"
|
||||
#define CMVEIV2_FIRMWARE FW_DIR "CMVei.bin.v2"
|
||||
|
||||
#define UEA_FW_NAME_MAX 30
|
||||
#define NB_MODEM 4
|
||||
|
||||
|
|
@ -694,26 +722,26 @@ err:
|
|||
static int uea_load_firmware(struct usb_device *usb, unsigned int ver)
|
||||
{
|
||||
int ret;
|
||||
char *fw_name = FW_DIR "eagle.fw";
|
||||
char *fw_name = EAGLE_FIRMWARE;
|
||||
|
||||
uea_enters(usb);
|
||||
uea_info(usb, "pre-firmware device, uploading firmware\n");
|
||||
|
||||
switch (ver) {
|
||||
case ADI930:
|
||||
fw_name = FW_DIR "adi930.fw";
|
||||
fw_name = ADI930_FIRMWARE;
|
||||
break;
|
||||
case EAGLE_I:
|
||||
fw_name = FW_DIR "eagleI.fw";
|
||||
fw_name = EAGLE_I_FIRMWARE;
|
||||
break;
|
||||
case EAGLE_II:
|
||||
fw_name = FW_DIR "eagleII.fw";
|
||||
fw_name = EAGLE_II_FIRMWARE;
|
||||
break;
|
||||
case EAGLE_III:
|
||||
fw_name = FW_DIR "eagleIII.fw";
|
||||
fw_name = EAGLE_III_FIRMWARE;
|
||||
break;
|
||||
case EAGLE_IV:
|
||||
fw_name = FW_DIR "eagleIV.fw";
|
||||
fw_name = EAGLE_IV_FIRMWARE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -869,19 +897,19 @@ static int request_dsp(struct uea_softc *sc)
|
|||
|
||||
if (UEA_CHIP_VERSION(sc) == EAGLE_IV) {
|
||||
if (IS_ISDN(sc))
|
||||
dsp_name = FW_DIR "DSP4i.bin";
|
||||
dsp_name = DSP4I_FIRMWARE;
|
||||
else
|
||||
dsp_name = FW_DIR "DSP4p.bin";
|
||||
dsp_name = DSP4P_FIRMWARE;
|
||||
} else if (UEA_CHIP_VERSION(sc) == ADI930) {
|
||||
if (IS_ISDN(sc))
|
||||
dsp_name = FW_DIR "DSP9i.bin";
|
||||
dsp_name = DSP9I_FIRMWARE;
|
||||
else
|
||||
dsp_name = FW_DIR "DSP9p.bin";
|
||||
dsp_name = DSP9P_FIRMWARE;
|
||||
} else {
|
||||
if (IS_ISDN(sc))
|
||||
dsp_name = FW_DIR "DSPei.bin";
|
||||
dsp_name = DSPEI_FIRMWARE;
|
||||
else
|
||||
dsp_name = FW_DIR "DSPep.bin";
|
||||
dsp_name = DSPEP_FIRMWARE;
|
||||
}
|
||||
|
||||
ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
|
||||
|
|
@ -1925,7 +1953,7 @@ static int load_XILINX_firmware(struct uea_softc *sc)
|
|||
int ret, size, u, ln;
|
||||
const u8 *pfw;
|
||||
u8 value;
|
||||
char *fw_name = FW_DIR "930-fpga.bin";
|
||||
char *fw_name = FPGA930_FIRMWARE;
|
||||
|
||||
uea_enters(INS_TO_USBDEV(sc));
|
||||
|
||||
|
|
@ -2753,3 +2781,28 @@ module_usb_driver(uea_driver);
|
|||
MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka");
|
||||
MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_FIRMWARE(EAGLE_FIRMWARE);
|
||||
MODULE_FIRMWARE(ADI930_FIRMWARE);
|
||||
MODULE_FIRMWARE(EAGLE_I_FIRMWARE);
|
||||
MODULE_FIRMWARE(EAGLE_II_FIRMWARE);
|
||||
MODULE_FIRMWARE(EAGLE_III_FIRMWARE);
|
||||
MODULE_FIRMWARE(EAGLE_IV_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSP4I_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSP4P_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSP9I_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSP9P_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSPEI_FIRMWARE);
|
||||
MODULE_FIRMWARE(DSPEP_FIRMWARE);
|
||||
MODULE_FIRMWARE(FPGA930_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV4P_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV4PV2_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV4I_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV4IV2_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV9P_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV9PV2_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV9I_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMV9IV2_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMVEP_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMVEPV2_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMVEI_FIRMWARE);
|
||||
MODULE_FIRMWARE(CMVEIV2_FIRMWARE);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
static int usbatm_print_packet(const unsigned char *data, int len);
|
||||
static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char *data, int len);
|
||||
#define PACKETDEBUG(arg...) usbatm_print_packet(arg)
|
||||
#define vdbg(arg...) dev_dbg(arg)
|
||||
#else
|
||||
|
|
@ -230,8 +230,8 @@ static int usbatm_submit_urb(struct urb *urb)
|
|||
struct usbatm_channel *channel = urb->context;
|
||||
int ret;
|
||||
|
||||
vdbg("%s: submitting urb 0x%p, size %u",
|
||||
__func__, urb, urb->transfer_buffer_length);
|
||||
/* vdbg("%s: submitting urb 0x%p, size %u",
|
||||
__func__, urb, urb->transfer_buffer_length); */
|
||||
|
||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
|
|
@ -261,8 +261,8 @@ static void usbatm_complete(struct urb *urb)
|
|||
unsigned long flags;
|
||||
int status = urb->status;
|
||||
|
||||
vdbg("%s: urb 0x%p, status %d, actual_length %d",
|
||||
__func__, urb, status, urb->actual_length);
|
||||
/* vdbg("%s: urb 0x%p, status %d, actual_length %d",
|
||||
__func__, urb, status, urb->actual_length); */
|
||||
|
||||
/* usually in_interrupt(), but not always */
|
||||
spin_lock_irqsave(&channel->lock, flags);
|
||||
|
|
@ -311,7 +311,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4);
|
||||
u8 pti = ((source[3] & 0xe) >> 1);
|
||||
|
||||
vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
|
||||
vdbg(&instance->usb_intf->dev, "%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti);
|
||||
|
||||
if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) {
|
||||
instance->cached_vpi = vpi;
|
||||
|
|
@ -381,7 +381,9 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
goto out;
|
||||
}
|
||||
|
||||
vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc);
|
||||
vdbg(&instance->usb_intf->dev,
|
||||
"%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)",
|
||||
__func__, length, pdu_length, vcc);
|
||||
|
||||
if (!(skb = dev_alloc_skb(length))) {
|
||||
if (printk_ratelimit())
|
||||
|
|
@ -391,7 +393,9 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
goto out;
|
||||
}
|
||||
|
||||
vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize);
|
||||
vdbg(&instance->usb_intf->dev,
|
||||
"%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)",
|
||||
__func__, skb, skb->truesize);
|
||||
|
||||
if (!atm_charge(vcc, skb->truesize)) {
|
||||
atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n",
|
||||
|
|
@ -405,10 +409,11 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char
|
|||
length);
|
||||
__skb_put(skb, length);
|
||||
|
||||
vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
|
||||
vdbg(&instance->usb_intf->dev,
|
||||
"%s: sending skb 0x%p, skb->len %u, skb->truesize %u",
|
||||
__func__, skb, skb->len, skb->truesize);
|
||||
|
||||
PACKETDEBUG(skb->data, skb->len);
|
||||
PACKETDEBUG(instance, skb->data, skb->len);
|
||||
|
||||
vcc->push(vcc, skb);
|
||||
|
||||
|
|
@ -474,7 +479,8 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance,
|
|||
unsigned int bytes_written;
|
||||
unsigned int stride = instance->tx_channel.stride;
|
||||
|
||||
vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space);
|
||||
vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u",
|
||||
__func__, skb->len, avail_space);
|
||||
UDSL_ASSERT(instance, !(avail_space % stride));
|
||||
|
||||
for (bytes_written = 0; bytes_written < avail_space && ctrl->len;
|
||||
|
|
@ -534,7 +540,8 @@ static void usbatm_rx_process(unsigned long data)
|
|||
struct urb *urb;
|
||||
|
||||
while ((urb = usbatm_pop_urb(&instance->rx_channel))) {
|
||||
vdbg("%s: processing urb 0x%p", __func__, urb);
|
||||
vdbg(&instance->usb_intf->dev,
|
||||
"%s: processing urb 0x%p", __func__, urb);
|
||||
|
||||
if (usb_pipeisoc(urb->pipe)) {
|
||||
unsigned char *merge_start = NULL;
|
||||
|
|
@ -608,7 +615,8 @@ static void usbatm_tx_process(unsigned long data)
|
|||
buffer + bytes_written,
|
||||
buf_size - bytes_written);
|
||||
|
||||
vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p",
|
||||
vdbg(&instance->usb_intf->dev,
|
||||
"%s: wrote %u bytes from skb 0x%p to urb 0x%p",
|
||||
__func__, bytes_written, skb, urb);
|
||||
|
||||
if (!UDSL_SKB(skb)->len) {
|
||||
|
|
@ -664,7 +672,8 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
struct usbatm_control *ctrl = UDSL_SKB(skb);
|
||||
int err;
|
||||
|
||||
vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len);
|
||||
vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
|
||||
skb, skb->len);
|
||||
|
||||
/* racy disconnection check - fine */
|
||||
if (!instance || instance->disconnected) {
|
||||
|
|
@ -688,7 +697,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
PACKETDEBUG(skb->data, skb->len);
|
||||
PACKETDEBUG(instance, skb->data, skb->len);
|
||||
|
||||
/* initialize the control block */
|
||||
ctrl->atm.vcc = vcc;
|
||||
|
|
@ -1202,7 +1211,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
|
|||
if (i >= num_rcv_urbs)
|
||||
list_add_tail(&urb->urb_list, &channel->list);
|
||||
|
||||
vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p",
|
||||
vdbg(&intf->dev, "%s: alloced buffer 0x%p buf size %u urb 0x%p",
|
||||
__func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
|
||||
}
|
||||
|
||||
|
|
@ -1359,7 +1368,8 @@ MODULE_VERSION(DRIVER_VERSION);
|
|||
************/
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
static int usbatm_print_packet(const unsigned char *data, int len)
|
||||
static int usbatm_print_packet(struct usbatm_data *instance,
|
||||
const unsigned char *data, int len)
|
||||
{
|
||||
unsigned char buffer[256];
|
||||
int i = 0, j = 0;
|
||||
|
|
@ -1369,7 +1379,7 @@ static int usbatm_print_packet(const unsigned char *data, int len)
|
|||
sprintf(buffer, "%.3d :", i);
|
||||
for (j = 0; (j < 16) && (i < len); j++, i++)
|
||||
sprintf(buffer, "%s %2.2x", buffer, data[i]);
|
||||
dbg("%s", buffer);
|
||||
dev_dbg(&instance->usb_intf->dev, "%s", buffer);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ if USB_CHIPIDEA
|
|||
config USB_CHIPIDEA_UDC
|
||||
bool "ChipIdea device controller"
|
||||
depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
Say Y here to enable device controller functionality of the
|
||||
ChipIdea driver.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG
|
||||
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o
|
||||
|
||||
ci_hdrc-y := core.o
|
||||
|
|
@ -15,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
|
|||
endif
|
||||
|
||||
ifneq ($(CONFIG_OF_DEVICE),)
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o
|
||||
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx6q.o
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ struct ci13xxx {
|
|||
enum ci_role role;
|
||||
bool is_otg;
|
||||
struct work_struct work;
|
||||
struct work_struct vbus_work;
|
||||
struct workqueue_struct *wq;
|
||||
|
||||
struct dma_pool *qh_pool;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@
|
|||
#include <linux/usb/chipidea.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
|
||||
#include "ci.h"
|
||||
#include "ci13xxx_imx.h"
|
||||
|
||||
#define pdev_to_phy(pdev) \
|
||||
((struct usb_phy *)platform_get_drvdata(pdev))
|
||||
|
|
@ -34,6 +36,55 @@ struct ci13xxx_imx_data {
|
|||
struct regulator *reg_vbus;
|
||||
};
|
||||
|
||||
static const struct usbmisc_ops *usbmisc_ops;
|
||||
|
||||
/* Common functions shared by usbmisc drivers */
|
||||
|
||||
int usbmisc_set_ops(const struct usbmisc_ops *ops)
|
||||
{
|
||||
if (usbmisc_ops)
|
||||
return -EBUSY;
|
||||
|
||||
usbmisc_ops = ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_set_ops);
|
||||
|
||||
void usbmisc_unset_ops(const struct usbmisc_ops *ops)
|
||||
{
|
||||
usbmisc_ops = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_unset_ops);
|
||||
|
||||
int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args args;
|
||||
int ret;
|
||||
|
||||
usbdev->dev = dev;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells",
|
||||
0, &args);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n",
|
||||
ret);
|
||||
memset(usbdev, 0, sizeof(*usbdev));
|
||||
return ret;
|
||||
}
|
||||
usbdev->index = args.args[0];
|
||||
of_node_put(args.np);
|
||||
|
||||
if (of_find_property(np, "disable-over-current", NULL))
|
||||
usbdev->disable_oc = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
|
||||
|
||||
/* End of common functions shared by usbmisc drivers*/
|
||||
|
||||
static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = {
|
||||
.name = "ci13xxx_imx",
|
||||
.flags = CI13XXX_REQUIRE_TRANSCEIVER |
|
||||
|
|
@ -49,8 +100,13 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
|
|||
struct device_node *phy_np;
|
||||
struct resource *res;
|
||||
struct regulator *reg_vbus;
|
||||
struct pinctrl *pinctrl;
|
||||
int ret;
|
||||
|
||||
if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL)
|
||||
&& !usbmisc_ops)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n");
|
||||
|
|
@ -63,6 +119,11 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
||||
if (IS_ERR(pinctrl))
|
||||
dev_warn(&pdev->dev, "pinctrl get/select failed, err=%ld\n",
|
||||
PTR_ERR(pinctrl));
|
||||
|
||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(data->clk)) {
|
||||
dev_err(&pdev->dev,
|
||||
|
|
@ -120,6 +181,16 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
|
|||
*pdev->dev.dma_mask = DMA_BIT_MASK(32);
|
||||
dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
|
||||
}
|
||||
|
||||
if (usbmisc_ops && usbmisc_ops->init) {
|
||||
ret = usbmisc_ops->init(&pdev->dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"usbmisc init failed, ret=%d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
plat_ci = ci13xxx_add_device(&pdev->dev,
|
||||
pdev->resource, pdev->num_resources,
|
||||
&ci13xxx_imx_platdata);
|
||||
|
|
|
|||
28
drivers/usb/chipidea/ci13xxx_imx.h
Normal file
28
drivers/usb/chipidea/ci13xxx_imx.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/* Used to set SoC specific callbacks */
|
||||
struct usbmisc_ops {
|
||||
/* It's called once when probe a usb device */
|
||||
int (*init)(struct device *dev);
|
||||
};
|
||||
|
||||
struct usbmisc_usb_device {
|
||||
struct device *dev; /* usb controller device */
|
||||
int index;
|
||||
|
||||
int disable_oc:1; /* over current detect disabled */
|
||||
};
|
||||
|
||||
int usbmisc_set_ops(const struct usbmisc_ops *ops);
|
||||
void usbmisc_unset_ops(const struct usbmisc_ops *ops);
|
||||
int
|
||||
usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev);
|
||||
|
|
@ -273,14 +273,13 @@ static void ci_role_work(struct work_struct *work)
|
|||
struct ci13xxx *ci = container_of(work, struct ci13xxx, work);
|
||||
enum ci_role role = ci_otg_role(ci);
|
||||
|
||||
hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
|
||||
|
||||
if (role != ci->role) {
|
||||
dev_dbg(ci->dev, "switching from %s to %s\n",
|
||||
ci_role(ci)->name, ci->roles[role]->name);
|
||||
|
||||
ci_role_stop(ci);
|
||||
ci_role_start(ci, role);
|
||||
enable_irq(ci->irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -320,17 +319,22 @@ static irqreturn_t ci_irq(int irq, void *data)
|
|||
{
|
||||
struct ci13xxx *ci = data;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
u32 otgsc = 0;
|
||||
|
||||
if (ci->is_otg) {
|
||||
u32 sts = hw_read(ci, OP_OTGSC, ~0);
|
||||
if (ci->is_otg)
|
||||
otgsc = hw_read(ci, OP_OTGSC, ~0);
|
||||
|
||||
if (sts & OTGSC_IDIS) {
|
||||
queue_work(ci->wq, &ci->work);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
if (ci->role != CI_ROLE_END)
|
||||
ret = ci_role(ci)->irq(ci);
|
||||
|
||||
if (ci->is_otg && (otgsc & OTGSC_IDIS)) {
|
||||
hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS);
|
||||
disable_irq_nosync(ci->irq);
|
||||
queue_work(ci->wq, &ci->work);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEFINE_IDA(ci_ida);
|
||||
|
|
@ -462,6 +466,8 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
|
|||
|
||||
if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
|
||||
ci->is_otg = true;
|
||||
/* ID pin needs 1ms debouce time, we delay 2ms for safe */
|
||||
mdelay(2);
|
||||
ci->role = ci_otg_role(ci);
|
||||
} else {
|
||||
ci->role = ci->roles[CI_ROLE_HOST]
|
||||
|
|
|
|||
|
|
@ -305,6 +305,18 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
|
|||
return reg;
|
||||
}
|
||||
|
||||
static void hw_enable_vbus_intr(struct ci13xxx *ci)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS);
|
||||
hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE);
|
||||
queue_work(ci->wq, &ci->vbus_work);
|
||||
}
|
||||
|
||||
static void hw_disable_vbus_intr(struct ci13xxx *ci)
|
||||
{
|
||||
hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* hw_test_and_clear_setup_guard: test & clear setup guard (execute without
|
||||
* interruption)
|
||||
|
|
@ -371,6 +383,16 @@ static int hw_usb_reset(struct ci13xxx *ci)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vbus_work(struct work_struct *work)
|
||||
{
|
||||
struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work);
|
||||
|
||||
if (hw_read(ci, OP_OTGSC, OTGSC_AVV))
|
||||
usb_gadget_vbus_connect(&ci->gadget);
|
||||
else
|
||||
usb_gadget_vbus_disconnect(&ci->gadget);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* UTIL block
|
||||
*****************************************************************************/
|
||||
|
|
@ -1370,6 +1392,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
|
|||
if (is_active) {
|
||||
pm_runtime_get_sync(&_gadget->dev);
|
||||
hw_device_reset(ci, USBMODE_CM_DC);
|
||||
hw_enable_vbus_intr(ci);
|
||||
hw_device_state(ci, ci->ep0out->qh.dma);
|
||||
} else {
|
||||
hw_device_state(ci, 0);
|
||||
|
|
@ -1544,8 +1567,10 @@ static int ci13xxx_start(struct usb_gadget *gadget,
|
|||
pm_runtime_get_sync(&ci->gadget.dev);
|
||||
if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
|
||||
if (ci->vbus_active) {
|
||||
if (ci->platdata->flags & CI13XXX_REGS_SHARED)
|
||||
if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
|
||||
hw_device_reset(ci, USBMODE_CM_DC);
|
||||
hw_enable_vbus_intr(ci);
|
||||
}
|
||||
} else {
|
||||
pm_runtime_put_sync(&ci->gadget.dev);
|
||||
goto done;
|
||||
|
|
@ -1651,6 +1676,13 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
|
|||
} else {
|
||||
retval = IRQ_NONE;
|
||||
}
|
||||
|
||||
intr = hw_read(ci, OP_OTGSC, ~0);
|
||||
hw_write(ci, OP_OTGSC, ~0, intr);
|
||||
|
||||
if (intr & (OTGSC_AVVIE & OTGSC_AVVIS))
|
||||
queue_work(ci->wq, &ci->vbus_work);
|
||||
|
||||
spin_unlock(&ci->lock);
|
||||
|
||||
return retval;
|
||||
|
|
@ -1726,6 +1758,7 @@ static int udc_start(struct ci13xxx *ci)
|
|||
retval = hw_device_reset(ci, USBMODE_CM_DC);
|
||||
if (retval)
|
||||
goto put_transceiver;
|
||||
hw_enable_vbus_intr(ci);
|
||||
}
|
||||
|
||||
retval = device_register(&ci->gadget.dev);
|
||||
|
|
@ -1788,6 +1821,9 @@ static void udc_stop(struct ci13xxx *ci)
|
|||
if (ci == NULL)
|
||||
return;
|
||||
|
||||
hw_disable_vbus_intr(ci);
|
||||
cancel_work_sync(&ci->vbus_work);
|
||||
|
||||
usb_del_gadget_udc(&ci->gadget);
|
||||
|
||||
destroy_eps(ci);
|
||||
|
|
@ -1828,6 +1864,7 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
|
|||
rdrv->irq = udc_irq;
|
||||
rdrv->name = "gadget";
|
||||
ci->roles[CI_ROLE_GADGET] = rdrv;
|
||||
INIT_WORK(&ci->vbus_work, vbus_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
162
drivers/usb/chipidea/usbmisc_imx6q.c
Normal file
162
drivers/usb/chipidea/usbmisc_imx6q.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include "ci13xxx_imx.h"
|
||||
|
||||
#define USB_DEV_MAX 4
|
||||
|
||||
#define BM_OVER_CUR_DIS BIT(7)
|
||||
|
||||
struct imx6q_usbmisc {
|
||||
void __iomem *base;
|
||||
spinlock_t lock;
|
||||
struct clk *clk;
|
||||
struct usbmisc_usb_device usbdev[USB_DEV_MAX];
|
||||
};
|
||||
|
||||
static struct imx6q_usbmisc *usbmisc;
|
||||
|
||||
static struct usbmisc_usb_device *get_usbdev(struct device *dev)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < USB_DEV_MAX; i++) {
|
||||
if (usbmisc->usbdev[i].dev == dev)
|
||||
return &usbmisc->usbdev[i];
|
||||
else if (!usbmisc->usbdev[i].dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= USB_DEV_MAX)
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return &usbmisc->usbdev[i];
|
||||
}
|
||||
|
||||
static int usbmisc_imx6q_init(struct device *dev)
|
||||
{
|
||||
|
||||
struct usbmisc_usb_device *usbdev;
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
usbdev = get_usbdev(dev);
|
||||
if (IS_ERR(usbdev))
|
||||
return PTR_ERR(usbdev);
|
||||
|
||||
if (usbdev->disable_oc) {
|
||||
spin_lock_irqsave(&usbmisc->lock, flags);
|
||||
reg = readl(usbmisc->base + usbdev->index * 4);
|
||||
writel(reg | BM_OVER_CUR_DIS,
|
||||
usbmisc->base + usbdev->index * 4);
|
||||
spin_unlock_irqrestore(&usbmisc->lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct usbmisc_ops imx6q_usbmisc_ops = {
|
||||
.init = usbmisc_imx6q_init,
|
||||
};
|
||||
|
||||
static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx6q-usbmisc"},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct imx6q_usbmisc *data;
|
||||
int ret;
|
||||
|
||||
if (usbmisc)
|
||||
return -EBUSY;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&data->lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
data->base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!data->base)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
data->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(data->clk)) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to get clock, err=%ld\n", PTR_ERR(data->clk));
|
||||
return PTR_ERR(data->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(data->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"clk_prepare_enable failed, err=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = usbmisc_set_ops(&imx6q_usbmisc_ops);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(data->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usbmisc = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev)
|
||||
{
|
||||
usbmisc_unset_ops(&imx6q_usbmisc_ops);
|
||||
clk_disable_unprepare(usbmisc->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver usbmisc_imx6q_driver = {
|
||||
.probe = usbmisc_imx6q_probe,
|
||||
.remove = __devexit_p(usbmisc_imx6q_remove),
|
||||
.driver = {
|
||||
.name = "usbmisc_imx6q",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = usbmisc_imx6q_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
int __init usbmisc_imx6q_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&usbmisc_imx6q_driver);
|
||||
}
|
||||
subsys_initcall(usbmisc_imx6q_drv_init);
|
||||
|
||||
void __exit usbmisc_imx6q_drv_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&usbmisc_imx6q_driver);
|
||||
}
|
||||
module_exit(usbmisc_imx6q_drv_exit);
|
||||
|
||||
MODULE_ALIAS("platform:usbmisc-imx6q");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("driver for imx6q usb non-core registers");
|
||||
MODULE_AUTHOR("Richard Zhao <[email protected]>");
|
||||
|
|
@ -39,7 +39,6 @@
|
|||
#include <linux/serial.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/tty_flip.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ config USB_SUSPEND
|
|||
|
||||
config USB_OTG
|
||||
bool "OTG support"
|
||||
depends on USB && EXPERIMENTAL
|
||||
depends on USB
|
||||
depends on USB_SUSPEND
|
||||
default n
|
||||
help
|
||||
|
|
|
|||
|
|
@ -702,6 +702,8 @@ int usb_get_configuration(struct usb_device *dev)
|
|||
if (result < 0) {
|
||||
dev_err(ddev, "unable to read config index %d "
|
||||
"descriptor/%s: %d\n", cfgno, "start", result);
|
||||
if (result != -EPIPE)
|
||||
goto err;
|
||||
dev_err(ddev, "chopping to %d config(s)\n", cfgno);
|
||||
dev->descriptor.bNumConfigurations = cfgno;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
|
|||
char *pages_start, *data_end, *speed;
|
||||
unsigned int length;
|
||||
ssize_t total_written = 0;
|
||||
struct usb_device *childdev = NULL;
|
||||
|
||||
/* don't bother with anything else if we're not writing any data */
|
||||
if (*nbytes <= 0)
|
||||
|
|
@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
|
|||
free_pages((unsigned long)pages_start, 1);
|
||||
|
||||
/* Now look at all of this device's children. */
|
||||
for (chix = 0; chix < usbdev->maxchild; chix++) {
|
||||
struct usb_device *childdev = usbdev->children[chix];
|
||||
|
||||
usb_hub_for_each_child(usbdev, chix, childdev) {
|
||||
if (childdev) {
|
||||
usb_lock_device(childdev);
|
||||
ret = usb_device_dump(buffer, nbytes, skip_bytes,
|
||||
file_offset, childdev, bus,
|
||||
level + 1, chix, ++cnt);
|
||||
level + 1, chix - 1, ++cnt);
|
||||
usb_unlock_device(childdev);
|
||||
if (ret == -EFAULT)
|
||||
return total_written;
|
||||
|
|
|
|||
|
|
@ -1928,6 +1928,38 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int proc_disconnect_claim(struct dev_state *ps, void __user *arg)
|
||||
{
|
||||
struct usbdevfs_disconnect_claim dc;
|
||||
struct usb_interface *intf;
|
||||
|
||||
if (copy_from_user(&dc, arg, sizeof(dc)))
|
||||
return -EFAULT;
|
||||
|
||||
intf = usb_ifnum_to_if(ps->dev, dc.interface);
|
||||
if (!intf)
|
||||
return -EINVAL;
|
||||
|
||||
if (intf->dev.driver) {
|
||||
struct usb_driver *driver = to_usb_driver(intf->dev.driver);
|
||||
|
||||
if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER) &&
|
||||
strncmp(dc.driver, intf->dev.driver->name,
|
||||
sizeof(dc.driver)) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER) &&
|
||||
strncmp(dc.driver, intf->dev.driver->name,
|
||||
sizeof(dc.driver)) == 0)
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(&intf->dev, "disconnect by usbfs\n");
|
||||
usb_driver_release_interface(driver, intf);
|
||||
}
|
||||
|
||||
return claimintf(ps, dc.interface);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: All requests here that have interface numbers as parameters
|
||||
* are assuming that somehow the configuration has been prevented from
|
||||
|
|
@ -2101,6 +2133,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
|
|||
case USBDEVFS_GET_CAPABILITIES:
|
||||
ret = proc_get_capabilities(ps, p);
|
||||
break;
|
||||
case USBDEVFS_DISCONNECT_CLAIM:
|
||||
ret = proc_disconnect_claim(ps, p);
|
||||
break;
|
||||
}
|
||||
usb_unlock_device(dev);
|
||||
if (ret >= 0)
|
||||
|
|
|
|||
|
|
@ -125,10 +125,9 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
|
|||
{
|
||||
struct usb_dynid *dynid, *n;
|
||||
struct usb_driver *usb_driver = to_usb_driver(driver);
|
||||
u32 idVendor = 0;
|
||||
u32 idProduct = 0;
|
||||
int fields = 0;
|
||||
int retval = 0;
|
||||
u32 idVendor;
|
||||
u32 idProduct;
|
||||
int fields;
|
||||
|
||||
fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
|
||||
if (fields < 2)
|
||||
|
|
@ -141,14 +140,10 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)
|
|||
(id->idProduct == idProduct)) {
|
||||
list_del(&dynid->node);
|
||||
kfree(dynid);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&usb_driver->dynids.lock);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
static DRIVER_ATTR(remove_id, S_IRUGO | S_IWUSR, show_dynids, store_remove_id);
|
||||
|
|
|
|||
|
|
@ -24,10 +24,6 @@ struct ep_device {
|
|||
#define to_ep_device(_dev) \
|
||||
container_of(_dev, struct ep_device, dev)
|
||||
|
||||
struct device_type usb_ep_device_type = {
|
||||
.name = "usb_endpoint",
|
||||
};
|
||||
|
||||
struct ep_attribute {
|
||||
struct attribute attr;
|
||||
ssize_t (*show)(struct usb_device *,
|
||||
|
|
@ -172,6 +168,11 @@ static void ep_device_release(struct device *dev)
|
|||
kfree(ep_dev);
|
||||
}
|
||||
|
||||
struct device_type usb_ep_device_type = {
|
||||
.name = "usb_endpoint",
|
||||
.release = ep_device_release,
|
||||
};
|
||||
|
||||
int usb_create_ep_devs(struct device *parent,
|
||||
struct usb_host_endpoint *endpoint,
|
||||
struct usb_device *udev)
|
||||
|
|
@ -190,7 +191,6 @@ int usb_create_ep_devs(struct device *parent,
|
|||
ep_dev->dev.groups = ep_dev_groups;
|
||||
ep_dev->dev.type = &usb_ep_device_type;
|
||||
ep_dev->dev.parent = parent;
|
||||
ep_dev->dev.release = ep_device_release;
|
||||
dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
|
||||
|
||||
retval = device_register(&ep_dev->dev);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/kernel.h>
|
||||
|
|
@ -123,9 +124,8 @@ static inline int is_root_hub(struct usb_device *udev)
|
|||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff)
|
||||
#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff)
|
||||
#define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff))
|
||||
#define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff))
|
||||
|
||||
/* usb 3.0 root hub device descriptor */
|
||||
static const u8 usb3_rh_dev_descriptor[18] = {
|
||||
|
|
@ -2151,15 +2151,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
|
|||
irqreturn_t usb_hcd_irq (int irq, void *__hcd)
|
||||
{
|
||||
struct usb_hcd *hcd = __hcd;
|
||||
unsigned long flags;
|
||||
irqreturn_t rc;
|
||||
|
||||
/* IRQF_DISABLED doesn't work correctly with shared IRQs
|
||||
* when the first handler doesn't use it. So let's just
|
||||
* assume it's never used.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
|
||||
rc = IRQ_NONE;
|
||||
else if (hcd->driver->irq(hcd) == IRQ_NONE)
|
||||
|
|
@ -2167,7 +2160,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
|
|||
else
|
||||
rc = IRQ_HANDLED;
|
||||
|
||||
local_irq_restore(flags);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_irq);
|
||||
|
|
@ -2355,14 +2347,6 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
|
|||
int retval;
|
||||
|
||||
if (hcd->driver->irq) {
|
||||
|
||||
/* IRQF_DISABLED doesn't work as advertised when used together
|
||||
* with IRQF_SHARED. As usb_hcd_irq() will always disable
|
||||
* interrupts we can remove it here.
|
||||
*/
|
||||
if (irqflags & IRQF_SHARED)
|
||||
irqflags &= ~IRQF_DISABLED;
|
||||
|
||||
snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
|
||||
hcd->driver->description, hcd->self.busnum);
|
||||
retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,13 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
struct usb_port {
|
||||
struct usb_device *child;
|
||||
struct device dev;
|
||||
struct dev_state *port_owner;
|
||||
enum usb_port_connect_type connect_type;
|
||||
};
|
||||
|
||||
struct usb_hub {
|
||||
struct device *intfdev; /* the "interface" device */
|
||||
struct usb_device *hdev;
|
||||
|
|
@ -83,7 +90,7 @@ struct usb_hub {
|
|||
u8 indicator[USB_MAXCHILDREN];
|
||||
struct delayed_work leds;
|
||||
struct delayed_work init_work;
|
||||
struct dev_state **port_owners;
|
||||
struct usb_port **ports;
|
||||
};
|
||||
|
||||
static inline int hub_is_superspeed(struct usb_device *hdev)
|
||||
|
|
@ -156,6 +163,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
|
|||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 100
|
||||
|
||||
#define to_usb_port(_dev) \
|
||||
container_of(_dev, struct usb_port, dev)
|
||||
|
||||
static int usb_reset_and_verify_device(struct usb_device *udev);
|
||||
|
||||
|
|
@ -174,7 +183,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus)
|
|||
/* Note that hdev or one of its children must be locked! */
|
||||
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
|
||||
{
|
||||
if (!hdev || !hdev->actconfig)
|
||||
if (!hdev || !hdev->actconfig || !hdev->maxchild)
|
||||
return NULL;
|
||||
return usb_get_intfdata(hdev->actconfig->interface[0]);
|
||||
}
|
||||
|
|
@ -869,8 +878,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
|
|||
struct usb_device *hdev = hub->hdev;
|
||||
int ret = 0;
|
||||
|
||||
if (hdev->children[port1-1] && set_state)
|
||||
usb_set_device_state(hdev->children[port1-1],
|
||||
if (hub->ports[port1 - 1]->child && set_state)
|
||||
usb_set_device_state(hub->ports[port1 - 1]->child,
|
||||
USB_STATE_NOTATTACHED);
|
||||
if (!hub->error && !hub_is_superspeed(hub->hdev))
|
||||
ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
|
||||
|
|
@ -1026,7 +1035,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
|||
* which ports need attention.
|
||||
*/
|
||||
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
||||
struct usb_device *udev = hdev->children[port1-1];
|
||||
struct usb_device *udev = hub->ports[port1 - 1]->child;
|
||||
u16 portstatus, portchange;
|
||||
|
||||
portstatus = portchange = 0;
|
||||
|
|
@ -1191,8 +1200,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
|
|||
if (type != HUB_SUSPEND) {
|
||||
/* Disconnect all the children */
|
||||
for (i = 0; i < hdev->maxchild; ++i) {
|
||||
if (hdev->children[i])
|
||||
usb_disconnect(&hdev->children[i]);
|
||||
if (hub->ports[i]->child)
|
||||
usb_disconnect(&hub->ports[i]->child);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1222,6 +1231,52 @@ static int hub_post_reset(struct usb_interface *intf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void usb_port_device_release(struct device *dev)
|
||||
{
|
||||
struct usb_port *port_dev = to_usb_port(dev);
|
||||
|
||||
kfree(port_dev);
|
||||
}
|
||||
|
||||
static void usb_hub_remove_port_device(struct usb_hub *hub,
|
||||
int port1)
|
||||
{
|
||||
device_unregister(&hub->ports[port1 - 1]->dev);
|
||||
}
|
||||
|
||||
struct device_type usb_port_device_type = {
|
||||
.name = "usb_port",
|
||||
.release = usb_port_device_release,
|
||||
};
|
||||
|
||||
static int usb_hub_create_port_device(struct usb_hub *hub,
|
||||
int port1)
|
||||
{
|
||||
struct usb_port *port_dev = NULL;
|
||||
int retval;
|
||||
|
||||
port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
|
||||
if (!port_dev) {
|
||||
retval = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hub->ports[port1 - 1] = port_dev;
|
||||
port_dev->dev.parent = hub->intfdev;
|
||||
port_dev->dev.type = &usb_port_device_type;
|
||||
dev_set_name(&port_dev->dev, "port%d", port1);
|
||||
|
||||
retval = device_register(&port_dev->dev);
|
||||
if (retval)
|
||||
goto error_register;
|
||||
return 0;
|
||||
|
||||
error_register:
|
||||
put_device(&port_dev->dev);
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int hub_configure(struct usb_hub *hub,
|
||||
struct usb_endpoint_descriptor *endpoint)
|
||||
{
|
||||
|
|
@ -1231,7 +1286,7 @@ static int hub_configure(struct usb_hub *hub,
|
|||
u16 hubstatus, hubchange;
|
||||
u16 wHubCharacteristics;
|
||||
unsigned int pipe;
|
||||
int maxp, ret;
|
||||
int maxp, ret, i;
|
||||
char *message = "out of memory";
|
||||
|
||||
hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
|
||||
|
|
@ -1271,11 +1326,9 @@ static int hub_configure(struct usb_hub *hub,
|
|||
dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
|
||||
(hdev->maxchild == 1) ? "" : "s");
|
||||
|
||||
hdev->children = kzalloc(hdev->maxchild *
|
||||
sizeof(struct usb_device *), GFP_KERNEL);
|
||||
hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *),
|
||||
GFP_KERNEL);
|
||||
if (!hdev->children || !hub->port_owners) {
|
||||
hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *),
|
||||
GFP_KERNEL);
|
||||
if (!hub->ports) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -1484,6 +1537,11 @@ static int hub_configure(struct usb_hub *hub,
|
|||
if (hub->has_indicators && blinkenlights)
|
||||
hub->indicator [0] = INDICATOR_CYCLE;
|
||||
|
||||
for (i = 0; i < hdev->maxchild; i++)
|
||||
if (usb_hub_create_port_device(hub, i + 1) < 0)
|
||||
dev_err(hub->intfdev,
|
||||
"couldn't create port%d device.\n", i + 1);
|
||||
|
||||
hub_activate(hub, HUB_INIT);
|
||||
return 0;
|
||||
|
||||
|
|
@ -1508,6 +1566,7 @@ static void hub_disconnect(struct usb_interface *intf)
|
|||
{
|
||||
struct usb_hub *hub = usb_get_intfdata(intf);
|
||||
struct usb_device *hdev = interface_to_usbdev(intf);
|
||||
int i;
|
||||
|
||||
/* Take the hub off the event list and don't let it be added again */
|
||||
spin_lock_irq(&hub_event_lock);
|
||||
|
|
@ -1523,14 +1582,16 @@ static void hub_disconnect(struct usb_interface *intf)
|
|||
hub_quiesce(hub, HUB_DISCONNECT);
|
||||
|
||||
usb_set_intfdata (intf, NULL);
|
||||
|
||||
for (i = 0; i < hdev->maxchild; i++)
|
||||
usb_hub_remove_port_device(hub, i + 1);
|
||||
hub->hdev->maxchild = 0;
|
||||
|
||||
if (hub->hdev->speed == USB_SPEED_HIGH)
|
||||
highspeed_hubs--;
|
||||
|
||||
usb_free_urb(hub->urb);
|
||||
kfree(hdev->children);
|
||||
kfree(hub->port_owners);
|
||||
kfree(hub->ports);
|
||||
kfree(hub->descriptor);
|
||||
kfree(hub->status);
|
||||
kfree(hub->buffer);
|
||||
|
|
@ -1617,6 +1678,7 @@ static int
|
|||
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
||||
{
|
||||
struct usb_device *hdev = interface_to_usbdev (intf);
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
|
||||
/* assert ifno == 0 (part of hub spec) */
|
||||
switch (code) {
|
||||
|
|
@ -1630,11 +1692,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
|||
else {
|
||||
info->nports = hdev->maxchild;
|
||||
for (i = 0; i < info->nports; i++) {
|
||||
if (hdev->children[i] == NULL)
|
||||
if (hub->ports[i]->child == NULL)
|
||||
info->port[i] = 0;
|
||||
else
|
||||
info->port[i] =
|
||||
hdev->children[i]->devnum;
|
||||
hub->ports[i]->child->devnum;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&device_state_lock);
|
||||
|
|
@ -1662,7 +1724,7 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1,
|
|||
/* This assumes that devices not managed by the hub driver
|
||||
* will always have maxchild equal to 0.
|
||||
*/
|
||||
*ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]);
|
||||
*ppowner = &(hdev_to_hub(hdev)->ports[port1 - 1]->port_owner);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1699,16 +1761,14 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1,
|
|||
|
||||
void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
int n;
|
||||
struct dev_state **powner;
|
||||
|
||||
n = find_port_owner(hdev, 1, &powner);
|
||||
if (n == 0) {
|
||||
for (; n < hdev->maxchild; (++n, ++powner)) {
|
||||
if (*powner == owner)
|
||||
*powner = NULL;
|
||||
}
|
||||
for (n = 0; n < hdev->maxchild; n++) {
|
||||
if (hub->ports[n]->port_owner == owner)
|
||||
hub->ports[n]->port_owner = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* The caller must hold udev's lock */
|
||||
|
|
@ -1719,17 +1779,17 @@ bool usb_device_is_owned(struct usb_device *udev)
|
|||
if (udev->state == USB_STATE_NOTATTACHED || !udev->parent)
|
||||
return false;
|
||||
hub = hdev_to_hub(udev->parent);
|
||||
return !!hub->port_owners[udev->portnum - 1];
|
||||
return !!hub->ports[udev->portnum - 1]->port_owner;
|
||||
}
|
||||
|
||||
|
||||
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(udev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < udev->maxchild; ++i) {
|
||||
if (udev->children[i])
|
||||
recursively_mark_NOTATTACHED(udev->children[i]);
|
||||
if (hub->ports[i]->child)
|
||||
recursively_mark_NOTATTACHED(hub->ports[i]->child);
|
||||
}
|
||||
if (udev->state == USB_STATE_SUSPENDED)
|
||||
udev->active_duration -= jiffies;
|
||||
|
|
@ -1893,6 +1953,7 @@ static void hub_free_dev(struct usb_device *udev)
|
|||
void usb_disconnect(struct usb_device **pdev)
|
||||
{
|
||||
struct usb_device *udev = *pdev;
|
||||
struct usb_hub *hub = hdev_to_hub(udev);
|
||||
int i;
|
||||
|
||||
/* mark the device as inactive, so any further urb submissions for
|
||||
|
|
@ -1907,8 +1968,8 @@ void usb_disconnect(struct usb_device **pdev)
|
|||
|
||||
/* Free up all the children before we remove this device */
|
||||
for (i = 0; i < udev->maxchild; i++) {
|
||||
if (udev->children[i])
|
||||
usb_disconnect(&udev->children[i]);
|
||||
if (hub->ports[i]->child)
|
||||
usb_disconnect(&hub->ports[i]->child);
|
||||
}
|
||||
|
||||
/* deallocate hcd/hardware state ... nuking all pending urbs and
|
||||
|
|
@ -2113,7 +2174,8 @@ static void set_usb_port_removable(struct usb_device *udev)
|
|||
return;
|
||||
|
||||
if (hub_is_superspeed(hdev)) {
|
||||
if (hub->descriptor->u.ss.DeviceRemovable & (1 << port))
|
||||
if (le16_to_cpu(hub->descriptor->u.ss.DeviceRemovable)
|
||||
& (1 << port))
|
||||
removable = false;
|
||||
} else {
|
||||
if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8)))
|
||||
|
|
@ -3072,7 +3134,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
|
|||
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
|
||||
struct usb_device *udev;
|
||||
|
||||
udev = hdev->children [port1-1];
|
||||
udev = hub->ports[port1 - 1]->child;
|
||||
if (udev && udev->can_submit) {
|
||||
dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
|
||||
if (PMSG_IS_AUTO(msg))
|
||||
|
|
@ -3999,7 +4061,7 @@ hub_power_remaining (struct usb_hub *hub)
|
|||
|
||||
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
|
||||
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
|
||||
struct usb_device *udev = hdev->children[port1 - 1];
|
||||
struct usb_device *udev = hub->ports[port1 - 1]->child;
|
||||
int delta;
|
||||
|
||||
if (!udev)
|
||||
|
|
@ -4063,7 +4125,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
#endif
|
||||
|
||||
/* Try to resuscitate an existing device */
|
||||
udev = hdev->children[port1-1];
|
||||
udev = hub->ports[port1 - 1]->child;
|
||||
if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
|
||||
udev->state != USB_STATE_NOTATTACHED) {
|
||||
usb_lock_device(udev);
|
||||
|
|
@ -4092,7 +4154,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
|
||||
/* Disconnect any existing devices under this port */
|
||||
if (udev)
|
||||
usb_disconnect(&hdev->children[port1-1]);
|
||||
usb_disconnect(&hub->ports[port1 - 1]->child);
|
||||
clear_bit(port1, hub->change_bits);
|
||||
|
||||
/* We can forget about a "removed" device when there's a physical
|
||||
|
|
@ -4228,7 +4290,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
if (hdev->state == USB_STATE_NOTATTACHED)
|
||||
status = -ENOTCONN;
|
||||
else
|
||||
hdev->children[port1-1] = udev;
|
||||
hub->ports[port1 - 1]->child = udev;
|
||||
spin_unlock_irq(&device_state_lock);
|
||||
|
||||
/* Run it through the hoops (find a driver, etc) */
|
||||
|
|
@ -4236,7 +4298,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
|||
status = usb_new_device(udev);
|
||||
if (status) {
|
||||
spin_lock_irq(&device_state_lock);
|
||||
hdev->children[port1-1] = NULL;
|
||||
hub->ports[port1 - 1]->child = NULL;
|
||||
spin_unlock_irq(&device_state_lock);
|
||||
}
|
||||
}
|
||||
|
|
@ -4282,7 +4344,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
|
|||
int ret;
|
||||
|
||||
hdev = hub->hdev;
|
||||
udev = hdev->children[port-1];
|
||||
udev = hub->ports[port - 1]->child;
|
||||
if (!hub_is_superspeed(hdev)) {
|
||||
if (!(portchange & USB_PORT_STAT_C_SUSPEND))
|
||||
return 0;
|
||||
|
|
@ -4436,7 +4498,7 @@ static void hub_events(void)
|
|||
*/
|
||||
if (!(portstatus & USB_PORT_STAT_ENABLE)
|
||||
&& !connect_change
|
||||
&& hdev->children[i-1]) {
|
||||
&& hub->ports[i - 1]->child) {
|
||||
dev_err (hub_dev,
|
||||
"port %i "
|
||||
"disabled by hub (EMI?), "
|
||||
|
|
@ -4993,3 +5055,75 @@ void usb_queue_reset_device(struct usb_interface *iface)
|
|||
schedule_work(&iface->reset_ws);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_queue_reset_device);
|
||||
|
||||
/**
|
||||
* usb_hub_find_child - Get the pointer of child device
|
||||
* attached to the port which is specified by @port1.
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num to indicate which port the child device
|
||||
* is attached to.
|
||||
*
|
||||
* USB drivers call this function to get hub's child device
|
||||
* pointer.
|
||||
*
|
||||
* Return NULL if input param is invalid and
|
||||
* child's usb_device pointer if non-NULL.
|
||||
*/
|
||||
struct usb_device *usb_hub_find_child(struct usb_device *hdev,
|
||||
int port1)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
|
||||
if (port1 < 1 || port1 > hdev->maxchild)
|
||||
return NULL;
|
||||
return hub->ports[port1 - 1]->child;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hub_find_child);
|
||||
|
||||
/**
|
||||
* usb_set_hub_port_connect_type - set hub port connect type.
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num of the port
|
||||
* @type: connect type of the port
|
||||
*/
|
||||
void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
|
||||
enum usb_port_connect_type type)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
|
||||
hub->ports[port1 - 1]->connect_type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_get_hub_port_connect_type - Get the port's connect type
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num of the port
|
||||
*
|
||||
* Return connect type of the port and if input params are
|
||||
* invalid, return USB_PORT_CONNECT_TYPE_UNKNOWN.
|
||||
*/
|
||||
enum usb_port_connect_type
|
||||
usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
|
||||
return hub->ports[port1 - 1]->connect_type;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/**
|
||||
* usb_get_hub_port_acpi_handle - Get the usb port's acpi handle
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @port1: port num of the port
|
||||
*
|
||||
* Return port's acpi handle if successful, NULL if params are
|
||||
* invaild.
|
||||
*/
|
||||
acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
|
||||
int port1)
|
||||
{
|
||||
struct usb_hub *hub = hdev_to_hub(hdev);
|
||||
|
||||
return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -146,8 +146,6 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
|
|||
dr->wIndex = cpu_to_le16(index);
|
||||
dr->wLength = cpu_to_le16(size);
|
||||
|
||||
/* dbg("usb_control_msg"); */
|
||||
|
||||
ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
|
||||
|
||||
kfree(dr);
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void usb_detect_quirks(struct usb_device *udev)
|
|||
* for all devices. It will affect things like hub resets
|
||||
* and EMF-related port disables.
|
||||
*/
|
||||
if (!(udev->quirks & USB_QUIRK_RESET_MORPHS))
|
||||
if (!(udev->quirks & USB_QUIRK_RESET))
|
||||
udev->persist_enabled = 1;
|
||||
#endif /* CONFIG_PM */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char *
|
|||
struct usb_device *udev;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET_MORPHS));
|
||||
return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
|
@ -204,15 +204,15 @@ set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr,
|
|||
const char *buf, size_t count)
|
||||
{
|
||||
struct usb_device *udev = to_usb_device(dev);
|
||||
int config;
|
||||
int val;
|
||||
|
||||
if (sscanf(buf, "%d", &config) != 1 || config < 0 || config > 1)
|
||||
if (sscanf(buf, "%d", &val) != 1 || val < 0 || val > 1)
|
||||
return -EINVAL;
|
||||
usb_lock_device(udev);
|
||||
if (config)
|
||||
udev->quirks |= USB_QUIRK_RESET_MORPHS;
|
||||
if (val)
|
||||
udev->quirks |= USB_QUIRK_RESET;
|
||||
else
|
||||
udev->quirks &= ~USB_QUIRK_RESET_MORPHS;
|
||||
udev->quirks &= ~USB_QUIRK_RESET;
|
||||
usb_unlock_device(udev);
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,20 +19,91 @@
|
|||
|
||||
#include "usb.h"
|
||||
|
||||
static int usb_acpi_check_upc(struct usb_device *udev, acpi_handle handle)
|
||||
/**
|
||||
* usb_acpi_power_manageable - check whether usb port has
|
||||
* acpi power resource.
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @index: port index based zero
|
||||
*
|
||||
* Return true if the port has acpi power resource and false if no.
|
||||
*/
|
||||
bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
|
||||
{
|
||||
acpi_handle port_handle;
|
||||
int port1 = index + 1;
|
||||
|
||||
port_handle = usb_get_hub_port_acpi_handle(hdev,
|
||||
port1);
|
||||
if (port_handle)
|
||||
return acpi_bus_power_manageable(port_handle);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
|
||||
|
||||
/**
|
||||
* usb_acpi_set_power_state - control usb port's power via acpi power
|
||||
* resource
|
||||
* @hdev: USB device belonging to the usb hub
|
||||
* @index: port index based zero
|
||||
* @enable: power state expected to be set
|
||||
*
|
||||
* Notice to use usb_acpi_power_manageable() to check whether the usb port
|
||||
* has acpi power resource before invoking this function.
|
||||
*
|
||||
* Returns 0 on success, else negative errno.
|
||||
*/
|
||||
int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
|
||||
{
|
||||
acpi_handle port_handle;
|
||||
unsigned char state;
|
||||
int port1 = index + 1;
|
||||
int error = -EINVAL;
|
||||
|
||||
port_handle = (acpi_handle)usb_get_hub_port_acpi_handle(hdev,
|
||||
port1);
|
||||
if (!port_handle)
|
||||
return error;
|
||||
|
||||
if (enable)
|
||||
state = ACPI_STATE_D0;
|
||||
else
|
||||
state = ACPI_STATE_D3_COLD;
|
||||
|
||||
error = acpi_bus_set_power(port_handle, state);
|
||||
if (!error)
|
||||
dev_dbg(&hdev->dev, "The power of hub port %d was set to %d\n",
|
||||
port1, enable);
|
||||
else
|
||||
dev_dbg(&hdev->dev, "The power of hub port failed to be set\n");
|
||||
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
|
||||
|
||||
static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
|
||||
acpi_handle handle, int port1)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
union acpi_object *upc;
|
||||
struct acpi_pld pld;
|
||||
int ret = 0;
|
||||
|
||||
status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
|
||||
|
||||
/*
|
||||
* Accoding to ACPI Spec 9.13. PLD indicates whether usb port is
|
||||
* user visible and _UPC indicates whether it is connectable. If
|
||||
* the port was visible and connectable, it could be freely connected
|
||||
* and disconnected with USB devices. If no visible and connectable,
|
||||
* a usb device is directly hard-wired to the port. If no visible and
|
||||
* no connectable, the port would be not used.
|
||||
*/
|
||||
status = acpi_get_physical_device_location(handle, &pld);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
|
||||
upc = buffer.pointer;
|
||||
|
||||
if (!upc || (upc->type != ACPI_TYPE_PACKAGE)
|
||||
|| upc->package.count != 4) {
|
||||
ret = -EINVAL;
|
||||
|
|
@ -40,69 +111,107 @@ static int usb_acpi_check_upc(struct usb_device *udev, acpi_handle handle)
|
|||
}
|
||||
|
||||
if (upc->package.elements[0].integer.value)
|
||||
udev->removable = USB_DEVICE_REMOVABLE;
|
||||
else
|
||||
udev->removable = USB_DEVICE_FIXED;
|
||||
if (pld.user_visible)
|
||||
usb_set_hub_port_connect_type(hdev, port1,
|
||||
USB_PORT_CONNECT_TYPE_HOT_PLUG);
|
||||
else
|
||||
usb_set_hub_port_connect_type(hdev, port1,
|
||||
USB_PORT_CONNECT_TYPE_HARD_WIRED);
|
||||
else if (!pld.user_visible)
|
||||
usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED);
|
||||
|
||||
out:
|
||||
kfree(upc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_pld pld;
|
||||
|
||||
status = acpi_get_physical_device_location(handle, &pld);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
if (pld.user_visible)
|
||||
udev->removable = USB_DEVICE_REMOVABLE;
|
||||
else
|
||||
udev->removable = USB_DEVICE_FIXED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
|
||||
{
|
||||
struct usb_device *udev;
|
||||
struct device *parent;
|
||||
acpi_handle *parent_handle;
|
||||
|
||||
if (!is_usb_device(dev))
|
||||
return -ENODEV;
|
||||
|
||||
udev = to_usb_device(dev);
|
||||
parent = dev->parent;
|
||||
parent_handle = DEVICE_ACPI_HANDLE(parent);
|
||||
|
||||
if (!parent_handle)
|
||||
return -ENODEV;
|
||||
|
||||
*handle = acpi_get_child(parent_handle, udev->portnum);
|
||||
|
||||
if (!*handle)
|
||||
return -ENODEV;
|
||||
int port_num;
|
||||
|
||||
/*
|
||||
* PLD will tell us whether a port is removable to the user or
|
||||
* not. If we don't get an answer from PLD (it's not present
|
||||
* or it's malformed) then try to infer it from UPC. If a
|
||||
* device isn't connectable then it's probably not removable.
|
||||
* In the ACPI DSDT table, only usb root hub and usb ports are
|
||||
* acpi device nodes. The hierarchy like following.
|
||||
* Device (EHC1)
|
||||
* Device (HUBN)
|
||||
* Device (PR01)
|
||||
* Device (PR11)
|
||||
* Device (PR12)
|
||||
* Device (PR13)
|
||||
* ...
|
||||
* So all binding process is divided into two parts. binding
|
||||
* root hub and usb ports.
|
||||
*/
|
||||
if (usb_acpi_check_pld(udev, *handle) != 0)
|
||||
usb_acpi_check_upc(udev, *handle);
|
||||
if (is_usb_device(dev)) {
|
||||
udev = to_usb_device(dev);
|
||||
if (udev->parent) {
|
||||
enum usb_port_connect_type type;
|
||||
|
||||
/*
|
||||
* According usb port's connect type to set usb device's
|
||||
* removability.
|
||||
*/
|
||||
type = usb_get_hub_port_connect_type(udev->parent,
|
||||
udev->portnum);
|
||||
switch (type) {
|
||||
case USB_PORT_CONNECT_TYPE_HOT_PLUG:
|
||||
udev->removable = USB_DEVICE_REMOVABLE;
|
||||
break;
|
||||
case USB_PORT_CONNECT_TYPE_HARD_WIRED:
|
||||
udev->removable = USB_DEVICE_FIXED;
|
||||
break;
|
||||
default:
|
||||
udev->removable = USB_DEVICE_REMOVABLE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* root hub's parent is the usb hcd. */
|
||||
parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
|
||||
*handle = acpi_get_child(parent_handle, udev->portnum);
|
||||
if (!*handle)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
} else if (is_usb_port(dev)) {
|
||||
sscanf(dev_name(dev), "port%d", &port_num);
|
||||
/* Get the struct usb_device point of port's hub */
|
||||
udev = to_usb_device(dev->parent->parent);
|
||||
|
||||
/*
|
||||
* The root hub ports' parent is the root hub. The non-root-hub
|
||||
* ports' parent is the parent hub port which the hub is
|
||||
* connected to.
|
||||
*/
|
||||
if (!udev->parent) {
|
||||
*handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
|
||||
port_num);
|
||||
if (!*handle)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
parent_handle =
|
||||
usb_get_hub_port_acpi_handle(udev->parent,
|
||||
udev->portnum);
|
||||
if (!parent_handle)
|
||||
return -ENODEV;
|
||||
|
||||
*handle = acpi_get_child(parent_handle, port_num);
|
||||
if (!*handle)
|
||||
return -ENODEV;
|
||||
}
|
||||
usb_acpi_check_port_connect_type(udev, *handle, port_num);
|
||||
} else
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct acpi_bus_type usb_acpi_bus = {
|
||||
.bus = &usb_bus_type,
|
||||
.find_bridge = NULL,
|
||||
.find_bridge = usb_acpi_find_device,
|
||||
.find_device = usb_acpi_find_device,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
struct dev_state;
|
||||
|
||||
|
|
@ -115,6 +116,7 @@ extern struct bus_type usb_bus_type;
|
|||
extern struct device_type usb_device_type;
|
||||
extern struct device_type usb_if_device_type;
|
||||
extern struct device_type usb_ep_device_type;
|
||||
extern struct device_type usb_port_device_type;
|
||||
extern struct usb_device_driver usb_generic_driver;
|
||||
|
||||
static inline int is_usb_device(const struct device *dev)
|
||||
|
|
@ -132,6 +134,11 @@ static inline int is_usb_endpoint(const struct device *dev)
|
|||
return dev->type == &usb_ep_device_type;
|
||||
}
|
||||
|
||||
static inline int is_usb_port(const struct device *dev)
|
||||
{
|
||||
return dev->type == &usb_port_device_type;
|
||||
}
|
||||
|
||||
/* Do the same for device drivers and interface drivers. */
|
||||
|
||||
static inline int is_usb_device_driver(struct device_driver *drv)
|
||||
|
|
@ -162,10 +169,16 @@ extern void usb_notify_add_device(struct usb_device *udev);
|
|||
extern void usb_notify_remove_device(struct usb_device *udev);
|
||||
extern void usb_notify_add_bus(struct usb_bus *ubus);
|
||||
extern void usb_notify_remove_bus(struct usb_bus *ubus);
|
||||
extern enum usb_port_connect_type
|
||||
usb_get_hub_port_connect_type(struct usb_device *hdev, int port1);
|
||||
extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
|
||||
enum usb_port_connect_type type);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int usb_acpi_register(void);
|
||||
extern void usb_acpi_unregister(void);
|
||||
extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
|
||||
int port1);
|
||||
#else
|
||||
static inline int usb_acpi_register(void) { return 0; };
|
||||
static inline void usb_acpi_unregister(void) { };
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ config USB_DWC3
|
|||
tristate "DesignWare USB3 DRD Core Support"
|
||||
depends on (USB && USB_GADGET)
|
||||
select USB_OTG_UTILS
|
||||
select USB_GADGET_DUALSPEED
|
||||
select USB_GADGET_SUPERSPEED
|
||||
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
|
||||
help
|
||||
Say Y or M here if your system has a Dual Role SuperSpeed
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ void dwc3_put_device_id(int id)
|
|||
|
||||
ret = test_bit(id, dwc3_devs);
|
||||
WARN(!ret, "dwc3: ID %d not in use\n", id);
|
||||
smp_mb__before_clear_bit();
|
||||
clear_bit(id, dwc3_devs);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dwc3_put_device_id);
|
||||
|
|
@ -136,6 +138,8 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc)
|
|||
reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST;
|
||||
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
|
||||
|
||||
usb_phy_init(dwc->usb2_phy);
|
||||
usb_phy_init(dwc->usb3_phy);
|
||||
mdelay(100);
|
||||
|
||||
/* Clear USB3 PHY reset */
|
||||
|
|
@ -464,12 +468,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
regs = devm_ioremap(dev, res->start, resource_size(res));
|
||||
regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
|
||||
if (!regs) {
|
||||
dev_err(dev, "ioremap failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
|
||||
if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
|
||||
dev_err(dev, "no usb2 phy configured\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
|
||||
if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
|
||||
dev_err(dev, "no usb3 phy configured\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
spin_lock_init(&dwc->lock);
|
||||
platform_set_drvdata(pdev, dwc);
|
||||
|
||||
|
|
|
|||
|
|
@ -457,7 +457,6 @@ enum dwc3_phy {
|
|||
enum dwc3_ep0_next {
|
||||
DWC3_EP0_UNKNOWN = 0,
|
||||
DWC3_EP0_COMPLETE,
|
||||
DWC3_EP0_NRDY_SETUP,
|
||||
DWC3_EP0_NRDY_DATA,
|
||||
DWC3_EP0_NRDY_STATUS,
|
||||
};
|
||||
|
|
@ -624,6 +623,8 @@ struct dwc3_scratchpad_array {
|
|||
* @maximum_speed: maximum speed requested (mainly for testing purposes)
|
||||
* @revision: revision register contents
|
||||
* @mode: mode of operation
|
||||
* @usb2_phy: pointer to USB2 PHY
|
||||
* @usb3_phy: pointer to USB3 PHY
|
||||
* @is_selfpowered: true when we are selfpowered
|
||||
* @three_stage_setup: set if we perform a three phase setup
|
||||
* @ep0_bounced: true when we used bounce buffer
|
||||
|
|
@ -667,6 +668,9 @@ struct dwc3 {
|
|||
struct usb_gadget gadget;
|
||||
struct usb_gadget_driver *gadget_driver;
|
||||
|
||||
struct usb_phy *usb2_phy;
|
||||
struct usb_phy *usb3_phy;
|
||||
|
||||
void __iomem *regs;
|
||||
size_t regs_size;
|
||||
|
||||
|
|
@ -779,7 +783,6 @@ struct dwc3_event_depevt {
|
|||
#define DEPEVT_STREAMEVT_NOTFOUND 2
|
||||
|
||||
/* Control-only Status */
|
||||
#define DEPEVT_STATUS_CONTROL_SETUP 0
|
||||
#define DEPEVT_STATUS_CONTROL_DATA 1
|
||||
#define DEPEVT_STATUS_CONTROL_STATUS 2
|
||||
|
||||
|
|
|
|||
|
|
@ -19,16 +19,74 @@
|
|||
#include <linux/platform_data/dwc3-exynos.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct dwc3_exynos {
|
||||
struct platform_device *dwc3;
|
||||
struct platform_device *usb2_phy;
|
||||
struct platform_device *usb3_phy;
|
||||
struct device *dev;
|
||||
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
|
||||
{
|
||||
struct nop_usb_xceiv_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 0);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
exynos->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
|
||||
ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 1);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
exynos->usb3_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB3;
|
||||
|
||||
ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(exynos->usb2_phy);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(exynos->usb3_phy);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
platform_device_del(exynos->usb2_phy);
|
||||
|
||||
err2:
|
||||
platform_device_put(exynos->usb3_phy);
|
||||
|
||||
err1:
|
||||
platform_device_put(exynos->usb2_phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
|
||||
|
|
@ -51,6 +109,12 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev)
|
|||
if (devid < 0)
|
||||
goto err1;
|
||||
|
||||
ret = dwc3_exynos_register_phys(exynos);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "couldn't register PHYs\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dwc3 = platform_device_alloc("dwc3", devid);
|
||||
if (!dwc3) {
|
||||
dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
|
||||
|
|
@ -120,6 +184,8 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev)
|
|||
struct dwc3_exynos_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
platform_device_unregister(exynos->dwc3);
|
||||
platform_device_unregister(exynos->usb2_phy);
|
||||
platform_device_unregister(exynos->usb3_phy);
|
||||
|
||||
dwc3_put_device_id(exynos->dwc3->id);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,9 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
|
|
@ -131,6 +134,8 @@ struct dwc3_omap {
|
|||
spinlock_t lock;
|
||||
|
||||
struct platform_device *dwc3;
|
||||
struct platform_device *usb2_phy;
|
||||
struct platform_device *usb3_phy;
|
||||
struct device *dev;
|
||||
|
||||
int irq;
|
||||
|
|
@ -152,6 +157,59 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
|
|||
writel(value, base + offset);
|
||||
}
|
||||
|
||||
static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap)
|
||||
{
|
||||
struct nop_usb_xceiv_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 0);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
omap->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
|
||||
ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 1);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
omap->usb3_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB3;
|
||||
|
||||
ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(omap->usb2_phy);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(omap->usb3_phy);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
platform_device_del(omap->usb2_phy);
|
||||
|
||||
err2:
|
||||
platform_device_put(omap->usb3_phy);
|
||||
|
||||
err1:
|
||||
platform_device_put(omap->usb2_phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
|
||||
{
|
||||
|
|
@ -251,6 +309,12 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = dwc3_omap_register_phys(omap);
|
||||
if (ret) {
|
||||
dev_err(dev, "couldn't register PHYs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
devid = dwc3_get_device_id();
|
||||
if (devid < 0)
|
||||
return -ENODEV;
|
||||
|
|
@ -371,6 +435,8 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev)
|
|||
struct dwc3_omap *omap = platform_get_drvdata(pdev);
|
||||
|
||||
platform_device_unregister(omap->dwc3);
|
||||
platform_device_unregister(omap->usb2_phy);
|
||||
platform_device_unregister(omap->usb3_phy);
|
||||
|
||||
dwc3_put_device_id(omap->dwc3->id);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/nop-usb-xceiv.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
/* FIXME define these in <linux/pci_ids.h> */
|
||||
|
|
@ -51,8 +54,64 @@
|
|||
struct dwc3_pci {
|
||||
struct device *dev;
|
||||
struct platform_device *dwc3;
|
||||
struct platform_device *usb2_phy;
|
||||
struct platform_device *usb3_phy;
|
||||
};
|
||||
|
||||
static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue)
|
||||
{
|
||||
struct nop_usb_xceiv_platform_data pdata;
|
||||
struct platform_device *pdev;
|
||||
int ret;
|
||||
|
||||
memset(&pdata, 0x00, sizeof(pdata));
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 0);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
glue->usb2_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB2;
|
||||
|
||||
ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
pdev = platform_device_alloc("nop_usb_xceiv", 1);
|
||||
if (!pdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
glue->usb3_phy = pdev;
|
||||
pdata.type = USB_PHY_TYPE_USB3;
|
||||
|
||||
ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata));
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(glue->usb2_phy);
|
||||
if (ret)
|
||||
goto err2;
|
||||
|
||||
ret = platform_device_add(glue->usb3_phy);
|
||||
if (ret)
|
||||
goto err3;
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
platform_device_del(glue->usb2_phy);
|
||||
|
||||
err2:
|
||||
platform_device_put(glue->usb3_phy);
|
||||
|
||||
err1:
|
||||
platform_device_put(glue->usb2_phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit dwc3_pci_probe(struct pci_dev *pci,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
|
|
@ -80,6 +139,12 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci,
|
|||
pci_set_power_state(pci, PCI_D0);
|
||||
pci_set_master(pci);
|
||||
|
||||
ret = dwc3_pci_register_phys(glue);
|
||||
if (ret) {
|
||||
dev_err(dev, "couldn't register PHYs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
devid = dwc3_get_device_id();
|
||||
if (devid < 0) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -144,6 +209,8 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci)
|
|||
{
|
||||
struct dwc3_pci *glue = pci_get_drvdata(pci);
|
||||
|
||||
platform_device_unregister(glue->usb2_phy);
|
||||
platform_device_unregister(glue->usb3_phy);
|
||||
dwc3_put_device_id(glue->dwc3->id);
|
||||
platform_device_unregister(glue->dwc3);
|
||||
pci_set_drvdata(pci, NULL);
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
|
|||
struct dwc3_request *req)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
int ret = 0;
|
||||
|
||||
req->request.actual = 0;
|
||||
req->request.status = -EINPROGRESS;
|
||||
|
|
@ -156,16 +155,72 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
|
|||
|
||||
dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
|
||||
DWC3_EP0_DIR_IN);
|
||||
} else if (dwc->delayed_status) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In case gadget driver asked us to delay the STATUS phase,
|
||||
* handle it here.
|
||||
*/
|
||||
if (dwc->delayed_status) {
|
||||
unsigned direction;
|
||||
|
||||
direction = !dwc->ep0_expect_in;
|
||||
dwc->delayed_status = false;
|
||||
|
||||
if (dwc->ep0state == EP0_STATUS_PHASE)
|
||||
__dwc3_ep0_do_control_status(dwc, dwc->eps[1]);
|
||||
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
|
||||
else
|
||||
dev_dbg(dwc->dev, "too early for delayed status\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
/*
|
||||
* Unfortunately we have uncovered a limitation wrt the Data Phase.
|
||||
*
|
||||
* Section 9.4 says we can wait for the XferNotReady(DATA) event to
|
||||
* come before issueing Start Transfer command, but if we do, we will
|
||||
* miss situations where the host starts another SETUP phase instead of
|
||||
* the DATA phase. Such cases happen at least on TD.7.6 of the Link
|
||||
* Layer Compliance Suite.
|
||||
*
|
||||
* The problem surfaces due to the fact that in case of back-to-back
|
||||
* SETUP packets there will be no XferNotReady(DATA) generated and we
|
||||
* will be stuck waiting for XferNotReady(DATA) forever.
|
||||
*
|
||||
* By looking at tables 9-13 and 9-14 of the Databook, we can see that
|
||||
* it tells us to start Data Phase right away. It also mentions that if
|
||||
* we receive a SETUP phase instead of the DATA phase, core will issue
|
||||
* XferComplete for the DATA phase, before actually initiating it in
|
||||
* the wire, with the TRB's status set to "SETUP_PENDING". Such status
|
||||
* can only be used to print some debugging logs, as the core expects
|
||||
* us to go through to the STATUS phase and start a CONTROL_STATUS TRB,
|
||||
* just so it completes right away, without transferring anything and,
|
||||
* only then, we can go back to the SETUP phase.
|
||||
*
|
||||
* Because of this scenario, SNPS decided to change the programming
|
||||
* model of control transfers and support on-demand transfers only for
|
||||
* the STATUS phase. To fix the issue we have now, we will always wait
|
||||
* for gadget driver to queue the DATA phase's struct usb_request, then
|
||||
* start it right away.
|
||||
*
|
||||
* If we're actually in a 2-stage transfer, we will wait for
|
||||
* XferNotReady(STATUS).
|
||||
*/
|
||||
if (dwc->three_stage_setup) {
|
||||
unsigned direction;
|
||||
|
||||
direction = dwc->ep0_expect_in;
|
||||
dwc->ep0state = EP0_DATA_PHASE;
|
||||
|
||||
__dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req);
|
||||
|
||||
dep->flags &= ~DWC3_EP0_DIR_IN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
|
||||
|
|
@ -207,9 +262,14 @@ out:
|
|||
|
||||
static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
|
||||
{
|
||||
struct dwc3_ep *dep = dwc->eps[0];
|
||||
struct dwc3_ep *dep;
|
||||
|
||||
/* reinitialize physical ep1 */
|
||||
dep = dwc->eps[1];
|
||||
dep->flags = DWC3_EP_ENABLED;
|
||||
|
||||
/* stall is always issued on EP0 */
|
||||
dep = dwc->eps[0];
|
||||
__dwc3_gadget_ep_set_halt(dep, 1);
|
||||
dep->flags = DWC3_EP_ENABLED;
|
||||
dwc->delayed_status = false;
|
||||
|
|
@ -698,6 +758,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
|||
struct dwc3_trb *trb;
|
||||
struct dwc3_ep *ep0;
|
||||
u32 transferred;
|
||||
u32 status;
|
||||
u32 length;
|
||||
u8 epnum;
|
||||
|
||||
|
|
@ -710,6 +771,17 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
|
|||
ur = &r->request;
|
||||
|
||||
trb = dwc->ep0_trb;
|
||||
|
||||
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
|
||||
if (status == DWC3_TRBSTS_SETUP_PENDING) {
|
||||
dev_dbg(dwc->dev, "Setup Pending received\n");
|
||||
|
||||
if (r)
|
||||
dwc3_gadget_giveback(ep0, r, -ECONNRESET);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
length = trb->size & DWC3_TRB_SIZE_MASK;
|
||||
|
||||
if (dwc->ep0_bounced) {
|
||||
|
|
@ -745,8 +817,11 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
|
|||
{
|
||||
struct dwc3_request *r;
|
||||
struct dwc3_ep *dep;
|
||||
struct dwc3_trb *trb;
|
||||
u32 status;
|
||||
|
||||
dep = dwc->eps[0];
|
||||
trb = dwc->ep0_trb;
|
||||
|
||||
if (!list_empty(&dep->request_list)) {
|
||||
r = next_request(&dep->request_list);
|
||||
|
|
@ -766,6 +841,10 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc,
|
|||
}
|
||||
}
|
||||
|
||||
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
|
||||
if (status == DWC3_TRBSTS_SETUP_PENDING)
|
||||
dev_dbg(dwc->dev, "Setup Pending received\n");
|
||||
|
||||
dwc->ep0state = EP0_SETUP_PHASE;
|
||||
dwc3_ep0_out_start(dwc);
|
||||
}
|
||||
|
|
@ -799,12 +878,6 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
|
|||
}
|
||||
}
|
||||
|
||||
static void dwc3_ep0_do_control_setup(struct dwc3 *dwc,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
dwc3_ep0_out_start(dwc);
|
||||
}
|
||||
|
||||
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
||||
struct dwc3_ep *dep, struct dwc3_request *req)
|
||||
{
|
||||
|
|
@ -857,29 +930,6 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
|||
WARN_ON(ret < 0);
|
||||
}
|
||||
|
||||
static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
struct dwc3_ep *dep;
|
||||
struct dwc3_request *req;
|
||||
|
||||
dep = dwc->eps[0];
|
||||
|
||||
if (list_empty(&dep->request_list)) {
|
||||
dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n");
|
||||
dep->flags |= DWC3_EP_PENDING_REQUEST;
|
||||
|
||||
if (event->endpoint_number)
|
||||
dep->flags |= DWC3_EP0_DIR_IN;
|
||||
return;
|
||||
}
|
||||
|
||||
req = next_request(&dep->request_list);
|
||||
dep = dwc->eps[event->endpoint_number];
|
||||
|
||||
__dwc3_ep0_do_control_data(dwc, dep, req);
|
||||
}
|
||||
|
||||
static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
|
@ -911,100 +961,61 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc,
|
|||
__dwc3_ep0_do_control_status(dwc, dep);
|
||||
}
|
||||
|
||||
static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
|
||||
{
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
u32 cmd;
|
||||
int ret;
|
||||
|
||||
if (!dep->resource_index)
|
||||
return;
|
||||
|
||||
cmd = DWC3_DEPCMD_ENDTRANSFER;
|
||||
cmd |= DWC3_DEPCMD_CMDIOC;
|
||||
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms);
|
||||
WARN_ON_ONCE(ret);
|
||||
dep->resource_index = 0;
|
||||
}
|
||||
|
||||
static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
|
||||
const struct dwc3_event_depevt *event)
|
||||
{
|
||||
dwc->setup_packet_pending = true;
|
||||
|
||||
/*
|
||||
* This part is very tricky: If we have just handled
|
||||
* XferNotReady(Setup) and we're now expecting a
|
||||
* XferComplete but, instead, we receive another
|
||||
* XferNotReady(Setup), we should STALL and restart
|
||||
* the state machine.
|
||||
*
|
||||
* In all other cases, we just continue waiting
|
||||
* for the XferComplete event.
|
||||
*
|
||||
* We are a little bit unsafe here because we're
|
||||
* not trying to ensure that last event was, indeed,
|
||||
* XferNotReady(Setup).
|
||||
*
|
||||
* Still, we don't expect any condition where that
|
||||
* should happen and, even if it does, it would be
|
||||
* another error condition.
|
||||
*/
|
||||
if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) {
|
||||
switch (event->status) {
|
||||
case DEPEVT_STATUS_CONTROL_SETUP:
|
||||
dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n");
|
||||
dwc3_ep0_stall_and_restart(dwc);
|
||||
break;
|
||||
case DEPEVT_STATUS_CONTROL_DATA:
|
||||
/* FALLTHROUGH */
|
||||
case DEPEVT_STATUS_CONTROL_STATUS:
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
dev_vdbg(dwc->dev, "waiting for XferComplete\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->status) {
|
||||
case DEPEVT_STATUS_CONTROL_SETUP:
|
||||
dev_vdbg(dwc->dev, "Control Setup\n");
|
||||
|
||||
dwc->ep0state = EP0_SETUP_PHASE;
|
||||
|
||||
dwc3_ep0_do_control_setup(dwc, event);
|
||||
break;
|
||||
|
||||
case DEPEVT_STATUS_CONTROL_DATA:
|
||||
dev_vdbg(dwc->dev, "Control Data\n");
|
||||
|
||||
dwc->ep0state = EP0_DATA_PHASE;
|
||||
|
||||
if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) {
|
||||
dev_vdbg(dwc->dev, "Expected %d got %d\n",
|
||||
dwc->ep0_next_event,
|
||||
DWC3_EP0_NRDY_DATA);
|
||||
|
||||
dwc3_ep0_stall_and_restart(dwc);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* One of the possible error cases is when Host _does_
|
||||
* request for Data Phase, but it does so on the wrong
|
||||
* direction.
|
||||
* We already have a DATA transfer in the controller's cache,
|
||||
* if we receive a XferNotReady(DATA) we will ignore it, unless
|
||||
* it's for the wrong direction.
|
||||
*
|
||||
* Here, we already know ep0_next_event is DATA (see above),
|
||||
* so we only need to check for direction.
|
||||
* In that case, we must issue END_TRANSFER command to the Data
|
||||
* Phase we already have started and issue SetStall on the
|
||||
* control endpoint.
|
||||
*/
|
||||
if (dwc->ep0_expect_in != event->endpoint_number) {
|
||||
struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in];
|
||||
|
||||
dev_vdbg(dwc->dev, "Wrong direction for Data phase\n");
|
||||
dwc3_ep0_end_control_data(dwc, dep);
|
||||
dwc3_ep0_stall_and_restart(dwc);
|
||||
return;
|
||||
}
|
||||
|
||||
dwc3_ep0_do_control_data(dwc, event);
|
||||
break;
|
||||
|
||||
case DEPEVT_STATUS_CONTROL_STATUS:
|
||||
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
|
||||
return;
|
||||
|
||||
dev_vdbg(dwc->dev, "Control Status\n");
|
||||
|
||||
dwc->ep0state = EP0_STATUS_PHASE;
|
||||
|
||||
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) {
|
||||
dev_vdbg(dwc->dev, "Expected %d got %d\n",
|
||||
dwc->ep0_next_event,
|
||||
DWC3_EP0_NRDY_STATUS);
|
||||
|
||||
dwc3_ep0_stall_and_restart(dwc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dwc->delayed_status) {
|
||||
WARN_ON_ONCE(event->endpoint_number != 1);
|
||||
dev_vdbg(dwc->dev, "Mass Storage delayed status\n");
|
||||
|
|
|
|||
|
|
@ -434,15 +434,25 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep)
|
|||
|
||||
static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
|
||||
const struct usb_endpoint_descriptor *desc,
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc)
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc,
|
||||
bool ignore)
|
||||
{
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
|
||||
memset(¶ms, 0x00, sizeof(params));
|
||||
|
||||
params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc))
|
||||
| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc))
|
||||
| DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1);
|
||||
| DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
|
||||
|
||||
/* Burst size is only needed in SuperSpeed mode */
|
||||
if (dwc->gadget.speed == USB_SPEED_SUPER) {
|
||||
u32 burst = dep->endpoint.maxburst - 1;
|
||||
|
||||
params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst);
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM;
|
||||
|
||||
params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN
|
||||
| DWC3_DEPCFG_XFER_NOT_READY_EN;
|
||||
|
|
@ -501,7 +511,8 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep)
|
|||
*/
|
||||
static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
|
||||
const struct usb_endpoint_descriptor *desc,
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc)
|
||||
const struct usb_ss_ep_comp_descriptor *comp_desc,
|
||||
bool ignore)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
u32 reg;
|
||||
|
|
@ -513,7 +524,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc);
|
||||
ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -561,27 +572,7 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
|
|||
if (!list_empty(&dep->req_queued)) {
|
||||
dwc3_stop_active_transfer(dwc, dep->number);
|
||||
|
||||
/*
|
||||
* NOTICE: We are violating what the Databook says about the
|
||||
* EndTransfer command. Ideally we would _always_ wait for the
|
||||
* EndTransfer Command Completion IRQ, but that's causing too
|
||||
* much trouble synchronizing between us and gadget driver.
|
||||
*
|
||||
* We have discussed this with the IP Provider and it was
|
||||
* suggested to giveback all requests here, but give HW some
|
||||
* extra time to synchronize with the interconnect. We're using
|
||||
* an arbitraty 100us delay for that.
|
||||
*
|
||||
* Note also that a similar handling was tested by Synopsys
|
||||
* (thanks a lot Paul) and nothing bad has come out of it.
|
||||
* In short, what we're doing is:
|
||||
*
|
||||
* - Issue EndTransfer WITH CMDIOC bit set
|
||||
* - Wait 100us
|
||||
* - giveback all requests to gadget driver
|
||||
*/
|
||||
udelay(100);
|
||||
|
||||
/* - giveback all requests to gadget driver */
|
||||
while (!list_empty(&dep->req_queued)) {
|
||||
req = next_request(&dep->req_queued);
|
||||
|
||||
|
|
@ -660,6 +651,12 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
|||
dep = to_dwc3_ep(ep);
|
||||
dwc = dep->dwc;
|
||||
|
||||
if (dep->flags & DWC3_EP_ENABLED) {
|
||||
dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n",
|
||||
dep->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (usb_endpoint_type(desc)) {
|
||||
case USB_ENDPOINT_XFER_CONTROL:
|
||||
strlcat(dep->name, "-control", sizeof(dep->name));
|
||||
|
|
@ -677,16 +674,10 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
|
|||
dev_err(dwc->dev, "invalid endpoint transfer type\n");
|
||||
}
|
||||
|
||||
if (dep->flags & DWC3_EP_ENABLED) {
|
||||
dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n",
|
||||
dep->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc);
|
||||
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
return ret;
|
||||
|
|
@ -1105,12 +1096,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
|||
}
|
||||
|
||||
ret = __dwc3_gadget_kick_transfer(dep, 0, true);
|
||||
if (ret && ret != -EBUSY) {
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
||||
if (ret && ret != -EBUSY)
|
||||
dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
|
||||
dep->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1119,16 +1107,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
|||
* core may not see the modified TRB(s).
|
||||
*/
|
||||
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
|
||||
(dep->flags & DWC3_EP_BUSY)) {
|
||||
(dep->flags & DWC3_EP_BUSY) &&
|
||||
!(dep->flags & DWC3_EP_MISSED_ISOC)) {
|
||||
WARN_ON_ONCE(!dep->resource_index);
|
||||
ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index,
|
||||
false);
|
||||
if (ret && ret != -EBUSY) {
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
||||
if (ret && ret != -EBUSY)
|
||||
dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
|
||||
dep->name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1533,14 +1519,14 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
|||
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
|
||||
|
||||
dep = dwc->eps[0];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
dep = dwc->eps[1];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
goto err1;
|
||||
|
|
@ -1765,7 +1751,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) {
|
||||
struct dwc3_ep *dep = dwc->eps[i];
|
||||
dep = dwc->eps[i];
|
||||
|
||||
if (!(dep->flags & DWC3_EP_ENABLED))
|
||||
continue;
|
||||
|
|
@ -1892,6 +1878,25 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
|
|||
if (!dep->resource_index)
|
||||
return;
|
||||
|
||||
/*
|
||||
* NOTICE: We are violating what the Databook says about the
|
||||
* EndTransfer command. Ideally we would _always_ wait for the
|
||||
* EndTransfer Command Completion IRQ, but that's causing too
|
||||
* much trouble synchronizing between us and gadget driver.
|
||||
*
|
||||
* We have discussed this with the IP Provider and it was
|
||||
* suggested to giveback all requests here, but give HW some
|
||||
* extra time to synchronize with the interconnect. We're using
|
||||
* an arbitraty 100us delay for that.
|
||||
*
|
||||
* Note also that a similar handling was tested by Synopsys
|
||||
* (thanks a lot Paul) and nothing bad has come out of it.
|
||||
* In short, what we're doing is:
|
||||
*
|
||||
* - Issue EndTransfer WITH CMDIOC bit set
|
||||
* - Wait 100us
|
||||
*/
|
||||
|
||||
cmd = DWC3_DEPCMD_ENDTRANSFER;
|
||||
cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC;
|
||||
cmd |= DWC3_DEPCMD_PARAM(dep->resource_index);
|
||||
|
|
@ -1899,6 +1904,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
|
|||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms);
|
||||
WARN_ON_ONCE(ret);
|
||||
dep->resource_index = 0;
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
static void dwc3_stop_active_transfers(struct dwc3 *dwc)
|
||||
|
|
@ -2156,14 +2163,14 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
|
|||
}
|
||||
|
||||
dep = dwc->eps[0];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
return;
|
||||
}
|
||||
|
||||
dep = dwc->eps[1];
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL);
|
||||
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true);
|
||||
if (ret) {
|
||||
dev_err(dwc->dev, "failed to enable %s\n", dep->name);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ static int ehci_wait_for_port(int port);
|
|||
* Return -ENODEV for any general failure
|
||||
* Return -EIO if wait for port fails
|
||||
*/
|
||||
int dbgp_external_startup(void)
|
||||
static int _dbgp_external_startup(void)
|
||||
{
|
||||
int devnum;
|
||||
struct usb_debug_descriptor dbgp_desc;
|
||||
|
|
@ -613,6 +613,11 @@ err:
|
|||
goto try_again;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int dbgp_external_startup(struct usb_hcd *hcd)
|
||||
{
|
||||
return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dbgp_external_startup);
|
||||
|
||||
static int ehci_reset_port(int port)
|
||||
|
|
@ -804,7 +809,7 @@ try_next_port:
|
|||
dbgp_ehci_status("ehci skip - already configured");
|
||||
}
|
||||
|
||||
ret = dbgp_external_startup();
|
||||
ret = _dbgp_external_startup();
|
||||
if (ret == -EIO)
|
||||
goto next_debug_port;
|
||||
|
||||
|
|
@ -934,7 +939,7 @@ static void early_dbgp_write(struct console *con, const char *str, u32 n)
|
|||
ctrl = readl(&ehci_debug->control);
|
||||
if (!(ctrl & DBGP_ENABLED)) {
|
||||
dbgp_not_safe = 1;
|
||||
dbgp_external_startup();
|
||||
_dbgp_external_startup();
|
||||
} else {
|
||||
cmd |= CMD_RUN;
|
||||
writel(cmd, &ehci_regs->command);
|
||||
|
|
@ -974,10 +979,14 @@ struct console early_dbgp_console = {
|
|||
.index = -1,
|
||||
};
|
||||
|
||||
int dbgp_reset_prep(void)
|
||||
int dbgp_reset_prep(struct usb_hcd *hcd)
|
||||
{
|
||||
int ret = xen_dbgp_reset_prep(hcd);
|
||||
u32 ctrl;
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dbgp_not_safe = 1;
|
||||
if (!ehci_debug)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -154,16 +154,25 @@ config USB_LPC32XX
|
|||
|
||||
config USB_ATMEL_USBA
|
||||
tristate "Atmel USBA"
|
||||
select USB_GADGET_DUALSPEED
|
||||
depends on AVR32 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
|
||||
help
|
||||
USBA is the integrated high-speed USB Device controller on
|
||||
the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
|
||||
|
||||
config USB_BCM63XX_UDC
|
||||
tristate "Broadcom BCM63xx Peripheral Controller"
|
||||
depends on BCM63XX
|
||||
help
|
||||
Many Broadcom BCM63xx chipsets (such as the BCM6328) have a
|
||||
high speed USB Device Port with support for four fixed endpoints
|
||||
(plus endpoint zero).
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "bcm63xx_udc".
|
||||
|
||||
config USB_FSL_USB2
|
||||
tristate "Freescale Highspeed USB DR Peripheral Controller"
|
||||
depends on FSL_SOC || ARCH_MXC
|
||||
select USB_GADGET_DUALSPEED
|
||||
select USB_FSL_MPH_DR_OF if OF
|
||||
help
|
||||
Some of Freescale PowerPC and i.MX processors have a High Speed
|
||||
|
|
@ -179,7 +188,6 @@ config USB_FSL_USB2
|
|||
config USB_FUSB300
|
||||
tristate "Faraday FUSB300 USB Peripheral Controller"
|
||||
depends on !PHYS_ADDR_T_64BIT
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
Faraday usb device controller FUSB300 driver
|
||||
|
||||
|
|
@ -227,7 +235,6 @@ config USB_PXA25X_SMALL
|
|||
|
||||
config USB_R8A66597
|
||||
tristate "Renesas R8A66597 USB Peripheral Controller"
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
R8A66597 is a discrete USB host and peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
|
@ -240,7 +247,6 @@ config USB_R8A66597
|
|||
config USB_RENESAS_USBHS_UDC
|
||||
tristate 'Renesas USBHS controller'
|
||||
depends on USB_RENESAS_USBHS
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
Renesas USBHS is a discrete USB host and peripheral controller chip
|
||||
that supports both full and high speed USB 2.0 data transfers.
|
||||
|
|
@ -268,7 +274,6 @@ config USB_PXA27X
|
|||
config USB_S3C_HSOTG
|
||||
tristate "S3C HS/OtG USB Device controller"
|
||||
depends on S3C_DEV_USB_HSOTG
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
The Samsung S3C64XX USB2.0 high-speed gadget controller
|
||||
integrated into the S3C64XX series SoC.
|
||||
|
|
@ -305,7 +310,6 @@ config USB_S3C2410_DEBUG
|
|||
config USB_S3C_HSUDC
|
||||
tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller"
|
||||
depends on ARCH_S3C24XX
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
|
||||
integrated with dual speed USB 2.0 device controller. It has
|
||||
|
|
@ -315,7 +319,6 @@ config USB_S3C_HSUDC
|
|||
|
||||
config USB_MV_UDC
|
||||
tristate "Marvell USB2.0 Device Controller"
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
Marvell Socs (including PXA and MMP series) include a high speed
|
||||
USB2.0 OTG controller, which can be configured as high speed or
|
||||
|
|
@ -338,14 +341,12 @@ config USB_MV_U3D
|
|||
config USB_GADGET_MUSB_HDRC
|
||||
tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)"
|
||||
depends on USB_MUSB_HDRC
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
This OTG-capable silicon IP is used in dual designs including
|
||||
the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
|
||||
|
||||
config USB_M66592
|
||||
tristate "Renesas M66592 USB Peripheral Controller"
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
M66592 is a discrete USB peripheral controller chip that
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
|
@ -362,7 +363,6 @@ config USB_M66592
|
|||
config USB_AMD5536UDC
|
||||
tristate "AMD5536 UDC"
|
||||
depends on PCI
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge.
|
||||
It is a USB Highspeed DMA capable USB device controller. Beside ep0
|
||||
|
|
@ -389,7 +389,6 @@ config USB_FSL_QE
|
|||
|
||||
config USB_NET2272
|
||||
tristate "PLX NET2272"
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
PLX NET2272 is a USB peripheral controller which supports
|
||||
both full and high speed USB 2.0 data transfers.
|
||||
|
|
@ -413,7 +412,6 @@ config USB_NET2272_DMA
|
|||
config USB_NET2280
|
||||
tristate "NetChip 228x"
|
||||
depends on PCI
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
NetChip 2280 / 2282 is a PCI based USB peripheral controller which
|
||||
supports both full and high speed USB 2.0 data transfers.
|
||||
|
|
@ -443,7 +441,6 @@ config USB_GOKU
|
|||
config USB_EG20T
|
||||
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
|
||||
depends on PCI
|
||||
select USB_GADGET_DUALSPEED
|
||||
help
|
||||
This is a USB device driver for EG20T PCH.
|
||||
EG20T PCH is the platform controller hub that is used in Intel's
|
||||
|
|
@ -470,8 +467,6 @@ config USB_EG20T
|
|||
config USB_DUMMY_HCD
|
||||
tristate "Dummy HCD (DEVELOPMENT)"
|
||||
depends on USB=y || (USB=m && USB_GADGET=m)
|
||||
select USB_GADGET_DUALSPEED
|
||||
select USB_GADGET_SUPERSPEED
|
||||
help
|
||||
This host controller driver emulates USB, looping all data transfer
|
||||
requests back to a USB "gadget driver" in the same host. The host
|
||||
|
|
@ -496,18 +491,15 @@ config USB_DUMMY_HCD
|
|||
|
||||
endmenu
|
||||
|
||||
# Selected by UDC drivers that support high-speed operation.
|
||||
config USB_GADGET_DUALSPEED
|
||||
bool
|
||||
|
||||
# Selected by UDC drivers that support super-speed opperation
|
||||
config USB_GADGET_SUPERSPEED
|
||||
bool
|
||||
depends on USB_GADGET_DUALSPEED
|
||||
|
||||
#
|
||||
# USB Gadget Drivers
|
||||
#
|
||||
|
||||
# composite based drivers
|
||||
config USB_LIBCOMPOSITE
|
||||
tristate
|
||||
depends on USB_GADGET
|
||||
|
||||
choice
|
||||
tristate "USB Gadget Drivers"
|
||||
default USB_ETH
|
||||
|
|
@ -531,6 +523,7 @@ choice
|
|||
|
||||
config USB_ZERO
|
||||
tristate "Gadget Zero (DEVELOPMENT)"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
Gadget Zero is a two-configuration device. It either sinks and
|
||||
sources bulk data; or it loops back a configurable number of
|
||||
|
|
@ -564,8 +557,9 @@ config USB_ZERO_HNPTEST
|
|||
one serve as the USB host instead (in the "B-Host" role).
|
||||
|
||||
config USB_AUDIO
|
||||
tristate "Audio Gadget (EXPERIMENTAL)"
|
||||
tristate "Audio Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_PCM
|
||||
help
|
||||
This Gadget Audio driver is compatible with USB Audio Class
|
||||
|
|
@ -594,6 +588,7 @@ config GADGET_UAC1
|
|||
config USB_ETH
|
||||
tristate "Ethernet Gadget (with CDC Ethernet support)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select CRC32
|
||||
help
|
||||
This driver implements Ethernet style communication, in one of
|
||||
|
|
@ -629,6 +624,7 @@ config USB_ETH
|
|||
config USB_ETH_RNDIS
|
||||
bool "RNDIS support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
default y
|
||||
help
|
||||
Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
|
||||
|
|
@ -647,6 +643,7 @@ config USB_ETH_RNDIS
|
|||
config USB_ETH_EEM
|
||||
bool "Ethernet Emulation Model (EEM) support"
|
||||
depends on USB_ETH
|
||||
select USB_LIBCOMPOSITE
|
||||
default n
|
||||
help
|
||||
CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
|
||||
|
|
@ -663,6 +660,7 @@ config USB_ETH_EEM
|
|||
config USB_G_NCM
|
||||
tristate "Network Control Model (NCM) support"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
select CRC32
|
||||
help
|
||||
This driver implements USB CDC NCM subclass standard. NCM is
|
||||
|
|
@ -674,8 +672,7 @@ config USB_G_NCM
|
|||
dynamically linked module called "g_ncm".
|
||||
|
||||
config USB_GADGETFS
|
||||
tristate "Gadget Filesystem (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
tristate "Gadget Filesystem"
|
||||
help
|
||||
This driver provides a filesystem based API that lets user mode
|
||||
programs implement a single-configuration USB device, including
|
||||
|
|
@ -683,15 +680,12 @@ config USB_GADGETFS
|
|||
All endpoints, transfer speeds, and transfer types supported by
|
||||
the hardware are available, through read() and write() calls.
|
||||
|
||||
Currently, this option is still labelled as EXPERIMENTAL because
|
||||
of existing race conditions in the underlying in-kernel AIO core.
|
||||
|
||||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "gadgetfs".
|
||||
|
||||
config USB_FUNCTIONFS
|
||||
tristate "Function Filesystem (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
tristate "Function Filesystem"
|
||||
select USB_LIBCOMPOSITE
|
||||
select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS)
|
||||
help
|
||||
The Function Filesystem (FunctionFS) lets one create USB
|
||||
|
|
@ -755,6 +749,7 @@ config USB_FILE_STORAGE_TEST
|
|||
config USB_MASS_STORAGE
|
||||
tristate "Mass Storage Gadget"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Mass Storage Gadget acts as a USB Mass Storage disk drive.
|
||||
As its storage repository it can use a regular file or a block
|
||||
|
|
@ -770,6 +765,7 @@ config USB_MASS_STORAGE
|
|||
config USB_GADGET_TARGET
|
||||
tristate "USB Gadget Target Fabric Module"
|
||||
depends on TARGET_CORE
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This fabric is an USB gadget. Two USB protocols are supported that is
|
||||
BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
|
||||
|
|
@ -779,6 +775,7 @@ config USB_GADGET_TARGET
|
|||
|
||||
config USB_G_SERIAL
|
||||
tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Serial Gadget talks to the Linux-USB generic serial driver.
|
||||
This driver supports a CDC-ACM module option, which can be used
|
||||
|
|
@ -797,8 +794,9 @@ config USB_G_SERIAL
|
|||
make MS-Windows work with CDC ACM.
|
||||
|
||||
config USB_MIDI_GADGET
|
||||
tristate "MIDI Gadget (EXPERIMENTAL)"
|
||||
depends on SND && EXPERIMENTAL
|
||||
tristate "MIDI Gadget"
|
||||
depends on SND
|
||||
select USB_LIBCOMPOSITE
|
||||
select SND_RAWMIDI
|
||||
help
|
||||
The MIDI Gadget acts as a USB Audio device, with one MIDI
|
||||
|
|
@ -812,6 +810,7 @@ config USB_MIDI_GADGET
|
|||
|
||||
config USB_G_PRINTER
|
||||
tristate "Printer Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Printer Gadget channels data between the USB host and a
|
||||
userspace program driving the print engine. The user space
|
||||
|
|
@ -828,6 +827,7 @@ config USB_G_PRINTER
|
|||
config USB_CDC_COMPOSITE
|
||||
tristate "CDC Composite Device (Ethernet and ACM)"
|
||||
depends on NET
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link.
|
||||
|
|
@ -842,6 +842,7 @@ config USB_CDC_COMPOSITE
|
|||
config USB_G_NOKIA
|
||||
tristate "Nokia composite gadget"
|
||||
depends on PHONET
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Nokia composite gadget provides support for acm, obex
|
||||
and phonet in only one composite gadget driver.
|
||||
|
|
@ -852,6 +853,7 @@ config USB_G_NOKIA
|
|||
config USB_G_ACM_MS
|
||||
tristate "CDC Composite Device (ACM and mass storage)"
|
||||
depends on BLOCK
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This driver provides two functions in one configuration:
|
||||
a mass storage, and a CDC ACM (serial port) link.
|
||||
|
|
@ -860,9 +862,10 @@ config USB_G_ACM_MS
|
|||
dynamically linked module called "g_acm_ms".
|
||||
|
||||
config USB_G_MULTI
|
||||
tristate "Multifunction Composite Gadget (EXPERIMENTAL)"
|
||||
tristate "Multifunction Composite Gadget"
|
||||
depends on BLOCK && NET
|
||||
select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The Multifunction Composite Gadget provides Ethernet (RNDIS
|
||||
and/or CDC Ethernet), mass storage and ACM serial link
|
||||
|
|
@ -903,6 +906,7 @@ config USB_G_MULTI_CDC
|
|||
|
||||
config USB_G_HID
|
||||
tristate "HID Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
The HID gadget driver provides generic emulation of USB
|
||||
Human Interface Devices (HID).
|
||||
|
|
@ -913,8 +917,10 @@ config USB_G_HID
|
|||
Say "y" to link the driver statically, or "m" to build a
|
||||
dynamically linked module called "g_hid".
|
||||
|
||||
# Standalone / single function gadgets
|
||||
config USB_G_DBGP
|
||||
tristate "EHCI Debug Device Gadget"
|
||||
select USB_LIBCOMPOSITE
|
||||
help
|
||||
This gadget emulates an EHCI Debug device. This is useful when you want
|
||||
to interact with an EHCI Debug Port.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
|
||||
|
||||
obj-$(CONFIG_USB_GADGET) += udc-core.o
|
||||
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
|
||||
libcomposite-y := usbstring.o config.o epautoconf.o
|
||||
libcomposite-y += composite.o
|
||||
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
|
||||
obj-$(CONFIG_USB_NET2272) += net2272.o
|
||||
obj-$(CONFIG_USB_NET2280) += net2280.o
|
||||
|
|
@ -16,6 +19,7 @@ obj-$(CONFIG_USB_OMAP) += omap_udc.o
|
|||
obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
|
||||
obj-$(CONFIG_USB_AT91) += at91_udc.o
|
||||
obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
|
||||
obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o
|
||||
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
|
||||
fsl_usb2_udc-y := fsl_udc_core.o
|
||||
fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "u_serial.h"
|
||||
|
||||
|
|
@ -41,15 +41,12 @@
|
|||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
#include "u_serial.c"
|
||||
#include "f_acm.c"
|
||||
#include "f_mass_storage.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
|
|
@ -89,17 +86,11 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -157,7 +148,6 @@ static struct usb_configuration acm_ms_config_driver = {
|
|||
|
||||
static int __init acm_ms_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
void *retp;
|
||||
|
|
@ -174,44 +164,22 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
|
|||
goto fail0;
|
||||
}
|
||||
|
||||
/* set bcdDevice */
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0) {
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
} else {
|
||||
WARNING(cdev, "controller '%s' not recognized; trying %s\n",
|
||||
gadget->name,
|
||||
acm_ms_config_driver.label);
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
/* register our configuration */
|
||||
status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
|
||||
DRIVER_DESC);
|
||||
fsg_common_put(&fsg_common);
|
||||
|
|
@ -232,11 +200,12 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver acm_ms_driver = {
|
||||
static __refdata struct usb_composite_driver acm_ms_driver = {
|
||||
.name = "g_acm_ms",
|
||||
.dev = &device_desc,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.strings = dev_strings,
|
||||
.bind = acm_ms_bind,
|
||||
.unbind = __exit_p(acm_ms_unbind),
|
||||
};
|
||||
|
||||
|
|
@ -246,7 +215,7 @@ MODULE_LICENSE("GPL v2");
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&acm_ms_driver, acm_ms_bind);
|
||||
return usb_composite_probe(&acm_ms_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -1401,7 +1401,7 @@ static int udc_wakeup(struct usb_gadget *gadget)
|
|||
}
|
||||
|
||||
static int amd5536_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int amd5536_stop(struct usb_gadget_driver *driver);
|
||||
/* gadget operations */
|
||||
static const struct usb_gadget_ops udc_ops = {
|
||||
|
|
@ -1914,7 +1914,7 @@ static int setup_ep0(struct udc *dev)
|
|||
|
||||
/* Called by gadget driver to register itself */
|
||||
static int amd5536_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct udc *dev = udc;
|
||||
int retval;
|
||||
|
|
@ -1932,7 +1932,7 @@ static int amd5536_start(struct usb_gadget_driver *driver,
|
|||
dev->driver = driver;
|
||||
dev->gadget.dev.driver = &driver->driver;
|
||||
|
||||
retval = bind(&dev->gadget);
|
||||
retval = bind(&dev->gadget, driver);
|
||||
|
||||
/* Some gadget drivers use both ep0 directions.
|
||||
* NOTE: to gadget driver, ep0 is just one endpoint...
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
|
|||
const struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
|
||||
struct at91_udc *udc = ep->udc;
|
||||
struct at91_udc *udc;
|
||||
u16 maxpacket;
|
||||
u32 tmp;
|
||||
unsigned long flags;
|
||||
|
|
@ -483,6 +483,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
udc = ep->udc;
|
||||
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
|
||||
DBG("bogus device state\n");
|
||||
return -ESHUTDOWN;
|
||||
|
|
@ -1699,7 +1700,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
|
|||
int retval;
|
||||
struct resource *res;
|
||||
|
||||
if (!dev->platform_data) {
|
||||
if (!dev->platform_data && !pdev->dev.of_node) {
|
||||
/* small (so we copy it) but critical! */
|
||||
DBG("missing platform_data\n");
|
||||
return -ENODEV;
|
||||
|
|
|
|||
|
|
@ -12,35 +12,21 @@
|
|||
/* #define VERBOSE_DEBUG */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
#define DRIVER_DESC "Linux USB Audio Gadget"
|
||||
#define DRIVER_VERSION "Feb 2, 2012"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -149,39 +135,18 @@ static struct usb_configuration audio_config_driver = {
|
|||
|
||||
static int __init audio_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
int status;
|
||||
|
||||
gcnum = usb_gadget_controller_number(cdev->gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
else {
|
||||
ERROR(cdev, "controller '%s' not recognized; trying %s\n",
|
||||
cdev->gadget->name,
|
||||
audio_config_driver.label);
|
||||
device_desc.bcdDevice =
|
||||
__constant_cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
cdev->gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
|
||||
INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
|
||||
return 0;
|
||||
|
|
@ -198,17 +163,18 @@ static int __exit audio_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver audio_driver = {
|
||||
static __refdata struct usb_composite_driver audio_driver = {
|
||||
.name = "g_audio",
|
||||
.dev = &device_desc,
|
||||
.strings = audio_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = audio_bind,
|
||||
.unbind = __exit_p(audio_unbind),
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&audio_driver, audio_bind);
|
||||
return usb_composite_probe(&audio_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
2464
drivers/usb/gadget/bcm63xx_udc.c
Normal file
2464
drivers/usb/gadget/bcm63xx_udc.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "u_ether.h"
|
||||
|
|
@ -34,6 +33,7 @@
|
|||
#define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
|
|
@ -43,10 +43,6 @@
|
|||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
#include "u_serial.c"
|
||||
#include "f_acm.c"
|
||||
#include "f_ecm.c"
|
||||
|
|
@ -92,15 +88,10 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -152,7 +143,6 @@ static struct usb_configuration cdc_config_driver = {
|
|||
|
||||
static int __init cdc_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
|
||||
|
|
@ -172,47 +162,22 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
goto fail0;
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
else {
|
||||
/* We assume that can_support_ecm() tells the truth;
|
||||
* but if the controller isn't recognized at all then
|
||||
* that assumption is a bit more likely to be wrong.
|
||||
*/
|
||||
WARNING(cdev, "controller '%s' not recognized; trying %s\n",
|
||||
gadget->name,
|
||||
cdc_config_driver.label);
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
/* register our configuration */
|
||||
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
|
||||
if (status < 0)
|
||||
goto fail1;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
|
||||
DRIVER_DESC);
|
||||
|
||||
|
|
@ -232,11 +197,12 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver cdc_driver = {
|
||||
static __refdata struct usb_composite_driver cdc_driver = {
|
||||
.name = "g_cdc",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = cdc_bind,
|
||||
.unbind = __exit_p(cdc_unbind),
|
||||
};
|
||||
|
||||
|
|
@ -246,7 +212,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&cdc_driver, cdc_bind);
|
||||
return usb_composite_probe(&cdc_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,44 +28,6 @@
|
|||
* with the relevant device-wide data.
|
||||
*/
|
||||
|
||||
/* big enough to hold our biggest descriptor */
|
||||
#define USB_BUFSIZ 1024
|
||||
|
||||
static struct usb_composite_driver *composite;
|
||||
static int (*composite_gadget_bind)(struct usb_composite_dev *cdev);
|
||||
|
||||
/* Some systems will need runtime overrides for the product identifiers
|
||||
* published in the device descriptor, either numbers or strings or both.
|
||||
* String parameters are in UTF-8 (superset of ASCII's 7 bit characters).
|
||||
*/
|
||||
|
||||
static ushort idVendor;
|
||||
module_param(idVendor, ushort, 0644);
|
||||
MODULE_PARM_DESC(idVendor, "USB Vendor ID");
|
||||
|
||||
static ushort idProduct;
|
||||
module_param(idProduct, ushort, 0644);
|
||||
MODULE_PARM_DESC(idProduct, "USB Product ID");
|
||||
|
||||
static ushort bcdDevice;
|
||||
module_param(bcdDevice, ushort, 0644);
|
||||
MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
|
||||
|
||||
static char *iManufacturer;
|
||||
module_param(iManufacturer, charp, 0644);
|
||||
MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
|
||||
|
||||
static char *iProduct;
|
||||
module_param(iProduct, charp, 0644);
|
||||
MODULE_PARM_DESC(iProduct, "USB Product string");
|
||||
|
||||
static char *iSerialNumber;
|
||||
module_param(iSerialNumber, charp, 0644);
|
||||
MODULE_PARM_DESC(iSerialNumber, "SerialNumber string");
|
||||
|
||||
static char composite_manufacturer[50];
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
* next_ep_desc() - advance to the next EP descriptor
|
||||
* @t: currect pointer within descriptor array
|
||||
|
|
@ -192,6 +154,7 @@ ep_found:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(config_ep_by_speed);
|
||||
|
||||
/**
|
||||
* usb_add_function() - add a function to a configuration
|
||||
|
|
@ -250,6 +213,7 @@ done:
|
|||
function->name, function, value);
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_add_function);
|
||||
|
||||
/**
|
||||
* usb_function_deactivate - prevent function and gadget enumeration
|
||||
|
|
@ -286,6 +250,7 @@ int usb_function_deactivate(struct usb_function *function)
|
|||
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_function_deactivate);
|
||||
|
||||
/**
|
||||
* usb_function_activate - allow function and gadget enumeration
|
||||
|
|
@ -300,9 +265,10 @@ int usb_function_deactivate(struct usb_function *function)
|
|||
int usb_function_activate(struct usb_function *function)
|
||||
{
|
||||
struct usb_composite_dev *cdev = function->config->cdev;
|
||||
unsigned long flags;
|
||||
int status = 0;
|
||||
|
||||
spin_lock(&cdev->lock);
|
||||
spin_lock_irqsave(&cdev->lock, flags);
|
||||
|
||||
if (WARN_ON(cdev->deactivations == 0))
|
||||
status = -EINVAL;
|
||||
|
|
@ -312,9 +278,10 @@ int usb_function_activate(struct usb_function *function)
|
|||
status = usb_gadget_connect(cdev->gadget);
|
||||
}
|
||||
|
||||
spin_unlock(&cdev->lock);
|
||||
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_function_activate);
|
||||
|
||||
/**
|
||||
* usb_interface_id() - allocate an unused interface ID
|
||||
|
|
@ -351,16 +318,18 @@ int usb_interface_id(struct usb_configuration *config,
|
|||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_interface_id);
|
||||
|
||||
static int config_buf(struct usb_configuration *config,
|
||||
enum usb_device_speed speed, void *buf, u8 type)
|
||||
{
|
||||
struct usb_config_descriptor *c = buf;
|
||||
void *next = buf + USB_DT_CONFIG_SIZE;
|
||||
int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
|
||||
int len;
|
||||
struct usb_function *f;
|
||||
int status;
|
||||
|
||||
len = USB_COMP_EP0_BUFSIZ - USB_DT_CONFIG_SIZE;
|
||||
/* write the config descriptor */
|
||||
c = buf;
|
||||
c->bLength = USB_DT_CONFIG_SIZE;
|
||||
|
|
@ -790,6 +759,7 @@ done:
|
|||
config->bConfigurationValue, status);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_add_config);
|
||||
|
||||
static void remove_config(struct usb_composite_dev *cdev,
|
||||
struct usb_configuration *config)
|
||||
|
|
@ -889,10 +859,10 @@ static int lookup_string(
|
|||
static int get_string(struct usb_composite_dev *cdev,
|
||||
void *buf, u16 language, int id)
|
||||
{
|
||||
struct usb_composite_driver *composite = cdev->driver;
|
||||
struct usb_configuration *c;
|
||||
struct usb_function *f;
|
||||
int len;
|
||||
const char *str;
|
||||
|
||||
/* Yes, not only is USB's I18N support probably more than most
|
||||
* folk will ever care about ... also, it's all supported here.
|
||||
|
|
@ -932,26 +902,6 @@ static int get_string(struct usb_composite_dev *cdev,
|
|||
return s->bLength;
|
||||
}
|
||||
|
||||
/* Otherwise, look up and return a specified string. First
|
||||
* check if the string has not been overridden.
|
||||
*/
|
||||
if (cdev->manufacturer_override == id)
|
||||
str = iManufacturer ?: composite->iManufacturer ?:
|
||||
composite_manufacturer;
|
||||
else if (cdev->product_override == id)
|
||||
str = iProduct ?: composite->iProduct;
|
||||
else if (cdev->serial_override == id)
|
||||
str = iSerialNumber ?: composite->iSerialNumber;
|
||||
else
|
||||
str = NULL;
|
||||
if (str) {
|
||||
struct usb_gadget_strings strings = {
|
||||
.language = language,
|
||||
.strings = &(struct usb_string) { 0xff, str }
|
||||
};
|
||||
return usb_gadget_get_string(&strings, 0xff, buf);
|
||||
}
|
||||
|
||||
/* String IDs are device-scoped, so we look up each string
|
||||
* table we're told about. These lookups are infrequent;
|
||||
* simpler-is-better here.
|
||||
|
|
@ -1003,6 +953,7 @@ int usb_string_id(struct usb_composite_dev *cdev)
|
|||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_string_id);
|
||||
|
||||
/**
|
||||
* usb_string_ids() - allocate unused string IDs in batch
|
||||
|
|
@ -1034,6 +985,7 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_string_ids_tab);
|
||||
|
||||
/**
|
||||
* usb_string_ids_n() - allocate unused string IDs in batch
|
||||
|
|
@ -1062,7 +1014,7 @@ int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
|
|||
c->next_string_id += n;
|
||||
return next + 1;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_string_ids_n);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
|
@ -1359,8 +1311,8 @@ static void composite_disconnect(struct usb_gadget *gadget)
|
|||
spin_lock_irqsave(&cdev->lock, flags);
|
||||
if (cdev->config)
|
||||
reset_config(cdev);
|
||||
if (composite->disconnect)
|
||||
composite->disconnect(cdev);
|
||||
if (cdev->driver->disconnect)
|
||||
cdev->driver->disconnect(cdev);
|
||||
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -1396,35 +1348,67 @@ composite_unbind(struct usb_gadget *gadget)
|
|||
struct usb_configuration, list);
|
||||
remove_config(cdev, c);
|
||||
}
|
||||
if (composite->unbind)
|
||||
composite->unbind(cdev);
|
||||
if (cdev->driver->unbind)
|
||||
cdev->driver->unbind(cdev);
|
||||
|
||||
if (cdev->req) {
|
||||
kfree(cdev->req->buf);
|
||||
usb_ep_free_request(gadget->ep0, cdev->req);
|
||||
}
|
||||
device_remove_file(&gadget->dev, &dev_attr_suspended);
|
||||
kfree(cdev->def_manufacturer);
|
||||
kfree(cdev);
|
||||
set_gadget_data(gadget, NULL);
|
||||
composite = NULL;
|
||||
}
|
||||
|
||||
static u8 override_id(struct usb_composite_dev *cdev, u8 *desc)
|
||||
static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
|
||||
const struct usb_device_descriptor *old)
|
||||
{
|
||||
if (!*desc) {
|
||||
int ret = usb_string_id(cdev);
|
||||
if (unlikely(ret < 0))
|
||||
WARNING(cdev, "failed to override string ID\n");
|
||||
else
|
||||
*desc = ret;
|
||||
}
|
||||
__le16 idVendor;
|
||||
__le16 idProduct;
|
||||
__le16 bcdDevice;
|
||||
u8 iSerialNumber;
|
||||
u8 iManufacturer;
|
||||
u8 iProduct;
|
||||
|
||||
return *desc;
|
||||
/*
|
||||
* these variables may have been set in
|
||||
* usb_composite_overwrite_options()
|
||||
*/
|
||||
idVendor = new->idVendor;
|
||||
idProduct = new->idProduct;
|
||||
bcdDevice = new->bcdDevice;
|
||||
iSerialNumber = new->iSerialNumber;
|
||||
iManufacturer = new->iManufacturer;
|
||||
iProduct = new->iProduct;
|
||||
|
||||
*new = *old;
|
||||
if (idVendor)
|
||||
new->idVendor = idVendor;
|
||||
if (idProduct)
|
||||
new->idProduct = idProduct;
|
||||
if (bcdDevice)
|
||||
new->bcdDevice = bcdDevice;
|
||||
else
|
||||
new->bcdDevice = cpu_to_le16(get_default_bcdDevice());
|
||||
if (iSerialNumber)
|
||||
new->iSerialNumber = iSerialNumber;
|
||||
if (iManufacturer)
|
||||
new->iManufacturer = iManufacturer;
|
||||
if (iProduct)
|
||||
new->iProduct = iProduct;
|
||||
}
|
||||
|
||||
static int composite_bind(struct usb_gadget *gadget)
|
||||
static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv)
|
||||
{
|
||||
return container_of(gdrv, struct usb_composite_driver, gadget_driver);
|
||||
}
|
||||
|
||||
static int composite_bind(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *gdriver)
|
||||
{
|
||||
struct usb_composite_dev *cdev;
|
||||
struct usb_composite_driver *composite = to_cdriver(gdriver);
|
||||
int status = -ENOMEM;
|
||||
|
||||
cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
|
||||
|
|
@ -1440,13 +1424,12 @@ static int composite_bind(struct usb_gadget *gadget)
|
|||
cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
|
||||
if (!cdev->req)
|
||||
goto fail;
|
||||
cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
|
||||
cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
|
||||
if (!cdev->req->buf)
|
||||
goto fail;
|
||||
cdev->req->complete = composite_setup_complete;
|
||||
gadget->ep0->driver_data = cdev;
|
||||
|
||||
cdev->bufsiz = USB_BUFSIZ;
|
||||
cdev->driver = composite;
|
||||
|
||||
/*
|
||||
|
|
@ -1467,49 +1450,11 @@ static int composite_bind(struct usb_gadget *gadget)
|
|||
* serial number), register function drivers, potentially update
|
||||
* power state and consumption, etc
|
||||
*/
|
||||
status = composite_gadget_bind(cdev);
|
||||
status = composite->bind(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
cdev->desc = *composite->dev;
|
||||
|
||||
/* standardized runtime overrides for device ID data */
|
||||
if (idVendor)
|
||||
cdev->desc.idVendor = cpu_to_le16(idVendor);
|
||||
else
|
||||
idVendor = le16_to_cpu(cdev->desc.idVendor);
|
||||
if (idProduct)
|
||||
cdev->desc.idProduct = cpu_to_le16(idProduct);
|
||||
else
|
||||
idProduct = le16_to_cpu(cdev->desc.idProduct);
|
||||
if (bcdDevice)
|
||||
cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
|
||||
else
|
||||
bcdDevice = le16_to_cpu(cdev->desc.bcdDevice);
|
||||
|
||||
/* string overrides */
|
||||
if (iManufacturer || !cdev->desc.iManufacturer) {
|
||||
if (!iManufacturer && !composite->iManufacturer &&
|
||||
!*composite_manufacturer)
|
||||
snprintf(composite_manufacturer,
|
||||
sizeof composite_manufacturer,
|
||||
"%s %s with %s",
|
||||
init_utsname()->sysname,
|
||||
init_utsname()->release,
|
||||
gadget->name);
|
||||
|
||||
cdev->manufacturer_override =
|
||||
override_id(cdev, &cdev->desc.iManufacturer);
|
||||
}
|
||||
|
||||
if (iProduct || (!cdev->desc.iProduct && composite->iProduct))
|
||||
cdev->product_override =
|
||||
override_id(cdev, &cdev->desc.iProduct);
|
||||
|
||||
if (iSerialNumber ||
|
||||
(!cdev->desc.iSerialNumber && composite->iSerialNumber))
|
||||
cdev->serial_override =
|
||||
override_id(cdev, &cdev->desc.iSerialNumber);
|
||||
update_unchanged_dev_desc(&cdev->desc, composite->dev);
|
||||
|
||||
/* has userspace failed to provide a serial number? */
|
||||
if (composite->needs_serial && !cdev->desc.iSerialNumber)
|
||||
|
|
@ -1546,8 +1491,8 @@ composite_suspend(struct usb_gadget *gadget)
|
|||
f->suspend(f);
|
||||
}
|
||||
}
|
||||
if (composite->suspend)
|
||||
composite->suspend(cdev);
|
||||
if (cdev->driver->suspend)
|
||||
cdev->driver->suspend(cdev);
|
||||
|
||||
cdev->suspended = 1;
|
||||
|
||||
|
|
@ -1565,8 +1510,8 @@ composite_resume(struct usb_gadget *gadget)
|
|||
* suspend/resume callbacks?
|
||||
*/
|
||||
DBG(cdev, "resume\n");
|
||||
if (composite->resume)
|
||||
composite->resume(cdev);
|
||||
if (cdev->driver->resume)
|
||||
cdev->driver->resume(cdev);
|
||||
if (cdev->config) {
|
||||
list_for_each_entry(f, &cdev->config->functions, list) {
|
||||
if (f->resume)
|
||||
|
|
@ -1584,13 +1529,8 @@ composite_resume(struct usb_gadget *gadget)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_gadget_driver composite_driver = {
|
||||
#ifdef CONFIG_USB_GADGET_SUPERSPEED
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
#else
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
#endif
|
||||
|
||||
static const struct usb_gadget_driver composite_driver_template = {
|
||||
.bind = composite_bind,
|
||||
.unbind = composite_unbind,
|
||||
|
||||
.setup = composite_setup,
|
||||
|
|
@ -1623,25 +1563,26 @@ static struct usb_gadget_driver composite_driver = {
|
|||
* while it was binding. That would usually be done in order to wait for
|
||||
* some userspace participation.
|
||||
*/
|
||||
int usb_composite_probe(struct usb_composite_driver *driver,
|
||||
int (*bind)(struct usb_composite_dev *cdev))
|
||||
int usb_composite_probe(struct usb_composite_driver *driver)
|
||||
{
|
||||
if (!driver || !driver->dev || !bind || composite)
|
||||
struct usb_gadget_driver *gadget_driver;
|
||||
|
||||
if (!driver || !driver->dev || !driver->bind)
|
||||
return -EINVAL;
|
||||
|
||||
if (!driver->name)
|
||||
driver->name = "composite";
|
||||
if (!driver->iProduct)
|
||||
driver->iProduct = driver->name;
|
||||
composite_driver.function = (char *) driver->name;
|
||||
composite_driver.driver.name = driver->name;
|
||||
composite_driver.max_speed =
|
||||
min_t(u8, composite_driver.max_speed, driver->max_speed);
|
||||
composite = driver;
|
||||
composite_gadget_bind = bind;
|
||||
|
||||
return usb_gadget_probe_driver(&composite_driver, composite_bind);
|
||||
driver->gadget_driver = composite_driver_template;
|
||||
gadget_driver = &driver->gadget_driver;
|
||||
|
||||
gadget_driver->function = (char *) driver->name;
|
||||
gadget_driver->driver.name = driver->name;
|
||||
gadget_driver->max_speed = driver->max_speed;
|
||||
|
||||
return usb_gadget_probe_driver(gadget_driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_composite_probe);
|
||||
|
||||
/**
|
||||
* usb_composite_unregister() - unregister a composite driver
|
||||
|
|
@ -1652,10 +1593,9 @@ int usb_composite_probe(struct usb_composite_driver *driver,
|
|||
*/
|
||||
void usb_composite_unregister(struct usb_composite_driver *driver)
|
||||
{
|
||||
if (composite != driver)
|
||||
return;
|
||||
usb_gadget_unregister_driver(&composite_driver);
|
||||
usb_gadget_unregister_driver(&driver->gadget_driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_composite_unregister);
|
||||
|
||||
/**
|
||||
* usb_composite_setup_continue() - Continue with the control transfer
|
||||
|
|
@ -1692,4 +1632,60 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev)
|
|||
|
||||
spin_unlock_irqrestore(&cdev->lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_composite_setup_continue);
|
||||
|
||||
static char *composite_default_mfr(struct usb_gadget *gadget)
|
||||
{
|
||||
char *mfr;
|
||||
int len;
|
||||
|
||||
len = snprintf(NULL, 0, "%s %s with %s", init_utsname()->sysname,
|
||||
init_utsname()->release, gadget->name);
|
||||
len++;
|
||||
mfr = kmalloc(len, GFP_KERNEL);
|
||||
if (!mfr)
|
||||
return NULL;
|
||||
snprintf(mfr, len, "%s %s with %s", init_utsname()->sysname,
|
||||
init_utsname()->release, gadget->name);
|
||||
return mfr;
|
||||
}
|
||||
|
||||
void usb_composite_overwrite_options(struct usb_composite_dev *cdev,
|
||||
struct usb_composite_overwrite *covr)
|
||||
{
|
||||
struct usb_device_descriptor *desc = &cdev->desc;
|
||||
struct usb_gadget_strings *gstr = cdev->driver->strings[0];
|
||||
struct usb_string *dev_str = gstr->strings;
|
||||
|
||||
if (covr->idVendor)
|
||||
desc->idVendor = cpu_to_le16(covr->idVendor);
|
||||
|
||||
if (covr->idProduct)
|
||||
desc->idProduct = cpu_to_le16(covr->idProduct);
|
||||
|
||||
if (covr->bcdDevice)
|
||||
desc->bcdDevice = cpu_to_le16(covr->bcdDevice);
|
||||
|
||||
if (covr->serial_number) {
|
||||
desc->iSerialNumber = dev_str[USB_GADGET_SERIAL_IDX].id;
|
||||
dev_str[USB_GADGET_SERIAL_IDX].s = covr->serial_number;
|
||||
}
|
||||
if (covr->manufacturer) {
|
||||
desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
dev_str[USB_GADGET_MANUFACTURER_IDX].s = covr->manufacturer;
|
||||
|
||||
} else if (!strlen(dev_str[USB_GADGET_MANUFACTURER_IDX].s)) {
|
||||
desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
cdev->def_manufacturer = composite_default_mfr(cdev->gadget);
|
||||
dev_str[USB_GADGET_MANUFACTURER_IDX].s = cdev->def_manufacturer;
|
||||
}
|
||||
|
||||
if (covr->product) {
|
||||
desc->iProduct = dev_str[USB_GADGET_PRODUCT_IDX].id;
|
||||
dev_str[USB_GADGET_PRODUCT_IDX].s = covr->product;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_composite_overwrite_options);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/device.h>
|
||||
|
|
@ -53,7 +54,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen,
|
|||
}
|
||||
return dest - (u8 *)buf;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf);
|
||||
|
||||
/**
|
||||
* usb_gadget_config_buf - builts a complete configuration descriptor
|
||||
|
|
@ -106,6 +107,7 @@ int usb_gadget_config_buf(
|
|||
cp->bmAttributes |= USB_CONFIG_ATT_ONE;
|
||||
return len;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_gadget_config_buf);
|
||||
|
||||
/**
|
||||
* usb_copy_descriptors - copy a vector of USB descriptors
|
||||
|
|
@ -155,4 +157,4 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_copy_descriptors);
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@
|
|||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
/* See comments in "zero.c" */
|
||||
#include "epautoconf.c"
|
||||
|
||||
#ifdef CONFIG_USB_G_DBGP_SERIAL
|
||||
#include "u_serial.c"
|
||||
#endif
|
||||
|
|
@ -292,7 +289,8 @@ fail_1:
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __init dbgp_bind(struct usb_gadget *gadget)
|
||||
static int __init dbgp_bind(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
int err, stp;
|
||||
|
||||
|
|
@ -402,9 +400,10 @@ fail:
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct usb_gadget_driver dbgp_driver = {
|
||||
static __refdata struct usb_gadget_driver dbgp_driver = {
|
||||
.function = "dbgp",
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = dbgp_bind,
|
||||
.unbind = dbgp_unbind,
|
||||
.setup = dbgp_setup,
|
||||
.disconnect = dbgp_disconnect,
|
||||
|
|
@ -416,7 +415,7 @@ static struct usb_gadget_driver dbgp_driver = {
|
|||
|
||||
static int __init dbgp_init(void)
|
||||
{
|
||||
return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind);
|
||||
return usb_gadget_probe_driver(&dbgp_driver);
|
||||
}
|
||||
|
||||
static void __exit dbgp_exit(void)
|
||||
|
|
|
|||
|
|
@ -909,6 +909,7 @@ static int dummy_udc_start(struct usb_gadget *g,
|
|||
dum->devstatus = 0;
|
||||
|
||||
dum->driver = driver;
|
||||
dum->gadget.dev.driver = &driver->driver;
|
||||
dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
|
||||
driver->driver.name);
|
||||
return 0;
|
||||
|
|
@ -923,6 +924,7 @@ static int dummy_udc_stop(struct usb_gadget *g,
|
|||
dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
|
||||
driver->driver.name);
|
||||
|
||||
dum->gadget.dev.driver = NULL;
|
||||
dum->driver = NULL;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
|
|
@ -22,17 +23,6 @@
|
|||
|
||||
#include "gadget_chips.h"
|
||||
|
||||
|
||||
/* we must assign addresses for configurable endpoints (like net2280) */
|
||||
static unsigned epnum;
|
||||
|
||||
// #define MANY_ENDPOINTS
|
||||
#ifdef MANY_ENDPOINTS
|
||||
/* more than 15 configurable endpoints */
|
||||
static unsigned in_epnum;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This should work with endpoints from controller drivers sharing the
|
||||
* same endpoint naming convention. By example:
|
||||
|
|
@ -176,16 +166,14 @@ ep_matches (
|
|||
if (isdigit (ep->name [2])) {
|
||||
u8 num = simple_strtoul (&ep->name [2], NULL, 10);
|
||||
desc->bEndpointAddress |= num;
|
||||
#ifdef MANY_ENDPOINTS
|
||||
} else if (desc->bEndpointAddress & USB_DIR_IN) {
|
||||
if (++in_epnum > 15)
|
||||
if (++gadget->in_epnum > 15)
|
||||
return 0;
|
||||
desc->bEndpointAddress = USB_DIR_IN | in_epnum;
|
||||
#endif
|
||||
desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
|
||||
} else {
|
||||
if (++epnum > 15)
|
||||
if (++gadget->out_epnum > 15)
|
||||
return 0;
|
||||
desc->bEndpointAddress |= epnum;
|
||||
desc->bEndpointAddress |= gadget->out_epnum;
|
||||
}
|
||||
|
||||
/* report (variable) full speed bulk maxpacket */
|
||||
|
|
@ -328,6 +316,7 @@ found_ep:
|
|||
ep->comp_desc = NULL;
|
||||
return ep;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
|
||||
|
||||
/**
|
||||
* usb_ep_autoconfig() - choose an endpoint matching the
|
||||
|
|
@ -367,7 +356,7 @@ struct usb_ep *usb_ep_autoconfig(
|
|||
{
|
||||
return usb_ep_autoconfig_ss(gadget, desc, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
|
||||
|
||||
/**
|
||||
* usb_ep_autoconfig_reset - reset endpoint autoconfig state
|
||||
|
|
@ -385,9 +374,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
|
|||
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
|
||||
ep->driver_data = NULL;
|
||||
}
|
||||
#ifdef MANY_ENDPOINTS
|
||||
in_epnum = 0;
|
||||
#endif
|
||||
epnum = 0;
|
||||
gadget->in_epnum = 0;
|
||||
gadget->out_epnum = 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
/* #define VERBOSE_DEBUG */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
|
||||
#if defined USB_ETH_RNDIS
|
||||
# undef USB_ETH_RNDIS
|
||||
|
|
@ -102,11 +100,6 @@ static inline bool has_rndis(void)
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_ecm.c"
|
||||
#include "f_subset.c"
|
||||
#ifdef USB_ETH_RNDIS
|
||||
|
|
@ -117,6 +110,7 @@ static inline bool has_rndis(void)
|
|||
#include "u_ether.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!
|
||||
* Instead: allocate your own, using normal USB-IF procedures.
|
||||
|
|
@ -195,17 +189,10 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = PREFIX DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -288,7 +275,6 @@ static struct usb_configuration eth_config_driver = {
|
|||
|
||||
static int __init eth_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
|
||||
|
|
@ -323,42 +309,15 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
|
|||
device_desc.bNumConfigurations = 2;
|
||||
}
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
else {
|
||||
/* We assume that can_support_ecm() tells the truth;
|
||||
* but if the controller isn't recognized at all then
|
||||
* that assumption is a bit more likely to be wrong.
|
||||
*/
|
||||
dev_warn(&gadget->dev,
|
||||
"controller '%s' not recognized; trying %s\n",
|
||||
gadget->name,
|
||||
eth_config_driver.label);
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
/* register our configuration(s); RNDIS first, if it's used */
|
||||
if (has_rndis()) {
|
||||
|
|
@ -372,6 +331,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
|
||||
DRIVER_DESC);
|
||||
|
||||
|
|
@ -388,11 +348,12 @@ static int __exit eth_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver eth_driver = {
|
||||
static __refdata struct usb_composite_driver eth_driver = {
|
||||
.name = "g_ether",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.bind = eth_bind,
|
||||
.unbind = __exit_p(eth_unbind),
|
||||
};
|
||||
|
||||
|
|
@ -402,7 +363,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(ð_driver, eth_bind);
|
||||
return usb_composite_probe(ð_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -897,10 +897,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
|
|||
return -ENOMEM;
|
||||
|
||||
/* export host's Ethernet address in CDC format */
|
||||
snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
|
||||
"%02X%02X%02X%02X%02X%02X",
|
||||
ethaddr[0], ethaddr[1], ethaddr[2],
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]);
|
||||
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
|
||||
ecm_string_defs[1].s = ecm->ethaddr;
|
||||
|
||||
ecm->port.cdc_filter = DEFAULT_FILTER;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/cdev.h>
|
||||
|
|
@ -18,6 +17,7 @@
|
|||
#include <linux/poll.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/usb/g_hid.h>
|
||||
|
||||
static int major, minors;
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
|
@ -349,7 +348,6 @@ struct fsg_config {
|
|||
|
||||
const char *vendor_name; /* 8 characters or less */
|
||||
const char *product_name; /* 16 characters or less */
|
||||
u16 release;
|
||||
|
||||
char can_stall;
|
||||
};
|
||||
|
|
@ -2773,18 +2771,7 @@ buffhds_first_it:
|
|||
bh->next = common->buffhds;
|
||||
|
||||
/* Prepare inquiryString */
|
||||
if (cfg->release != 0xffff) {
|
||||
i = cfg->release;
|
||||
} else {
|
||||
i = usb_gadget_controller_number(gadget);
|
||||
if (i >= 0) {
|
||||
i = 0x0300 + i;
|
||||
} else {
|
||||
WARNING(common, "controller '%s' not recognized\n",
|
||||
gadget->name);
|
||||
i = 0x0399;
|
||||
}
|
||||
}
|
||||
i = get_default_bcdDevice();
|
||||
snprintf(common->inquiry_string, sizeof common->inquiry_string,
|
||||
"%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
|
||||
/* Assume product name dependent on the first LUN */
|
||||
|
|
@ -3110,7 +3097,6 @@ fsg_config_from_params(struct fsg_config *cfg,
|
|||
/* Let MSF use defaults */
|
||||
cfg->vendor_name = 0;
|
||||
cfg->product_name = 0;
|
||||
cfg->release = 0xffff;
|
||||
|
||||
cfg->ops = NULL;
|
||||
cfg->private_data = NULL;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <sound/core.h>
|
||||
|
|
|
|||
|
|
@ -1346,10 +1346,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
|
|||
return -ENOMEM;
|
||||
|
||||
/* export host's Ethernet address in CDC format */
|
||||
snprintf(ncm->ethaddr, sizeof ncm->ethaddr,
|
||||
"%02X%02X%02X%02X%02X%02X",
|
||||
ethaddr[0], ethaddr[1], ethaddr[2],
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]);
|
||||
snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr);
|
||||
ncm_string_defs[1].s = ncm->ethaddr;
|
||||
|
||||
spin_lock_init(&ncm->lock);
|
||||
|
|
|
|||
|
|
@ -795,7 +795,7 @@ static int sourcesink_setup(struct usb_configuration *c,
|
|||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||
|
||||
req->length = USB_BUFSIZ;
|
||||
req->length = USB_COMP_EP0_BUFSIZ;
|
||||
|
||||
/* composite driver infrastructure handles everything except
|
||||
* the two control test requests.
|
||||
|
|
|
|||
|
|
@ -436,10 +436,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
|
|||
return -ENOMEM;
|
||||
|
||||
/* export host's Ethernet address in CDC format */
|
||||
snprintf(geth->ethaddr, sizeof geth->ethaddr,
|
||||
"%02X%02X%02X%02X%02X%02X",
|
||||
ethaddr[0], ethaddr[1], ethaddr[2],
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]);
|
||||
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
|
||||
geth_string_defs[1].s = geth->ethaddr;
|
||||
|
||||
geth->port.cdc_filter = DEFAULT_FILTER;
|
||||
|
|
|
|||
|
|
@ -463,7 +463,7 @@ snd_fail:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int __devexit snd_uac2_remove(struct platform_device *pdev)
|
||||
static int snd_uac2_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct snd_card *card = platform_get_drvdata(pdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -251,26 +251,12 @@
|
|||
#include <linux/freezer.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define DRIVER_DESC "File-backed Storage Gadget"
|
||||
#define DRIVER_NAME "g_file_storage"
|
||||
#define DRIVER_VERSION "1 September 2010"
|
||||
|
|
@ -3213,7 +3199,6 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
|
|||
static int __init check_parameters(struct fsg_dev *fsg)
|
||||
{
|
||||
int prot;
|
||||
int gcnum;
|
||||
|
||||
/* Store the default values */
|
||||
mod_data.transport_type = USB_PR_BULK;
|
||||
|
|
@ -3228,16 +3213,8 @@ static int __init check_parameters(struct fsg_dev *fsg)
|
|||
if (gadget_is_at91(fsg->gadget))
|
||||
mod_data.can_stall = 0;
|
||||
|
||||
if (mod_data.release == 0xffff) { // Parameter wasn't set
|
||||
gcnum = usb_gadget_controller_number(fsg->gadget);
|
||||
if (gcnum >= 0)
|
||||
mod_data.release = 0x0300 + gcnum;
|
||||
else {
|
||||
WARNING(fsg, "controller '%s' not recognized\n",
|
||||
fsg->gadget->name);
|
||||
mod_data.release = 0x0399;
|
||||
}
|
||||
}
|
||||
if (mod_data.release == 0xffff)
|
||||
mod_data.release = get_default_bcdDevice();
|
||||
|
||||
prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
|
||||
|
||||
|
|
@ -3331,7 +3308,8 @@ static int __init check_parameters(struct fsg_dev *fsg)
|
|||
}
|
||||
|
||||
|
||||
static int __init fsg_bind(struct usb_gadget *gadget)
|
||||
static int __init fsg_bind(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
struct fsg_dev *fsg = the_fsg;
|
||||
int rc;
|
||||
|
|
@ -3603,9 +3581,10 @@ static void fsg_resume(struct usb_gadget *gadget)
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_gadget_driver fsg_driver = {
|
||||
static __refdata struct usb_gadget_driver fsg_driver = {
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.function = (char *) fsg_string_product,
|
||||
.bind = fsg_bind,
|
||||
.unbind = fsg_unbind,
|
||||
.disconnect = fsg_disconnect,
|
||||
.setup = fsg_setup,
|
||||
|
|
@ -3653,7 +3632,8 @@ static int __init fsg_init(void)
|
|||
if ((rc = fsg_alloc()) != 0)
|
||||
return rc;
|
||||
fsg = the_fsg;
|
||||
if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0)
|
||||
rc = usb_gadget_probe_driver(&fsg_driver);
|
||||
if (rc != 0)
|
||||
kref_put(&fsg->ref, fsg_release);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1255,7 +1255,7 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
|
|||
}
|
||||
|
||||
static int fsl_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int fsl_stop(struct usb_gadget_driver *driver);
|
||||
/* defined in gadget.h */
|
||||
static struct usb_gadget_ops fsl_gadget_ops = {
|
||||
|
|
@ -1951,7 +1951,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc)
|
|||
* Called by initialization code of gadget drivers
|
||||
*----------------------------------------------------------------*/
|
||||
static int fsl_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
int retval = -ENODEV;
|
||||
unsigned long flags = 0;
|
||||
|
|
@ -1976,7 +1976,7 @@ static int fsl_start(struct usb_gadget_driver *driver,
|
|||
spin_unlock_irqrestore(&udc_controller->lock, flags);
|
||||
|
||||
/* bind udc driver to gadget driver */
|
||||
retval = bind(&udc_controller->gadget);
|
||||
retval = bind(&udc_controller->gadget, driver);
|
||||
if (retval) {
|
||||
VDBG("bind to %s --> %d", driver->driver.name, retval);
|
||||
udc_controller->gadget.dev.driver = NULL;
|
||||
|
|
|
|||
|
|
@ -1311,7 +1311,7 @@ static void init_controller(struct fusb300 *fusb300)
|
|||
static struct fusb300 *the_controller;
|
||||
|
||||
static int fusb300_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct fusb300 *fusb300 = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1339,7 +1339,7 @@ static int fusb300_udc_start(struct usb_gadget_driver *driver,
|
|||
goto error;
|
||||
}
|
||||
|
||||
retval = bind(&fusb300->gadget);
|
||||
retval = bind(&fusb300->gadget, driver);
|
||||
if (retval) {
|
||||
pr_err("bind to driver error (%d)\n", retval);
|
||||
device_del(&fusb300->gadget.dev);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#define pr_fmt(fmt) "g_ffs: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
/*
|
||||
* kbuild is not very cooperative with respect to linking separately
|
||||
|
|
@ -22,12 +21,6 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
# if defined USB_ETH_RNDIS
|
||||
# undef USB_ETH_RNDIS
|
||||
|
|
@ -76,6 +69,8 @@ struct gfs_ffs_obj {
|
|||
struct ffs_data *ffs_data;
|
||||
};
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct usb_device_descriptor gfs_dev_desc = {
|
||||
.bLength = sizeof gfs_dev_desc,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
|
|
@ -117,6 +112,9 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = {
|
|||
|
||||
/* String IDs are assigned dynamically */
|
||||
static struct usb_string gfs_strings[] = {
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
{ .s = "FunctionFS + RNDIS" },
|
||||
#endif
|
||||
|
|
@ -163,13 +161,13 @@ static int gfs_bind(struct usb_composite_dev *cdev);
|
|||
static int gfs_unbind(struct usb_composite_dev *cdev);
|
||||
static int gfs_do_config(struct usb_configuration *c);
|
||||
|
||||
static struct usb_composite_driver gfs_driver = {
|
||||
static __refdata struct usb_composite_driver gfs_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.dev = &gfs_dev_desc,
|
||||
.strings = gfs_dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = gfs_bind,
|
||||
.unbind = gfs_unbind,
|
||||
.iProduct = DRIVER_DESC,
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(gfs_lock);
|
||||
|
|
@ -268,7 +266,7 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
|
|||
}
|
||||
gfs_registered = true;
|
||||
|
||||
ret = usb_composite_probe(&gfs_driver, gfs_bind);
|
||||
ret = usb_composite_probe(&gfs_driver);
|
||||
if (unlikely(ret < 0))
|
||||
gfs_registered = false;
|
||||
|
||||
|
|
@ -357,6 +355,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
|||
ret = usb_string_ids_tab(cdev, gfs_strings);
|
||||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
for (i = func_num; --i; ) {
|
||||
ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
|
||||
|
|
@ -369,9 +368,10 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
|
||||
struct gfs_configuration *c = gfs_configurations + i;
|
||||
int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
|
||||
|
||||
c->c.label = gfs_strings[i].s;
|
||||
c->c.iConfiguration = gfs_strings[i].id;
|
||||
c->c.label = gfs_strings[sid].s;
|
||||
c->c.iConfiguration = gfs_strings[sid].id;
|
||||
c->c.bConfigurationValue = 1 + i;
|
||||
c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
|||
if (unlikely(ret < 0))
|
||||
goto error_unbind;
|
||||
}
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
return 0;
|
||||
|
||||
error_unbind:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#ifndef __GADGET_CHIPS_H
|
||||
#define __GADGET_CHIPS_H
|
||||
|
||||
#include <linux/usb/gadget.h>
|
||||
|
||||
/*
|
||||
* NOTICE: the entries below are alphabetical and should be kept
|
||||
* that way.
|
||||
|
|
@ -25,106 +27,12 @@
|
|||
* If you have forgotten the alphabetical order let VIM/EMACS
|
||||
* do that for you.
|
||||
*/
|
||||
#define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name))
|
||||
#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
|
||||
#define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name))
|
||||
#define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name))
|
||||
#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name))
|
||||
#define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name))
|
||||
#define gadget_is_dwc3(g) (!strcmp("dwc3-gadget", (g)->name))
|
||||
#define gadget_is_fsl_qe(g) (!strcmp("fsl_qe_udc", (g)->name))
|
||||
#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name))
|
||||
#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
|
||||
#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name))
|
||||
#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name))
|
||||
#define gadget_is_lpc32xx(g) (!strcmp("lpc32xx_udc", (g)->name))
|
||||
#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name))
|
||||
#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
|
||||
#define gadget_is_net2272(g) (!strcmp("net2272", (g)->name))
|
||||
#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
|
||||
#define gadget_is_omap(g) (!strcmp("omap_udc", (g)->name))
|
||||
#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name))
|
||||
#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
|
||||
#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
|
||||
#define gadget_is_r8a66597(g) (!strcmp("r8a66597_udc", (g)->name))
|
||||
#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
|
||||
#define gadget_is_s3c2410(g) (!strcmp("s3c2410_udc", (g)->name))
|
||||
#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name))
|
||||
#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name))
|
||||
|
||||
/**
|
||||
* usb_gadget_controller_number - support bcdDevice id convention
|
||||
* @gadget: the controller being driven
|
||||
*
|
||||
* Return a 2-digit BCD value associated with the peripheral controller,
|
||||
* suitable for use as part of a bcdDevice value, or a negative error code.
|
||||
*
|
||||
* NOTE: this convention is purely optional, and has no meaning in terms of
|
||||
* any USB specification. If you want to use a different convention in your
|
||||
* gadget driver firmware -- maybe a more formal revision ID -- feel free.
|
||||
*
|
||||
* Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
|
||||
* to change their behavior accordingly. For example it might help avoiding
|
||||
* some chip bug.
|
||||
*/
|
||||
static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
|
||||
{
|
||||
if (gadget_is_net2280(gadget))
|
||||
return 0x01;
|
||||
else if (gadget_is_dummy(gadget))
|
||||
return 0x02;
|
||||
else if (gadget_is_pxa(gadget))
|
||||
return 0x03;
|
||||
else if (gadget_is_goku(gadget))
|
||||
return 0x06;
|
||||
else if (gadget_is_omap(gadget))
|
||||
return 0x08;
|
||||
else if (gadget_is_pxa27x(gadget))
|
||||
return 0x11;
|
||||
else if (gadget_is_s3c2410(gadget))
|
||||
return 0x12;
|
||||
else if (gadget_is_at91(gadget))
|
||||
return 0x13;
|
||||
else if (gadget_is_imx(gadget))
|
||||
return 0x14;
|
||||
else if (gadget_is_musbhdrc(gadget))
|
||||
return 0x16;
|
||||
else if (gadget_is_atmel_usba(gadget))
|
||||
return 0x18;
|
||||
else if (gadget_is_fsl_usb2(gadget))
|
||||
return 0x19;
|
||||
else if (gadget_is_amd5536udc(gadget))
|
||||
return 0x20;
|
||||
else if (gadget_is_m66592(gadget))
|
||||
return 0x21;
|
||||
else if (gadget_is_fsl_qe(gadget))
|
||||
return 0x22;
|
||||
else if (gadget_is_ci13xxx_pci(gadget))
|
||||
return 0x23;
|
||||
else if (gadget_is_langwell(gadget))
|
||||
return 0x24;
|
||||
else if (gadget_is_r8a66597(gadget))
|
||||
return 0x25;
|
||||
else if (gadget_is_s3c_hsotg(gadget))
|
||||
return 0x26;
|
||||
else if (gadget_is_pch(gadget))
|
||||
return 0x27;
|
||||
else if (gadget_is_ci13xxx_msm(gadget))
|
||||
return 0x28;
|
||||
else if (gadget_is_renesas_usbhs(gadget))
|
||||
return 0x29;
|
||||
else if (gadget_is_s3c_hsudc(gadget))
|
||||
return 0x30;
|
||||
else if (gadget_is_net2272(gadget))
|
||||
return 0x31;
|
||||
else if (gadget_is_dwc3(gadget))
|
||||
return 0x32;
|
||||
else if (gadget_is_lpc32xx(gadget))
|
||||
return 0x33;
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gadget_supports_altsettings - return true if altsettings work
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
|
|
@ -31,16 +30,13 @@
|
|||
#include <sound/rawmidi.h>
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/audio.h>
|
||||
#include <linux/usb/midi.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
#include "f_midi.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
|
@ -51,6 +47,8 @@ MODULE_LICENSE("GPL v2");
|
|||
static const char shortname[] = "g_midi";
|
||||
static const char longname[] = "MIDI Gadget";
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static int index = SNDRV_DEFAULT_IDX1;
|
||||
module_param(index, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter.");
|
||||
|
|
@ -85,9 +83,7 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
|
|||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_DESCRIPTION_IDX 2
|
||||
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = USB_DT_DEVICE_SIZE,
|
||||
|
|
@ -102,8 +98,9 @@ static struct usb_device_descriptor device_desc = {
|
|||
};
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = "Grey Innovation",
|
||||
[STRING_PRODUCT_IDX].s = "MIDI Gadget",
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "Grey Innovation",
|
||||
[USB_GADGET_PRODUCT_IDX].s = "MIDI Gadget",
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
[STRING_DESCRIPTION_IDX].s = "MIDI",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
|
@ -140,61 +137,35 @@ static int __init midi_bind_config(struct usb_configuration *c)
|
|||
|
||||
static int __init midi_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int gcnum, status;
|
||||
int status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
|
||||
/* config description */
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
strings_dev[STRING_DESCRIPTION_IDX].id = status;
|
||||
|
||||
midi_config.iConfiguration = status;
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum < 0) {
|
||||
/* gmidi is so simple (no altsettings) that
|
||||
* it SHOULD NOT have problems with bulk-capable hardware.
|
||||
* so warn about unrecognized controllers, don't panic.
|
||||
*/
|
||||
pr_warning("%s: controller '%s' not recognized\n",
|
||||
__func__, gadget->name);
|
||||
device_desc.bcdDevice = cpu_to_le16(0x9999);
|
||||
} else {
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
|
||||
}
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id;
|
||||
|
||||
status = usb_add_config(cdev, &midi_config, midi_bind_config);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
pr_info("%s\n", longname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver midi_driver = {
|
||||
static __refdata struct usb_composite_driver midi_driver = {
|
||||
.name = (char *) longname,
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = midi_bind,
|
||||
.unbind = __exit_p(midi_unbind),
|
||||
};
|
||||
|
||||
static int __init midi_init(void)
|
||||
{
|
||||
return usb_composite_probe(&midi_driver, midi_bind);
|
||||
return usb_composite_probe(&midi_driver);
|
||||
}
|
||||
module_init(midi_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -994,7 +994,7 @@ static int goku_get_frame(struct usb_gadget *_gadget)
|
|||
}
|
||||
|
||||
static int goku_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int goku_stop(struct usb_gadget_driver *driver);
|
||||
|
||||
static const struct usb_gadget_ops goku_ops = {
|
||||
|
|
@ -1348,7 +1348,7 @@ static struct goku_udc *the_controller;
|
|||
* the driver might get unbound.
|
||||
*/
|
||||
static int goku_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct goku_udc *dev = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1368,7 +1368,7 @@ static int goku_start(struct usb_gadget_driver *driver,
|
|||
driver->driver.bus = NULL;
|
||||
dev->driver = driver;
|
||||
dev->gadget.dev.driver = &driver->driver;
|
||||
retval = bind(&dev->gadget);
|
||||
retval = bind(&dev->gadget, driver);
|
||||
if (retval) {
|
||||
DBG(dev, "bind to driver %s --> error %d\n",
|
||||
driver->driver.name, retval);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
#define DRIVER_DESC "HID Gadget"
|
||||
#define DRIVER_VERSION "2010/03/16"
|
||||
|
||||
|
|
@ -33,12 +36,6 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_hid.c"
|
||||
|
||||
|
||||
|
|
@ -50,6 +47,7 @@ struct hidg_func_node {
|
|||
static LIST_HEAD(hidg_func_list);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
|
|
@ -92,15 +90,10 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -150,7 +143,7 @@ static int __init hid_bind(struct usb_composite_dev *cdev)
|
|||
{
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
struct list_head *tmp;
|
||||
int status, gcnum, funcs = 0;
|
||||
int status, funcs = 0;
|
||||
|
||||
list_for_each(tmp, &hidg_func_list)
|
||||
funcs++;
|
||||
|
|
@ -163,38 +156,22 @@ static int __init hid_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
return status;
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
else
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
|
||||
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
/* register our configuration */
|
||||
status = usb_add_config(cdev, &config_driver, do_config);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -242,11 +219,12 @@ static int __devexit hidg_plat_driver_remove(struct platform_device *pdev)
|
|||
/****************************** Some noise ******************************/
|
||||
|
||||
|
||||
static struct usb_composite_driver hidg_driver = {
|
||||
static __refdata struct usb_composite_driver hidg_driver = {
|
||||
.name = "g_hid",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = hid_bind,
|
||||
.unbind = __exit_p(hid_unbind),
|
||||
};
|
||||
|
||||
|
|
@ -272,7 +250,7 @@ static int __init hidg_init(void)
|
|||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = usb_composite_probe(&hidg_driver, hid_bind);
|
||||
status = usb_composite_probe(&hidg_driver);
|
||||
if (status < 0)
|
||||
platform_driver_unregister(&hidg_plat_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -828,7 +828,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
if (value == 0)
|
||||
data->state = STATE_EP_ENABLED;
|
||||
break;
|
||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||
case USB_SPEED_HIGH:
|
||||
/* fails if caller didn't provide that descriptor... */
|
||||
ep->desc = &data->hs_desc;
|
||||
|
|
@ -836,7 +835,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
if (value == 0)
|
||||
data->state = STATE_EP_ENABLED;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
DBG(data->dev, "unconnected, %s init abandoned\n",
|
||||
data->name);
|
||||
|
|
@ -1324,7 +1322,6 @@ static const struct file_operations ep0_io_operations = {
|
|||
* Unrecognized ep0 requests may be handled in user space.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||
static void make_qualifier (struct dev_data *dev)
|
||||
{
|
||||
struct usb_qualifier_descriptor qual;
|
||||
|
|
@ -1347,7 +1344,6 @@ static void make_qualifier (struct dev_data *dev)
|
|||
|
||||
memcpy (dev->rbuf, &qual, sizeof qual);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
config_buf (struct dev_data *dev, u8 type, unsigned index)
|
||||
|
|
@ -1427,7 +1423,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
dev->dev->bMaxPacketSize0 = dev->gadget->ep0->maxpacket;
|
||||
req->buf = dev->dev;
|
||||
break;
|
||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||
case USB_DT_DEVICE_QUALIFIER:
|
||||
if (!dev->hs_config)
|
||||
break;
|
||||
|
|
@ -1437,7 +1432,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|||
break;
|
||||
case USB_DT_OTHER_SPEED_CONFIG:
|
||||
// FALLTHROUGH
|
||||
#endif
|
||||
case USB_DT_CONFIG:
|
||||
value = config_buf (dev,
|
||||
w_value >> 8,
|
||||
|
|
@ -1685,8 +1679,8 @@ gadgetfs_unbind (struct usb_gadget *gadget)
|
|||
|
||||
static struct dev_data *the_device;
|
||||
|
||||
static int
|
||||
gadgetfs_bind (struct usb_gadget *gadget)
|
||||
static int gadgetfs_bind(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
struct dev_data *dev = the_device;
|
||||
|
||||
|
|
@ -1763,12 +1757,8 @@ gadgetfs_suspend (struct usb_gadget *gadget)
|
|||
}
|
||||
|
||||
static struct usb_gadget_driver gadgetfs_driver = {
|
||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
#else
|
||||
.max_speed = USB_SPEED_FULL,
|
||||
#endif
|
||||
.function = (char *) driver_desc,
|
||||
.bind = gadgetfs_bind,
|
||||
.unbind = gadgetfs_unbind,
|
||||
.setup = gadgetfs_setup,
|
||||
.disconnect = gadgetfs_disconnect,
|
||||
|
|
@ -1783,7 +1773,8 @@ static struct usb_gadget_driver gadgetfs_driver = {
|
|||
|
||||
static void gadgetfs_nop(struct usb_gadget *arg) { }
|
||||
|
||||
static int gadgetfs_probe (struct usb_gadget *gadget)
|
||||
static int gadgetfs_probe(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
CHIP = gadget->name;
|
||||
return -EISNAM;
|
||||
|
|
@ -1791,6 +1782,7 @@ static int gadgetfs_probe (struct usb_gadget *gadget)
|
|||
|
||||
static struct usb_gadget_driver probe_driver = {
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = gadgetfs_probe,
|
||||
.unbind = gadgetfs_nop,
|
||||
.setup = (void *)gadgetfs_nop,
|
||||
.disconnect = gadgetfs_nop,
|
||||
|
|
@ -1900,7 +1892,12 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|||
|
||||
/* triggers gadgetfs_bind(); then we can enumerate. */
|
||||
spin_unlock_irq (&dev->lock);
|
||||
value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind);
|
||||
if (dev->hs_config)
|
||||
gadgetfs_driver.max_speed = USB_SPEED_HIGH;
|
||||
else
|
||||
gadgetfs_driver.max_speed = USB_SPEED_FULL;
|
||||
|
||||
value = usb_gadget_probe_driver(&gadgetfs_driver);
|
||||
if (value != 0) {
|
||||
kfree (dev->buf);
|
||||
dev->buf = NULL;
|
||||
|
|
@ -2039,7 +2036,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
|
|||
return -ESRCH;
|
||||
|
||||
/* fake probe to determine $CHIP */
|
||||
(void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe);
|
||||
usb_gadget_probe_driver(&probe_driver);
|
||||
if (!CHIP)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
|||
|
|
@ -141,8 +141,6 @@ struct lpc32xx_ep {
|
|||
u32 totalints;
|
||||
|
||||
bool wedge;
|
||||
|
||||
const struct usb_endpoint_descriptor *desc;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -556,10 +554,8 @@ static int proc_udc_show(struct seq_file *s, void *unused)
|
|||
|
||||
if (udc->enabled && udc->vbus) {
|
||||
proc_ep_show(s, &udc->ep[0]);
|
||||
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {
|
||||
if (ep->desc)
|
||||
proc_ep_show(s, ep);
|
||||
}
|
||||
list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list)
|
||||
proc_ep_show(s, ep);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
|
|
@ -1453,7 +1449,6 @@ static void udc_reinit(struct lpc32xx_udc *udc)
|
|||
|
||||
if (i != 0)
|
||||
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
|
||||
ep->desc = NULL;
|
||||
ep->ep.maxpacket = ep->maxpacket;
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
ep->req_pending = 0;
|
||||
|
|
@ -1515,7 +1510,7 @@ static void nuke(struct lpc32xx_ep *ep, int status)
|
|||
done(ep, req, status);
|
||||
}
|
||||
|
||||
if (ep->desc && status == -ESHUTDOWN) {
|
||||
if (status == -ESHUTDOWN) {
|
||||
uda_disable_hwepint(ep->udc, ep->hwep_num);
|
||||
udc_disable_hwep(ep->udc, ep->hwep_num);
|
||||
}
|
||||
|
|
@ -1658,9 +1653,6 @@ static int lpc32xx_ep_disable(struct usb_ep *_ep)
|
|||
|
||||
nuke(ep, -ESHUTDOWN);
|
||||
|
||||
/* restore the endpoint's pristine config */
|
||||
ep->desc = NULL;
|
||||
|
||||
/* Clear all DMA statuses for this EP */
|
||||
udc_ep_dma_disable(udc, ep->hwep_num);
|
||||
writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr));
|
||||
|
|
@ -1696,7 +1688,7 @@ static int lpc32xx_ep_enable(struct usb_ep *_ep,
|
|||
unsigned long flags;
|
||||
|
||||
/* Verify EP data */
|
||||
if ((!_ep) || (!ep) || (!desc) || (ep->desc) ||
|
||||
if ((!_ep) || (!ep) || (!desc) ||
|
||||
(desc->bDescriptorType != USB_DT_ENDPOINT)) {
|
||||
dev_dbg(udc->dev, "bad ep or descriptor\n");
|
||||
return -EINVAL;
|
||||
|
|
@ -1754,7 +1746,6 @@ static int lpc32xx_ep_enable(struct usb_ep *_ep,
|
|||
|
||||
/* Initialize endpoint to match the selected descriptor */
|
||||
ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
|
||||
ep->desc = desc;
|
||||
ep->ep.maxpacket = maxpacket;
|
||||
|
||||
/* Map hardware endpoint from base and direction */
|
||||
|
|
@ -1837,7 +1828,7 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
|
|||
|
||||
udc = ep->udc;
|
||||
|
||||
if (!_ep || (!ep->desc && ep->hwep_num_base != 0)) {
|
||||
if (!_ep) {
|
||||
dev_dbg(udc->dev, "invalid ep\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1976,7 +1967,7 @@ static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value)
|
|||
struct lpc32xx_udc *udc = ep->udc;
|
||||
unsigned long flags;
|
||||
|
||||
if ((!ep) || (ep->desc == NULL) || (ep->hwep_num <= 1))
|
||||
if ((!ep) || (ep->hwep_num <= 1))
|
||||
return -EINVAL;
|
||||
|
||||
/* Don't halt an IN EP */
|
||||
|
|
@ -2262,7 +2253,7 @@ static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex)
|
|||
case USB_RECIP_ENDPOINT:
|
||||
tmp = wIndex & USB_ENDPOINT_NUMBER_MASK;
|
||||
ep = &udc->ep[tmp];
|
||||
if ((tmp == 0) || (tmp >= NUM_ENDPOINTS) || (tmp && !ep->desc))
|
||||
if ((tmp == 0) || (tmp >= NUM_ENDPOINTS))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wIndex & USB_DIR_IN) {
|
||||
|
|
@ -2599,9 +2590,8 @@ static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lpc32xx_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
static int lpc32xx_stop(struct usb_gadget_driver *driver);
|
||||
static int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *);
|
||||
static int lpc32xx_stop(struct usb_gadget *, struct usb_gadget_driver *);
|
||||
|
||||
static const struct usb_gadget_ops lpc32xx_udc_ops = {
|
||||
.get_frame = lpc32xx_get_frame,
|
||||
|
|
@ -2609,8 +2599,8 @@ static const struct usb_gadget_ops lpc32xx_udc_ops = {
|
|||
.set_selfpowered = lpc32xx_set_selfpowered,
|
||||
.vbus_session = lpc32xx_vbus_session,
|
||||
.pullup = lpc32xx_pullup,
|
||||
.start = lpc32xx_start,
|
||||
.stop = lpc32xx_stop,
|
||||
.udc_start = lpc32xx_start,
|
||||
.udc_stop = lpc32xx_stop,
|
||||
};
|
||||
|
||||
static void nop_release(struct device *dev)
|
||||
|
|
@ -2618,10 +2608,9 @@ static void nop_release(struct device *dev)
|
|||
/* nothing to free */
|
||||
}
|
||||
|
||||
static struct lpc32xx_udc controller = {
|
||||
static const struct lpc32xx_udc controller_template = {
|
||||
.gadget = {
|
||||
.ops = &lpc32xx_udc_ops,
|
||||
.ep0 = &controller.ep[0].ep,
|
||||
.name = driver_name,
|
||||
.dev = {
|
||||
.init_name = "gadget",
|
||||
|
|
@ -2633,7 +2622,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep0",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 0,
|
||||
.hwep_num = 0, /* Can be 0 or 1, has special handling */
|
||||
|
|
@ -2645,7 +2633,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep1-int",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 2,
|
||||
.hwep_num = 0, /* 2 or 3, will be set later */
|
||||
|
|
@ -2657,7 +2644,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep2-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 4,
|
||||
.hwep_num = 0, /* 4 or 5, will be set later */
|
||||
|
|
@ -2669,7 +2655,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep3-iso",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 1023,
|
||||
.hwep_num_base = 6,
|
||||
.hwep_num = 0, /* 6 or 7, will be set later */
|
||||
|
|
@ -2681,7 +2666,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep4-int",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 8,
|
||||
.hwep_num = 0, /* 8 or 9, will be set later */
|
||||
|
|
@ -2693,7 +2677,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep5-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 10,
|
||||
.hwep_num = 0, /* 10 or 11, will be set later */
|
||||
|
|
@ -2705,7 +2688,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep6-iso",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 1023,
|
||||
.hwep_num_base = 12,
|
||||
.hwep_num = 0, /* 12 or 13, will be set later */
|
||||
|
|
@ -2717,7 +2699,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep7-int",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 14,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2729,7 +2710,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep8-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 16,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2741,7 +2721,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep9-iso",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 1023,
|
||||
.hwep_num_base = 18,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2753,7 +2732,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep10-int",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 20,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2765,7 +2743,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep11-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 22,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2777,7 +2754,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep12-iso",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 1023,
|
||||
.hwep_num_base = 24,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2789,7 +2765,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep13-int",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 26,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2801,7 +2776,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep14-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 64,
|
||||
.hwep_num_base = 28,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2813,7 +2787,6 @@ static struct lpc32xx_udc controller = {
|
|||
.name = "ep15-bulk",
|
||||
.ops = &lpc32xx_ep_ops,
|
||||
},
|
||||
.udc = &controller,
|
||||
.maxpacket = 1023,
|
||||
.hwep_num_base = 30,
|
||||
.hwep_num = 0,
|
||||
|
|
@ -2987,14 +2960,13 @@ static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int lpc32xx_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
static int lpc32xx_start(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
struct lpc32xx_udc *udc = &controller;
|
||||
int retval, i;
|
||||
struct lpc32xx_udc *udc = to_udc(gadget);
|
||||
int i;
|
||||
|
||||
if (!driver || driver->max_speed < USB_SPEED_FULL ||
|
||||
!bind || !driver->setup) {
|
||||
if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) {
|
||||
dev_err(udc->dev, "bad parameter.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -3011,18 +2983,6 @@ static int lpc32xx_start(struct usb_gadget_driver *driver,
|
|||
udc->selfpowered = 1;
|
||||
udc->vbus = 0;
|
||||
|
||||
retval = bind(&udc->gadget);
|
||||
if (retval) {
|
||||
dev_err(udc->dev, "bind() returned %d\n", retval);
|
||||
udc->enabled = 0;
|
||||
udc->selfpowered = 0;
|
||||
udc->driver = NULL;
|
||||
udc->gadget.dev.driver = NULL;
|
||||
return retval;
|
||||
}
|
||||
|
||||
dev_dbg(udc->dev, "bound to %s\n", driver->driver.name);
|
||||
|
||||
/* Force VBUS process once to check for cable insertion */
|
||||
udc->last_vbus = udc->vbus = 0;
|
||||
schedule_work(&udc->vbus_job);
|
||||
|
|
@ -3034,22 +2994,19 @@ static int lpc32xx_start(struct usb_gadget_driver *driver,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lpc32xx_stop(struct usb_gadget_driver *driver)
|
||||
static int lpc32xx_stop(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver)
|
||||
{
|
||||
int i;
|
||||
struct lpc32xx_udc *udc = &controller;
|
||||
struct lpc32xx_udc *udc = to_udc(gadget);
|
||||
|
||||
if (!driver || driver != udc->driver || !driver->unbind)
|
||||
if (!driver || driver != udc->driver)
|
||||
return -EINVAL;
|
||||
|
||||
/* Disable USB pullup */
|
||||
isp1301_pullup_enable(udc, 0, 1);
|
||||
|
||||
for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++)
|
||||
disable_irq(udc->udp_irq[i]);
|
||||
|
||||
if (udc->clocked) {
|
||||
|
||||
spin_lock(&udc->lock);
|
||||
stop_activity(udc);
|
||||
spin_unlock(&udc->lock);
|
||||
|
|
@ -3069,20 +3026,16 @@ static int lpc32xx_stop(struct usb_gadget_driver *driver)
|
|||
}
|
||||
|
||||
udc->enabled = 0;
|
||||
pullup(udc, 0);
|
||||
|
||||
driver->unbind(&udc->gadget);
|
||||
udc->gadget.dev.driver = NULL;
|
||||
udc->driver = NULL;
|
||||
|
||||
dev_dbg(udc->dev, "unbound from %s\n", driver->driver.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpc32xx_udc_shutdown(struct platform_device *dev)
|
||||
{
|
||||
/* Force disconnect on reboot */
|
||||
struct lpc32xx_udc *udc = &controller;
|
||||
struct lpc32xx_udc *udc = platform_get_drvdata(dev);
|
||||
|
||||
pullup(udc, 0);
|
||||
}
|
||||
|
|
@ -3120,12 +3073,21 @@ static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F;
|
|||
static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct lpc32xx_udc *udc = &controller;
|
||||
struct lpc32xx_udc *udc;
|
||||
int retval, i;
|
||||
struct resource *res;
|
||||
dma_addr_t dma_handle;
|
||||
struct device_node *isp1301_node;
|
||||
|
||||
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
|
||||
if (!udc)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(udc, &controller_template, sizeof(*udc));
|
||||
for (i = 0; i <= 15; i++)
|
||||
udc->ep[i].udc = udc;
|
||||
udc->gadget.ep0 = &udc->ep[0].ep;
|
||||
|
||||
/* init software state */
|
||||
udc->gadget.dev.parent = dev;
|
||||
udc->pdev = pdev;
|
||||
|
|
@ -3140,8 +3102,10 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
udc->isp1301_i2c_client = isp1301_get_client(isp1301_node);
|
||||
if (!udc->isp1301_i2c_client)
|
||||
return -EPROBE_DEFER;
|
||||
if (!udc->isp1301_i2c_client) {
|
||||
retval = -EPROBE_DEFER;
|
||||
goto phy_fail;
|
||||
}
|
||||
|
||||
dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n",
|
||||
udc->isp1301_i2c_client->addr);
|
||||
|
|
@ -3160,8 +3124,10 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
|||
* IORESOURCE_IRQ, USB transceiver interrupt number
|
||||
*/
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENXIO;
|
||||
if (!res) {
|
||||
retval = -ENXIO;
|
||||
goto resource_fail;
|
||||
}
|
||||
|
||||
spin_lock_init(&udc->lock);
|
||||
|
||||
|
|
@ -3171,7 +3137,8 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
|||
if (udc->udp_irq[i] < 0) {
|
||||
dev_err(udc->dev,
|
||||
"irq resource %d not available!\n", i);
|
||||
return udc->udp_irq[i];
|
||||
retval = udc->udp_irq[i];
|
||||
goto irq_fail;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3179,7 +3146,8 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
|||
udc->io_p_size = resource_size(res);
|
||||
if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) {
|
||||
dev_err(udc->dev, "someone's using UDC memory\n");
|
||||
return -EBUSY;
|
||||
retval = -EBUSY;
|
||||
goto request_mem_region_fail;
|
||||
}
|
||||
|
||||
udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size);
|
||||
|
|
@ -3208,7 +3176,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
|
|||
udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg");
|
||||
if (IS_ERR(udc->usb_otg_clk)) {
|
||||
dev_err(udc->dev, "failed to acquire USB otg clock\n");
|
||||
retval = PTR_ERR(udc->usb_slv_clk);
|
||||
retval = PTR_ERR(udc->usb_otg_clk);
|
||||
goto usb_otg_clk_get_fail;
|
||||
}
|
||||
|
||||
|
|
@ -3376,7 +3344,11 @@ pll_get_fail:
|
|||
io_map_fail:
|
||||
release_mem_region(udc->io_p_start, udc->io_p_size);
|
||||
dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval);
|
||||
|
||||
request_mem_region_fail:
|
||||
irq_fail:
|
||||
resource_fail:
|
||||
phy_fail:
|
||||
kfree(udc);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -3414,6 +3386,7 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev)
|
|||
clk_put(udc->usb_pll_clk);
|
||||
iounmap(udc->udp_baseaddr);
|
||||
release_mem_region(udc->io_p_start, udc->io_p_size);
|
||||
kfree(udc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1466,7 +1466,7 @@ static struct usb_ep_ops m66592_ep_ops = {
|
|||
static struct m66592 *the_controller;
|
||||
|
||||
static int m66592_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct m66592 *m66592 = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1492,7 +1492,7 @@ static int m66592_start(struct usb_gadget_driver *driver,
|
|||
goto error;
|
||||
}
|
||||
|
||||
retval = bind(&m66592->gadget);
|
||||
retval = bind(&m66592->gadget, driver);
|
||||
if (retval) {
|
||||
pr_err("bind to driver error (%d)\n", retval);
|
||||
device_del(&m66592->gadget.dev);
|
||||
|
|
|
|||
|
|
@ -29,9 +29,8 @@
|
|||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
|
@ -47,14 +46,10 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
#include "f_mass_storage.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct usb_device_descriptor msg_device_desc = {
|
||||
.bLength = sizeof msg_device_desc,
|
||||
|
|
@ -85,6 +80,22 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings stringtab_dev = {
|
||||
.language = 0x0409, /* en-us */
|
||||
.strings = strings_dev,
|
||||
};
|
||||
|
||||
static struct usb_gadget_strings *dev_strings[] = {
|
||||
&stringtab_dev,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/****************************** Configurations ******************************/
|
||||
|
||||
|
|
@ -143,10 +154,15 @@ static int __init msg_bind(struct usb_composite_dev *cdev)
|
|||
{
|
||||
int status;
|
||||
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&cdev->gadget->dev,
|
||||
DRIVER_DESC ", version: " DRIVER_VERSION "\n");
|
||||
set_bit(0, &msg_registered);
|
||||
|
|
@ -156,12 +172,13 @@ static int __init msg_bind(struct usb_composite_dev *cdev)
|
|||
|
||||
/****************************** Some noise ******************************/
|
||||
|
||||
static struct usb_composite_driver msg_driver = {
|
||||
static __refdata struct usb_composite_driver msg_driver = {
|
||||
.name = "g_mass_storage",
|
||||
.dev = &msg_device_desc,
|
||||
.iProduct = DRIVER_DESC,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.needs_serial = 1,
|
||||
.strings = dev_strings,
|
||||
.bind = msg_bind,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
|
@ -170,7 +187,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init msg_init(void)
|
||||
{
|
||||
return usb_composite_probe(&msg_driver, msg_bind);
|
||||
return usb_composite_probe(&msg_driver);
|
||||
}
|
||||
module_init(msg_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@
|
|||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
|
||||
#if defined USB_ETH_RNDIS
|
||||
# undef USB_ETH_RNDIS
|
||||
#endif
|
||||
|
|
@ -42,12 +40,6 @@ MODULE_LICENSE("GPL");
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_mass_storage.c"
|
||||
|
||||
#include "u_serial.c"
|
||||
|
|
@ -61,7 +53,7 @@ MODULE_LICENSE("GPL");
|
|||
#endif
|
||||
#include "u_ether.c"
|
||||
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
/***************************** Device Descriptor ****************************/
|
||||
|
||||
|
|
@ -112,21 +104,16 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
|
||||
|
||||
enum {
|
||||
#ifdef CONFIG_USB_G_MULTI_RNDIS
|
||||
MULTI_STRING_RNDIS_CONFIG_IDX,
|
||||
#endif
|
||||
#ifdef CONFIG_USB_G_MULTI_CDC
|
||||
MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
|
||||
MULTI_STRING_CDC_CONFIG_IDX,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
#ifdef CONFIG_USB_G_MULTI_RNDIS
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
[MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
|
||||
#endif
|
||||
#ifdef CONFIG_USB_G_MULTI_CDC
|
||||
[MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM",
|
||||
#endif
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -260,7 +247,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
|
|||
static int __ref multi_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status, gcnum;
|
||||
int status;
|
||||
|
||||
if (!can_support_ecm(cdev->gadget)) {
|
||||
dev_err(&gadget->dev, "controller '%s' not usable\n",
|
||||
|
|
@ -288,19 +275,11 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* set bcdDevice */
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0) {
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
} else {
|
||||
WARNING(cdev, "controller '%s' not recognized\n", gadget->name);
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
/* allocate string IDs */
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (unlikely(status < 0))
|
||||
goto fail2;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
/* register configurations */
|
||||
status = rndis_config_register(cdev);
|
||||
|
|
@ -310,6 +289,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
|
|||
status = cdc_config_register(cdev);
|
||||
if (unlikely(status < 0))
|
||||
goto fail2;
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
|
||||
/* we're done */
|
||||
dev_info(&gadget->dev, DRIVER_DESC "\n");
|
||||
|
|
@ -338,20 +318,20 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
|
|||
/****************************** Some noise ******************************/
|
||||
|
||||
|
||||
static struct usb_composite_driver multi_driver = {
|
||||
static __refdata struct usb_composite_driver multi_driver = {
|
||||
.name = "g_multi",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = multi_bind,
|
||||
.unbind = __exit_p(multi_unbind),
|
||||
.iProduct = DRIVER_DESC,
|
||||
.needs_serial = 1,
|
||||
};
|
||||
|
||||
|
||||
static int __init multi_init(void)
|
||||
{
|
||||
return usb_composite_probe(&multi_driver, multi_bind);
|
||||
return usb_composite_probe(&multi_driver);
|
||||
}
|
||||
module_init(multi_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@
|
|||
#define EPSTATUS_TIMEOUT 10000
|
||||
#define PRIME_TIMEOUT 10000
|
||||
#define READSAFE_TIMEOUT 1000
|
||||
#define DTD_TIMEOUT 1000
|
||||
|
||||
#define LOOPS_USEC_SHIFT 4
|
||||
#define LOOPS_USEC_SHIFT 1
|
||||
#define LOOPS_USEC (1 << LOOPS_USEC_SHIFT)
|
||||
#define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT)
|
||||
|
||||
|
|
@ -64,7 +63,6 @@ static const char driver_desc[] = DRIVER_DESC;
|
|||
|
||||
/* controller device global variable */
|
||||
static struct mv_udc *the_controller;
|
||||
int mv_usb_otgsc;
|
||||
|
||||
static void nuke(struct mv_ep *ep, int status);
|
||||
static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver);
|
||||
|
|
@ -357,17 +355,24 @@ done:
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
|
||||
dma_addr_t *dma, int *is_last)
|
||||
{
|
||||
u32 temp;
|
||||
struct mv_dtd *dtd;
|
||||
struct mv_udc *udc;
|
||||
struct mv_dqh *dqh;
|
||||
u32 temp, mult = 0;
|
||||
|
||||
/* how big will this transfer be? */
|
||||
*length = min(req->req.length - req->req.actual,
|
||||
(unsigned)EP_MAX_LENGTH_TRANSFER);
|
||||
if (usb_endpoint_xfer_isoc(req->ep->ep.desc)) {
|
||||
dqh = req->ep->dqh;
|
||||
mult = (dqh->max_packet_length >> EP_QUEUE_HEAD_MULT_POS)
|
||||
& 0x3;
|
||||
*length = min(req->req.length - req->req.actual,
|
||||
(unsigned)(mult * req->ep->ep.maxpacket));
|
||||
} else
|
||||
*length = min(req->req.length - req->req.actual,
|
||||
(unsigned)EP_MAX_LENGTH_TRANSFER);
|
||||
|
||||
udc = req->ep->udc;
|
||||
|
||||
|
|
@ -375,7 +380,7 @@ static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
|
|||
* Be careful that no _GFP_HIGHMEM is set,
|
||||
* or we can not use dma_to_virt
|
||||
*/
|
||||
dtd = dma_pool_alloc(udc->dtd_pool, GFP_KERNEL, dma);
|
||||
dtd = dma_pool_alloc(udc->dtd_pool, GFP_ATOMIC, dma);
|
||||
if (dtd == NULL)
|
||||
return dtd;
|
||||
|
||||
|
|
@ -409,6 +414,8 @@ static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length,
|
|||
if (*is_last && !req->req.no_interrupt)
|
||||
temp |= DTD_IOC;
|
||||
|
||||
temp |= mult << 10;
|
||||
|
||||
dtd->size_ioc_sts = temp;
|
||||
|
||||
mb();
|
||||
|
|
@ -708,6 +715,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
|||
struct mv_req *req = container_of(_req, struct mv_req, req);
|
||||
struct mv_udc *udc = ep->udc;
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
|
||||
/* catch various bogus parameters */
|
||||
if (!_req || !req->req.complete || !req->req.buf
|
||||
|
|
@ -719,10 +727,6 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
|||
dev_err(&udc->dev->dev, "%s, bad ep", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
|
||||
if (req->req.length > ep->ep.maxpacket)
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
udc = ep->udc;
|
||||
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
|
||||
|
|
@ -755,15 +759,17 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
|||
|
||||
/* build dtds and push them to device queue */
|
||||
if (!req_to_dtd(req)) {
|
||||
int retval;
|
||||
retval = queue_dtd(ep, req);
|
||||
if (retval) {
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
return retval;
|
||||
dev_err(&udc->dev->dev, "Failed to queue dtd\n");
|
||||
goto err_unmap_dma;
|
||||
}
|
||||
} else {
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
return -ENOMEM;
|
||||
dev_err(&udc->dev->dev, "Failed to dma_pool_alloc\n");
|
||||
retval = -ENOMEM;
|
||||
goto err_unmap_dma;
|
||||
}
|
||||
|
||||
/* Update ep0 state */
|
||||
|
|
@ -775,6 +781,22 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
|||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap_dma:
|
||||
if (req->mapped) {
|
||||
dma_unmap_single(ep->udc->gadget.dev.parent,
|
||||
req->req.dma, req->req.length,
|
||||
((ep_dir(ep) == EP_DIR_IN) ?
|
||||
DMA_TO_DEVICE : DMA_FROM_DEVICE));
|
||||
req->req.dma = DMA_ADDR_INVALID;
|
||||
req->mapped = 0;
|
||||
} else
|
||||
dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
|
||||
req->req.dma, req->req.length,
|
||||
((ep_dir(ep) == EP_DIR_IN) ?
|
||||
DMA_TO_DEVICE : DMA_FROM_DEVICE));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req)
|
||||
|
|
@ -1065,7 +1087,7 @@ static int udc_reset(struct mv_udc *udc)
|
|||
tmp |= USBMODE_CTRL_MODE_DEVICE;
|
||||
|
||||
/* turn setup lockout off, require setup tripwire in usbcmd */
|
||||
tmp |= USBMODE_SETUP_LOCK_OFF | USBMODE_STREAM_DISABLE;
|
||||
tmp |= USBMODE_SETUP_LOCK_OFF;
|
||||
|
||||
writel(tmp, &udc->op_regs->usbmode);
|
||||
|
||||
|
|
@ -1199,12 +1221,16 @@ static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active)
|
|||
udc_start(udc);
|
||||
}
|
||||
} else if (udc->driver && udc->softconnect) {
|
||||
if (!udc->active)
|
||||
goto out;
|
||||
|
||||
/* stop all the transfer in queue*/
|
||||
stop_activity(udc, udc->driver);
|
||||
udc_stop(udc);
|
||||
mv_udc_disable(udc);
|
||||
}
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -1243,7 +1269,7 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on)
|
|||
}
|
||||
|
||||
static int mv_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int mv_udc_stop(struct usb_gadget_driver *driver);
|
||||
/* device controller usb_gadget_ops structure */
|
||||
static const struct usb_gadget_ops mv_ops = {
|
||||
|
|
@ -1348,7 +1374,7 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver)
|
|||
}
|
||||
|
||||
static int mv_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct mv_udc *udc = the_controller;
|
||||
int retval = 0;
|
||||
|
|
@ -1373,7 +1399,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver,
|
|||
|
||||
spin_unlock_irqrestore(&udc->lock, flags);
|
||||
|
||||
retval = bind(&udc->gadget);
|
||||
retval = bind(&udc->gadget, driver);
|
||||
if (retval) {
|
||||
dev_err(&udc->dev->dev, "bind to driver %s --> %d\n",
|
||||
driver->driver.name, retval);
|
||||
|
|
@ -1499,15 +1525,17 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
|
|||
}
|
||||
|
||||
/* prime the data phase */
|
||||
if (!req_to_dtd(req))
|
||||
if (!req_to_dtd(req)) {
|
||||
retval = queue_dtd(ep, req);
|
||||
else{ /* no mem */
|
||||
if (retval) {
|
||||
dev_err(&udc->dev->dev,
|
||||
"Failed to queue dtd when prime status\n");
|
||||
goto out;
|
||||
}
|
||||
} else{ /* no mem */
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
dev_err(&udc->dev->dev, "response error on GET_STATUS request\n");
|
||||
dev_err(&udc->dev->dev,
|
||||
"Failed to dma_pool_alloc when prime status\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1515,6 +1543,15 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
|
|||
|
||||
return 0;
|
||||
out:
|
||||
if (req->mapped) {
|
||||
dma_unmap_single(ep->udc->gadget.dev.parent,
|
||||
req->req.dma, req->req.length,
|
||||
((ep_dir(ep) == EP_DIR_IN) ?
|
||||
DMA_TO_DEVICE : DMA_FROM_DEVICE));
|
||||
req->req.dma = DMA_ADDR_INVALID;
|
||||
req->mapped = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -2468,9 +2505,11 @@ static void mv_udc_shutdown(struct platform_device *dev)
|
|||
u32 mode;
|
||||
|
||||
/* reset controller mode to IDLE */
|
||||
mv_udc_enable(udc);
|
||||
mode = readl(&udc->op_regs->usbmode);
|
||||
mode &= ~3;
|
||||
writel(mode, &udc->op_regs->usbmode);
|
||||
mv_udc_disable(udc);
|
||||
}
|
||||
|
||||
static struct platform_driver udc_driver = {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
/* #define VERBOSE_DEBUG */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb/composite.h>
|
||||
|
||||
#include "u_ether.h"
|
||||
|
||||
|
|
@ -36,11 +36,6 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_ncm.c"
|
||||
#include "u_ether.c"
|
||||
|
||||
|
|
@ -57,6 +52,7 @@
|
|||
#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
|
|
@ -97,17 +93,11 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -149,7 +139,6 @@ static struct usb_configuration ncm_config_driver = {
|
|||
|
||||
static int __init gncm_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
|
||||
|
|
@ -158,48 +147,22 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
return status;
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
|
||||
else {
|
||||
/* We assume that can_support_ecm() tells the truth;
|
||||
* but if the controller isn't recognized at all then
|
||||
* that assumption is a bit more likely to be wrong.
|
||||
*/
|
||||
dev_warn(&gadget->dev,
|
||||
"controller '%s' not recognized; trying %s\n",
|
||||
gadget->name,
|
||||
ncm_config_driver.label);
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(0x0300 | 0x0099);
|
||||
}
|
||||
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device descriptor strings: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
device_desc.iProduct = status;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
status = usb_add_config(cdev, &ncm_config_driver,
|
||||
ncm_do_config);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
|
||||
|
||||
return 0;
|
||||
|
|
@ -215,11 +178,12 @@ static int __exit gncm_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver ncm_driver = {
|
||||
static __refdata struct usb_composite_driver ncm_driver = {
|
||||
.name = "g_ncm",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = gncm_bind,
|
||||
.unbind = __exit_p(gncm_unbind),
|
||||
};
|
||||
|
||||
|
|
@ -229,7 +193,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&ncm_driver, gncm_bind);
|
||||
return usb_composite_probe(&ncm_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "u_serial.h"
|
||||
|
|
@ -38,11 +37,6 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "u_serial.c"
|
||||
#include "f_acm.c"
|
||||
#include "f_ecm.c"
|
||||
|
|
@ -52,23 +46,23 @@
|
|||
#include "u_ether.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
#define NOKIA_VENDOR_ID 0x0421 /* Nokia */
|
||||
#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_DESCRIPTION_IDX 2
|
||||
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
|
||||
|
||||
static char manufacturer_nokia[] = "Nokia";
|
||||
static const char product_nokia[] = NOKIA_LONG_NAME;
|
||||
static const char description_nokia[] = "PC-Suite Configuration";
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer_nokia,
|
||||
[STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = manufacturer_nokia,
|
||||
[USB_GADGET_PRODUCT_IDX].s = NOKIA_LONG_NAME,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
[STRING_DESCRIPTION_IDX].s = description_nokia,
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
|
@ -90,6 +84,7 @@ static struct usb_device_descriptor device_desc = {
|
|||
.bDeviceClass = USB_CLASS_COMM,
|
||||
.idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
|
||||
.idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
|
||||
.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM),
|
||||
/* .iManufacturer = DYNAMIC */
|
||||
/* .iProduct = DYNAMIC */
|
||||
.bNumConfigurations = 1,
|
||||
|
|
@ -151,7 +146,6 @@ static struct usb_configuration nokia_config_100ma_driver = {
|
|||
|
||||
static int __init nokia_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
|
||||
|
|
@ -167,41 +161,17 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
goto err_ether;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto err_usb;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto err_usb;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
|
||||
device_desc.iProduct = status;
|
||||
|
||||
/* config description */
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto err_usb;
|
||||
strings_dev[STRING_DESCRIPTION_IDX].id = status;
|
||||
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
status = strings_dev[STRING_DESCRIPTION_IDX].id;
|
||||
nokia_config_500ma_driver.iConfiguration = status;
|
||||
nokia_config_100ma_driver.iConfiguration = status;
|
||||
|
||||
/* set up other descriptors */
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM);
|
||||
else {
|
||||
/* this should only work with hw that supports altsettings
|
||||
* and several endpoints, anything else, panic.
|
||||
*/
|
||||
pr_err("nokia_bind: controller '%s' not recognized\n",
|
||||
gadget->name);
|
||||
if (!gadget_supports_altsettings(gadget))
|
||||
goto err_usb;
|
||||
}
|
||||
|
||||
/* finally register the configuration */
|
||||
status = usb_add_config(cdev, &nokia_config_500ma_driver,
|
||||
|
|
@ -214,6 +184,7 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
goto err_usb;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
|
||||
|
||||
return 0;
|
||||
|
|
@ -237,17 +208,18 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver nokia_driver = {
|
||||
static __refdata struct usb_composite_driver nokia_driver = {
|
||||
.name = "g_nokia",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = nokia_bind,
|
||||
.unbind = __exit_p(nokia_unbind),
|
||||
};
|
||||
|
||||
static int __init nokia_init(void)
|
||||
{
|
||||
return usb_composite_probe(&nokia_driver, nokia_bind);
|
||||
return usb_composite_probe(&nokia_driver);
|
||||
}
|
||||
module_init(nokia_init);
|
||||
|
||||
|
|
|
|||
|
|
@ -1308,7 +1308,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
|
|||
}
|
||||
|
||||
static int omap_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int omap_udc_stop(struct usb_gadget_driver *driver);
|
||||
|
||||
static struct usb_gadget_ops omap_gadget_ops = {
|
||||
|
|
@ -2040,7 +2040,7 @@ static inline int machine_without_vbus_sense(void)
|
|||
}
|
||||
|
||||
static int omap_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
int status = -ENODEV;
|
||||
struct omap_ep *ep;
|
||||
|
|
@ -2082,7 +2082,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver,
|
|||
if (udc->dc_clk != NULL)
|
||||
omap_udc_enable_clock(1);
|
||||
|
||||
status = bind(&udc->gadget);
|
||||
status = bind(&udc->gadget, driver);
|
||||
if (status) {
|
||||
DBG("bind to %s --> %d\n", driver->driver.name, status);
|
||||
udc->gadget.dev.driver = NULL;
|
||||
|
|
|
|||
|
|
@ -1236,7 +1236,7 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA)
|
|||
}
|
||||
|
||||
static int pch_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int pch_udc_stop(struct usb_gadget_driver *driver);
|
||||
static const struct usb_gadget_ops pch_udc_ops = {
|
||||
.get_frame = pch_udc_pcd_get_frame,
|
||||
|
|
@ -2982,7 +2982,7 @@ static int init_dma_pools(struct pch_udc_dev *dev)
|
|||
}
|
||||
|
||||
static int pch_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct pch_udc_dev *dev = pch_udc;
|
||||
int retval;
|
||||
|
|
@ -3006,7 +3006,7 @@ static int pch_udc_start(struct usb_gadget_driver *driver,
|
|||
dev->gadget.dev.driver = &driver->driver;
|
||||
|
||||
/* Invoke the bind routine of the gadget driver */
|
||||
retval = bind(&dev->gadget);
|
||||
retval = bind(&dev->gadget, driver);
|
||||
|
||||
if (retval) {
|
||||
dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/fs.h>
|
||||
|
|
@ -38,25 +37,13 @@
|
|||
#include <asm/unaligned.h>
|
||||
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/g_printer.h>
|
||||
|
||||
#include "gadget_chips.h"
|
||||
|
||||
|
||||
/*
|
||||
* Kbuild is not very cooperative with respect to linking separately
|
||||
* compiled library objects into one module. So for now we won't use
|
||||
* separate compilation ... ensuring init/exit sections work to shrink
|
||||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
#define DRIVER_DESC "Printer Gadget"
|
||||
#define DRIVER_VERSION "2007 OCT 06"
|
||||
|
|
@ -120,8 +107,7 @@ static struct printer_dev usb_printer_gadget;
|
|||
* parameters are in UTF-8 (superset of ASCII's 7 bit characters).
|
||||
*/
|
||||
|
||||
static char *iSerialNum;
|
||||
module_param(iSerialNum, charp, S_IRUGO);
|
||||
module_param_named(iSerialNum, coverwrite.serial_number, charp, S_IRUGO);
|
||||
MODULE_PARM_DESC(iSerialNum, "1");
|
||||
|
||||
static char *iPNPstring;
|
||||
|
|
@ -141,18 +127,10 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
|
|||
* descriptors are built on demand.
|
||||
*/
|
||||
|
||||
#define STRING_MANUFACTURER 1
|
||||
#define STRING_PRODUCT 2
|
||||
#define STRING_SERIALNUM 3
|
||||
|
||||
/* holds our biggest descriptor */
|
||||
#define USB_DESC_BUFSIZE 256
|
||||
#define USB_BUFSIZE 8192
|
||||
|
||||
/* This device advertises one configuration. */
|
||||
#define DEV_CONFIG_VALUE 1
|
||||
#define PRINTER_INTERFACE 0
|
||||
|
||||
static struct usb_device_descriptor device_desc = {
|
||||
.bLength = sizeof device_desc,
|
||||
.bDescriptorType = USB_DT_DEVICE,
|
||||
|
|
@ -162,16 +140,12 @@ static struct usb_device_descriptor device_desc = {
|
|||
.bDeviceProtocol = 0,
|
||||
.idVendor = cpu_to_le16(PRINTER_VENDOR_NUM),
|
||||
.idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM),
|
||||
.iManufacturer = STRING_MANUFACTURER,
|
||||
.iProduct = STRING_PRODUCT,
|
||||
.iSerialNumber = STRING_SERIALNUM,
|
||||
.bNumConfigurations = 1
|
||||
};
|
||||
|
||||
static struct usb_interface_descriptor intf_desc = {
|
||||
.bLength = sizeof intf_desc,
|
||||
.bDescriptorType = USB_DT_INTERFACE,
|
||||
.bInterfaceNumber = PRINTER_INTERFACE,
|
||||
.bNumEndpoints = 2,
|
||||
.bInterfaceClass = USB_CLASS_PRINTER,
|
||||
.bInterfaceSubClass = 1, /* Printer Sub-Class */
|
||||
|
|
@ -252,7 +226,6 @@ static const struct usb_descriptor_header *otg_desc[] = {
|
|||
|
||||
/* descriptors that are built on-demand */
|
||||
|
||||
static char manufacturer [50];
|
||||
static char product_desc [40] = DRIVER_DESC;
|
||||
static char serial_num [40] = "1";
|
||||
static char pnp_string [1024] =
|
||||
|
|
@ -260,9 +233,9 @@ static char pnp_string [1024] =
|
|||
|
||||
/* static strings, in UTF-8 */
|
||||
static struct usb_string strings [] = {
|
||||
{ STRING_MANUFACTURER, manufacturer, },
|
||||
{ STRING_PRODUCT, product_desc, },
|
||||
{ STRING_SERIALNUM, serial_num, },
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = product_desc,
|
||||
[USB_GADGET_SERIAL_IDX].s = serial_num,
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -871,25 +844,13 @@ static int set_interface(struct printer_dev *dev, unsigned number)
|
|||
int result = 0;
|
||||
|
||||
/* Free the current interface */
|
||||
switch (dev->interface) {
|
||||
case PRINTER_INTERFACE:
|
||||
printer_reset_interface(dev);
|
||||
break;
|
||||
}
|
||||
printer_reset_interface(dev);
|
||||
|
||||
switch (number) {
|
||||
case PRINTER_INTERFACE:
|
||||
result = set_printer_interface(dev);
|
||||
if (result) {
|
||||
printer_reset_interface(dev);
|
||||
} else {
|
||||
dev->interface = PRINTER_INTERFACE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
/* FALL THROUGH */
|
||||
}
|
||||
result = set_printer_interface(dev);
|
||||
if (result)
|
||||
printer_reset_interface(dev);
|
||||
else
|
||||
dev->interface = number;
|
||||
|
||||
if (!result)
|
||||
INFO(dev, "Using interface %x\n", number);
|
||||
|
|
@ -972,7 +933,7 @@ static int printer_func_setup(struct usb_function *f,
|
|||
switch (ctrl->bRequest) {
|
||||
case 0: /* Get the IEEE-1284 PNP String */
|
||||
/* Only one printer interface is supported. */
|
||||
if ((wIndex>>8) != PRINTER_INTERFACE)
|
||||
if ((wIndex>>8) != dev->interface)
|
||||
break;
|
||||
|
||||
value = (pnp_string[0]<<8)|pnp_string[1];
|
||||
|
|
@ -983,7 +944,7 @@ static int printer_func_setup(struct usb_function *f,
|
|||
|
||||
case 1: /* Get Port Status */
|
||||
/* Only one printer interface is supported. */
|
||||
if (wIndex != PRINTER_INTERFACE)
|
||||
if (wIndex != dev->interface)
|
||||
break;
|
||||
|
||||
*(u8 *)req->buf = dev->printer_status;
|
||||
|
|
@ -992,7 +953,7 @@ static int printer_func_setup(struct usb_function *f,
|
|||
|
||||
case 2: /* Soft Reset */
|
||||
/* Only one printer interface is supported. */
|
||||
if (wIndex != PRINTER_INTERFACE)
|
||||
if (wIndex != dev->interface)
|
||||
break;
|
||||
|
||||
printer_soft_reset(dev);
|
||||
|
|
@ -1020,6 +981,37 @@ unknown:
|
|||
static int __init printer_func_bind(struct usb_configuration *c,
|
||||
struct usb_function *f)
|
||||
{
|
||||
struct printer_dev *dev = container_of(f, struct printer_dev, function);
|
||||
struct usb_composite_dev *cdev = c->cdev;
|
||||
struct usb_ep *in_ep, *out_ep;
|
||||
int id;
|
||||
|
||||
id = usb_interface_id(c, f);
|
||||
if (id < 0)
|
||||
return id;
|
||||
intf_desc.bInterfaceNumber = id;
|
||||
|
||||
/* all we really need is bulk IN/OUT */
|
||||
in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc);
|
||||
if (!in_ep) {
|
||||
autoconf_fail:
|
||||
dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n",
|
||||
cdev->gadget->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
in_ep->driver_data = in_ep; /* claim */
|
||||
|
||||
out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
|
||||
if (!out_ep)
|
||||
goto autoconf_fail;
|
||||
out_ep->driver_data = out_ep; /* claim */
|
||||
|
||||
/* assumes that all endpoints are dual-speed */
|
||||
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
|
||||
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
|
||||
|
||||
dev->in_ep = in_ep;
|
||||
dev->out_ep = out_ep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1035,7 +1027,8 @@ static int printer_func_set_alt(struct usb_function *f,
|
|||
int ret = -ENOTSUPP;
|
||||
|
||||
if (!alt)
|
||||
ret = set_interface(dev, PRINTER_INTERFACE);
|
||||
ret = set_interface(dev, intf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1107,13 +1100,13 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
{
|
||||
struct usb_gadget *gadget = c->cdev->gadget;
|
||||
struct printer_dev *dev;
|
||||
struct usb_ep *in_ep, *out_ep;
|
||||
int status = -ENOMEM;
|
||||
int gcnum;
|
||||
size_t len;
|
||||
u32 i;
|
||||
struct usb_request *req;
|
||||
|
||||
usb_ep_autoconfig_reset(gadget);
|
||||
|
||||
dev = &usb_printer_gadget;
|
||||
|
||||
dev->function.name = shortname;
|
||||
|
|
@ -1125,6 +1118,10 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
dev->function.set_alt = printer_func_set_alt;
|
||||
dev->function.disable = printer_func_disable;
|
||||
|
||||
status = usb_add_function(c, &dev->function);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Setup the sysfs files for the printer gadget. */
|
||||
dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
|
||||
NULL, "g_printer");
|
||||
|
|
@ -1145,23 +1142,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0) {
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
|
||||
} else {
|
||||
dev_warn(&gadget->dev, "controller '%s' not recognized\n",
|
||||
gadget->name);
|
||||
/* unrecognized, but safe unless bulk is REALLY quirky */
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(0xFFFF);
|
||||
}
|
||||
snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
|
||||
if (iSerialNum)
|
||||
strlcpy(serial_num, iSerialNum, sizeof serial_num);
|
||||
|
||||
if (iPNPstring)
|
||||
strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2);
|
||||
|
||||
|
|
@ -1169,26 +1149,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|||
pnp_string[0] = (len >> 8) & 0xFF;
|
||||
pnp_string[1] = len & 0xFF;
|
||||
|
||||
/* all we really need is bulk IN/OUT */
|
||||
usb_ep_autoconfig_reset(gadget);
|
||||
in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc);
|
||||
if (!in_ep) {
|
||||
autoconf_fail:
|
||||
dev_err(&gadget->dev, "can't autoconfigure on %s\n",
|
||||
gadget->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
in_ep->driver_data = in_ep; /* claim */
|
||||
|
||||
out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc);
|
||||
if (!out_ep)
|
||||
goto autoconf_fail;
|
||||
out_ep->driver_data = out_ep; /* claim */
|
||||
|
||||
/* assumes that all endpoints are dual-speed */
|
||||
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
|
||||
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
|
||||
|
||||
usb_gadget_set_selfpowered(gadget);
|
||||
|
||||
if (gadget->is_otg) {
|
||||
|
|
@ -1215,9 +1175,6 @@ autoconf_fail:
|
|||
dev->current_rx_bytes = 0;
|
||||
dev->current_rx_buf = NULL;
|
||||
|
||||
dev->in_ep = in_ep;
|
||||
dev->out_ep = out_ep;
|
||||
|
||||
for (i = 0; i < QLEN; i++) {
|
||||
req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
|
||||
if (!req) {
|
||||
|
|
@ -1250,8 +1207,6 @@ autoconf_fail:
|
|||
dev->gadget = gadget;
|
||||
|
||||
INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
|
||||
INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
|
||||
in_ep->name);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
@ -1266,14 +1221,28 @@ static int printer_unbind(struct usb_composite_dev *cdev)
|
|||
|
||||
static int __init printer_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
|
||||
int ret;
|
||||
|
||||
ret = usb_string_ids_tab(cdev, strings);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
|
||||
|
||||
ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver printer_driver = {
|
||||
static __refdata struct usb_composite_driver printer_driver = {
|
||||
.name = shortname,
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_HIGH,
|
||||
.bind = printer_bind,
|
||||
.unbind = printer_unbind,
|
||||
};
|
||||
|
||||
|
|
@ -1297,7 +1266,7 @@ init(void)
|
|||
return status;
|
||||
}
|
||||
|
||||
status = usb_composite_probe(&printer_driver, printer_bind);
|
||||
status = usb_composite_probe(&printer_driver);
|
||||
if (status) {
|
||||
class_destroy(usb_gadget_class);
|
||||
unregister_chrdev_region(g_printer_devno, 1);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/io.h>
|
||||
|
|
@ -1000,7 +999,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
|
|||
}
|
||||
|
||||
static int pxa25x_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int pxa25x_stop(struct usb_gadget_driver *driver);
|
||||
|
||||
static const struct usb_gadget_ops pxa25x_udc_ops = {
|
||||
|
|
@ -1258,7 +1257,7 @@ static void udc_enable (struct pxa25x_udc *dev)
|
|||
* the driver might get unbound.
|
||||
*/
|
||||
static int pxa25x_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct pxa25x_udc *dev = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1286,7 +1285,7 @@ fail:
|
|||
dev->gadget.dev.driver = NULL;
|
||||
return retval;
|
||||
}
|
||||
retval = bind(&dev->gadget);
|
||||
retval = bind(&dev->gadget, driver);
|
||||
if (retval) {
|
||||
DMSG("bind to driver %s --> error %d\n",
|
||||
driver->driver.name, retval);
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ dump_state(struct pxa25x_udc *dev)
|
|||
dev->stats.read.bytes, dev->stats.read.ops);
|
||||
|
||||
for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) {
|
||||
if (dev->ep [i].desc == NULL)
|
||||
if (dev->ep[i].ep.desc == NULL)
|
||||
continue;
|
||||
DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1672,7 +1672,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
|
|||
}
|
||||
|
||||
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int pxa27x_udc_stop(struct usb_gadget_driver *driver);
|
||||
|
||||
static const struct usb_gadget_ops pxa_udc_ops = {
|
||||
|
|
@ -1803,7 +1803,7 @@ static void udc_enable(struct pxa_udc *udc)
|
|||
* Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
|
||||
*/
|
||||
static int pxa27x_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct pxa_udc *udc = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1826,7 +1826,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver,
|
|||
dev_err(udc->dev, "device_add error %d\n", retval);
|
||||
goto add_fail;
|
||||
}
|
||||
retval = bind(&udc->gadget);
|
||||
retval = bind(&udc->gadget, driver);
|
||||
if (retval) {
|
||||
dev_err(udc->dev, "bind to driver %s --> error %d\n",
|
||||
driver->driver.name, retval);
|
||||
|
|
|
|||
|
|
@ -863,26 +863,8 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
|
|||
*/
|
||||
pr_warning("%s: unknown RNDIS message 0x%08X len %d\n",
|
||||
__func__, MsgType, MsgLength);
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < MsgLength; i += 16) {
|
||||
pr_debug("%03d: "
|
||||
" %02x %02x %02x %02x"
|
||||
" %02x %02x %02x %02x"
|
||||
" %02x %02x %02x %02x"
|
||||
" %02x %02x %02x %02x"
|
||||
"\n",
|
||||
i,
|
||||
buf[i], buf [i+1],
|
||||
buf[i+2], buf[i+3],
|
||||
buf[i+4], buf [i+5],
|
||||
buf[i+6], buf[i+7],
|
||||
buf[i+8], buf [i+9],
|
||||
buf[i+10], buf[i+11],
|
||||
buf[i+12], buf [i+13],
|
||||
buf[i+14], buf[i+15]);
|
||||
}
|
||||
}
|
||||
print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET,
|
||||
buf, MsgLength);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2197,7 +2197,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
|
|||
/* issue soft reset */
|
||||
writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL);
|
||||
|
||||
timeout = 1000;
|
||||
timeout = 10000;
|
||||
do {
|
||||
grstctl = readl(hsotg->regs + GRSTCTL);
|
||||
} while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0);
|
||||
|
|
@ -2207,7 +2207,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
timeout = 1000;
|
||||
timeout = 10000;
|
||||
|
||||
while (1) {
|
||||
u32 grstctl = readl(hsotg->regs + GRSTCTL);
|
||||
|
|
@ -3516,7 +3516,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
|
|||
hsotg->dev = dev;
|
||||
hsotg->plat = plat;
|
||||
|
||||
hsotg->clk = clk_get(&pdev->dev, "otg");
|
||||
hsotg->clk = devm_clk_get(&pdev->dev, "otg");
|
||||
if (IS_ERR(hsotg->clk)) {
|
||||
dev_err(dev, "cannot get otg clock\n");
|
||||
return PTR_ERR(hsotg->clk);
|
||||
|
|
@ -3667,7 +3667,6 @@ err_supplies:
|
|||
|
||||
err_clk:
|
||||
clk_disable_unprepare(hsotg->clk);
|
||||
clk_put(hsotg->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -3693,7 +3692,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev)
|
|||
regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
|
||||
|
||||
clk_disable_unprepare(hsotg->clk);
|
||||
clk_put(hsotg->clk);
|
||||
|
||||
device_unregister(&hsotg->gadget.dev);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ struct s3c_hsudc_req {
|
|||
* @dev: The device reference used by probe function.
|
||||
* @lock: Lock to synchronize the usage of Endpoints (EP's are indexed).
|
||||
* @regs: Remapped base address of controller's register space.
|
||||
* @mem_rsrc: Device memory resource used for remapping device register space.
|
||||
* irq: IRQ number used by the controller.
|
||||
* uclk: Reference to the controller clock.
|
||||
* ep0state: Current state of EP0.
|
||||
|
|
@ -150,7 +149,6 @@ struct s3c_hsudc {
|
|||
struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)];
|
||||
spinlock_t lock;
|
||||
void __iomem *regs;
|
||||
struct resource *mem_rsrc;
|
||||
int irq;
|
||||
struct clk *uclk;
|
||||
int ep0state;
|
||||
|
|
@ -835,9 +833,9 @@ static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep,
|
|||
{
|
||||
struct s3c_hsudc_req *hsreq;
|
||||
|
||||
hsreq = kzalloc(sizeof *hsreq, gfp_flags);
|
||||
hsreq = kzalloc(sizeof(*hsreq), gfp_flags);
|
||||
if (!hsreq)
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&hsreq->queue);
|
||||
return &hsreq->req;
|
||||
|
|
@ -906,16 +904,16 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req,
|
|||
csr = readl((u32)hsudc->regs + offset);
|
||||
if (!(csr & S3C_ESR_TX_SUCCESS) &&
|
||||
(s3c_hsudc_write_fifo(hsep, hsreq) == 1))
|
||||
hsreq = 0;
|
||||
hsreq = NULL;
|
||||
} else {
|
||||
csr = readl((u32)hsudc->regs + offset);
|
||||
if ((csr & S3C_ESR_RX_SUCCESS)
|
||||
&& (s3c_hsudc_read_fifo(hsep, hsreq) == 1))
|
||||
hsreq = 0;
|
||||
hsreq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (hsreq != 0)
|
||||
if (hsreq)
|
||||
list_add_tail(&hsreq->queue, &hsep->queue);
|
||||
|
||||
spin_unlock_irqrestore(&hsudc->lock, flags);
|
||||
|
|
@ -1271,7 +1269,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
|
|||
struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data;
|
||||
int ret, i;
|
||||
|
||||
hsudc = kzalloc(sizeof(struct s3c_hsudc) +
|
||||
hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) +
|
||||
sizeof(struct s3c_hsudc_ep) * pd->epnum,
|
||||
GFP_KERNEL);
|
||||
if (!hsudc) {
|
||||
|
|
@ -1296,25 +1294,12 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "unable to obtain driver resource data\n");
|
||||
ret = -ENODEV;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
hsudc->mem_rsrc = request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&pdev->dev));
|
||||
if (!hsudc->mem_rsrc) {
|
||||
dev_err(dev, "failed to reserve register area\n");
|
||||
ret = -ENODEV;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
hsudc->regs = ioremap(res->start, resource_size(res));
|
||||
hsudc->regs = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!hsudc->regs) {
|
||||
dev_err(dev, "error mapping device register area\n");
|
||||
ret = -EBUSY;
|
||||
goto err_remap;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
spin_lock_init(&hsudc->lock);
|
||||
|
|
@ -1337,21 +1322,22 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev)
|
|||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "unable to obtain IRQ number\n");
|
||||
goto err_irq;
|
||||
goto err_res;
|
||||
}
|
||||
hsudc->irq = ret;
|
||||
|
||||
ret = request_irq(hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc);
|
||||
ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0,
|
||||
driver_name, hsudc);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "irq request failed\n");
|
||||
goto err_irq;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
hsudc->uclk = clk_get(&pdev->dev, "usb-device");
|
||||
hsudc->uclk = devm_clk_get(&pdev->dev, "usb-device");
|
||||
if (IS_ERR(hsudc->uclk)) {
|
||||
dev_err(dev, "failed to find usb-device clock source\n");
|
||||
ret = PTR_ERR(hsudc->uclk);
|
||||
goto err_clk;
|
||||
goto err_res;
|
||||
}
|
||||
clk_enable(hsudc->uclk);
|
||||
|
||||
|
|
@ -1377,21 +1363,12 @@ err_add_udc:
|
|||
device_unregister(&hsudc->gadget.dev);
|
||||
err_add_device:
|
||||
clk_disable(hsudc->uclk);
|
||||
clk_put(hsudc->uclk);
|
||||
err_clk:
|
||||
free_irq(hsudc->irq, hsudc);
|
||||
err_irq:
|
||||
iounmap(hsudc->regs);
|
||||
|
||||
err_remap:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_res:
|
||||
if (!IS_ERR_OR_NULL(hsudc->transceiver))
|
||||
usb_put_phy(hsudc->transceiver);
|
||||
|
||||
regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
|
||||
err_supplies:
|
||||
kfree(hsudc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "s3c2410_udc: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
@ -27,6 +29,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
|
@ -35,7 +38,6 @@
|
|||
#include <linux/usb/gadget.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <mach/irqs.h>
|
||||
|
|
@ -115,7 +117,7 @@ static int dprintk(int level, const char *fmt, ...)
|
|||
sizeof(printk_buf)-len, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return printk(KERN_DEBUG "%s", printk_buf);
|
||||
return pr_debug("%s", printk_buf);
|
||||
}
|
||||
#else
|
||||
static int dprintk(int level, const char *fmt, ...)
|
||||
|
|
@ -125,10 +127,10 @@ static int dprintk(int level, const char *fmt, ...)
|
|||
#endif
|
||||
static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
|
||||
{
|
||||
u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
|
||||
u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg;
|
||||
u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
|
||||
u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
|
||||
u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
|
||||
u32 ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2;
|
||||
u32 ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2;
|
||||
|
||||
addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
|
||||
pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
|
||||
|
|
@ -164,10 +166,10 @@ static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
|
|||
"EP2_I_CSR2 : 0x%04X\n"
|
||||
"EP2_O_CSR1 : 0x%04X\n"
|
||||
"EP2_O_CSR2 : 0x%04X\n",
|
||||
addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
|
||||
addr_reg, pwr_reg, ep_int_reg, usb_int_reg,
|
||||
ep_int_en_reg, usb_int_en_reg, ep0_csr,
|
||||
ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
|
||||
ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
|
||||
ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2,
|
||||
ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2
|
||||
);
|
||||
|
||||
return 0;
|
||||
|
|
@ -230,7 +232,7 @@ static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
|
|||
{
|
||||
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
|
||||
|
||||
udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
|
||||
udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
|
||||
| S3C2410_UDC_EP0_CSR_DE),
|
||||
S3C2410_UDC_EP0_CSR_REG);
|
||||
}
|
||||
|
|
@ -263,7 +265,7 @@ static void s3c2410_udc_done(struct s3c2410_ep *ep,
|
|||
|
||||
list_del_init(&req->queue);
|
||||
|
||||
if (likely (req->req.status == -EINPROGRESS))
|
||||
if (likely(req->req.status == -EINPROGRESS))
|
||||
req->req.status = status;
|
||||
else
|
||||
status = req->req.status;
|
||||
|
|
@ -280,9 +282,9 @@ static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
|
|||
if (&ep->queue == NULL)
|
||||
return;
|
||||
|
||||
while (!list_empty (&ep->queue)) {
|
||||
while (!list_empty(&ep->queue)) {
|
||||
struct s3c2410_request *req;
|
||||
req = list_entry (ep->queue.next, struct s3c2410_request,
|
||||
req = list_entry(ep->queue.next, struct s3c2410_request,
|
||||
queue);
|
||||
s3c2410_udc_done(ep, req, status);
|
||||
}
|
||||
|
|
@ -389,10 +391,10 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
|
|||
|
||||
if (idx == 0) {
|
||||
/* Reset signal => no need to say 'data sent' */
|
||||
if (! (udc_read(S3C2410_UDC_USB_INT_REG)
|
||||
if (!(udc_read(S3C2410_UDC_USB_INT_REG)
|
||||
& S3C2410_UDC_USBINT_RESET))
|
||||
s3c2410_udc_set_ep0_de_in(base_addr);
|
||||
ep->dev->ep0state=EP0_IDLE;
|
||||
ep->dev->ep0state = EP0_IDLE;
|
||||
} else {
|
||||
udc_write(idx, S3C2410_UDC_INDEX_REG);
|
||||
ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
|
||||
|
|
@ -406,7 +408,7 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
|
|||
} else {
|
||||
if (idx == 0) {
|
||||
/* Reset signal => no need to say 'data sent' */
|
||||
if (! (udc_read(S3C2410_UDC_USB_INT_REG)
|
||||
if (!(udc_read(S3C2410_UDC_USB_INT_REG)
|
||||
& S3C2410_UDC_USBINT_RESET))
|
||||
s3c2410_udc_set_ep0_ipr(base_addr);
|
||||
} else {
|
||||
|
|
@ -442,7 +444,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
|
|||
u8 *buf;
|
||||
u32 ep_csr;
|
||||
unsigned bufferspace;
|
||||
int is_last=1;
|
||||
int is_last = 1;
|
||||
unsigned avail;
|
||||
int fifo_count = 0;
|
||||
u32 idx;
|
||||
|
|
@ -510,7 +512,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
|
|||
/* Only ep0 debug messages are interesting */
|
||||
if (idx == 0)
|
||||
dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
|
||||
__func__, fifo_count,is_last);
|
||||
__func__, fifo_count, is_last);
|
||||
|
||||
if (is_last) {
|
||||
if (idx == 0) {
|
||||
|
|
@ -542,7 +544,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
|
|||
|
||||
static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
|
||||
{
|
||||
unsigned char *outbuf = (unsigned char*)crq;
|
||||
unsigned char *outbuf = (unsigned char *)crq;
|
||||
int bytes_read = 0;
|
||||
|
||||
udc_write(0, S3C2410_UDC_INDEX_REG);
|
||||
|
|
@ -648,7 +650,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
|
|||
|
||||
switch (crq->bRequest) {
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n");
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ...\n");
|
||||
|
||||
if (crq->bRequestType == USB_RECIP_DEVICE) {
|
||||
dev->req_config = 1;
|
||||
|
|
@ -657,7 +659,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
|
|||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n");
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ...\n");
|
||||
|
||||
if (crq->bRequestType == USB_RECIP_INTERFACE) {
|
||||
dev->req_config = 1;
|
||||
|
|
@ -666,7 +668,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
|
|||
break;
|
||||
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n");
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ...\n");
|
||||
|
||||
if (crq->bRequestType == USB_RECIP_DEVICE) {
|
||||
tmp = crq->wValue & 0x7F;
|
||||
|
|
@ -679,13 +681,12 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
|
|||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS:
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n");
|
||||
dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ...\n");
|
||||
s3c2410_udc_clear_ep0_opr(base_addr);
|
||||
|
||||
if (dev->req_std) {
|
||||
if (!s3c2410_udc_get_status(dev, crq)) {
|
||||
if (!s3c2410_udc_get_status(dev, crq))
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -750,7 +751,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
|
|||
/* deferred i/o == no response yet */
|
||||
} else if (dev->req_pending) {
|
||||
dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
|
||||
dev->req_pending=0;
|
||||
dev->req_pending = 0;
|
||||
}
|
||||
|
||||
dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
|
||||
|
|
@ -801,16 +802,14 @@ static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
|
|||
|
||||
case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */
|
||||
dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
|
||||
if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
|
||||
if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req)
|
||||
s3c2410_udc_write_fifo(ep, req);
|
||||
}
|
||||
break;
|
||||
|
||||
case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */
|
||||
dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
|
||||
if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
|
||||
s3c2410_udc_read_fifo(ep,req);
|
||||
}
|
||||
if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req)
|
||||
s3c2410_udc_read_fifo(ep, req);
|
||||
break;
|
||||
|
||||
case EP0_END_XFER:
|
||||
|
|
@ -836,7 +835,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
|
|||
u32 ep_csr1;
|
||||
u32 idx;
|
||||
|
||||
if (likely (!list_empty(&ep->queue)))
|
||||
if (likely(!list_empty(&ep->queue)))
|
||||
req = list_entry(ep->queue.next,
|
||||
struct s3c2410_request, queue);
|
||||
else
|
||||
|
|
@ -858,9 +857,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
|
||||
s3c2410_udc_write_fifo(ep,req);
|
||||
}
|
||||
if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req)
|
||||
s3c2410_udc_write_fifo(ep, req);
|
||||
} else {
|
||||
udc_write(idx, S3C2410_UDC_INDEX_REG);
|
||||
ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
|
||||
|
|
@ -873,9 +871,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
|
||||
s3c2410_udc_read_fifo(ep,req);
|
||||
}
|
||||
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req)
|
||||
s3c2410_udc_read_fifo(ep, req);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1057,7 +1054,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
|
|||
struct s3c2410_ep *ep;
|
||||
u32 max, tmp;
|
||||
unsigned long flags;
|
||||
u32 csr1,csr2;
|
||||
u32 csr1, csr2;
|
||||
u32 int_en_reg;
|
||||
|
||||
ep = to_s3c2410_ep(_ep);
|
||||
|
|
@ -1073,7 +1070,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
|
|||
|
||||
max = usb_endpoint_maxp(desc) & 0x1fff;
|
||||
|
||||
local_irq_save (flags);
|
||||
local_irq_save(flags);
|
||||
_ep->maxpacket = max & 0x7ff;
|
||||
ep->ep.desc = desc;
|
||||
ep->halted = 0;
|
||||
|
|
@ -1117,11 +1114,11 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
|
|||
|
||||
/* print some debug message */
|
||||
tmp = desc->bEndpointAddress;
|
||||
dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
|
||||
_ep->name,ep->num, tmp,
|
||||
dprintk(DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
|
||||
_ep->name, ep->num, tmp,
|
||||
desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
|
||||
|
||||
local_irq_restore (flags);
|
||||
local_irq_restore(flags);
|
||||
s3c2410_udc_set_halt(_ep, 0);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1149,7 +1146,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
|
|||
ep->ep.desc = NULL;
|
||||
ep->halted = 1;
|
||||
|
||||
s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
|
||||
s3c2410_udc_nuke(ep->dev, ep, -ESHUTDOWN);
|
||||
|
||||
/* disable irqs */
|
||||
int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
|
||||
|
|
@ -1170,16 +1167,16 @@ s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
|
|||
{
|
||||
struct s3c2410_request *req;
|
||||
|
||||
dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags);
|
||||
dprintk(DEBUG_VERBOSE, "%s(%p,%d)\n", __func__, _ep, mem_flags);
|
||||
|
||||
if (!_ep)
|
||||
return NULL;
|
||||
|
||||
req = kzalloc (sizeof(struct s3c2410_request), mem_flags);
|
||||
req = kzalloc(sizeof(struct s3c2410_request), mem_flags);
|
||||
if (!req)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD (&req->queue);
|
||||
INIT_LIST_HEAD(&req->queue);
|
||||
return &req->req;
|
||||
}
|
||||
|
||||
|
|
@ -1197,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
|
|||
if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name))
|
||||
return;
|
||||
|
||||
WARN_ON (!list_empty (&req->queue));
|
||||
WARN_ON(!list_empty(&req->queue));
|
||||
kfree(req);
|
||||
}
|
||||
|
||||
|
|
@ -1220,12 +1217,12 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
|
|||
}
|
||||
|
||||
dev = ep->dev;
|
||||
if (unlikely (!dev->driver
|
||||
if (unlikely(!dev->driver
|
||||
|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
local_irq_save (flags);
|
||||
local_irq_save(flags);
|
||||
|
||||
if (unlikely(!_req || !_req->complete
|
||||
|| !_req->buf || !list_empty(&req->queue))) {
|
||||
|
|
@ -1233,7 +1230,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
|
|||
dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
|
||||
else {
|
||||
dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
|
||||
__func__, !_req->complete,!_req->buf,
|
||||
__func__, !_req->complete, !_req->buf,
|
||||
!list_empty(&req->queue));
|
||||
}
|
||||
|
||||
|
|
@ -1299,7 +1296,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
|
|||
}
|
||||
|
||||
/* pio or dma irq handler advances the queue. */
|
||||
if (likely (req != 0))
|
||||
if (likely(req))
|
||||
list_add_tail(&req->queue, &ep->queue);
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
|
@ -1329,11 +1326,11 @@ static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|||
|
||||
udc = to_s3c2410_udc(ep->gadget);
|
||||
|
||||
local_irq_save (flags);
|
||||
local_irq_save(flags);
|
||||
|
||||
list_for_each_entry (req, &ep->queue, queue) {
|
||||
list_for_each_entry(req, &ep->queue, queue) {
|
||||
if (&req->req == _req) {
|
||||
list_del_init (&req->queue);
|
||||
list_del_init(&req->queue);
|
||||
_req->status = -ECONNRESET;
|
||||
retval = 0;
|
||||
break;
|
||||
|
|
@ -1348,7 +1345,7 @@ static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
|
|||
s3c2410_udc_done(ep, req, -ECONNRESET);
|
||||
}
|
||||
|
||||
local_irq_restore (flags);
|
||||
local_irq_restore(flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -1367,7 +1364,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
local_irq_save (flags);
|
||||
local_irq_save(flags);
|
||||
|
||||
idx = ep->bEndpointAddress & 0x7F;
|
||||
|
||||
|
|
@ -1376,7 +1373,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
|
|||
s3c2410_udc_set_ep0_de_out(base_addr);
|
||||
} else {
|
||||
udc_write(idx, S3C2410_UDC_INDEX_REG);
|
||||
ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN)
|
||||
ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
|
||||
? S3C2410_UDC_IN_CSR1_REG
|
||||
: S3C2410_UDC_OUT_CSR1_REG);
|
||||
|
||||
|
|
@ -1404,7 +1401,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
|
|||
}
|
||||
|
||||
ep->halted = value ? 1 : 0;
|
||||
local_irq_restore (flags);
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1484,9 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
|
|||
}
|
||||
s3c2410_udc_disable(udc);
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1542,7 +1539,7 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
|
|||
}
|
||||
|
||||
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *));
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *));
|
||||
static int s3c2410_udc_stop(struct usb_gadget_driver *driver);
|
||||
|
||||
static const struct usb_gadget_ops s3c2410_ops = {
|
||||
|
|
@ -1617,20 +1614,20 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
|
|||
u32 i;
|
||||
|
||||
/* device/ep0 records init */
|
||||
INIT_LIST_HEAD (&dev->gadget.ep_list);
|
||||
INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
|
||||
INIT_LIST_HEAD(&dev->gadget.ep_list);
|
||||
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
|
||||
dev->ep0state = EP0_IDLE;
|
||||
|
||||
for (i = 0; i < S3C2410_ENDPOINTS; i++) {
|
||||
struct s3c2410_ep *ep = &dev->ep[i];
|
||||
|
||||
if (i != 0)
|
||||
list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
|
||||
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
|
||||
|
||||
ep->dev = dev;
|
||||
ep->ep.desc = NULL;
|
||||
ep->halted = 0;
|
||||
INIT_LIST_HEAD (&ep->queue);
|
||||
INIT_LIST_HEAD(&ep->queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1668,7 +1665,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
|
|||
}
|
||||
|
||||
static int s3c2410_udc_start(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
struct s3c2410_udc *udc = the_controller;
|
||||
int retval;
|
||||
|
|
@ -1683,13 +1680,13 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver,
|
|||
return -EBUSY;
|
||||
|
||||
if (!bind || !driver->setup || driver->max_speed < USB_SPEED_FULL) {
|
||||
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
|
||||
dev_err(&udc->gadget.dev, "Invalid driver: bind %p setup %p speed %d\n",
|
||||
bind, driver->setup, driver->max_speed);
|
||||
return -EINVAL;
|
||||
}
|
||||
#if defined(MODULE)
|
||||
if (!driver->unbind) {
|
||||
printk(KERN_ERR "Invalid driver: no unbind method\n");
|
||||
dev_err(&udc->gadget.dev, "Invalid driver: no unbind method\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1699,15 +1696,17 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver,
|
|||
udc->gadget.dev.driver = &driver->driver;
|
||||
|
||||
/* Bind the driver */
|
||||
if ((retval = device_add(&udc->gadget.dev)) != 0) {
|
||||
printk(KERN_ERR "Error in device_add() : %d\n",retval);
|
||||
retval = device_add(&udc->gadget.dev);
|
||||
if (retval) {
|
||||
dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
|
||||
goto register_error;
|
||||
}
|
||||
|
||||
dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
|
||||
driver->driver.name);
|
||||
|
||||
if ((retval = bind(&udc->gadget)) != 0) {
|
||||
retval = bind(&udc->gadget, driver);
|
||||
if (retval) {
|
||||
device_del(&udc->gadget.dev);
|
||||
goto register_error;
|
||||
}
|
||||
|
|
@ -1865,7 +1864,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
|
|||
memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
|
||||
}
|
||||
|
||||
spin_lock_init (&udc->lock);
|
||||
spin_lock_init(&udc->lock);
|
||||
udc_info = pdev->dev.platform_data;
|
||||
|
||||
rsrc_start = S3C2410_PA_USBDEV;
|
||||
|
|
@ -2028,7 +2027,8 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
|
||||
static int
|
||||
s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
|
||||
{
|
||||
s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
|
||||
|
||||
|
|
@ -2073,7 +2073,7 @@ static int __init udc_init(void)
|
|||
|
||||
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
|
||||
if (IS_ERR(s3c2410_udc_debugfs_root)) {
|
||||
printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
|
||||
pr_err("%s: debugfs dir creation failed %ld\n",
|
||||
gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
|
||||
s3c2410_udc_debugfs_root = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_flip.h>
|
||||
|
|
@ -37,17 +36,13 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_acm.c"
|
||||
#include "f_obex.c"
|
||||
#include "f_serial.c"
|
||||
#include "u_serial.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
/* Thanks to NetChip Technologies for donating this product ID.
|
||||
*
|
||||
|
|
@ -61,15 +56,12 @@
|
|||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_DESCRIPTION_IDX 2
|
||||
|
||||
static char manufacturer[50];
|
||||
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = GS_VERSION_NAME,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
[STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */,
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
|
@ -94,7 +86,7 @@ static struct usb_device_descriptor device_desc = {
|
|||
/* .bMaxPacketSize0 = f(hardware) */
|
||||
.idVendor = cpu_to_le16(GS_VENDOR_ID),
|
||||
/* .idProduct = f(use_acm) */
|
||||
/* .bcdDevice = f(hardware) */
|
||||
.bcdDevice = cpu_to_le16(GS_VERSION_NUM),
|
||||
/* .iManufacturer = DYNAMIC */
|
||||
/* .iProduct = DYNAMIC */
|
||||
.bNumConfigurations = 1,
|
||||
|
|
@ -162,8 +154,6 @@ static struct usb_configuration serial_config_driver = {
|
|||
|
||||
static int __init gs_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int status;
|
||||
|
||||
status = gserial_setup(cdev->gadget, n_ports);
|
||||
|
|
@ -174,50 +164,14 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
|
|||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
|
||||
/* device description: manufacturer, product */
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
status = usb_string_id(cdev);
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = status;
|
||||
|
||||
device_desc.iManufacturer = status;
|
||||
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = status;
|
||||
|
||||
device_desc.iProduct = status;
|
||||
|
||||
/* config description */
|
||||
status = usb_string_id(cdev);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
strings_dev[STRING_DESCRIPTION_IDX].id = status;
|
||||
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
status = strings_dev[STRING_DESCRIPTION_IDX].id;
|
||||
serial_config_driver.iConfiguration = status;
|
||||
|
||||
/* set up other descriptors */
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum);
|
||||
else {
|
||||
/* this is so simple (for now, no altsettings) that it
|
||||
* SHOULD NOT have problems with bulk-capable hardware.
|
||||
* so warn about unrcognized controllers -- don't panic.
|
||||
*
|
||||
* things like configuration and altsetting numbering
|
||||
* can need hardware-specific attention though.
|
||||
*/
|
||||
pr_warning("gs_bind: controller '%s' not recognized\n",
|
||||
gadget->name);
|
||||
device_desc.bcdDevice =
|
||||
cpu_to_le16(GS_VERSION_NUM | 0x0099);
|
||||
}
|
||||
|
||||
if (gadget_is_otg(cdev->gadget)) {
|
||||
serial_config_driver.descriptors = otg_desc;
|
||||
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
||||
|
|
@ -229,6 +183,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
|
|||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
INFO(cdev, "%s\n", GS_VERSION_NAME);
|
||||
|
||||
return 0;
|
||||
|
|
@ -238,11 +193,12 @@ fail:
|
|||
return status;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver gserial_driver = {
|
||||
static __refdata struct usb_composite_driver gserial_driver = {
|
||||
.name = "g_serial",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.bind = gs_bind,
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
|
|
@ -271,7 +227,7 @@ static int __init init(void)
|
|||
}
|
||||
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
|
||||
|
||||
return usb_composite_probe(&gserial_driver, gs_bind);
|
||||
return usb_composite_probe(&gserial_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,10 @@
|
|||
#include <target/configfs_macros.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "usbstring.c"
|
||||
#include "epautoconf.c"
|
||||
#include "config.c"
|
||||
#include "composite.c"
|
||||
|
||||
#include "tcm_usb_gadget.h"
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
static struct target_fabric_configfs *usbg_fabric_configfs;
|
||||
|
||||
static inline struct f_uas *to_f_uas(struct usb_function *f)
|
||||
|
|
@ -1977,7 +1974,6 @@ static struct usb_interface_descriptor bot_intf_desc = {
|
|||
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = USB_SC_SCSI,
|
||||
.bInterfaceProtocol = USB_PR_BULK,
|
||||
.iInterface = USB_G_STR_INT_UAS,
|
||||
};
|
||||
|
||||
static struct usb_interface_descriptor uasp_intf_desc = {
|
||||
|
|
@ -1988,7 +1984,6 @@ static struct usb_interface_descriptor uasp_intf_desc = {
|
|||
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
|
||||
.bInterfaceSubClass = USB_SC_SCSI,
|
||||
.bInterfaceProtocol = USB_PR_UAS,
|
||||
.iInterface = USB_G_STR_INT_BBB,
|
||||
};
|
||||
|
||||
static struct usb_endpoint_descriptor uasp_bi_desc = {
|
||||
|
|
@ -2209,20 +2204,16 @@ static struct usb_device_descriptor usbg_device_desc = {
|
|||
.bDeviceClass = USB_CLASS_PER_INTERFACE,
|
||||
.idVendor = cpu_to_le16(UAS_VENDOR_ID),
|
||||
.idProduct = cpu_to_le16(UAS_PRODUCT_ID),
|
||||
.iManufacturer = USB_G_STR_MANUFACTOR,
|
||||
.iProduct = USB_G_STR_PRODUCT,
|
||||
.iSerialNumber = USB_G_STR_SERIAL,
|
||||
|
||||
.bNumConfigurations = 1,
|
||||
};
|
||||
|
||||
static struct usb_string usbg_us_strings[] = {
|
||||
{ USB_G_STR_MANUFACTOR, "Target Manufactor"},
|
||||
{ USB_G_STR_PRODUCT, "Target Product"},
|
||||
{ USB_G_STR_SERIAL, "000000000001"},
|
||||
{ USB_G_STR_CONFIG, "default config"},
|
||||
{ USB_G_STR_INT_UAS, "USB Attached SCSI"},
|
||||
{ USB_G_STR_INT_BBB, "Bulk Only Transport"},
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "Target Manufactor",
|
||||
[USB_GADGET_PRODUCT_IDX].s = "Target Product",
|
||||
[USB_GADGET_SERIAL_IDX].s = "000000000001",
|
||||
[USB_G_STR_CONFIG].s = "default config",
|
||||
[USB_G_STR_INT_UAS].s = "USB Attached SCSI",
|
||||
[USB_G_STR_INT_BBB].s = "Bulk Only Transport",
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
@ -2244,7 +2235,6 @@ static int guas_unbind(struct usb_composite_dev *cdev)
|
|||
static struct usb_configuration usbg_config_driver = {
|
||||
.label = "Linux Target",
|
||||
.bConfigurationValue = 1,
|
||||
.iConfiguration = USB_G_STR_CONFIG,
|
||||
.bmAttributes = USB_CONFIG_ATT_SELFPOWER,
|
||||
};
|
||||
|
||||
|
|
@ -2417,6 +2407,9 @@ static int usbg_cfg_bind(struct usb_configuration *c)
|
|||
fu->function.disable = usbg_disable;
|
||||
fu->tpg = the_only_tpg_I_currently_have;
|
||||
|
||||
bot_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_BBB].id;
|
||||
uasp_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_UAS].id;
|
||||
|
||||
ret = usb_add_function(c, &fu->function);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
@ -2431,22 +2424,38 @@ static int usb_target_bind(struct usb_composite_dev *cdev)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = usb_string_ids_tab(cdev, usbg_us_strings);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
usbg_device_desc.iManufacturer =
|
||||
usbg_us_strings[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
usbg_device_desc.iProduct = usbg_us_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
usbg_device_desc.iSerialNumber =
|
||||
usbg_us_strings[USB_GADGET_SERIAL_IDX].id;
|
||||
usbg_config_driver.iConfiguration =
|
||||
usbg_us_strings[USB_G_STR_CONFIG].id;
|
||||
|
||||
ret = usb_add_config(cdev, &usbg_config_driver,
|
||||
usbg_cfg_bind);
|
||||
if (ret)
|
||||
return ret;
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver usbg_driver = {
|
||||
static __refdata struct usb_composite_driver usbg_driver = {
|
||||
.name = "g_target",
|
||||
.dev = &usbg_device_desc,
|
||||
.strings = usbg_strings,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.bind = usb_target_bind,
|
||||
.unbind = guas_unbind,
|
||||
};
|
||||
|
||||
static int usbg_attach(struct usbg_tpg *tpg)
|
||||
{
|
||||
return usb_composite_probe(&usbg_driver, usb_target_bind);
|
||||
return usb_composite_probe(&usbg_driver);
|
||||
}
|
||||
|
||||
static void usbg_detach(struct usbg_tpg *tpg)
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@
|
|||
#define UASP_SS_EP_COMP_LOG_STREAMS 4
|
||||
#define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS)
|
||||
|
||||
#define USB_G_STR_MANUFACTOR 1
|
||||
#define USB_G_STR_PRODUCT 2
|
||||
#define USB_G_STR_SERIAL 3
|
||||
#define USB_G_STR_CONFIG 4
|
||||
#define USB_G_STR_INT_UAS 5
|
||||
#define USB_G_STR_INT_BBB 6
|
||||
enum {
|
||||
USB_G_STR_CONFIG = USB_GADGET_FIRST_AVAIL_IDX,
|
||||
USB_G_STR_INT_UAS,
|
||||
USB_G_STR_INT_BBB,
|
||||
};
|
||||
|
||||
#define USB_G_ALT_INT_BBB 0
|
||||
#define USB_G_ALT_INT_UAS 1
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
/* #define VERBOSE_DEBUG */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/ctype.h>
|
||||
|
|
@ -83,17 +84,10 @@ struct eth_dev {
|
|||
|
||||
#define DEFAULT_QLEN 2 /* double buffering by default */
|
||||
|
||||
|
||||
#ifdef CONFIG_USB_GADGET_DUALSPEED
|
||||
|
||||
static unsigned qmult = 5;
|
||||
module_param(qmult, uint, S_IRUGO|S_IWUSR);
|
||||
MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");
|
||||
|
||||
#else /* full speed (low speed doesn't do bulk) */
|
||||
#define qmult 1
|
||||
#endif
|
||||
|
||||
/* for dual-speed hardware, use deeper queues at high/super speed */
|
||||
static inline int qlen(struct usb_gadget *gadget)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
|
|||
*/
|
||||
static inline int usb_gadget_start(struct usb_gadget *gadget,
|
||||
struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int (*bind)(struct usb_gadget *, struct usb_gadget_driver *))
|
||||
{
|
||||
return gadget->ops->start(driver, bind);
|
||||
}
|
||||
|
|
@ -262,8 +262,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
|
|||
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
|
||||
|
||||
if (udc_is_newstyle(udc)) {
|
||||
udc->driver->disconnect(udc->gadget);
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
udc->driver->disconnect(udc->gadget);
|
||||
udc->driver->unbind(udc->gadget);
|
||||
usb_gadget_udc_stop(udc->gadget, udc->driver);
|
||||
} else {
|
||||
|
|
@ -311,13 +311,12 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
|
||||
int (*bind)(struct usb_gadget *))
|
||||
int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
|
||||
{
|
||||
struct usb_udc *udc = NULL;
|
||||
int ret;
|
||||
|
||||
if (!driver || !bind || !driver->setup)
|
||||
if (!driver || !driver->bind || !driver->setup)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&udc_lock);
|
||||
|
|
@ -339,7 +338,7 @@ found:
|
|||
udc->dev.driver = &driver->driver;
|
||||
|
||||
if (udc_is_newstyle(udc)) {
|
||||
ret = bind(udc->gadget);
|
||||
ret = driver->bind(udc->gadget, driver);
|
||||
if (ret)
|
||||
goto err1;
|
||||
ret = usb_gadget_udc_start(udc->gadget, driver);
|
||||
|
|
@ -350,7 +349,7 @@ found:
|
|||
usb_gadget_connect(udc->gadget);
|
||||
} else {
|
||||
|
||||
ret = usb_gadget_start(udc->gadget, driver, bind);
|
||||
ret = usb_gadget_start(udc->gadget, driver, driver->bind);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/device.h>
|
||||
|
|
@ -68,4 +69,4 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
|
|||
buf [1] = USB_DT_STRING;
|
||||
return buf [0];
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(usb_gadget_get_string);
|
||||
|
|
|
|||
|
|
@ -23,16 +23,12 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "uvc_queue.c"
|
||||
#include "uvc_video.c"
|
||||
#include "uvc_v4l2.c"
|
||||
#include "f_uvc.c"
|
||||
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
/* --------------------------------------------------------------------------
|
||||
* Device descriptor
|
||||
*/
|
||||
|
|
@ -47,13 +43,12 @@ static char webcam_config_label[] = "Video";
|
|||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_DESCRIPTION_IDX 2
|
||||
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
|
||||
|
||||
static struct usb_string webcam_strings[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = webcam_vendor_label,
|
||||
[STRING_PRODUCT_IDX].s = webcam_product_label,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label,
|
||||
[USB_GADGET_PRODUCT_IDX].s = webcam_product_label,
|
||||
[USB_GADGET_SERIAL_IDX].s = "",
|
||||
[STRING_DESCRIPTION_IDX].s = webcam_config_label,
|
||||
{ }
|
||||
};
|
||||
|
|
@ -358,26 +353,22 @@ webcam_bind(struct usb_composite_dev *cdev)
|
|||
/* Allocate string descriptor numbers ... note that string contents
|
||||
* can be overridden by the composite_dev glue.
|
||||
*/
|
||||
if ((ret = usb_string_id(cdev)) < 0)
|
||||
ret = usb_string_ids_tab(cdev, webcam_strings);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
webcam_strings[STRING_MANUFACTURER_IDX].id = ret;
|
||||
webcam_device_descriptor.iManufacturer = ret;
|
||||
|
||||
if ((ret = usb_string_id(cdev)) < 0)
|
||||
goto error;
|
||||
webcam_strings[STRING_PRODUCT_IDX].id = ret;
|
||||
webcam_device_descriptor.iProduct = ret;
|
||||
|
||||
if ((ret = usb_string_id(cdev)) < 0)
|
||||
goto error;
|
||||
webcam_strings[STRING_DESCRIPTION_IDX].id = ret;
|
||||
webcam_config_driver.iConfiguration = ret;
|
||||
webcam_device_descriptor.iManufacturer =
|
||||
webcam_strings[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
webcam_device_descriptor.iProduct =
|
||||
webcam_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
webcam_config_driver.iConfiguration =
|
||||
webcam_strings[STRING_DESCRIPTION_IDX].id;
|
||||
|
||||
/* Register our configuration. */
|
||||
if ((ret = usb_add_config(cdev, &webcam_config_driver,
|
||||
webcam_config_bind)) < 0)
|
||||
goto error;
|
||||
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
INFO(cdev, "Webcam Video Gadget\n");
|
||||
return 0;
|
||||
|
||||
|
|
@ -390,18 +381,19 @@ error:
|
|||
* Driver
|
||||
*/
|
||||
|
||||
static struct usb_composite_driver webcam_driver = {
|
||||
static __refdata struct usb_composite_driver webcam_driver = {
|
||||
.name = "g_webcam",
|
||||
.dev = &webcam_device_descriptor,
|
||||
.strings = webcam_device_strings,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.bind = webcam_bind,
|
||||
.unbind = webcam_unbind,
|
||||
};
|
||||
|
||||
static int __init
|
||||
webcam_init(void)
|
||||
{
|
||||
return usb_composite_probe(&webcam_driver, webcam_bind);
|
||||
return usb_composite_probe(&webcam_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "g_zero.h"
|
||||
|
|
@ -58,15 +57,11 @@
|
|||
* the runtime footprint, and giving us at least some parts of what
|
||||
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
||||
*/
|
||||
#include "composite.c"
|
||||
#include "usbstring.c"
|
||||
#include "config.c"
|
||||
#include "epautoconf.c"
|
||||
|
||||
#include "f_sourcesink.c"
|
||||
#include "f_loopback.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
USB_GADGET_COMPOSITE_OPTIONS();
|
||||
|
||||
#define DRIVER_VERSION "Cinco de Mayo 2008"
|
||||
|
||||
|
|
@ -141,20 +136,13 @@ const struct usb_descriptor_header *otg_desc[] = {
|
|||
#endif
|
||||
|
||||
/* string IDs are assigned dynamically */
|
||||
|
||||
#define STRING_MANUFACTURER_IDX 0
|
||||
#define STRING_PRODUCT_IDX 1
|
||||
#define STRING_SERIAL_IDX 2
|
||||
|
||||
static char manufacturer[50];
|
||||
|
||||
/* default serial number takes at least two packets */
|
||||
static char serial[] = "0123456789.0123456789.0123456789";
|
||||
|
||||
static struct usb_string strings_dev[] = {
|
||||
[STRING_MANUFACTURER_IDX].s = manufacturer,
|
||||
[STRING_PRODUCT_IDX].s = longname,
|
||||
[STRING_SERIAL_IDX].s = serial,
|
||||
[USB_GADGET_MANUFACTURER_IDX].s = "",
|
||||
[USB_GADGET_PRODUCT_IDX].s = longname,
|
||||
[USB_GADGET_SERIAL_IDX].s = serial,
|
||||
{ } /* end of list */
|
||||
};
|
||||
|
||||
|
|
@ -265,30 +253,18 @@ static void zero_resume(struct usb_composite_dev *cdev)
|
|||
|
||||
static int __init zero_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
int gcnum;
|
||||
struct usb_gadget *gadget = cdev->gadget;
|
||||
int id;
|
||||
int status;
|
||||
|
||||
/* Allocate string descriptor numbers ... note that string
|
||||
* contents can be overridden by the composite_dev glue.
|
||||
*/
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
strings_dev[STRING_MANUFACTURER_IDX].id = id;
|
||||
device_desc.iManufacturer = id;
|
||||
status = usb_string_ids_tab(cdev, strings_dev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
strings_dev[STRING_PRODUCT_IDX].id = id;
|
||||
device_desc.iProduct = id;
|
||||
|
||||
id = usb_string_id(cdev);
|
||||
if (id < 0)
|
||||
return id;
|
||||
strings_dev[STRING_SERIAL_IDX].id = id;
|
||||
device_desc.iSerialNumber = id;
|
||||
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
|
||||
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
|
||||
device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id;
|
||||
|
||||
setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
|
||||
|
||||
|
|
@ -303,28 +279,10 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
|
|||
loopback_add(cdev, autoresume != 0);
|
||||
}
|
||||
|
||||
gcnum = usb_gadget_controller_number(gadget);
|
||||
if (gcnum >= 0)
|
||||
device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
|
||||
else {
|
||||
/* gadget zero is so simple (for now, no altsettings) that
|
||||
* it SHOULD NOT have problems with bulk-capable hardware.
|
||||
* so just warn about unrcognized controllers -- don't panic.
|
||||
*
|
||||
* things like configuration and altsetting numbering
|
||||
* can need hardware-specific attention though.
|
||||
*/
|
||||
pr_warning("%s: controller '%s' not recognized\n",
|
||||
longname, gadget->name);
|
||||
device_desc.bcdDevice = cpu_to_le16(0x9999);
|
||||
}
|
||||
usb_composite_overwrite_options(cdev, &coverwrite);
|
||||
|
||||
INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
|
||||
|
||||
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
gadget->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -334,11 +292,12 @@ static int zero_unbind(struct usb_composite_dev *cdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_composite_driver zero_driver = {
|
||||
static __refdata struct usb_composite_driver zero_driver = {
|
||||
.name = "zero",
|
||||
.dev = &device_desc,
|
||||
.strings = dev_strings,
|
||||
.max_speed = USB_SPEED_SUPER,
|
||||
.bind = zero_bind,
|
||||
.unbind = zero_unbind,
|
||||
.suspend = zero_suspend,
|
||||
.resume = zero_resume,
|
||||
|
|
@ -349,7 +308,7 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
return usb_composite_probe(&zero_driver, zero_bind);
|
||||
return usb_composite_probe(&zero_driver);
|
||||
}
|
||||
module_init(init);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ config USB_C67X00_HCD
|
|||
module will be called c67x00.
|
||||
|
||||
config USB_XHCI_HCD
|
||||
tristate "xHCI HCD (USB 3.0) support (EXPERIMENTAL)"
|
||||
depends on USB && USB_ARCH_HAS_XHCI && EXPERIMENTAL
|
||||
tristate "xHCI HCD (USB 3.0) support"
|
||||
depends on USB && USB_ARCH_HAS_XHCI
|
||||
---help---
|
||||
The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0
|
||||
"SuperSpeed" host controller hardware.
|
||||
|
|
@ -262,7 +262,7 @@ config USB_ISP116X_HCD
|
|||
|
||||
config USB_ISP1760_HCD
|
||||
tristate "ISP 1760 HCD support"
|
||||
depends on USB && EXPERIMENTAL
|
||||
depends on USB
|
||||
---help---
|
||||
The ISP1760 chip is a USB 2.0 host controller.
|
||||
|
||||
|
|
@ -292,7 +292,7 @@ config USB_OHCI_HCD
|
|||
depends on USB && USB_ARCH_HAS_OHCI
|
||||
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
|
||||
select USB_OTG_UTILS if ARCH_OMAP
|
||||
select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008
|
||||
depends on USB_ISP1301 || !(ARCH_LPC32XX || ARCH_PNX4008)
|
||||
---help---
|
||||
The Open Host Controller Interface (OHCI) is a standard for accessing
|
||||
USB 1.1 host controller hardware. It does more in hardware than Intel's
|
||||
|
|
@ -376,7 +376,7 @@ config USB_OHCI_HCD_PCI
|
|||
|
||||
config USB_OHCI_HCD_SSB
|
||||
bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)"
|
||||
depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL
|
||||
depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD)
|
||||
select USB_HCD_SSB
|
||||
select USB_OHCI_HCD_PLATFORM
|
||||
default n
|
||||
|
|
@ -414,21 +414,21 @@ config USB_CNS3XXX_OHCI
|
|||
|
||||
config USB_OHCI_HCD_PLATFORM
|
||||
bool "Generic OHCI driver for a platform device"
|
||||
depends on USB_OHCI_HCD && EXPERIMENTAL
|
||||
depends on USB_OHCI_HCD
|
||||
default n
|
||||
---help---
|
||||
Adds an OHCI host driver for a generic platform device, which
|
||||
provieds a memory space and an irq.
|
||||
provides a memory space and an irq.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config USB_EHCI_HCD_PLATFORM
|
||||
bool "Generic EHCI driver for a platform device"
|
||||
depends on USB_EHCI_HCD && EXPERIMENTAL
|
||||
depends on USB_EHCI_HCD
|
||||
default n
|
||||
---help---
|
||||
Adds an EHCI host driver for a generic platform device, which
|
||||
provieds a memory space and an irq.
|
||||
provides a memory space and an irq.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ config USB_OHCI_LITTLE_ENDIAN
|
|||
|
||||
config USB_UHCI_HCD
|
||||
tristate "UHCI HCD (most Intel and VIA) support"
|
||||
depends on USB && (PCI || SPARC_LEON)
|
||||
depends on USB && (PCI || SPARC_LEON || ARCH_VT8500)
|
||||
---help---
|
||||
The Universal Host Controller Interface is a standard by Intel for
|
||||
accessing the USB hardware in the PC (which is also called the USB
|
||||
|
|
@ -468,7 +468,15 @@ config USB_UHCI_HCD
|
|||
config USB_UHCI_SUPPORT_NON_PCI_HC
|
||||
bool
|
||||
depends on USB_UHCI_HCD
|
||||
default y if SPARC_LEON
|
||||
default y if (SPARC_LEON || ARCH_VT8500)
|
||||
|
||||
config USB_UHCI_PLATFORM
|
||||
bool "Generic UHCI Platform Driver support"
|
||||
depends on USB_UHCI_SUPPORT_NON_PCI_HC
|
||||
default y if ARCH_VT8500
|
||||
---help---
|
||||
Enable support for generic UHCI platform devices that require no
|
||||
additional configuration.
|
||||
|
||||
config USB_UHCI_BIG_ENDIAN_MMIO
|
||||
bool
|
||||
|
|
@ -583,8 +591,7 @@ config USB_RENESAS_USBHS_HCD
|
|||
module will be called renesas-usbhs.
|
||||
|
||||
config USB_WHCI_HCD
|
||||
tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
tristate "Wireless USB Host Controller Interface (WHCI) driver"
|
||||
depends on PCI && USB && UWB
|
||||
select USB_WUSB
|
||||
select UWB_WHCI
|
||||
|
|
@ -596,8 +603,7 @@ config USB_WHCI_HCD
|
|||
will be called "whci-hcd".
|
||||
|
||||
config USB_HWA_HCD
|
||||
tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
tristate "Host Wire Adapter (HWA) driver"
|
||||
depends on USB && UWB
|
||||
select USB_WUSB
|
||||
select UWB_HWA
|
||||
|
|
@ -648,7 +654,7 @@ config USB_OCTEON2_COMMON
|
|||
|
||||
config USB_HCD_BCMA
|
||||
tristate "BCMA usb host driver"
|
||||
depends on BCMA && EXPERIMENTAL
|
||||
depends on BCMA
|
||||
select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
|
||||
select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
|
||||
help
|
||||
|
|
@ -660,7 +666,7 @@ config USB_HCD_BCMA
|
|||
|
||||
config USB_HCD_SSB
|
||||
tristate "SSB usb host driver"
|
||||
depends on SSB && EXPERIMENTAL
|
||||
depends on SSB
|
||||
select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
|
||||
select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
|
||||
help
|
||||
|
|
|
|||
|
|
@ -150,31 +150,24 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
|
|||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
|
||||
driver->description)) {
|
||||
dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
retval = -EBUSY;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
|
||||
hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (hcd->regs == NULL) {
|
||||
dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
retval = -EFAULT;
|
||||
goto fail_ioremap;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
|
||||
iclk = clk_get(&pdev->dev, "ehci_clk");
|
||||
iclk = devm_clk_get(&pdev->dev, "ehci_clk");
|
||||
if (IS_ERR(iclk)) {
|
||||
dev_err(&pdev->dev, "Error getting interface clock\n");
|
||||
retval = -ENOENT;
|
||||
goto fail_get_iclk;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
fclk = clk_get(&pdev->dev, "uhpck");
|
||||
fclk = devm_clk_get(&pdev->dev, "uhpck");
|
||||
if (IS_ERR(fclk)) {
|
||||
dev_err(&pdev->dev, "Error getting function clock\n");
|
||||
retval = -ENOENT;
|
||||
goto fail_get_fclk;
|
||||
goto fail_request_resource;
|
||||
}
|
||||
|
||||
atmel_start_ehci(pdev);
|
||||
|
|
@ -187,13 +180,6 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
|
|||
|
||||
fail_add_hcd:
|
||||
atmel_stop_ehci(pdev);
|
||||
clk_put(fclk);
|
||||
fail_get_fclk:
|
||||
clk_put(iclk);
|
||||
fail_get_iclk:
|
||||
iounmap(hcd->regs);
|
||||
fail_ioremap:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
fail_request_resource:
|
||||
usb_put_hcd(hcd);
|
||||
fail_create_hcd:
|
||||
|
|
@ -209,13 +195,9 @@ static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
|
|||
|
||||
ehci_shutdown(hcd);
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
atmel_stop_ehci(pdev);
|
||||
clk_put(fclk);
|
||||
clk_put(iclk);
|
||||
fclk = iclk = NULL;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -98,23 +98,17 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
|||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
pr_debug("request_mem_region failed");
|
||||
ret = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!hcd->regs) {
|
||||
pr_debug("ioremap failed");
|
||||
pr_debug("devm_request_and_ioremap failed");
|
||||
ret = -ENOMEM;
|
||||
goto err2;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) {
|
||||
printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
|
||||
ret = -ENODEV;
|
||||
goto err3;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ret = usb_add_hcd(hcd, pdev->resource[1].start,
|
||||
|
|
@ -125,10 +119,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
|
||||
err3:
|
||||
iounmap(hcd->regs);
|
||||
err2:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err1:
|
||||
usb_put_hcd(hcd);
|
||||
return ret;
|
||||
|
|
@ -140,8 +130,6 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
|
|||
|
||||
usb_remove_hcd(hcd);
|
||||
alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
usb_put_hcd(hcd);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -105,27 +105,17 @@ static int cns3xxx_ehci_probe(struct platform_device *pdev)
|
|||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
|
||||
driver->description)) {
|
||||
dev_dbg(dev, "controller already in use\n");
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (hcd->regs == NULL) {
|
||||
dev_dbg(dev, "error mapping memory\n");
|
||||
retval = -EFAULT;
|
||||
goto err2;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
|
||||
if (retval == 0)
|
||||
return retval;
|
||||
|
||||
iounmap(hcd->regs);
|
||||
err2:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err1:
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
|
|
@ -137,8 +127,6 @@ static int cns3xxx_ehci_remove(struct platform_device *pdev)
|
|||
struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
iounmap(hcd->regs);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
|
||||
/*
|
||||
* EHCI and OHCI share the same clock and power,
|
||||
|
|
|
|||
|
|
@ -653,10 +653,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
|
|||
seen [seen_count++].qh = p.qh;
|
||||
} else
|
||||
temp = 0;
|
||||
if (p.qh) {
|
||||
tag = Q_NEXT_TYPE(ehci, hw->hw_next);
|
||||
p = p.qh->qh_next;
|
||||
}
|
||||
tag = Q_NEXT_TYPE(ehci, hw->hw_next);
|
||||
p = p.qh->qh_next;
|
||||
break;
|
||||
case Q_TYPE_FSTN:
|
||||
temp = scnprintf (next, size,
|
||||
|
|
|
|||
|
|
@ -210,11 +210,11 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
|
|||
usb_put_hcd(hcd);
|
||||
}
|
||||
|
||||
static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
||||
static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
||||
enum fsl_usb2_phy_modes phy_mode,
|
||||
unsigned int port_offset)
|
||||
{
|
||||
u32 portsc, temp;
|
||||
u32 portsc;
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
void __iomem *non_ehci = hcd->regs;
|
||||
struct device *dev = hcd->self.controller;
|
||||
|
|
@ -232,9 +232,15 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
|||
case FSL_USB2_PHY_ULPI:
|
||||
if (pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
|
||||
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
|
||||
USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL);
|
||||
setbits32(non_ehci + FSL_SOC_USB_CTRL,
|
||||
ULPI_PHY_CLK_SEL);
|
||||
/*
|
||||
* Due to controller issue of PHY_CLK_VALID in ULPI
|
||||
* mode, we set USB_CTRL_USB_EN before checking
|
||||
* PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
|
||||
*/
|
||||
clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
|
||||
UTMI_PHY_EN, USB_CTRL_USB_EN);
|
||||
}
|
||||
portsc |= PORT_PTS_ULPI;
|
||||
break;
|
||||
|
|
@ -247,9 +253,7 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
|||
case FSL_USB2_PHY_UTMI:
|
||||
if (pdata->controller_ver) {
|
||||
/* controller version 1.6 or above */
|
||||
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
|
||||
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp |
|
||||
UTMI_PHY_EN | USB_CTRL_USB_EN);
|
||||
setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
|
||||
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
|
||||
become stable - 10ms*/
|
||||
}
|
||||
|
|
@ -262,23 +266,33 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd,
|
|||
case FSL_USB2_PHY_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
|
||||
/* check PHY_CLK_VALID to get phy clk valid */
|
||||
if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
|
||||
PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
|
||||
printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
|
||||
|
||||
if (phy_mode != FSL_USB2_PHY_ULPI)
|
||||
setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
||||
static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
||||
{
|
||||
struct usb_hcd *hcd = ehci_to_hcd(ehci);
|
||||
struct fsl_usb2_platform_data *pdata;
|
||||
void __iomem *non_ehci = hcd->regs;
|
||||
u32 temp;
|
||||
|
||||
pdata = hcd->self.controller->platform_data;
|
||||
|
||||
/* Enable PHY interface in the control reg. */
|
||||
if (pdata->have_sysif_regs) {
|
||||
temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
|
||||
out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
|
||||
|
||||
/*
|
||||
* Turn on cache snooping hardware, since some PowerPC platforms
|
||||
* wholly rely on hardware to deal with cache coherent
|
||||
|
|
@ -293,7 +307,8 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
|||
|
||||
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
|
||||
(pdata->operating_mode == FSL_USB2_DR_OTG))
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
|
||||
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
|
||||
unsigned int chip, rev, svr;
|
||||
|
|
@ -307,9 +322,12 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
|||
ehci->has_fsl_port_bug = 1;
|
||||
|
||||
if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0);
|
||||
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
|
||||
ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1);
|
||||
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pdata->have_sysif_regs) {
|
||||
|
|
@ -322,12 +340,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
|
|||
#endif
|
||||
out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called after powerup, by probe or system-pm "wakeup" */
|
||||
static int ehci_fsl_reinit(struct ehci_hcd *ehci)
|
||||
{
|
||||
ehci_fsl_usb_setup(ehci);
|
||||
if (ehci_fsl_usb_setup(ehci))
|
||||
return -EINVAL;
|
||||
ehci_port_power(ehci, 0);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -61,4 +61,5 @@
|
|||
#define PLL_RESET (1<<8)
|
||||
#define UTMI_PHY_EN (1<<9)
|
||||
#define ULPI_PHY_CLK_SEL (1<<10)
|
||||
#define PHY_CLK_VALID (1<<17)
|
||||
#endif /* _EHCI_FSL_H */
|
||||
|
|
|
|||
|
|
@ -127,12 +127,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
|
|||
hcd->rsrc_start = res.start;
|
||||
hcd->rsrc_len = resource_size(&res);
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__);
|
||||
rv = -EBUSY;
|
||||
goto err_rmr;
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(dn, 0);
|
||||
if (irq == NO_IRQ) {
|
||||
printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
|
||||
|
|
@ -140,9 +134,9 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
|
|||
goto err_irq;
|
||||
}
|
||||
|
||||
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
hcd->regs = devm_request_and_ioremap(&op->dev, &res);
|
||||
if (!hcd->regs) {
|
||||
printk(KERN_ERR "%s: ioremap failed\n", __FILE__);
|
||||
pr_err("%s: devm_request_and_ioremap failed\n", __FILE__);
|
||||
rv = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
|
@ -161,17 +155,13 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
|
|||
|
||||
rv = usb_add_hcd(hcd, irq, 0);
|
||||
if (rv)
|
||||
goto err_ehci;
|
||||
goto err_ioremap;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ehci:
|
||||
iounmap(hcd->regs);
|
||||
err_ioremap:
|
||||
irq_dispose_mapping(irq);
|
||||
err_irq:
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
err_rmr:
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
return rv;
|
||||
|
|
@ -188,9 +178,7 @@ static int ehci_hcd_grlib_remove(struct platform_device *op)
|
|||
|
||||
usb_remove_hcd(hcd);
|
||||
|
||||
iounmap(hcd->regs);
|
||||
irq_dispose_mapping(hcd->irq);
|
||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
|
||||
usb_put_hcd(hcd);
|
||||
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
|
|||
|
||||
/* If the EHCI debug controller is active, special care must be
|
||||
* taken before and after a host controller reset */
|
||||
if (ehci->debug && !dbgp_reset_prep())
|
||||
if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci)))
|
||||
ehci->debug = NULL;
|
||||
|
||||
command |= CMD_RESET;
|
||||
|
|
@ -251,7 +251,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
|
|||
tdi_reset (ehci);
|
||||
|
||||
if (ehci->debug)
|
||||
dbgp_external_startup();
|
||||
dbgp_external_startup(ehci_to_hcd(ehci));
|
||||
|
||||
ehci->port_c_suspend = ehci->suspended_ports =
|
||||
ehci->resuming_ports = 0;
|
||||
|
|
|
|||
|
|
@ -353,10 +353,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
|||
goto shutdown;
|
||||
|
||||
if (unlikely(ehci->debug)) {
|
||||
if (!dbgp_reset_prep())
|
||||
if (!dbgp_reset_prep(hcd))
|
||||
ehci->debug = NULL;
|
||||
else
|
||||
dbgp_external_startup();
|
||||
dbgp_external_startup(hcd);
|
||||
}
|
||||
|
||||
/* Ideally and we've got a real resume here, and no port's power
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue