Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (32 commits)
  USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance, clear-feature ignore
  USB GADGET/PERIPHERAL: g_file_storage Bulk-Only Transport compliance
  usb_serial: some coding style fixes
  USB: Remove redundant dependencies on USB_ATM.
  USB: UHCI: disable remote wakeup when it's not needed
  USB: OHCI: work around bogus compiler warning
  USB: add Cypress c67x00 OTG controller HCD driver
  USB: add Cypress c67x00 OTG controller core driver
  USB: add Cypress c67x00 low level interface code
  USB: airprime: unlock mutex instead of trying to lock it again
  USB: storage: Update mailling list address
  USB: storage: UNUSUAL_DEVS() for PanDigital Picture frame.
  USB: Add the USB 2.0 extension descriptor.
  USB: add more FTDI device ids
  USB: fix cannot work usb storage when using ohci-sm501
  usb: gadget zero timer init fix
  usb: gadget zero style fixups (mostly whitespace)
  usb serial gadget: CDC ACM fixes
  usb: pxa27x_udc driver
  USB: INTOVA Pixtreme camera mass storage device
  ...
This commit is contained in:
Linus Torvalds 2008-05-02 11:03:08 -07:00
commit 1be1d6b7f3
45 changed files with 9213 additions and 537 deletions

View file

@ -4051,6 +4051,12 @@ L: linux-usb@vger.kernel.org
S: Maintained
W: http://www.kroah.com/linux-usb/
USB CYPRESS C67X00 DRIVER
P: Peter Korsgaard
M: jacmet@sunsite.dk
L: linux-usb@vger.kernel.org
S: Maintained
USB DAVICOM DM9601 DRIVER
P: Peter Korsgaard
M: jacmet@sunsite.dk

View file

@ -205,6 +205,7 @@ struct ub_scsi_cmd {
unsigned char key, asc, ascq; /* May be valid if error==-EIO */
int stat_count; /* Retries getting status. */
unsigned int timeo; /* jiffies until rq->timeout changes */
unsigned int len; /* Requested length */
unsigned int current_sg;
@ -318,6 +319,7 @@ struct ub_dev {
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
int reset; /* Reset is running */
int bad_resid;
unsigned int tagcnt;
char name[12];
struct usb_device *dev;
@ -764,6 +766,12 @@ static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb_len = rq->cmd_len;
cmd->len = rq->data_len;
/*
* To reapply this to every URB is not as incorrect as it looks.
* In return, we avoid any complicated tracking calculations.
*/
cmd->timeo = rq->timeout;
}
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
@ -785,10 +793,6 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
scsi_status = 0;
} else {
if (cmd->act_len != cmd->len) {
if ((cmd->key == MEDIUM_ERROR ||
cmd->key == UNIT_ATTENTION) &&
ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return;
scsi_status = SAM_STAT_CHECK_CONDITION;
} else {
scsi_status = 0;
@ -804,7 +808,10 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
scsi_status = DID_ERROR << 16;
} else {
if (cmd->error == -EIO) {
if (cmd->error == -EIO &&
(cmd->key == 0 ||
cmd->key == MEDIUM_ERROR ||
cmd->key == UNIT_ATTENTION)) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return;
}
@ -1259,14 +1266,19 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
len = le32_to_cpu(bcs->Residue);
if (len != cmd->len - cmd->act_len) {
/*
* It is all right to transfer less, the caller has
* to check. But it's not all right if the device
* counts disagree with our counts.
*/
goto Bad_End;
if (!sc->bad_resid) {
len = le32_to_cpu(bcs->Residue);
if (len != cmd->len - cmd->act_len) {
/*
* Only start ignoring if this cmd ended well.
*/
if (cmd->len == cmd->act_len) {
printk(KERN_NOTICE "%s: "
"bad residual %d of %d, ignoring\n",
sc->name, len, cmd->len);
sc->bad_resid = 1;
}
}
}
switch (bcs->Status) {
@ -1297,8 +1309,7 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_state_done(sc, cmd, -EIO);
} else {
printk(KERN_WARNING "%s: "
"wrong command state %d\n",
printk(KERN_WARNING "%s: wrong command state %d\n",
sc->name, cmd->state);
ub_state_done(sc, cmd, -EINVAL);
return;
@ -1336,7 +1347,10 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
if (cmd->timeo)
sc->work_timer.expires = jiffies + cmd->timeo;
else
sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
add_timer(&sc->work_timer);
cmd->state = UB_CMDST_DATA;
@ -1376,7 +1390,10 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return -1;
}
sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT;
if (cmd->timeo)
sc->work_timer.expires = jiffies + cmd->timeo;
else
sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT;
add_timer(&sc->work_timer);
return 0;
}
@ -1515,8 +1532,7 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
return;
}
if (cmd->state != UB_CMDST_SENSE) {
printk(KERN_WARNING "%s: "
"sense done with bad cmd state %d\n",
printk(KERN_WARNING "%s: sense done with bad cmd state %d\n",
sc->name, cmd->state);
return;
}
@ -1720,7 +1736,7 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
}
/*
* This is called once a new disk was seen by the block layer or by ub_probe().
* This is called by check_disk_change if we reported a media change.
* The main onjective here is to discover the features of the media such as
* the capacity, read-only status, etc. USB storage generally does not
* need to be spun up, but if we needed it, this would be the place.
@ -2136,8 +2152,7 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
}
if (ep_in == NULL || ep_out == NULL) {
printk(KERN_NOTICE "%s: failed endpoint check\n",
sc->name);
printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name);
return -ENODEV;
}
@ -2354,7 +2369,7 @@ static void ub_disconnect(struct usb_interface *intf)
spin_unlock_irqrestore(&ub_lock, flags);
/*
* Fence stall clearnings, operations triggered by unlinkings and so on.
* Fence stall clearings, operations triggered by unlinkings and so on.
* We do not attempt to unlink any URBs, because we do not trust the
* unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
*/
@ -2417,7 +2432,7 @@ static void ub_disconnect(struct usb_interface *intf)
spin_unlock_irqrestore(sc->lock, flags);
/*
* There is virtually no chance that other CPU runs times so long
* There is virtually no chance that other CPU runs a timeout so long
* after ub_urb_complete should have called del_timer, but only if HCD
* didn't forget to deliver a callback on unlink.
*/

View file

@ -17,6 +17,8 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_PRINTER) += class/

View file

@ -19,7 +19,6 @@ if USB_ATM
config USB_SPEEDTOUCH
tristate "Speedtouch USB support"
depends on USB_ATM
select FW_LOADER
help
Say Y here if you have an SpeedTouch USB or SpeedTouch 330
@ -32,7 +31,6 @@ config USB_SPEEDTOUCH
config USB_CXACRU
tristate "Conexant AccessRunner USB support"
depends on USB_ATM
select FW_LOADER
help
Say Y here if you have an ADSL USB modem based on the Conexant
@ -45,7 +43,6 @@ config USB_CXACRU
config USB_UEAGLEATM
tristate "ADI 930 and eagle USB DSL modem"
depends on USB_ATM
select FW_LOADER
help
Say Y here if you have an ADSL USB modem based on the ADI 930
@ -58,7 +55,6 @@ config USB_UEAGLEATM
config USB_XUSBATM
tristate "Other USB DSL modem support"
depends on USB_ATM
help
Say Y here if you have a DSL USB modem not explicitly supported by
another USB DSL drivers. In order to use your modem you will need to

View file

@ -0,0 +1,9 @@
#
# Makefile for Cypress C67X00 USB Controller
#
ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
obj-$(CONFIG_USB_C67X00_HCD) += c67x00.o
c67x00-objs := c67x00-drv.o c67x00-ll-hpi.o c67x00-hcd.o c67x00-sched.o

View file

@ -0,0 +1,243 @@
/*
* c67x00-drv.c: Cypress C67X00 USB Common infrastructure
*
* Copyright (C) 2006-2008 Barco N.V.
* Derived from the Cypress cy7c67200/300 ezusb linux driver and
* based on multiple host controller drivers inside the linux kernel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
/*
* This file implements the common infrastructure for using the c67x00.
* It is both the link between the platform configuration and subdrivers and
* the link between the common hardware parts and the subdrivers (e.g.
* interrupt handling).
*
* The c67x00 has 2 SIE's (serial interface engine) wich can be configured
* to be host, device or OTG (with some limitations, E.G. only SIE1 can be OTG).
*
* Depending on the platform configuration, the SIE's are created and
* the corresponding subdriver is initialized (c67x00_probe_sie).
*/
#include <linux/device.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/usb/c67x00.h>
#include "c67x00.h"
#include "c67x00-hcd.h"
static void c67x00_probe_sie(struct c67x00_sie *sie,
struct c67x00_device *dev, int sie_num)
{
spin_lock_init(&sie->lock);
sie->dev = dev;
sie->sie_num = sie_num;
sie->mode = c67x00_sie_config(dev->pdata->sie_config, sie_num);
switch (sie->mode) {
case C67X00_SIE_HOST:
c67x00_hcd_probe(sie);
break;
case C67X00_SIE_UNUSED:
dev_info(sie_dev(sie),
"Not using SIE %d as requested\n", sie->sie_num);
break;
default:
dev_err(sie_dev(sie),
"Unsupported configuration: 0x%x for SIE %d\n",
sie->mode, sie->sie_num);
break;
}
}
static void c67x00_remove_sie(struct c67x00_sie *sie)
{
switch (sie->mode) {
case C67X00_SIE_HOST:
c67x00_hcd_remove(sie);
break;
default:
break;
}
}
static irqreturn_t c67x00_irq(int irq, void *__dev)
{
struct c67x00_device *c67x00 = __dev;
struct c67x00_sie *sie;
u16 msg, int_status;
int i, count = 8;
int_status = c67x00_ll_hpi_status(c67x00);
if (!int_status)
return IRQ_NONE;
while (int_status != 0 && (count-- >= 0)) {
c67x00_ll_irq(c67x00, int_status);
for (i = 0; i < C67X00_SIES; i++) {
sie = &c67x00->sie[i];
msg = 0;
if (int_status & SIEMSG_FLG(i))
msg = c67x00_ll_fetch_siemsg(c67x00, i);
if (sie->irq)
sie->irq(sie, int_status, msg);
}
int_status = c67x00_ll_hpi_status(c67x00);
}
if (int_status)
dev_warn(&c67x00->pdev->dev, "Not all interrupts handled! "
"status = 0x%04x\n", int_status);
return IRQ_HANDLED;
}
/* ------------------------------------------------------------------------- */
static int __devinit c67x00_drv_probe(struct platform_device *pdev)
{
struct c67x00_device *c67x00;
struct c67x00_platform_data *pdata;
struct resource *res, *res2;
int ret, i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res2)
return -ENODEV;
pdata = pdev->dev.platform_data;
if (!pdata)
return -ENODEV;
c67x00 = kzalloc(sizeof(*c67x00), GFP_KERNEL);
if (!c67x00)
return -ENOMEM;
if (!request_mem_region(res->start, res->end - res->start + 1,
pdev->name)) {
dev_err(&pdev->dev, "Memory region busy\n");
ret = -EBUSY;
goto request_mem_failed;
}
c67x00->hpi.base = ioremap(res->start, res->end - res->start + 1);
if (!c67x00->hpi.base) {
dev_err(&pdev->dev, "Unable to map HPI registers\n");
ret = -EIO;
goto map_failed;
}
spin_lock_init(&c67x00->hpi.lock);
c67x00->hpi.regstep = pdata->hpi_regstep;
c67x00->pdata = pdev->dev.platform_data;
c67x00->pdev = pdev;
c67x00_ll_init(c67x00);
c67x00_ll_hpi_reg_init(c67x00);
ret = request_irq(res2->start, c67x00_irq, 0, pdev->name, c67x00);
if (ret) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto request_irq_failed;
}
ret = c67x00_ll_reset(c67x00);
if (ret) {
dev_err(&pdev->dev, "Device reset failed\n");
goto reset_failed;
}
for (i = 0; i < C67X00_SIES; i++)
c67x00_probe_sie(&c67x00->sie[i], c67x00, i);
platform_set_drvdata(pdev, c67x00);
return 0;
reset_failed:
free_irq(res2->start, c67x00);
request_irq_failed:
iounmap(c67x00->hpi.base);
map_failed:
release_mem_region(res->start, res->end - res->start + 1);
request_mem_failed:
kfree(c67x00);
return ret;
}
static int __devexit c67x00_drv_remove(struct platform_device *pdev)
{
struct c67x00_device *c67x00 = platform_get_drvdata(pdev);
struct resource *res;
int i;
for (i = 0; i < C67X00_SIES; i++)
c67x00_remove_sie(&c67x00->sie[i]);
c67x00_ll_release(c67x00);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res)
free_irq(res->start, c67x00);
iounmap(c67x00->hpi.base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, res->end - res->start + 1);
kfree(c67x00);
return 0;
}
static struct platform_driver c67x00_driver = {
.probe = c67x00_drv_probe,
.remove = __devexit_p(c67x00_drv_remove),
.driver = {
.owner = THIS_MODULE,
.name = "c67x00",
},
};
MODULE_ALIAS("platform:c67x00");
static int __init c67x00_init(void)
{
return platform_driver_register(&c67x00_driver);
}
static void __exit c67x00_exit(void)
{
platform_driver_unregister(&c67x00_driver);
}
module_init(c67x00_init);
module_exit(c67x00_exit);
MODULE_AUTHOR("Peter Korsgaard, Jan Veldeman, Grant Likely");
MODULE_DESCRIPTION("Cypress C67X00 USB Controller Driver");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,412 @@
/*
* c67x00-hcd.c: Cypress C67X00 USB Host Controller Driver
*
* Copyright (C) 2006-2008 Barco N.V.
* Derived from the Cypress cy7c67200/300 ezusb linux driver and
* based on multiple host controller drivers inside the linux kernel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
#include "c67x00.h"
#include "c67x00-hcd.h"
/* --------------------------------------------------------------------------
* Root Hub Support
*/
static __u8 c67x00_hub_des[] = {
0x09, /* __u8 bLength; */
0x29, /* __u8 bDescriptorType; Hub-descriptor */
0x02, /* __u8 bNbrPorts; */
0x00, /* __u16 wHubCharacteristics; */
0x00, /* (per-port OC, no power switching) */
0x32, /* __u8 bPwrOn2pwrGood; 2ms */
0x00, /* __u8 bHubContrCurrent; 0 mA */
0x00, /* __u8 DeviceRemovable; ** 7 Ports max ** */
0xff, /* __u8 PortPwrCtrlMask; ** 7 ports max ** */
};
static void c67x00_hub_reset_host_port(struct c67x00_sie *sie, int port)
{
struct c67x00_hcd *c67x00 = sie->private_data;
unsigned long flags;
c67x00_ll_husb_reset(sie, port);
spin_lock_irqsave(&c67x00->lock, flags);
c67x00_ll_husb_reset_port(sie, port);
spin_unlock_irqrestore(&c67x00->lock, flags);
c67x00_ll_set_husb_eot(sie->dev, DEFAULT_EOT);
}
static int c67x00_hub_status_data(struct usb_hcd *hcd, char *buf)
{
struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
struct c67x00_sie *sie = c67x00->sie;
u16 status;
int i;
*buf = 0;
status = c67x00_ll_usb_get_status(sie);
for (i = 0; i < C67X00_PORTS; i++)
if (status & PORT_CONNECT_CHANGE(i))
*buf |= (1 << i);
/* bit 0 denotes hub change, b1..n port change */
*buf <<= 1;
return !!*buf;
}
static int c67x00_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength)
{
struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
struct c67x00_sie *sie = c67x00->sie;
u16 status, usb_status;
int len = 0;
unsigned int port = wIndex-1;
u16 wPortChange, wPortStatus;
switch (typeReq) {
case GetHubStatus:
*(__le32 *) buf = cpu_to_le32(0);
len = 4; /* hub power */
break;
case GetPortStatus:
if (wIndex > C67X00_PORTS)
return -EPIPE;
status = c67x00_ll_usb_get_status(sie);
usb_status = c67x00_ll_get_usb_ctl(sie);
wPortChange = 0;
if (status & PORT_CONNECT_CHANGE(port))
wPortChange |= USB_PORT_STAT_C_CONNECTION;
wPortStatus = USB_PORT_STAT_POWER;
if (!(status & PORT_SE0_STATUS(port)))
wPortStatus |= USB_PORT_STAT_CONNECTION;
if (usb_status & LOW_SPEED_PORT(port)) {
wPortStatus |= USB_PORT_STAT_LOW_SPEED;
c67x00->low_speed_ports |= (1 << port);
} else
c67x00->low_speed_ports &= ~(1 << port);
if (usb_status & SOF_EOP_EN(port))
wPortStatus |= USB_PORT_STAT_ENABLE;
*(__le16 *) buf = cpu_to_le16(wPortStatus);
*(__le16 *) (buf + 2) = cpu_to_le16(wPortChange);
len = 4;
break;
case SetHubFeature: /* We don't implement these */
case ClearHubFeature:
switch (wValue) {
case C_HUB_OVER_CURRENT:
case C_HUB_LOCAL_POWER:
len = 0;
break;
default:
return -EPIPE;
}
break;
case SetPortFeature:
if (wIndex > C67X00_PORTS)
return -EPIPE;
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
dev_dbg(c67x00_hcd_dev(c67x00),
"SetPortFeature %d (SUSPEND)\n", port);
len = 0;
break;
case USB_PORT_FEAT_RESET:
c67x00_hub_reset_host_port(sie, port);
len = 0;
break;
case USB_PORT_FEAT_POWER:
/* Power always enabled */
len = 0;
break;
default:
dev_dbg(c67x00_hcd_dev(c67x00),
"%s: SetPortFeature %d (0x%04x) Error!\n",
__func__, port, wValue);
return -EPIPE;
}
break;
case ClearPortFeature:
if (wIndex > C67X00_PORTS)
return -EPIPE;
switch (wValue) {
case USB_PORT_FEAT_ENABLE:
/* Reset the port so that the c67x00 also notices the
* disconnect */
c67x00_hub_reset_host_port(sie, port);
len = 0;
break;
case USB_PORT_FEAT_C_ENABLE:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): C_ENABLE\n", port);
len = 0;
break;
case USB_PORT_FEAT_SUSPEND:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): SUSPEND\n", port);
len = 0;
break;
case USB_PORT_FEAT_C_SUSPEND:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): C_SUSPEND\n", port);
len = 0;
break;
case USB_PORT_FEAT_POWER:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): POWER\n", port);
return -EPIPE;
case USB_PORT_FEAT_C_CONNECTION:
c67x00_ll_usb_clear_status(sie,
PORT_CONNECT_CHANGE(port));
len = 0;
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): OVER_CURRENT\n", port);
len = 0;
break;
case USB_PORT_FEAT_C_RESET:
dev_dbg(c67x00_hcd_dev(c67x00),
"ClearPortFeature (%d): C_RESET\n", port);
len = 0;
break;
default:
dev_dbg(c67x00_hcd_dev(c67x00),
"%s: ClearPortFeature %d (0x%04x) Error!\n",
__func__, port, wValue);
return -EPIPE;
}
break;
case GetHubDescriptor:
len = min_t(unsigned int, sizeof(c67x00_hub_des), wLength);
memcpy(buf, c67x00_hub_des, len);
break;
default:
dev_dbg(c67x00_hcd_dev(c67x00), "%s: unknown\n", __func__);
return -EPIPE;
}
return 0;
}
/* ---------------------------------------------------------------------
* Main part of host controller driver
*/
/**
* c67x00_hcd_irq
*
* This function is called from the interrupt handler in c67x00-drv.c
*/
static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
{
struct c67x00_hcd *c67x00 = sie->private_data;
struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
/* Handle sie message flags */
if (msg) {
if (msg & HUSB_TDListDone)
c67x00_sched_kick(c67x00);
else
dev_warn(c67x00_hcd_dev(c67x00),
"Unknown SIE msg flag(s): 0x%04x\n", msg);
}
if (unlikely(hcd->state == HC_STATE_HALT))
return;
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
return;
/* Handle Start of frame events */
if (int_status & SOFEOP_FLG(sie->sie_num)) {
c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG);
c67x00_sched_kick(c67x00);
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
}
}
/**
* c67x00_hcd_start: Host controller start hook
*/
static int c67x00_hcd_start(struct usb_hcd *hcd)
{
hcd->uses_new_polling = 1;
hcd->state = HC_STATE_RUNNING;
hcd->poll_rh = 1;
return 0;
}
/**
* c67x00_hcd_stop: Host controller stop hook
*/
static void c67x00_hcd_stop(struct usb_hcd *hcd)
{
/* Nothing to do */
}
static int c67x00_hcd_get_frame(struct usb_hcd *hcd)
{
struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd);
u16 temp_val;
dev_dbg(c67x00_hcd_dev(c67x00), "%s\n", __func__);
temp_val = c67x00_ll_husb_get_frame(c67x00->sie);
temp_val &= HOST_FRAME_MASK;
return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
}
static struct hc_driver c67x00_hc_driver = {
.description = "c67x00-hcd",
.product_desc = "Cypress C67X00 Host Controller",
.hcd_priv_size = sizeof(struct c67x00_hcd),
.flags = HCD_USB11 | HCD_MEMORY,
/*
* basic lifecycle operations
*/
.start = c67x00_hcd_start,
.stop = c67x00_hcd_stop,
/*
* managing i/o requests and associated device resources
*/
.urb_enqueue = c67x00_urb_enqueue,
.urb_dequeue = c67x00_urb_dequeue,
.endpoint_disable = c67x00_endpoint_disable,
/*
* scheduling support
*/
.get_frame_number = c67x00_hcd_get_frame,
/*
* root hub support
*/
.hub_status_data = c67x00_hub_status_data,
.hub_control = c67x00_hub_control,
};
/* ---------------------------------------------------------------------
* Setup/Teardown routines
*/
int c67x00_hcd_probe(struct c67x00_sie *sie)
{
struct c67x00_hcd *c67x00;
struct usb_hcd *hcd;
unsigned long flags;
int retval;
if (usb_disabled())
return -ENODEV;
hcd = usb_create_hcd(&c67x00_hc_driver, sie_dev(sie), "c67x00_sie");
if (!hcd) {
retval = -ENOMEM;
goto err0;
}
c67x00 = hcd_to_c67x00_hcd(hcd);
spin_lock_init(&c67x00->lock);
c67x00->sie = sie;
INIT_LIST_HEAD(&c67x00->list[PIPE_ISOCHRONOUS]);
INIT_LIST_HEAD(&c67x00->list[PIPE_INTERRUPT]);
INIT_LIST_HEAD(&c67x00->list[PIPE_CONTROL]);
INIT_LIST_HEAD(&c67x00->list[PIPE_BULK]);
c67x00->urb_count = 0;
INIT_LIST_HEAD(&c67x00->td_list);
c67x00->td_base_addr = CY_HCD_BUF_ADDR + SIE_TD_OFFSET(sie->sie_num);
c67x00->buf_base_addr = CY_HCD_BUF_ADDR + SIE_BUF_OFFSET(sie->sie_num);
c67x00->max_frame_bw = MAX_FRAME_BW_STD;
c67x00_ll_husb_init_host_port(sie);
init_completion(&c67x00->endpoint_disable);
retval = c67x00_sched_start_scheduler(c67x00);
if (retval)
goto err1;
retval = usb_add_hcd(hcd, 0, 0);
if (retval) {
dev_dbg(sie_dev(sie), "%s: usb_add_hcd returned %d\n",
__func__, retval);
goto err2;
}
spin_lock_irqsave(&sie->lock, flags);
sie->private_data = c67x00;
sie->irq = c67x00_hcd_irq;
spin_unlock_irqrestore(&sie->lock, flags);
return retval;
err2:
c67x00_sched_stop_scheduler(c67x00);
err1:
usb_put_hcd(hcd);
err0:
return retval;
}
/* may be called with controller, bus, and devices active */
void c67x00_hcd_remove(struct c67x00_sie *sie)
{
struct c67x00_hcd *c67x00 = sie->private_data;
struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00);
c67x00_sched_stop_scheduler(c67x00);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
}

View file

@ -0,0 +1,133 @@
/*
* c67x00-hcd.h: Cypress C67X00 USB HCD
*
* Copyright (C) 2006-2008 Barco N.V.
* Derived from the Cypress cy7c67200/300 ezusb linux driver and
* based on multiple host controller drivers inside the linux kernel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
#ifndef _USB_C67X00_HCD_H
#define _USB_C67X00_HCD_H
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/usb.h>
#include "../core/hcd.h"
#include "c67x00.h"
/*
* The following parameters depend on the CPU speed, bus speed, ...
* These can be tuned for specific use cases, e.g. if isochronous transfers
* are very important, bandwith can be sacrificed to guarantee that the
* 1ms deadline will be met.
* If bulk transfers are important, the MAX_FRAME_BW can be increased,
* but some (or many) isochronous deadlines might not be met.
*
* The values are specified in bittime.
*/
/*
* The current implementation switches between _STD (default) and _ISO (when
* isochronous transfers are scheduled), in order to optimize the throughput
* in normal cicrumstances, but also provide good isochronous behaviour.
*
* Bandwidth is described in bit time so with a 12MHz USB clock and 1ms
* frames; there are 12000 bit times per frame.
*/
#define TOTAL_FRAME_BW 12000
#define DEFAULT_EOT 2250
#define MAX_FRAME_BW_STD (TOTAL_FRAME_BW - DEFAULT_EOT)
#define MAX_FRAME_BW_ISO 2400
/*
* Periodic transfers may only use 90% of the full frame, but as
* we currently don't even use 90% of the full frame, we may
* use the full usable time for periodic transfers.
*/
#define MAX_PERIODIC_BW(full_bw) full_bw
/* -------------------------------------------------------------------------- */
struct c67x00_hcd {
spinlock_t lock;
struct c67x00_sie *sie;
unsigned int low_speed_ports; /* bitmask of low speed ports */
unsigned int urb_count;
unsigned int urb_iso_count;
struct list_head list[4]; /* iso, int, ctrl, bulk */
#if PIPE_BULK != 3
#error "Sanity check failed, this code presumes PIPE_... to range from 0 to 3"
#endif
/* USB bandwidth allocated to td_list */
int bandwidth_allocated;
/* USB bandwidth allocated for isoc/int transfer */
int periodic_bw_allocated;
struct list_head td_list;
int max_frame_bw;
u16 td_base_addr;
u16 buf_base_addr;
u16 next_td_addr;
u16 next_buf_addr;
struct tasklet_struct tasklet;
struct completion endpoint_disable;
u16 current_frame;
u16 last_frame;
};
static inline struct c67x00_hcd *hcd_to_c67x00_hcd(struct usb_hcd *hcd)
{
return (struct c67x00_hcd *)(hcd->hcd_priv);
}
static inline struct usb_hcd *c67x00_hcd_to_hcd(struct c67x00_hcd *c67x00)
{
return container_of((void *)c67x00, struct usb_hcd, hcd_priv);
}
/* ---------------------------------------------------------------------
* Functions used by c67x00-drv
*/
int c67x00_hcd_probe(struct c67x00_sie *sie);
void c67x00_hcd_remove(struct c67x00_sie *sie);
/* ---------------------------------------------------------------------
* Transfer Descriptor scheduling functions
*/
int c67x00_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
int c67x00_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
void c67x00_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *ep);
void c67x00_hcd_msg_received(struct c67x00_sie *sie, u16 msg);
void c67x00_sched_kick(struct c67x00_hcd *c67x00);
int c67x00_sched_start_scheduler(struct c67x00_hcd *c67x00);
void c67x00_sched_stop_scheduler(struct c67x00_hcd *c67x00);
#define c67x00_hcd_dev(x) (c67x00_hcd_to_hcd(x)->self.controller)
#endif /* _USB_C67X00_HCD_H */

View file

@ -0,0 +1,480 @@
/*
* c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI
*
* Copyright (C) 2006-2008 Barco N.V.
* Derived from the Cypress cy7c67200/300 ezusb linux driver and
* based on multiple host controller drivers inside the linux kernel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
#include <asm/byteorder.h>
#include <linux/io.h>
#include <linux/usb/c67x00.h>
#include "c67x00.h"
#define COMM_REGS 14
struct c67x00_lcp_int_data {
u16 regs[COMM_REGS];
};
/* -------------------------------------------------------------------------- */
/* Interface definitions */
#define COMM_ACK 0x0FED
#define COMM_NAK 0xDEAD
#define COMM_RESET 0xFA50
#define COMM_EXEC_INT 0xCE01
#define COMM_INT_NUM 0x01C2
/* Registers 0 to COMM_REGS-1 */
#define COMM_R(x) (0x01C4 + 2 * (x))
#define HUSB_SIE_pCurrentTDPtr(x) ((x) ? 0x01B2 : 0x01B0)
#define HUSB_SIE_pTDListDone_Sem(x) ((x) ? 0x01B8 : 0x01B6)
#define HUSB_pEOT 0x01B4
/* Software interrupts */
/* 114, 115: */
#define HUSB_SIE_INIT_INT(x) ((x) ? 0x0073 : 0x0072)
#define HUSB_RESET_INT 0x0074
#define SUSB_INIT_INT 0x0071
#define SUSB_INIT_INT_LOC (SUSB_INIT_INT * 2)
/* -----------------------------------------------------------------------
* HPI implementation
*
* The c67x00 chip also support control via SPI or HSS serial
* interfaces. However, this driver assumes that register access can
* be performed from IRQ context. While this is a safe assuption with
* the HPI interface, it is not true for the serial interfaces.
*/
/* HPI registers */
#define HPI_DATA 0
#define HPI_MAILBOX 1
#define HPI_ADDR 2
#define HPI_STATUS 3
static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg)
{
return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep);
}
static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value)
{
__raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep);
}
static inline u16 hpi_read_word_nolock(struct c67x00_device *dev, u16 reg)
{
hpi_write_reg(dev, HPI_ADDR, reg);
return hpi_read_reg(dev, HPI_DATA);
}
static u16 hpi_read_word(struct c67x00_device *dev, u16 reg)
{
u16 value;
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
value = hpi_read_word_nolock(dev, reg);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
return value;
}
static void hpi_write_word_nolock(struct c67x00_device *dev, u16 reg, u16 value)
{
hpi_write_reg(dev, HPI_ADDR, reg);
hpi_write_reg(dev, HPI_DATA, value);
}
static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value)
{
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
hpi_write_word_nolock(dev, reg, value);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
/*
* Only data is little endian, addr has cpu endianess
*/
static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr,
u16 *data, u16 count)
{
unsigned long flags;
int i;
spin_lock_irqsave(&dev->hpi.lock, flags);
hpi_write_reg(dev, HPI_ADDR, addr);
for (i = 0; i < count; i++)
hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++));
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
/*
* Only data is little endian, addr has cpu endianess
*/
static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr,
u16 *data, u16 count)
{
unsigned long flags;
int i;
spin_lock_irqsave(&dev->hpi.lock, flags);
hpi_write_reg(dev, HPI_ADDR, addr);
for (i = 0; i < count; i++)
*data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA));
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
static void hpi_set_bits(struct c67x00_device *dev, u16 reg, u16 mask)
{
u16 value;
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
value = hpi_read_word_nolock(dev, reg);
hpi_write_word_nolock(dev, reg, value | mask);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
static void hpi_clear_bits(struct c67x00_device *dev, u16 reg, u16 mask)
{
u16 value;
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
value = hpi_read_word_nolock(dev, reg);
hpi_write_word_nolock(dev, reg, value & ~mask);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
}
static u16 hpi_recv_mbox(struct c67x00_device *dev)
{
u16 value;
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
value = hpi_read_reg(dev, HPI_MAILBOX);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
return value;
}
static u16 hpi_send_mbox(struct c67x00_device *dev, u16 value)
{
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
hpi_write_reg(dev, HPI_MAILBOX, value);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
return value;
}
u16 c67x00_ll_hpi_status(struct c67x00_device *dev)
{
u16 value;
unsigned long flags;
spin_lock_irqsave(&dev->hpi.lock, flags);
value = hpi_read_reg(dev, HPI_STATUS);
spin_unlock_irqrestore(&dev->hpi.lock, flags);
return value;
}
void c67x00_ll_hpi_reg_init(struct c67x00_device *dev)
{
int i;
hpi_recv_mbox(dev);
c67x00_ll_hpi_status(dev);
hpi_write_word(dev, HPI_IRQ_ROUTING_REG, 0);
for (i = 0; i < C67X00_SIES; i++) {
hpi_write_word(dev, SIEMSG_REG(i), 0);
hpi_read_word(dev, SIEMSG_REG(i));
}
}
void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie)
{
hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
SOFEOP_TO_HPI_EN(sie->sie_num));
}
void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie)
{
hpi_clear_bits(sie->dev, HPI_IRQ_ROUTING_REG,
SOFEOP_TO_HPI_EN(sie->sie_num));
}
/* -------------------------------------------------------------------------- */
/* Transactions */
static inline u16 ll_recv_msg(struct c67x00_device *dev)
{
u16 res;
res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ);
WARN_ON(!res);
return (res == 0) ? -EIO : 0;
}
/* -------------------------------------------------------------------------- */
/* General functions */
u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num)
{
u16 val;
val = hpi_read_word(dev, SIEMSG_REG(sie_num));
/* clear register to allow next message */
hpi_write_word(dev, SIEMSG_REG(sie_num), 0);
return val;
}
u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie)
{
return hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num));
}
/**
* c67x00_ll_usb_clear_status - clear the USB status bits
*/
void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits)
{
hpi_write_word(sie->dev, USB_STAT_REG(sie->sie_num), bits);
}
u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie)
{
return hpi_read_word(sie->dev, USB_STAT_REG(sie->sie_num));
}
/* -------------------------------------------------------------------------- */
static int c67x00_comm_exec_int(struct c67x00_device *dev, u16 nr,
struct c67x00_lcp_int_data *data)
{
int i, rc;
mutex_lock(&dev->hpi.lcp.mutex);
hpi_write_word(dev, COMM_INT_NUM, nr);
for (i = 0; i < COMM_REGS; i++)
hpi_write_word(dev, COMM_R(i), data->regs[i]);
hpi_send_mbox(dev, COMM_EXEC_INT);
rc = ll_recv_msg(dev);
mutex_unlock(&dev->hpi.lcp.mutex);
return rc;
}
/* -------------------------------------------------------------------------- */
/* Host specific functions */
void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value)
{
mutex_lock(&dev->hpi.lcp.mutex);
hpi_write_word(dev, HUSB_pEOT, value);
mutex_unlock(&dev->hpi.lcp.mutex);
}
static inline void c67x00_ll_husb_sie_init(struct c67x00_sie *sie)
{
struct c67x00_device *dev = sie->dev;
struct c67x00_lcp_int_data data;
int rc;
rc = c67x00_comm_exec_int(dev, HUSB_SIE_INIT_INT(sie->sie_num), &data);
BUG_ON(rc); /* No return path for error code; crash spectacularly */
}
void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port)
{
struct c67x00_device *dev = sie->dev;
struct c67x00_lcp_int_data data;
int rc;
data.regs[0] = 50; /* Reset USB port for 50ms */
data.regs[1] = port | (sie->sie_num << 1);
rc = c67x00_comm_exec_int(dev, HUSB_RESET_INT, &data);
BUG_ON(rc); /* No return path for error code; crash spectacularly */
}
void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr)
{
hpi_write_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num), addr);
}
u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie)
{
return hpi_read_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num));
}
u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie)
{
return hpi_read_word(sie->dev, HOST_FRAME_REG(sie->sie_num));
}
void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie)
{
/* Set port into host mode */
hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), HOST_MODE);
c67x00_ll_husb_sie_init(sie);
/* Clear interrupts */
c67x00_ll_usb_clear_status(sie, HOST_STAT_MASK);
/* Check */
if (!(hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)) & HOST_MODE))
dev_warn(sie_dev(sie),
"SIE %d not set to host mode\n", sie->sie_num);
}
void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port)
{
/* Clear connect change */
c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port));
/* Enable interrupts */
hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG,
SOFEOP_TO_CPU_EN(sie->sie_num));
hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num),
SOF_EOP_IRQ_EN | DONE_IRQ_EN);
/* Enable pull down transistors */
hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port));
}
/* -------------------------------------------------------------------------- */
void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status)
{
if ((int_status & MBX_OUT_FLG) == 0)
return;
dev->hpi.lcp.last_msg = hpi_recv_mbox(dev);
complete(&dev->hpi.lcp.msg_received);
}
/* -------------------------------------------------------------------------- */
int c67x00_ll_reset(struct c67x00_device *dev)
{
int rc;
mutex_lock(&dev->hpi.lcp.mutex);
hpi_send_mbox(dev, COMM_RESET);
rc = ll_recv_msg(dev);
mutex_unlock(&dev->hpi.lcp.mutex);
return rc;
}
/* -------------------------------------------------------------------------- */
/**
* c67x00_ll_write_mem_le16 - write into c67x00 memory
* Only data is little endian, addr has cpu endianess.
*/
void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
void *data, int len)
{
u8 *buf = data;
/* Sanity check */
if (addr + len > 0xffff) {
dev_err(&dev->pdev->dev,
"Trying to write beyond writable region!\n");
return;
}
if (addr & 0x01) {
/* unaligned access */
u16 tmp;
tmp = hpi_read_word(dev, addr - 1);
tmp = (tmp & 0x00ff) | (*buf++ << 8);
hpi_write_word(dev, addr - 1, tmp);
addr++;
len--;
}
hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2);
buf += len & ~0x01;
addr += len & ~0x01;
len &= 0x01;
if (len) {
u16 tmp;
tmp = hpi_read_word(dev, addr);
tmp = (tmp & 0xff00) | *buf;
hpi_write_word(dev, addr, tmp);
}
}
/**
* c67x00_ll_read_mem_le16 - read from c67x00 memory
* Only data is little endian, addr has cpu endianess.
*/
void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
void *data, int len)
{
u8 *buf = data;
if (addr & 0x01) {
/* unaligned access */
u16 tmp;
tmp = hpi_read_word(dev, addr - 1);
*buf++ = (tmp >> 8) & 0x00ff;
addr++;
len--;
}
hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2);
buf += len & ~0x01;
addr += len & ~0x01;
len &= 0x01;
if (len) {
u16 tmp;
tmp = hpi_read_word(dev, addr);
*buf = tmp & 0x00ff;
}
}
/* -------------------------------------------------------------------------- */
void c67x00_ll_init(struct c67x00_device *dev)
{
mutex_init(&dev->hpi.lcp.mutex);
init_completion(&dev->hpi.lcp.msg_received);
}
void c67x00_ll_release(struct c67x00_device *dev)
{
}

File diff suppressed because it is too large Load diff

294
drivers/usb/c67x00/c67x00.h Normal file
View file

@ -0,0 +1,294 @@
/*
* c67x00.h: Cypress C67X00 USB register and field definitions
*
* Copyright (C) 2006-2008 Barco N.V.
* Derived from the Cypress cy7c67200/300 ezusb linux driver and
* based on multiple host controller drivers inside the linux kernel.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
#ifndef _USB_C67X00_H
#define _USB_C67X00_H
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/mutex.h>
/* ---------------------------------------------------------------------
* Cypress C67x00 register definitions
*/
/* Hardware Revision Register */
#define HW_REV_REG 0xC004
/* General USB registers */
/* ===================== */
/* USB Control Register */
#define USB_CTL_REG(x) ((x) ? 0xC0AA : 0xC08A)
#define LOW_SPEED_PORT(x) ((x) ? 0x0800 : 0x0400)
#define HOST_MODE 0x0200
#define PORT_RES_EN(x) ((x) ? 0x0100 : 0x0080)
#define SOF_EOP_EN(x) ((x) ? 0x0002 : 0x0001)
/* USB status register - Notice it has different content in hcd/udc mode */
#define USB_STAT_REG(x) ((x) ? 0xC0B0 : 0xC090)
#define EP0_IRQ_FLG 0x0001
#define EP1_IRQ_FLG 0x0002
#define EP2_IRQ_FLG 0x0004
#define EP3_IRQ_FLG 0x0008
#define EP4_IRQ_FLG 0x0010
#define EP5_IRQ_FLG 0x0020
#define EP6_IRQ_FLG 0x0040
#define EP7_IRQ_FLG 0x0080
#define RESET_IRQ_FLG 0x0100
#define SOF_EOP_IRQ_FLG 0x0200
#define ID_IRQ_FLG 0x4000
#define VBUS_IRQ_FLG 0x8000
/* USB Host only registers */
/* ======================= */
/* Host n Control Register */
#define HOST_CTL_REG(x) ((x) ? 0xC0A0 : 0xC080)
#define PREAMBLE_EN 0x0080 /* Preamble enable */
#define SEQ_SEL 0x0040 /* Data Toggle Sequence Bit Select */
#define ISO_EN 0x0010 /* Isochronous enable */
#define ARM_EN 0x0001 /* Arm operation */
/* Host n Interrupt Enable Register */
#define HOST_IRQ_EN_REG(x) ((x) ? 0xC0AC : 0xC08C)
#define SOF_EOP_IRQ_EN 0x0200 /* SOF/EOP Interrupt Enable */
#define SOF_EOP_TMOUT_IRQ_EN 0x0800 /* SOF/EOP Timeout Interrupt Enable */
#define ID_IRQ_EN 0x4000 /* ID interrupt enable */
#define VBUS_IRQ_EN 0x8000 /* VBUS interrupt enable */
#define DONE_IRQ_EN 0x0001 /* Done Interrupt Enable */
/* USB status register */
#define HOST_STAT_MASK 0x02FD
#define PORT_CONNECT_CHANGE(x) ((x) ? 0x0020 : 0x0010)
#define PORT_SE0_STATUS(x) ((x) ? 0x0008 : 0x0004)
/* Host Frame Register */
#define HOST_FRAME_REG(x) ((x) ? 0xC0B6 : 0xC096)
#define HOST_FRAME_MASK 0x07FF
/* USB Peripheral only registers */
/* ============================= */
/* Device n Port Sel reg */
#define DEVICE_N_PORT_SEL(x) ((x) ? 0xC0A4 : 0xC084)
/* Device n Interrupt Enable Register */
#define DEVICE_N_IRQ_EN_REG(x) ((x) ? 0xC0AC : 0xC08C)
#define DEVICE_N_ENDPOINT_N_CTL_REG(dev, ep) ((dev) \
? (0x0280 + (ep << 4)) \
: (0x0200 + (ep << 4)))
#define DEVICE_N_ENDPOINT_N_STAT_REG(dev, ep) ((dev) \
? (0x0286 + (ep << 4)) \
: (0x0206 + (ep << 4)))
#define DEVICE_N_ADDRESS(dev) ((dev) ? (0xC0AE) : (0xC08E))
/* HPI registers */
/* ============= */
/* HPI Status register */
#define SOFEOP_FLG(x) (1 << ((x) ? 12 : 10))
#define SIEMSG_FLG(x) (1 << (4 + (x)))
#define RESET_FLG(x) ((x) ? 0x0200 : 0x0002)
#define DONE_FLG(x) (1 << (2 + (x)))
#define RESUME_FLG(x) (1 << (6 + (x)))
#define MBX_OUT_FLG 0x0001 /* Message out available */
#define MBX_IN_FLG 0x0100
#define ID_FLG 0x4000
#define VBUS_FLG 0x8000
/* Interrupt routing register */
#define HPI_IRQ_ROUTING_REG 0x0142
#define HPI_SWAP_ENABLE(x) ((x) ? 0x0100 : 0x0001)
#define RESET_TO_HPI_ENABLE(x) ((x) ? 0x0200 : 0x0002)
#define DONE_TO_HPI_ENABLE(x) ((x) ? 0x0008 : 0x0004)
#define RESUME_TO_HPI_ENABLE(x) ((x) ? 0x0080 : 0x0040)
#define SOFEOP_TO_HPI_EN(x) ((x) ? 0x2000 : 0x0800)
#define SOFEOP_TO_CPU_EN(x) ((x) ? 0x1000 : 0x0400)
#define ID_TO_HPI_ENABLE 0x4000
#define VBUS_TO_HPI_ENABLE 0x8000
/* SIE msg registers */
#define SIEMSG_REG(x) ((x) ? 0x0148 : 0x0144)
#define HUSB_TDListDone 0x1000
#define SUSB_EP0_MSG 0x0001
#define SUSB_EP1_MSG 0x0002
#define SUSB_EP2_MSG 0x0004
#define SUSB_EP3_MSG 0x0008
#define SUSB_EP4_MSG 0x0010
#define SUSB_EP5_MSG 0x0020
#define SUSB_EP6_MSG 0x0040
#define SUSB_EP7_MSG 0x0080
#define SUSB_RST_MSG 0x0100
#define SUSB_SOF_MSG 0x0200
#define SUSB_CFG_MSG 0x0400
#define SUSB_SUS_MSG 0x0800
#define SUSB_ID_MSG 0x4000
#define SUSB_VBUS_MSG 0x8000
/* BIOS interrupt routines */
#define SUSBx_RECEIVE_INT(x) ((x) ? 97 : 81)
#define SUSBx_SEND_INT(x) ((x) ? 96 : 80)
#define SUSBx_DEV_DESC_VEC(x) ((x) ? 0x00D4 : 0x00B4)
#define SUSBx_CONF_DESC_VEC(x) ((x) ? 0x00D6 : 0x00B6)
#define SUSBx_STRING_DESC_VEC(x) ((x) ? 0x00D8 : 0x00B8)
#define CY_HCD_BUF_ADDR 0x500 /* Base address for host */
#define SIE_TD_SIZE 0x200 /* size of the td list */
#define SIE_TD_BUF_SIZE 0x400 /* size of the data buffer */
#define SIE_TD_OFFSET(host) ((host) ? (SIE_TD_SIZE+SIE_TD_BUF_SIZE) : 0)
#define SIE_BUF_OFFSET(host) (SIE_TD_OFFSET(host) + SIE_TD_SIZE)
/* Base address of HCD + 2 x TD_SIZE + 2 x TD_BUF_SIZE */
#define CY_UDC_REQ_HEADER_BASE 0x1100
/* 8- byte request headers for IN/OUT transfers */
#define CY_UDC_REQ_HEADER_SIZE 8
#define CY_UDC_REQ_HEADER_ADDR(ep_num) (CY_UDC_REQ_HEADER_BASE + \
((ep_num) * CY_UDC_REQ_HEADER_SIZE))
#define CY_UDC_DESC_BASE_ADDRESS (CY_UDC_REQ_HEADER_ADDR(8))
#define CY_UDC_BIOS_REPLACE_BASE 0x1800
#define CY_UDC_REQ_BUFFER_BASE 0x2000
#define CY_UDC_REQ_BUFFER_SIZE 0x0400
#define CY_UDC_REQ_BUFFER_ADDR(ep_num) (CY_UDC_REQ_BUFFER_BASE + \
((ep_num) * CY_UDC_REQ_BUFFER_SIZE))
/* ---------------------------------------------------------------------
* Driver data structures
*/
struct c67x00_device;
/**
* struct c67x00_sie - Common data associated with a SIE
* @lock: lock to protect this struct and the associated chip registers
* @private_data: subdriver dependent data
* @irq: subdriver dependent irq handler, set NULL when not used
* @dev: link to common driver structure
* @sie_num: SIE number on chip, starting from 0
* @mode: SIE mode (host/peripheral/otg/not used)
*/
struct c67x00_sie {
/* Entries to be used by the subdrivers */
spinlock_t lock; /* protect this structure */
void *private_data;
void (*irq) (struct c67x00_sie *sie, u16 int_status, u16 msg);
/* Read only: */
struct c67x00_device *dev;
int sie_num;
int mode;
};
#define sie_dev(s) (&(s)->dev->pdev->dev)
/**
* struct c67x00_lcp
*/
struct c67x00_lcp {
/* Internal use only */
struct mutex mutex;
struct completion msg_received;
u16 last_msg;
};
/*
* struct c67x00_hpi
*/
struct c67x00_hpi {
void __iomem *base;
int regstep;
spinlock_t lock;
struct c67x00_lcp lcp;
};
#define C67X00_SIES 2
#define C67X00_PORTS 2
/**
* struct c67x00_device - Common data associated with a c67x00 instance
* @hpi: hpi addresses
* @sie: array of sie's on this chip
* @pdev: platform device of instance
* @pdata: configuration provided by the platform
*/
struct c67x00_device {
struct c67x00_hpi hpi;
struct c67x00_sie sie[C67X00_SIES];
struct platform_device *pdev;
struct c67x00_platform_data *pdata;
};
/* ---------------------------------------------------------------------
* Low level interface functions
*/
/* Host Port Interface (HPI) functions */
u16 c67x00_ll_hpi_status(struct c67x00_device *dev);
void c67x00_ll_hpi_reg_init(struct c67x00_device *dev);
void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie);
void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie);
/* General functions */
u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num);
u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie);
void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits);
u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie);
void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr,
void *data, int len);
void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr,
void *data, int len);
/* Host specific functions */
void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value);
void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port);
void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr);
u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie);
u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie);
void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie);
void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port);
/* Called by c67x00_irq to handle lcp interrupts */
void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status);
/* Setup and teardown */
void c67x00_ll_init(struct c67x00_device *dev);
void c67x00_ll_release(struct c67x00_device *dev);
int c67x00_ll_reset(struct c67x00_device *dev);
#endif /* _USB_C67X00_H */

View file

@ -394,7 +394,9 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
if (!io->urbs)
goto nomem;
urb_flags = URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
urb_flags = URB_NO_INTERRUPT;
if (dma)
urb_flags |= URB_NO_TRANSFER_DMA_MAP;
if (usb_pipein(pipe))
urb_flags |= URB_SHORT_NOT_OK;

View file

@ -231,6 +231,26 @@ config SUPERH_BUILT_IN_M66592
However, this problem is improved if change a value of
NET_IP_ALIGN to 4.
config USB_GADGET_PXA27X
boolean "PXA 27x"
depends on ARCH_PXA && PXA27x
help
Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller.
It has up to 23 endpoints, as well as endpoint zero (for
control transfers).
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "pxa27x_udc" and force all
gadget drivers to also be dynamically linked.
config USB_PXA27X
tristate
depends on USB_GADGET_PXA27X
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_GOKU
boolean "Toshiba TC86C001 'Goku-S'"
depends on PCI

View file

@ -9,6 +9,7 @@ obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o

View file

@ -235,10 +235,6 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_CDC
#endif
#ifdef CONFIG_USB_GADGET_PXA27X
#define DEV_CONFIG_CDC
#endif
#ifdef CONFIG_USB_GADGET_S3C2410
#define DEV_CONFIG_CDC
#endif
@ -270,6 +266,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET
#endif
#ifdef CONFIG_USB_GADGET_PXA27X
#define DEV_CONFIG_SUBSET
#endif
#ifdef CONFIG_USB_GADGET_SUPERH
#define DEV_CONFIG_SUBSET
#endif

View file

@ -2307,6 +2307,29 @@ static int halt_bulk_in_endpoint(struct fsg_dev *fsg)
return rc;
}
static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
{
int rc;
DBG(fsg, "bulk-in set wedge\n");
rc = usb_ep_set_wedge(fsg->bulk_in);
if (rc == -EAGAIN)
VDBG(fsg, "delayed bulk-in endpoint wedge\n");
while (rc != 0) {
if (rc != -EAGAIN) {
WARN(fsg, "usb_ep_set_wedge -> %d\n", rc);
rc = 0;
break;
}
/* Wait for a short time and then try again */
if (msleep_interruptible(100) != 0)
return -EINTR;
rc = usb_ep_set_wedge(fsg->bulk_in);
}
return rc;
}
static int pad_with_zeros(struct fsg_dev *fsg)
{
struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
@ -2957,7 +2980,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
* We aren't required to halt the OUT endpoint; instead
* we can simply accept and discard any data received
* until the next reset. */
halt_bulk_in_endpoint(fsg);
wedge_bulk_in_endpoint(fsg);
set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
return -EINVAL;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,487 @@
/*
* linux/drivers/usb/gadget/pxa27x_udc.h
* Intel PXA27x on-chip full speed USB device controller
*
* Inspired by original driver by Frank Becker, David Brownell, and others.
* Copyright (C) 2008 Robert Jarzmik
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LINUX_USB_GADGET_PXA27X_H
#define __LINUX_USB_GADGET_PXA27X_H
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/io.h>
/*
* Register definitions
*/
/* Offsets */
#define UDCCR 0x0000 /* UDC Control Register */
#define UDCICR0 0x0004 /* UDC Interrupt Control Register0 */
#define UDCICR1 0x0008 /* UDC Interrupt Control Register1 */
#define UDCISR0 0x000C /* UDC Interrupt Status Register 0 */
#define UDCISR1 0x0010 /* UDC Interrupt Status Register 1 */
#define UDCFNR 0x0014 /* UDC Frame Number Register */
#define UDCOTGICR 0x0018 /* UDC On-The-Go interrupt control */
#define UP2OCR 0x0020 /* USB Port 2 Output Control register */
#define UP3OCR 0x0024 /* USB Port 3 Output Control register */
#define UDCCSRn(x) (0x0100 + ((x)<<2)) /* UDC Control/Status register */
#define UDCBCRn(x) (0x0200 + ((x)<<2)) /* UDC Byte Count Register */
#define UDCDRn(x) (0x0300 + ((x)<<2)) /* UDC Data Register */
#define UDCCRn(x) (0x0400 + ((x)<<2)) /* UDC Control Register */
#define UDCCR_OEN (1 << 31) /* On-the-Go Enable */
#define UDCCR_AALTHNP (1 << 30) /* A-device Alternate Host Negotiation
Protocol Port Support */
#define UDCCR_AHNP (1 << 29) /* A-device Host Negotiation Protocol
Support */
#define UDCCR_BHNP (1 << 28) /* B-device Host Negotiation Protocol
Enable */
#define UDCCR_DWRE (1 << 16) /* Device Remote Wake-up Enable */
#define UDCCR_ACN (0x03 << 11) /* Active UDC configuration Number */
#define UDCCR_ACN_S 11
#define UDCCR_AIN (0x07 << 8) /* Active UDC interface Number */
#define UDCCR_AIN_S 8
#define UDCCR_AAISN (0x07 << 5) /* Active UDC Alternate Interface
Setting Number */
#define UDCCR_AAISN_S 5
#define UDCCR_SMAC (1 << 4) /* Switch Endpoint Memory to Active
Configuration */
#define UDCCR_EMCE (1 << 3) /* Endpoint Memory Configuration
Error */
#define UDCCR_UDR (1 << 2) /* UDC Resume */
#define UDCCR_UDA (1 << 1) /* UDC Active */
#define UDCCR_UDE (1 << 0) /* UDC Enable */
#define UDCICR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
#define UDCICR1_IECC (1 << 31) /* IntEn - Configuration Change */
#define UDCICR1_IESOF (1 << 30) /* IntEn - Start of Frame */
#define UDCICR1_IERU (1 << 29) /* IntEn - Resume */
#define UDCICR1_IESU (1 << 28) /* IntEn - Suspend */
#define UDCICR1_IERS (1 << 27) /* IntEn - Reset */
#define UDCICR_FIFOERR (1 << 1) /* FIFO Error interrupt for EP */
#define UDCICR_PKTCOMPL (1 << 0) /* Packet Complete interrupt for EP */
#define UDCICR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
#define UDCISR_INT(n, intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
#define UDCISR1_IRCC (1 << 31) /* IntReq - Configuration Change */
#define UDCISR1_IRSOF (1 << 30) /* IntReq - Start of Frame */
#define UDCISR1_IRRU (1 << 29) /* IntReq - Resume */
#define UDCISR1_IRSU (1 << 28) /* IntReq - Suspend */
#define UDCISR1_IRRS (1 << 27) /* IntReq - Reset */
#define UDCISR_INT_MASK (UDCICR_FIFOERR | UDCICR_PKTCOMPL)
#define UDCOTGICR_IESF (1 << 24) /* OTG SET_FEATURE command recvd */
#define UDCOTGICR_IEXR (1 << 17) /* Extra Transciever Interrupt
Rising Edge Interrupt Enable */
#define UDCOTGICR_IEXF (1 << 16) /* Extra Transciever Interrupt
Falling Edge Interrupt Enable */
#define UDCOTGICR_IEVV40R (1 << 9) /* OTG Vbus Valid 4.0V Rising Edge
Interrupt Enable */
#define UDCOTGICR_IEVV40F (1 << 8) /* OTG Vbus Valid 4.0V Falling Edge
Interrupt Enable */
#define UDCOTGICR_IEVV44R (1 << 7) /* OTG Vbus Valid 4.4V Rising Edge
Interrupt Enable */
#define UDCOTGICR_IEVV44F (1 << 6) /* OTG Vbus Valid 4.4V Falling Edge
Interrupt Enable */
#define UDCOTGICR_IESVR (1 << 5) /* OTG Session Valid Rising Edge
Interrupt Enable */
#define UDCOTGICR_IESVF (1 << 4) /* OTG Session Valid Falling Edge
Interrupt Enable */
#define UDCOTGICR_IESDR (1 << 3) /* OTG A-Device SRP Detect Rising
Edge Interrupt Enable */
#define UDCOTGICR_IESDF (1 << 2) /* OTG A-Device SRP Detect Falling
Edge Interrupt Enable */
#define UDCOTGICR_IEIDR (1 << 1) /* OTG ID Change Rising Edge
Interrupt Enable */
#define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge
Interrupt Enable */
/* Host Port 2 field bits */
#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */
#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */
/* Transceiver enablers */
#define UP2OCR_DPPDE (1 << 2) /* D+ Pull Down Enable */
#define UP2OCR_DMPDE (1 << 3) /* D- Pull Down Enable */
#define UP2OCR_DPPUE (1 << 4) /* D+ Pull Up Enable */
#define UP2OCR_DMPUE (1 << 5) /* D- Pull Up Enable */
#define UP2OCR_DPPUBE (1 << 6) /* D+ Pull Up Bypass Enable */
#define UP2OCR_DMPUBE (1 << 7) /* D- Pull Up Bypass Enable */
#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */
#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */
#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */
#define UP2OCR_HXS (1 << 16) /* Transceiver Output Select */
#define UP2OCR_HXOE (1 << 17) /* Transceiver Output Enable */
#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */
#define UDCCSR0_SA (1 << 7) /* Setup Active */
#define UDCCSR0_RNE (1 << 6) /* Receive FIFO Not Empty */
#define UDCCSR0_FST (1 << 5) /* Force Stall */
#define UDCCSR0_SST (1 << 4) /* Sent Stall */
#define UDCCSR0_DME (1 << 3) /* DMA Enable */
#define UDCCSR0_FTF (1 << 2) /* Flush Transmit FIFO */
#define UDCCSR0_IPR (1 << 1) /* IN Packet Ready */
#define UDCCSR0_OPC (1 << 0) /* OUT Packet Complete */
#define UDCCSR_DPE (1 << 9) /* Data Packet Error */
#define UDCCSR_FEF (1 << 8) /* Flush Endpoint FIFO */
#define UDCCSR_SP (1 << 7) /* Short Packet Control/Status */
#define UDCCSR_BNE (1 << 6) /* Buffer Not Empty (IN endpoints) */
#define UDCCSR_BNF (1 << 6) /* Buffer Not Full (OUT endpoints) */
#define UDCCSR_FST (1 << 5) /* Force STALL */
#define UDCCSR_SST (1 << 4) /* Sent STALL */
#define UDCCSR_DME (1 << 3) /* DMA Enable */
#define UDCCSR_TRN (1 << 2) /* Tx/Rx NAK */
#define UDCCSR_PC (1 << 1) /* Packet Complete */
#define UDCCSR_FS (1 << 0) /* FIFO needs service */
#define UDCCONR_CN (0x03 << 25) /* Configuration Number */
#define UDCCONR_CN_S 25
#define UDCCONR_IN (0x07 << 22) /* Interface Number */
#define UDCCONR_IN_S 22
#define UDCCONR_AISN (0x07 << 19) /* Alternate Interface Number */
#define UDCCONR_AISN_S 19
#define UDCCONR_EN (0x0f << 15) /* Endpoint Number */
#define UDCCONR_EN_S 15
#define UDCCONR_ET (0x03 << 13) /* Endpoint Type: */
#define UDCCONR_ET_S 13
#define UDCCONR_ET_INT (0x03 << 13) /* Interrupt */
#define UDCCONR_ET_BULK (0x02 << 13) /* Bulk */
#define UDCCONR_ET_ISO (0x01 << 13) /* Isochronous */
#define UDCCONR_ET_NU (0x00 << 13) /* Not used */
#define UDCCONR_ED (1 << 12) /* Endpoint Direction */
#define UDCCONR_MPS (0x3ff << 2) /* Maximum Packet Size */
#define UDCCONR_MPS_S 2
#define UDCCONR_DE (1 << 1) /* Double Buffering Enable */
#define UDCCONR_EE (1 << 0) /* Endpoint Enable */
#define UDCCR_MASK_BITS (UDCCR_OEN | UDCCR_SMAC | UDCCR_UDR | UDCCR_UDE)
#define UDCCSR_WR_MASK (UDCCSR_DME | UDCCSR_FST)
#define UDC_FNR_MASK (0x7ff)
#define UDC_BCR_MASK (0x3ff)
/*
* UDCCR = UDC Endpoint Configuration Registers
* UDCCSR = UDC Control/Status Register for this EP
* UDCBCR = UDC Byte Count Remaining (contents of OUT fifo)
* UDCDR = UDC Endpoint Data Register (the fifo)
*/
#define ofs_UDCCR(ep) (UDCCRn(ep->idx))
#define ofs_UDCCSR(ep) (UDCCSRn(ep->idx))
#define ofs_UDCBCR(ep) (UDCBCRn(ep->idx))
#define ofs_UDCDR(ep) (UDCDRn(ep->idx))
/* Register access macros */
#define udc_ep_readl(ep, reg) \
__raw_readl((ep)->dev->regs + ofs_##reg(ep))
#define udc_ep_writel(ep, reg, value) \
__raw_writel((value), ep->dev->regs + ofs_##reg(ep))
#define udc_ep_readb(ep, reg) \
__raw_readb((ep)->dev->regs + ofs_##reg(ep))
#define udc_ep_writeb(ep, reg, value) \
__raw_writeb((value), ep->dev->regs + ofs_##reg(ep))
#define udc_readl(dev, reg) \
__raw_readl((dev)->regs + (reg))
#define udc_writel(udc, reg, value) \
__raw_writel((value), (udc)->regs + (reg))
#define UDCCSR_MASK (UDCCSR_FST | UDCCSR_DME)
#define UDCCISR0_EP_MASK ~0
#define UDCCISR1_EP_MASK 0xffff
#define UDCCSR0_CTRL_REQ_MASK (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)
#define EPIDX(ep) (ep->idx)
#define EPADDR(ep) (ep->addr)
#define EPXFERTYPE(ep) (ep->type)
#define EPNAME(ep) (ep->name)
#define is_ep0(ep) (!ep->idx)
#define EPXFERTYPE_is_ISO(ep) (EPXFERTYPE(ep) == USB_ENDPOINT_XFER_ISOC)
/*
* Endpoint definitions
*
* Once enabled, pxa endpoint configuration is freezed, and cannot change
* unless a reset happens or the udc is disabled.
* Therefore, we must define all pxa potential endpoint definitions needed for
* all gadget and set them up before the udc is enabled.
*
* As the architecture chosen is fully static, meaning the pxa endpoint
* configurations are set up once and for all, we must provide a way to match
* one usb endpoint (usb_ep) to several pxa endpoints. The reason is that gadget
* layer autoconf doesn't choose the usb_ep endpoint on (config, interface, alt)
* criteria, while the pxa architecture requires that.
*
* The solution is to define several pxa endpoints matching one usb_ep. Ex:
* - "ep1-in" matches pxa endpoint EPA (which is an IN ep at addr 1, when
* the udc talks on (config=3, interface=0, alt=0)
* - "ep1-in" matches pxa endpoint EPB (which is an IN ep at addr 1, when
* the udc talks on (config=3, interface=0, alt=1)
* - "ep1-in" matches pxa endpoint EPC (which is an IN ep at addr 1, when
* the udc talks on (config=2, interface=0, alt=0)
*
* We'll define the pxa endpoint by its index (EPA => idx=1, EPB => idx=2, ...)
*/
/*
* Endpoint definition helpers
*/
#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
.desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
.bmAttributes = type, \
.wMaxPacketSize = maxpkt, }, \
.dev = &memory \
}
#define USB_EP_BULK(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
#define USB_EP_ISO(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
#define USB_EP_INT(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
{ \
.dev = &memory, \
.name = "ep" #_idx, \
.idx = _idx, .enabled = 0, \
.dir_in = dir, .addr = _addr, \
.config = _config, .interface = iface, .alternate = altset, \
.type = _type, .fifo_size = maxpkt, \
}
#define PXA_EP_BULK(_idx, addr, dir, config, iface, alt) \
PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE, \
config, iface, alt)
#define PXA_EP_ISO(_idx, addr, dir, config, iface, alt) \
PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE, \
config, iface, alt)
#define PXA_EP_INT(_idx, addr, dir, config, iface, alt) \
PXA_EP_DEF(_idx, addr, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE, \
config, iface, alt)
#define PXA_EP_IN_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 1, c, f, a)
#define PXA_EP_OUT_BULK(i, adr, c, f, a) PXA_EP_BULK(i, adr, 0, c, f, a)
#define PXA_EP_IN_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 1, c, f, a)
#define PXA_EP_OUT_ISO(i, adr, c, f, a) PXA_EP_ISO(i, adr, 0, c, f, a)
#define PXA_EP_IN_INT(i, adr, c, f, a) PXA_EP_INT(i, adr, 1, c, f, a)
#define PXA_EP_CTRL PXA_EP_DEF(0, 0, 0, 0, EP0_FIFO_SIZE, 0, 0, 0)
struct pxa27x_udc;
struct stats {
unsigned long in_ops;
unsigned long out_ops;
unsigned long in_bytes;
unsigned long out_bytes;
unsigned long irqs;
};
/**
* struct udc_usb_ep - container of each usb_ep structure
* @usb_ep: usb endpoint
* @desc: usb descriptor, especially type and address
* @dev: udc managing this endpoint
* @pxa_ep: matching pxa_ep (cache of find_pxa_ep() call)
*/
struct udc_usb_ep {
struct usb_ep usb_ep;
struct usb_endpoint_descriptor desc;
struct pxa_udc *dev;
struct pxa_ep *pxa_ep;
};
/**
* struct pxa_ep - pxa endpoint
* @dev: udc device
* @queue: requests queue
* @lock: lock to pxa_ep data (queues and stats)
* @enabled: true when endpoint enabled (not stopped by gadget layer)
* @idx: endpoint index (1 => epA, 2 => epB, ..., 24 => epX)
* @name: endpoint name (for trace/debug purpose)
* @dir_in: 1 if IN endpoint, 0 if OUT endpoint
* @addr: usb endpoint number
* @config: configuration in which this endpoint is active
* @interface: interface in which this endpoint is active
* @alternate: altsetting in which this endpoitn is active
* @fifo_size: max packet size in the endpoint fifo
* @type: endpoint type (bulk, iso, int, ...)
* @udccsr_value: save register of UDCCSR0 for suspend/resume
* @udccr_value: save register of UDCCR for suspend/resume
* @stats: endpoint statistics
*
* The *PROBLEM* is that pxa's endpoint configuration scheme is both misdesigned
* (cares about config/interface/altsetting, thus placing needless limits on
* device capability) and full of implementation bugs forcing it to be set up
* for use more or less like a pxa255.
*
* As we define the pxa_ep statically, we must guess all needed pxa_ep for all
* gadget which may work with this udc driver.
*/
struct pxa_ep {
struct pxa_udc *dev;
struct list_head queue;
spinlock_t lock; /* Protects this structure */
/* (queues, stats) */
unsigned enabled:1;
unsigned idx:5;
char *name;
/*
* Specific pxa endpoint data, needed for hardware initialization
*/
unsigned dir_in:1;
unsigned addr:3;
unsigned config:2;
unsigned interface:3;
unsigned alternate:3;
unsigned fifo_size;
unsigned type;
#ifdef CONFIG_PM
u32 udccsr_value;
u32 udccr_value;
#endif
struct stats stats;
};
/**
* struct pxa27x_request - container of each usb_request structure
* @req: usb request
* @udc_usb_ep: usb endpoint the request was submitted on
* @in_use: sanity check if request already queued on an pxa_ep
* @queue: linked list of requests, linked on pxa_ep->queue
*/
struct pxa27x_request {
struct usb_request req;
struct udc_usb_ep *udc_usb_ep;
unsigned in_use:1;
struct list_head queue;
};
enum ep0_state {
WAIT_FOR_SETUP,
SETUP_STAGE,
IN_DATA_STAGE,
OUT_DATA_STAGE,
IN_STATUS_STAGE,
OUT_STATUS_STAGE,
STALL,
WAIT_ACK_SET_CONF_INTERF
};
static char *ep0_state_name[] = {
"WAIT_FOR_SETUP", "SETUP_STAGE", "IN_DATA_STAGE", "OUT_DATA_STAGE",
"IN_STATUS_STAGE", "OUT_STATUS_STAGE", "STALL",
"WAIT_ACK_SET_CONF_INTERF"
};
#define EP0_STNAME(udc) ep0_state_name[(udc)->ep0state]
#define EP0_FIFO_SIZE 16U
#define BULK_FIFO_SIZE 64U
#define ISO_FIFO_SIZE 256U
#define INT_FIFO_SIZE 16U
struct udc_stats {
unsigned long irqs_reset;
unsigned long irqs_suspend;
unsigned long irqs_resume;
unsigned long irqs_reconfig;
};
#define NR_USB_ENDPOINTS (1 + 5) /* ep0 + ep1in-bulk + .. + ep3in-iso */
#define NR_PXA_ENDPOINTS (1 + 14) /* ep0 + epA + epB + .. + epX */
/**
* struct pxa_udc - udc structure
* @regs: mapped IO space
* @irq: udc irq
* @clk: udc clock
* @usb_gadget: udc gadget structure
* @driver: bound gadget (zero, g_ether, g_file_storage, ...)
* @dev: device
* @mach: machine info, used to activate specific GPIO
* @ep0state: control endpoint state machine state
* @stats: statistics on udc usage
* @udc_usb_ep: array of usb endpoints offered by the gadget
* @pxa_ep: array of pxa available endpoints
* @config: UDC active configuration
* @last_interface: UDC interface of the last SET_INTERFACE host request
* @last_alternate: UDC altsetting of the last SET_INTERFACE host request
* @udccsr0: save of udccsr0 in case of suspend
* @debugfs_root: root entry of debug filesystem
* @debugfs_state: debugfs entry for "udcstate"
* @debugfs_queues: debugfs entry for "queues"
* @debugfs_eps: debugfs entry for "epstate"
*/
struct pxa_udc {
void __iomem *regs;
int irq;
struct clk *clk;
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct device *dev;
struct pxa2xx_udc_mach_info *mach;
enum ep0_state ep0state;
struct udc_stats stats;
struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS];
struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS];
unsigned config:2;
unsigned last_interface:3;
unsigned last_alternate:3;
#ifdef CONFIG_PM
unsigned udccsr0;
#endif
#ifdef CONFIG_USB_GADGET_DEBUG_FS
struct dentry *debugfs_root;
struct dentry *debugfs_state;
struct dentry *debugfs_queues;
struct dentry *debugfs_eps;
#endif
};
static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget)
{
return container_of(gadget, struct pxa_udc, gadget);
}
/*
* Debugging/message support
*/
#define ep_dbg(ep, fmt, arg...) \
dev_dbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
#define ep_vdbg(ep, fmt, arg...) \
dev_vdbg(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
#define ep_err(ep, fmt, arg...) \
dev_err(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
#define ep_info(ep, fmt, arg...) \
dev_info(ep->dev->dev, "%s:%s: " fmt, EPNAME(ep), __func__, ## arg)
#define ep_warn(ep, fmt, arg...) \
dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg)
#endif /* __LINUX_USB_GADGET_PXA27X_H */

View file

@ -135,7 +135,10 @@ struct gs_port {
int port_in_use; /* open/close in progress */
wait_queue_head_t port_write_wait;/* waiting to write */
struct gs_buf *port_write_buf;
struct usb_cdc_line_coding port_line_coding;
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
u16 port_handshake_bits;
#define RS232_RTS (1 << 1)
#define RS232_DTE (1 << 0)
};
/* the device structure holds info for the USB device */
@ -199,6 +202,8 @@ static int gs_setup_standard(struct usb_gadget *gadget,
static int gs_setup_class(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req);
static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
struct usb_request *req);
static void gs_disconnect(struct usb_gadget *gadget);
static int gs_set_config(struct gs_dev *dev, unsigned config);
static void gs_reset_config(struct gs_dev *dev);
@ -406,7 +411,7 @@ static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
.bLength = sizeof(gs_acm_descriptor),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ACM_TYPE,
.bmCapabilities = 0,
.bmCapabilities = (1 << 1),
};
static const struct usb_cdc_union_desc gs_union_desc = {
@ -1502,6 +1507,8 @@ static int gs_setup(struct usb_gadget *gadget,
u16 wValue = le16_to_cpu(ctrl->wValue);
u16 wLength = le16_to_cpu(ctrl->wLength);
req->complete = gs_setup_complete;
switch (ctrl->bRequestType & USB_TYPE_MASK) {
case USB_TYPE_STANDARD:
ret = gs_setup_standard(gadget,ctrl);
@ -1679,18 +1686,14 @@ static int gs_setup_class(struct usb_gadget *gadget,
switch (ctrl->bRequest) {
case USB_CDC_REQ_SET_LINE_CODING:
/* FIXME Submit req to read the data; have its completion
* handler copy that data to port->port_line_coding (iff
* it's valid) and maybe pass it on. Until then, fail.
*/
pr_warning("gs_setup: set_line_coding "
"unuspported\n");
if (wLength != sizeof(struct usb_cdc_line_coding))
break;
ret = wLength;
req->complete = gs_setup_complete_set_line_coding;
break;
case USB_CDC_REQ_GET_LINE_CODING:
port = dev->dev_port[0]; /* ACM only has one port */
ret = min(wLength,
(u16)sizeof(struct usb_cdc_line_coding));
ret = min_t(int, wLength, sizeof(struct usb_cdc_line_coding));
if (port) {
spin_lock(&port->port_lock);
memcpy(req->buf, &port->port_line_coding, ret);
@ -1699,15 +1702,27 @@ static int gs_setup_class(struct usb_gadget *gadget,
break;
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
/* FIXME Submit req to read the data; have its completion
* handler use that to set the state (iff it's valid) and
* maybe pass it on. Until then, fail.
*/
pr_warning("gs_setup: set_control_line_state "
"unuspported\n");
if (wLength != 0)
break;
ret = 0;
if (port) {
/* REVISIT: we currently just remember this data.
* If we change that, update whatever hardware needs
* updating.
*/
spin_lock(&port->port_lock);
port->port_handshake_bits = wValue;
spin_unlock(&port->port_lock);
}
break;
default:
/* NOTE: strictly speaking, we should accept AT-commands
* using SEND_ENCPSULATED_COMMAND/GET_ENCAPSULATED_RESPONSE.
* But our call management descriptor says we don't handle
* call management, so we should be able to get by without
* handling those "required" commands (except by stalling).
*/
pr_err("gs_setup: unknown class request, "
"type=%02x, request=%02x, value=%04x, "
"index=%04x, length=%d\n",
@ -1719,6 +1734,42 @@ static int gs_setup_class(struct usb_gadget *gadget,
return ret;
}
static void gs_setup_complete_set_line_coding(struct usb_ep *ep,
struct usb_request *req)
{
struct gs_dev *dev = ep->driver_data;
struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */
switch (req->status) {
case 0:
/* normal completion */
if (req->actual != sizeof(port->port_line_coding))
usb_ep_set_halt(ep);
else if (port) {
struct usb_cdc_line_coding *value = req->buf;
/* REVISIT: we currently just remember this data.
* If we change that, (a) validate it first, then
* (b) update whatever hardware needs updating.
*/
spin_lock(&port->port_lock);
port->port_line_coding = *value;
spin_unlock(&port->port_lock);
}
break;
case -ESHUTDOWN:
/* disconnect */
gs_free_req(ep, req);
break;
default:
/* unexpected */
break;
}
return;
}
/*
* gs_setup_complete
*/
@ -1906,6 +1957,11 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
}
}
/* REVISIT the ACM mode should be able to actually *issue* some
* notifications, for at least serial state change events if
* not also for network connection; say so in bmCapabilities.
*/
pr_info("gs_set_config: %s configured, %s speed %s config\n",
GS_LONG_NAME,
gadget->speed == USB_SPEED_HIGH ? "high" : "full",

View file

@ -23,9 +23,7 @@
/*
* Gadget Zero only needs two bulk endpoints, and is an example of how you
* can write a hardware-agnostic gadget driver running inside a USB device.
*
* Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't
* affect most of the driver.
* Some hardware details are visible, but don't affect most of the driver.
*
* Use it with the Linux host/master side "usbtest" driver to get a basic
* functional test of your device-side usb stack, or with "usb-skeleton".
@ -37,6 +35,7 @@
* buflen=N default N=4096, buffer size used
* qlen=N default N=32, how many buffers in the loopback queue
* loopdefault default false, list loopback config first
* autoresume=N default N=0, seconds before triggering remote wakeup
*
* Many drivers will only have one configuration, letting them be much
* simpler if they also don't support high speed operation (like this
@ -62,13 +61,13 @@
/*-------------------------------------------------------------------------*/
#define DRIVER_VERSION "Lughnasadh, 2007"
#define DRIVER_VERSION "Earth Day 2008"
static const char shortname [] = "zero";
static const char longname [] = "Gadget Zero";
static const char shortname[] = "zero";
static const char longname[] = "Gadget Zero";
static const char source_sink [] = "source and sink data";
static const char loopback [] = "loop input to output";
static const char source_sink[] = "source and sink data";
static const char loopback[] = "loop input to output";
/*-------------------------------------------------------------------------*/
@ -120,16 +119,16 @@ static unsigned buflen = 4096;
static unsigned qlen = 32;
static unsigned pattern = 0;
module_param (buflen, uint, S_IRUGO);
module_param (qlen, uint, S_IRUGO);
module_param (pattern, uint, S_IRUGO|S_IWUSR);
module_param(buflen, uint, S_IRUGO);
module_param(qlen, uint, S_IRUGO);
module_param(pattern, uint, S_IRUGO|S_IWUSR);
/*
* if it's nonzero, autoresume says how many seconds to wait
* before trying to wake up the host after suspend.
*/
static unsigned autoresume = 0;
module_param (autoresume, uint, 0);
module_param(autoresume, uint, 0);
/*
* Normally the "loopback" configuration is second (index 1) so
@ -138,8 +137,7 @@ module_param (autoresume, uint, 0);
* Or controllers (like superh) that only support one config.
*/
static int loopdefault = 0;
module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
/*-------------------------------------------------------------------------*/
@ -176,24 +174,22 @@ module_param (loopdefault, bool, S_IRUGO|S_IWUSR);
#define CONFIG_SOURCE_SINK 3
#define CONFIG_LOOPBACK 2
static struct usb_device_descriptor
device_desc = {
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16 (0x0200),
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
.idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
.iSerialNumber = STRING_SERIAL,
.bNumConfigurations = 2,
};
static struct usb_config_descriptor
source_sink_config = {
static struct usb_config_descriptor source_sink_config = {
.bLength = sizeof source_sink_config,
.bDescriptorType = USB_DT_CONFIG,
@ -205,8 +201,7 @@ source_sink_config = {
.bMaxPower = 1, /* self-powered */
};
static struct usb_config_descriptor
loopback_config = {
static struct usb_config_descriptor loopback_config = {
.bLength = sizeof loopback_config,
.bDescriptorType = USB_DT_CONFIG,
@ -218,8 +213,7 @@ loopback_config = {
.bMaxPower = 1, /* self-powered */
};
static struct usb_otg_descriptor
otg_descriptor = {
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
@ -228,8 +222,7 @@ otg_descriptor = {
/* one interface in each configuration */
static const struct usb_interface_descriptor
source_sink_intf = {
static const struct usb_interface_descriptor source_sink_intf = {
.bLength = sizeof source_sink_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -238,8 +231,7 @@ source_sink_intf = {
.iInterface = STRING_SOURCE_SINK,
};
static const struct usb_interface_descriptor
loopback_intf = {
static const struct usb_interface_descriptor loopback_intf = {
.bLength = sizeof loopback_intf,
.bDescriptorType = USB_DT_INTERFACE,
@ -250,8 +242,7 @@ loopback_intf = {
/* two full speed bulk endpoints; their use is config-dependent */
static struct usb_endpoint_descriptor
fs_source_desc = {
static struct usb_endpoint_descriptor fs_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -259,8 +250,7 @@ fs_source_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor
fs_sink_desc = {
static struct usb_endpoint_descriptor fs_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -268,7 +258,7 @@ fs_sink_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static const struct usb_descriptor_header *fs_source_sink_function [] = {
static const struct usb_descriptor_header *fs_source_sink_function[] = {
(struct usb_descriptor_header *) &otg_descriptor,
(struct usb_descriptor_header *) &source_sink_intf,
(struct usb_descriptor_header *) &fs_sink_desc,
@ -276,7 +266,7 @@ static const struct usb_descriptor_header *fs_source_sink_function [] = {
NULL,
};
static const struct usb_descriptor_header *fs_loopback_function [] = {
static const struct usb_descriptor_header *fs_loopback_function[] = {
(struct usb_descriptor_header *) &otg_descriptor,
(struct usb_descriptor_header *) &loopback_intf,
(struct usb_descriptor_header *) &fs_sink_desc,
@ -293,36 +283,33 @@ static const struct usb_descriptor_header *fs_loopback_function [] = {
* for the config descriptor.
*/
static struct usb_endpoint_descriptor
hs_source_desc = {
static struct usb_endpoint_descriptor hs_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (512),
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
static struct usb_endpoint_descriptor
hs_sink_desc = {
static struct usb_endpoint_descriptor hs_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16 (512),
.wMaxPacketSize = __constant_cpu_to_le16(512),
};
static struct usb_qualifier_descriptor
dev_qualifier = {
static struct usb_qualifier_descriptor dev_qualifier = {
.bLength = sizeof dev_qualifier,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = __constant_cpu_to_le16 (0x0200),
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
.bNumConfigurations = 2,
};
static const struct usb_descriptor_header *hs_source_sink_function [] = {
static const struct usb_descriptor_header *hs_source_sink_function[] = {
(struct usb_descriptor_header *) &otg_descriptor,
(struct usb_descriptor_header *) &source_sink_intf,
(struct usb_descriptor_header *) &hs_source_desc,
@ -330,7 +317,7 @@ static const struct usb_descriptor_header *hs_source_sink_function [] = {
NULL,
};
static const struct usb_descriptor_header *hs_loopback_function [] = {
static const struct usb_descriptor_header *hs_loopback_function[] = {
(struct usb_descriptor_header *) &otg_descriptor,
(struct usb_descriptor_header *) &loopback_intf,
(struct usb_descriptor_header *) &hs_source_desc,
@ -355,7 +342,7 @@ static char serial[] = "0123456789.0123456789.0123456789";
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
static struct usb_string strings[] = {
{ STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, longname, },
{ STRING_SERIAL, serial, },
@ -364,7 +351,7 @@ static struct usb_string strings [] = {
{ } /* end of list */
};
static struct usb_gadget_strings stringtab = {
static struct usb_gadget_strings stringtab = {
.language = 0x0409, /* en-us */
.strings = strings,
};
@ -387,8 +374,7 @@ static struct usb_gadget_strings stringtab = {
* high bandwidth modes at high speed. (Maybe work like Intel's test
* device?)
*/
static int
config_buf (struct usb_gadget *gadget,
static int config_buf(struct usb_gadget *gadget,
u8 *buf, u8 type, unsigned index)
{
int is_source_sink;
@ -419,7 +405,7 @@ config_buf (struct usb_gadget *gadget,
if (!gadget_is_otg(gadget))
function++;
len = usb_gadget_config_buf (is_source_sink
len = usb_gadget_config_buf(is_source_sink
? &source_sink_config
: &loopback_config,
buf, USB_BUFSIZ, function);
@ -431,27 +417,26 @@ config_buf (struct usb_gadget *gadget,
/*-------------------------------------------------------------------------*/
static struct usb_request *
alloc_ep_req (struct usb_ep *ep, unsigned length)
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
{
struct usb_request *req;
req = usb_ep_alloc_request (ep, GFP_ATOMIC);
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (req) {
req->length = length;
req->buf = kmalloc(length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request (ep, req);
usb_ep_free_request(ep, req);
req = NULL;
}
}
return req;
}
static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request (ep, req);
usb_ep_free_request(ep, req);
}
/*-------------------------------------------------------------------------*/
@ -472,7 +457,7 @@ static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
/* optionally require specific source/sink data patterns */
static int
check_read_data (
check_read_data(
struct zero_dev *dev,
struct usb_ep *ep,
struct usb_request *req
@ -498,8 +483,8 @@ check_read_data (
continue;
break;
}
ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf);
usb_ep_set_halt (ep);
ERROR(dev, "bad OUT byte, buf[%d] = %d\n", i, *buf);
usb_ep_set_halt(ep);
return -EINVAL;
}
return 0;
@ -512,7 +497,7 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
switch (pattern) {
case 0:
memset (req->buf, 0, req->length);
memset(req->buf, 0, req->length);
break;
case 1:
for (i = 0; i < req->length; i++)
@ -525,7 +510,7 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
* irq delay between end of one request and start of the next.
* that prevents using hardware dma queues.
*/
static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
{
struct zero_dev *dev = ep->driver_data;
int status = req->status;
@ -534,8 +519,8 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
case 0: /* normal completion? */
if (ep == dev->out_ep) {
check_read_data (dev, ep, req);
memset (req->buf, 0x55, req->length);
check_read_data(dev, ep, req);
memset(req->buf, 0x55, req->length);
} else
reinit_write_data(ep, req);
break;
@ -544,11 +529,11 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
req->actual, req->length);
if (ep == dev->out_ep)
check_read_data (dev, ep, req);
free_ep_req (ep, req);
check_read_data(dev, ep, req);
free_ep_req(ep, req);
return;
case -EOVERFLOW: /* buffer overrun on read means that
@ -557,18 +542,18 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
*/
default:
#if 1
DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length);
#endif
case -EREMOTEIO: /* short read */
break;
}
status = usb_ep_queue (ep, req, GFP_ATOMIC);
status = usb_ep_queue(ep, req, GFP_ATOMIC);
if (status) {
ERROR (dev, "kill %s: resubmit %d bytes --> %d\n",
ERROR(dev, "kill %s: resubmit %d bytes --> %d\n",
ep->name, req->length, status);
usb_ep_set_halt (ep);
usb_ep_set_halt(ep);
/* FIXME recover later ... somehow */
}
}
@ -578,24 +563,24 @@ static struct usb_request *source_sink_start_ep(struct usb_ep *ep)
struct usb_request *req;
int status;
req = alloc_ep_req (ep, buflen);
req = alloc_ep_req(ep, buflen);
if (!req)
return NULL;
memset (req->buf, 0, req->length);
memset(req->buf, 0, req->length);
req->complete = source_sink_complete;
if (strcmp (ep->name, EP_IN_NAME) == 0)
if (strcmp(ep->name, EP_IN_NAME) == 0)
reinit_write_data(ep, req);
else
memset (req->buf, 0x55, req->length);
memset(req->buf, 0x55, req->length);
status = usb_ep_queue(ep, req, GFP_ATOMIC);
if (status) {
struct zero_dev *dev = ep->driver_data;
ERROR (dev, "start %s --> %d\n", ep->name, status);
free_ep_req (ep, req);
ERROR(dev, "start %s --> %d\n", ep->name, status);
free_ep_req(ep, req);
req = NULL;
}
@ -608,34 +593,34 @@ static int set_source_sink_config(struct zero_dev *dev)
struct usb_ep *ep;
struct usb_gadget *gadget = dev->gadget;
gadget_for_each_ep (ep, gadget) {
gadget_for_each_ep(ep, gadget) {
const struct usb_endpoint_descriptor *d;
/* one endpoint writes (sources) zeroes in (to the host) */
if (strcmp (ep->name, EP_IN_NAME) == 0) {
d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
result = usb_ep_enable (ep, d);
if (strcmp(ep->name, EP_IN_NAME) == 0) {
d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
result = usb_ep_enable(ep, d);
if (result == 0) {
ep->driver_data = dev;
if (source_sink_start_ep(ep) != NULL) {
dev->in_ep = ep;
continue;
}
usb_ep_disable (ep);
usb_ep_disable(ep);
result = -EIO;
}
/* one endpoint reads (sinks) anything out (from the host) */
} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
result = usb_ep_enable (ep, d);
} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
result = usb_ep_enable(ep, d);
if (result == 0) {
ep->driver_data = dev;
if (source_sink_start_ep(ep) != NULL) {
dev->out_ep = ep;
continue;
}
usb_ep_disable (ep);
usb_ep_disable(ep);
result = -EIO;
}
@ -644,11 +629,11 @@ static int set_source_sink_config(struct zero_dev *dev)
continue;
/* stop on error */
ERROR (dev, "can't start %s, result %d\n", ep->name, result);
ERROR(dev, "can't start %s, result %d\n", ep->name, result);
break;
}
if (result == 0)
DBG (dev, "buflen %d\n", buflen);
DBG(dev, "buflen %d\n", buflen);
/* caller is responsible for cleanup on error */
return result;
@ -656,7 +641,7 @@ static int set_source_sink_config(struct zero_dev *dev)
/*-------------------------------------------------------------------------*/
static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
{
struct zero_dev *dev = ep->driver_data;
int status = req->status;
@ -668,19 +653,19 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
/* loop this OUT packet back IN to the host */
req->zero = (req->actual < req->length);
req->length = req->actual;
status = usb_ep_queue (dev->in_ep, req, GFP_ATOMIC);
status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
if (status == 0)
return;
/* "should never get here" */
ERROR (dev, "can't loop %s to %s: %d\n",
ERROR(dev, "can't loop %s to %s: %d\n",
ep->name, dev->in_ep->name,
status);
}
/* queue the buffer for some later OUT packet */
req->length = buflen;
status = usb_ep_queue (dev->out_ep, req, GFP_ATOMIC);
status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
if (status == 0)
return;
@ -688,7 +673,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
/* FALLTHROUGH */
default:
ERROR (dev, "%s loop complete --> %d, %d/%d\n", ep->name,
ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name,
status, req->actual, req->length);
/* FALLTHROUGH */
@ -700,7 +685,7 @@ static void loopback_complete (struct usb_ep *ep, struct usb_request *req)
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
free_ep_req (ep, req);
free_ep_req(ep, req);
return;
}
}
@ -711,13 +696,13 @@ static int set_loopback_config(struct zero_dev *dev)
struct usb_ep *ep;
struct usb_gadget *gadget = dev->gadget;
gadget_for_each_ep (ep, gadget) {
gadget_for_each_ep(ep, gadget) {
const struct usb_endpoint_descriptor *d;
/* one endpoint writes data back IN to the host */
if (strcmp (ep->name, EP_IN_NAME) == 0) {
d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
result = usb_ep_enable (ep, d);
if (strcmp(ep->name, EP_IN_NAME) == 0) {
d = ep_desc(gadget, &hs_source_desc, &fs_source_desc);
result = usb_ep_enable(ep, d);
if (result == 0) {
ep->driver_data = dev;
dev->in_ep = ep;
@ -725,9 +710,9 @@ static int set_loopback_config(struct zero_dev *dev)
}
/* one endpoint just reads OUT packets */
} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
result = usb_ep_enable (ep, d);
} else if (strcmp(ep->name, EP_OUT_NAME) == 0) {
d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc);
result = usb_ep_enable(ep, d);
if (result == 0) {
ep->driver_data = dev;
dev->out_ep = ep;
@ -739,7 +724,7 @@ static int set_loopback_config(struct zero_dev *dev)
continue;
/* stop on error */
ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
ERROR(dev, "can't enable %s, result %d\n", ep->name, result);
break;
}
@ -753,19 +738,19 @@ static int set_loopback_config(struct zero_dev *dev)
ep = dev->out_ep;
for (i = 0; i < qlen && result == 0; i++) {
req = alloc_ep_req (ep, buflen);
req = alloc_ep_req(ep, buflen);
if (req) {
req->complete = loopback_complete;
result = usb_ep_queue (ep, req, GFP_ATOMIC);
result = usb_ep_queue(ep, req, GFP_ATOMIC);
if (result)
DBG (dev, "%s queue req --> %d\n",
DBG(dev, "%s queue req --> %d\n",
ep->name, result);
} else
result = -ENOMEM;
}
}
if (result == 0)
DBG (dev, "qlen %d, buflen %d\n", qlen, buflen);
DBG(dev, "qlen %d, buflen %d\n", qlen, buflen);
/* caller is responsible for cleanup on error */
return result;
@ -773,26 +758,26 @@ static int set_loopback_config(struct zero_dev *dev)
/*-------------------------------------------------------------------------*/
static void zero_reset_config (struct zero_dev *dev)
static void zero_reset_config(struct zero_dev *dev)
{
if (dev->config == 0)
return;
DBG (dev, "reset config\n");
DBG(dev, "reset config\n");
/* just disable endpoints, forcing completion of pending i/o.
* all our completion handlers free their requests in this case.
*/
if (dev->in_ep) {
usb_ep_disable (dev->in_ep);
usb_ep_disable(dev->in_ep);
dev->in_ep = NULL;
}
if (dev->out_ep) {
usb_ep_disable (dev->out_ep);
usb_ep_disable(dev->out_ep);
dev->out_ep = NULL;
}
dev->config = 0;
del_timer (&dev->resume);
del_timer(&dev->resume);
}
/* change our operational config. this code must agree with the code
@ -813,12 +798,12 @@ static int zero_set_config(struct zero_dev *dev, unsigned number)
if (number == dev->config)
return 0;
if (gadget_is_sa1100 (gadget) && dev->config) {
if (gadget_is_sa1100(gadget) && dev->config) {
/* tx fifo is full, but we can't clear it...*/
ERROR(dev, "can't change configurations\n");
return -ESPIPE;
}
zero_reset_config (dev);
zero_reset_config(dev);
switch (number) {
case CONFIG_SOURCE_SINK:
@ -837,7 +822,7 @@ static int zero_set_config(struct zero_dev *dev, unsigned number)
if (!result && (!dev->in_ep || !dev->out_ep))
result = -ENODEV;
if (result)
zero_reset_config (dev);
zero_reset_config(dev);
else {
char *speed;
@ -849,7 +834,7 @@ static int zero_set_config(struct zero_dev *dev, unsigned number)
}
dev->config = number;
INFO (dev, "%s speed config #%d: %s\n", speed, number,
INFO(dev, "%s speed config #%d: %s\n", speed, number,
(number == CONFIG_SOURCE_SINK)
? source_sink : loopback);
}
@ -858,10 +843,10 @@ static int zero_set_config(struct zero_dev *dev, unsigned number)
/*-------------------------------------------------------------------------*/
static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)
{
if (req->status || req->actual != req->length)
DBG ((struct zero_dev *) ep->driver_data,
DBG((struct zero_dev *) ep->driver_data,
"setup complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
}
@ -874,9 +859,9 @@ static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
* the work is in config-specific setup.
*/
static int
zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{
struct zero_dev *dev = get_gadget_data (gadget);
struct zero_dev *dev = get_gadget_data(gadget);
struct usb_request *req = dev->req;
int value = -EOPNOTSUPP;
u16 w_index = le16_to_cpu(ctrl->wIndex);
@ -895,14 +880,14 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
switch (w_value >> 8) {
case USB_DT_DEVICE:
value = min (w_length, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value);
value = min(w_length, (u16) sizeof device_desc);
memcpy(req->buf, &device_desc, value);
break;
case USB_DT_DEVICE_QUALIFIER:
if (!gadget_is_dualspeed(gadget))
break;
value = min (w_length, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value);
value = min(w_length, (u16) sizeof dev_qualifier);
memcpy(req->buf, &dev_qualifier, value);
break;
case USB_DT_OTHER_SPEED_CONFIG:
@ -910,11 +895,11 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break;
// FALLTHROUGH
case USB_DT_CONFIG:
value = config_buf (gadget, req->buf,
value = config_buf(gadget, req->buf,
w_value >> 8,
w_value & 0xff);
if (value >= 0)
value = min (w_length, (u16) value);
value = min(w_length, (u16) value);
break;
case USB_DT_STRING:
@ -923,10 +908,10 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* add string tables for other languages, using
* any UTF-8 characters
*/
value = usb_gadget_get_string (&stringtab,
value = usb_gadget_get_string(&stringtab,
w_value & 0xff, req->buf);
if (value >= 0)
value = min (w_length, (u16) value);
value = min(w_length, (u16) value);
break;
}
break;
@ -936,20 +921,20 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (ctrl->bRequestType != 0)
goto unknown;
if (gadget->a_hnp_support)
DBG (dev, "HNP available\n");
DBG(dev, "HNP available\n");
else if (gadget->a_alt_hnp_support)
DBG (dev, "HNP needs a different root port\n");
DBG(dev, "HNP needs a different root port\n");
else
VDBG (dev, "HNP inactive\n");
spin_lock (&dev->lock);
VDBG(dev, "HNP inactive\n");
spin_lock(&dev->lock);
value = zero_set_config(dev, w_value);
spin_unlock (&dev->lock);
spin_unlock(&dev->lock);
break;
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
goto unknown;
*(u8 *)req->buf = dev->config;
value = min (w_length, (u16) 1);
value = min(w_length, (u16) 1);
break;
/* until we add altsetting support, or other interfaces,
@ -959,7 +944,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_REQ_SET_INTERFACE:
if (ctrl->bRequestType != USB_RECIP_INTERFACE)
goto unknown;
spin_lock (&dev->lock);
spin_lock(&dev->lock);
if (dev->config && w_index == 0 && w_value == 0) {
u8 config = dev->config;
@ -970,11 +955,11 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
* if we had more than one interface we couldn't
* use this "reset the config" shortcut.
*/
zero_reset_config (dev);
zero_reset_config(dev);
zero_set_config(dev, config);
value = 0;
}
spin_unlock (&dev->lock);
spin_unlock(&dev->lock);
break;
case USB_REQ_GET_INTERFACE:
if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
@ -986,7 +971,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break;
}
*(u8 *)req->buf = 0;
value = min (w_length, (u16) 1);
value = min(w_length, (u16) 1);
break;
/*
@ -1018,7 +1003,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
default:
unknown:
VDBG (dev,
VDBG(dev,
"unknown control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
@ -1028,11 +1013,11 @@ unknown:
if (value >= 0) {
req->length = value;
req->zero = value < w_length;
value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
DBG(dev, "ep_queue --> %d\n", value);
req->status = 0;
zero_setup_complete (gadget->ep0, req);
zero_setup_complete(gadget->ep0, req);
}
}
@ -1040,28 +1025,26 @@ unknown:
return value;
}
static void
zero_disconnect (struct usb_gadget *gadget)
static void zero_disconnect(struct usb_gadget *gadget)
{
struct zero_dev *dev = get_gadget_data (gadget);
struct zero_dev *dev = get_gadget_data(gadget);
unsigned long flags;
spin_lock_irqsave (&dev->lock, flags);
zero_reset_config (dev);
spin_lock_irqsave(&dev->lock, flags);
zero_reset_config(dev);
/* a more significant application might have some non-usb
* activities to quiesce here, saving resources like power
* or pushing the notification up a network stack.
*/
spin_unlock_irqrestore (&dev->lock, flags);
spin_unlock_irqrestore(&dev->lock, flags);
/* next we may get setup() calls to enumerate new connections;
* or an unbind() during shutdown (including removing module).
*/
}
static void
zero_autoresume (unsigned long _dev)
static void zero_autoresume(unsigned long _dev)
{
struct zero_dev *dev = (struct zero_dev *) _dev;
int status;
@ -1070,32 +1053,30 @@ zero_autoresume (unsigned long _dev)
* more significant than just a timer firing...
*/
if (dev->gadget->speed != USB_SPEED_UNKNOWN) {
status = usb_gadget_wakeup (dev->gadget);
DBG (dev, "wakeup --> %d\n", status);
status = usb_gadget_wakeup(dev->gadget);
DBG(dev, "wakeup --> %d\n", status);
}
}
/*-------------------------------------------------------------------------*/
static void /* __init_or_exit */
zero_unbind (struct usb_gadget *gadget)
static void zero_unbind(struct usb_gadget *gadget)
{
struct zero_dev *dev = get_gadget_data (gadget);
struct zero_dev *dev = get_gadget_data(gadget);
DBG (dev, "unbind\n");
DBG(dev, "unbind\n");
/* we've already been disconnected ... no i/o is active */
if (dev->req) {
dev->req->length = USB_BUFSIZ;
free_ep_req (gadget->ep0, dev->req);
free_ep_req(gadget->ep0, dev->req);
}
del_timer_sync (&dev->resume);
kfree (dev);
set_gadget_data (gadget, NULL);
del_timer_sync(&dev->resume);
kfree(dev);
set_gadget_data(gadget, NULL);
}
static int __init
zero_bind (struct usb_gadget *gadget)
static int __init zero_bind(struct usb_gadget *gadget)
{
struct zero_dev *dev;
struct usb_ep *ep;
@ -1111,8 +1092,8 @@ zero_bind (struct usb_gadget *gadget)
* autoconfigure on any sane usb controller driver,
* but there may also be important quirks to address.
*/
usb_ep_autoconfig_reset (gadget);
ep = usb_ep_autoconfig (gadget, &fs_source_desc);
usb_ep_autoconfig_reset(gadget);
ep = usb_ep_autoconfig(gadget, &fs_source_desc);
if (!ep) {
autoconf_fail:
pr_err("%s: can't autoconfigure on %s\n",
@ -1122,15 +1103,15 @@ autoconf_fail:
EP_IN_NAME = ep->name;
ep->driver_data = ep; /* claim */
ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
ep = usb_ep_autoconfig(gadget, &fs_sink_desc);
if (!ep)
goto autoconf_fail;
EP_OUT_NAME = ep->name;
ep->driver_data = ep; /* claim */
gcnum = usb_gadget_controller_number (gadget);
gcnum = usb_gadget_controller_number(gadget);
if (gcnum >= 0)
device_desc.bcdDevice = cpu_to_le16 (0x0200 + gcnum);
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.
@ -1141,7 +1122,7 @@ autoconf_fail:
*/
pr_warning("%s: controller '%s' not recognized\n",
shortname, gadget->name);
device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
}
@ -1149,12 +1130,16 @@ autoconf_fail:
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
spin_lock_init (&dev->lock);
spin_lock_init(&dev->lock);
dev->gadget = gadget;
set_gadget_data (gadget, dev);
set_gadget_data(gadget, dev);
init_timer(&dev->resume);
dev->resume.function = zero_autoresume;
dev->resume.data = (unsigned long) dev;
/* preallocate control response and buffer */
dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
if (!dev->req)
goto enomem;
dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
@ -1182,11 +1167,8 @@ autoconf_fail:
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
usb_gadget_set_selfpowered (gadget);
usb_gadget_set_selfpowered(gadget);
init_timer (&dev->resume);
dev->resume.function = zero_autoresume;
dev->resume.data = (unsigned long) dev;
if (autoresume) {
source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
@ -1194,45 +1176,43 @@ autoconf_fail:
gadget->ep0->driver_data = dev;
INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
INFO (dev, "using %s, OUT %s IN %s\n", gadget->name,
INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
EP_OUT_NAME, EP_IN_NAME);
snprintf (manufacturer, sizeof manufacturer, "%s %s with %s",
snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
return 0;
enomem:
zero_unbind (gadget);
zero_unbind(gadget);
return -ENOMEM;
}
/*-------------------------------------------------------------------------*/
static void
zero_suspend (struct usb_gadget *gadget)
static void zero_suspend(struct usb_gadget *gadget)
{
struct zero_dev *dev = get_gadget_data (gadget);
struct zero_dev *dev = get_gadget_data(gadget);
if (gadget->speed == USB_SPEED_UNKNOWN)
return;
if (autoresume) {
mod_timer (&dev->resume, jiffies + (HZ * autoresume));
DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
mod_timer(&dev->resume, jiffies + (HZ * autoresume));
DBG(dev, "suspend, wakeup in %d seconds\n", autoresume);
} else
DBG (dev, "suspend\n");
DBG(dev, "suspend\n");
}
static void
zero_resume (struct usb_gadget *gadget)
static void zero_resume(struct usb_gadget *gadget)
{
struct zero_dev *dev = get_gadget_data (gadget);
struct zero_dev *dev = get_gadget_data(gadget);
DBG (dev, "resume\n");
del_timer (&dev->resume);
DBG(dev, "resume\n");
del_timer(&dev->resume);
}
@ -1264,15 +1244,15 @@ MODULE_AUTHOR("David Brownell");
MODULE_LICENSE("GPL");
static int __init init (void)
static int __init init(void)
{
return usb_gadget_register_driver (&zero_driver);
return usb_gadget_register_driver(&zero_driver);
}
module_init (init);
module_init(init);
static void __exit cleanup (void)
static void __exit cleanup(void)
{
usb_gadget_unregister_driver (&zero_driver);
usb_gadget_unregister_driver(&zero_driver);
}
module_exit (cleanup);
module_exit(cleanup);

View file

@ -4,6 +4,19 @@
comment "USB Host Controller Drivers"
depends on USB
config USB_C67X00_HCD
tristate "Cypress C67x00 HCD support"
depends on USB
help
The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
host/peripheral/OTG USB controllers.
Enable this option to support this chip in host controller mode.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called c67x00.
config USB_EHCI_HCD
tristate "EHCI HCD (USB 2.0) support"
depends on USB && USB_ARCH_HAS_EHCI
@ -95,6 +108,32 @@ config USB_ISP116X_HCD
To compile this driver as a module, choose M here: the
module will be called isp116x-hcd.
config USB_ISP1760_HCD
tristate "ISP 1760 HCD support"
depends on USB && EXPERIMENTAL
---help---
The ISP1760 chip is a USB 2.0 host controller.
This driver does not support isochronous transfers or OTG.
To compile this driver as a module, choose M here: the
module will be called isp1760-hcd.
config USB_ISP1760_PCI
bool "Support for the PCI bus"
depends on USB_ISP1760_HCD && PCI
---help---
Enables support for the device present on the PCI bus.
This should only be required if you happen to have the eval kit from
NXP and you are going to test it.
config USB_ISP1760_OF
bool "Support for the OF platform bus"
depends on USB_ISP1760_HCD && OF
---help---
Enables support for the device present on the PowerPC
OpenFirmware platform bus.
config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB && USB_ARCH_HAS_OHCI

View file

@ -6,6 +6,8 @@ ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
isp1760-objs := isp1760-hcd.o isp1760-if.o
obj-$(CONFIG_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
@ -16,4 +18,4 @@ obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,206 @@
#ifndef _ISP1760_HCD_H_
#define _ISP1760_HCD_H_
/* exports for if */
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
u64 irqflags, struct device *dev, const char *busname);
int init_kmem_once(void);
void deinit_kmem_cache(void);
/* EHCI capability registers */
#define HC_CAPLENGTH 0x00
#define HC_HCSPARAMS 0x04
#define HC_HCCPARAMS 0x08
/* EHCI operational registers */
#define HC_USBCMD 0x20
#define HC_USBSTS 0x24
#define HC_FRINDEX 0x2c
#define HC_CONFIGFLAG 0x60
#define HC_PORTSC1 0x64
#define HC_ISO_PTD_DONEMAP_REG 0x130
#define HC_ISO_PTD_SKIPMAP_REG 0x134
#define HC_ISO_PTD_LASTPTD_REG 0x138
#define HC_INT_PTD_DONEMAP_REG 0x140
#define HC_INT_PTD_SKIPMAP_REG 0x144
#define HC_INT_PTD_LASTPTD_REG 0x148
#define HC_ATL_PTD_DONEMAP_REG 0x150
#define HC_ATL_PTD_SKIPMAP_REG 0x154
#define HC_ATL_PTD_LASTPTD_REG 0x158
/* Configuration Register */
#define HC_HW_MODE_CTRL 0x300
#define ALL_ATX_RESET (1 << 31)
#define HW_DATA_BUS_32BIT (1 << 8)
#define HW_DACK_POL_HIGH (1 << 6)
#define HW_DREQ_POL_HIGH (1 << 5)
#define HW_INTR_HIGH_ACT (1 << 2)
#define HW_INTR_EDGE_TRIG (1 << 1)
#define HW_GLOBAL_INTR_EN (1 << 0)
#define HC_CHIP_ID_REG 0x304
#define HC_SCRATCH_REG 0x308
#define HC_RESET_REG 0x30c
#define SW_RESET_RESET_HC (1 << 1)
#define SW_RESET_RESET_ALL (1 << 0)
#define HC_BUFFER_STATUS_REG 0x334
#define ATL_BUFFER 0x1
#define INT_BUFFER 0x2
#define ISO_BUFFER 0x4
#define BUFFER_MAP 0x7
#define HC_MEMORY_REG 0x33c
#define HC_PORT1_CTRL 0x374
#define PORT1_POWER (3 << 3)
#define PORT1_INIT1 (1 << 7)
#define PORT1_INIT2 (1 << 23)
/* Interrupt Register */
#define HC_INTERRUPT_REG 0x310
#define HC_INTERRUPT_ENABLE 0x314
#define INTERRUPT_ENABLE_MASK (HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
#define FINAL_HW_CONFIG (HW_GLOBAL_INTR_EN | HW_DATA_BUS_32BIT)
#define HC_ISO_INT (1 << 9)
#define HC_ATL_INT (1 << 8)
#define HC_INTL_INT (1 << 7)
#define HC_EOT_INT (1 << 3)
#define HC_SOT_INT (1 << 1)
#define HC_ISO_IRQ_MASK_OR_REG 0x318
#define HC_INT_IRQ_MASK_OR_REG 0x31C
#define HC_ATL_IRQ_MASK_OR_REG 0x320
#define HC_ISO_IRQ_MASK_AND_REG 0x324
#define HC_INT_IRQ_MASK_AND_REG 0x328
#define HC_ATL_IRQ_MASK_AND_REG 0x32C
/* Register sets */
#define HC_BEGIN_OF_ATL 0x0c00
#define HC_BEGIN_OF_INT 0x0800
#define HC_BEGIN_OF_ISO 0x0400
#define HC_BEGIN_OF_PAYLOAD 0x1000
/* urb state*/
#define DELETE_URB (0x0008)
#define NO_TRANSFER_ACTIVE (0xffffffff)
#define ATL_REGS_OFFSET (0xc00)
#define INT_REGS_OFFSET (0x800)
/* Philips Transfer Descriptor (PTD) */
struct ptd {
__le32 dw0;
__le32 dw1;
__le32 dw2;
__le32 dw3;
__le32 dw4;
__le32 dw5;
__le32 dw6;
__le32 dw7;
};
struct inter_packet_info {
void *data_buffer;
u32 payload;
#define PTD_FIRE_NEXT (1 << 0)
#define PTD_URB_FINISHED (1 << 1)
struct urb *urb;
struct isp1760_qh *qh;
struct isp1760_qtd *qtd;
};
typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
struct isp1760_qtd *qtd);
#define isp1760_info(priv, fmt, args...) \
dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args)
#define isp1760_err(priv, fmt, args...) \
dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
/* chip memory management */
struct memory_chunk {
unsigned int start;
unsigned int size;
unsigned int free;
};
/*
* 60kb divided in:
* - 32 blocks @ 256 bytes
* - 20 blocks @ 1024 bytes
* - 4 blocks @ 8192 bytes
*/
#define BLOCK_1_NUM 32
#define BLOCK_2_NUM 20
#define BLOCK_3_NUM 4
#define BLOCK_1_SIZE 256
#define BLOCK_2_SIZE 1024
#define BLOCK_3_SIZE 8192
#define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM)
#define PAYLOAD_SIZE 0xf000
/* I saw if some reloads if the pointer was negative */
#define ISP1760_NULL_POINTER (0x400)
/* ATL */
/* DW0 */
#define PTD_VALID 1
#define PTD_LENGTH(x) (((u32) x) << 3)
#define PTD_MAXPACKET(x) (((u32) x) << 18)
#define PTD_MULTI(x) (((u32) x) << 29)
#define PTD_ENDPOINT(x) (((u32) x) << 31)
/* DW1 */
#define PTD_DEVICE_ADDR(x) (((u32) x) << 3)
#define PTD_PID_TOKEN(x) (((u32) x) << 10)
#define PTD_TRANS_BULK ((u32) 2 << 12)
#define PTD_TRANS_INT ((u32) 3 << 12)
#define PTD_TRANS_SPLIT ((u32) 1 << 14)
#define PTD_SE_USB_LOSPEED ((u32) 2 << 16)
#define PTD_PORT_NUM(x) (((u32) x) << 18)
#define PTD_HUB_NUM(x) (((u32) x) << 25)
#define PTD_PING(x) (((u32) x) << 26)
/* DW2 */
#define PTD_RL_CNT(x) (((u32) x) << 25)
#define PTD_DATA_START_ADDR(x) (((u32) x) << 8)
#define BASE_ADDR 0x1000
/* DW3 */
#define PTD_CERR(x) (((u32) x) << 23)
#define PTD_NAC_CNT(x) (((u32) x) << 19)
#define PTD_ACTIVE ((u32) 1 << 31)
#define PTD_DATA_TOGGLE(x) (((u32) x) << 25)
#define DW3_HALT_BIT (1 << 30)
#define DW3_ERROR_BIT (1 << 28)
#define DW3_QTD_ACTIVE (1 << 31)
#define INT_UNDERRUN (1 << 2)
#define INT_BABBLE (1 << 1)
#define INT_EXACT (1 << 0)
#define DW1_GET_PID(x) (((x) >> 10) & 0x3)
#define PTD_XFERRED_LENGTH(x) ((x) & 0x7fff)
#define PTD_XFERRED_LENGTH_LO(x) ((x) & 0x7ff)
#define SETUP_PID (2)
#define IN_PID (1)
#define OUT_PID (0)
#define GET_QTD_TOKEN_TYPE(x) ((x) & 0x3)
#define DATA_TOGGLE (1 << 31)
#define GET_DATA_TOGGLE(x) ((x) >> 31)
/* Errata 1 */
#define RL_COUNTER (0)
#define NAK_COUNTER (0)
#define ERR_COUNTER (2)
#define HC_ATL_PL_SIZE (8192)
#endif

View file

@ -0,0 +1,298 @@
/*
* Glue code for the ISP1760 driver and bus
* Currently there is support for
* - OpenFirmware
* - PCI
*
* (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
*
*/
#include <linux/usb.h>
#include <linux/io.h>
#include "../core/hcd.h"
#include "isp1760-hcd.h"
#ifdef CONFIG_USB_ISP1760_OF
#include <linux/of.h>
#include <linux/of_platform.h>
#endif
#ifdef CONFIG_USB_ISP1760_PCI
#include <linux/pci.h>
#endif
#ifdef CONFIG_USB_ISP1760_OF
static int of_isp1760_probe(struct of_device *dev,
const struct of_device_id *match)
{
struct usb_hcd *hcd;
struct device_node *dp = dev->node;
struct resource *res;
struct resource memory;
struct of_irq oirq;
int virq;
u64 res_len;
int ret;
ret = of_address_to_resource(dp, 0, &memory);
if (ret)
return -ENXIO;
res = request_mem_region(memory.start, memory.end - memory.start + 1,
dev->dev.bus_id);
if (!res)
return -EBUSY;
res_len = memory.end - memory.start + 1;
if (of_irq_map_one(dp, 0, &oirq)) {
ret = -ENODEV;
goto release_reg;
}
virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
oirq.size);
hcd = isp1760_register(memory.start, res_len, virq,
IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
if (IS_ERR(hcd)) {
ret = PTR_ERR(hcd);
goto release_reg;
}
dev_set_drvdata(&dev->dev, hcd);
return ret;
release_reg:
release_mem_region(memory.start, memory.end - memory.start + 1);
return ret;
}
static int of_isp1760_remove(struct of_device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(&dev->dev);
dev_set_drvdata(&dev->dev, NULL);
usb_remove_hcd(hcd);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
return 0;
}
static struct of_device_id of_isp1760_match[] = {
{
.compatible = "nxp,usb-isp1760",
},
{ },
};
MODULE_DEVICE_TABLE(of, of_isp1760_match);
static struct of_platform_driver isp1760_of_driver = {
.name = "nxp-isp1760",
.match_table = of_isp1760_match,
.probe = of_isp1760_probe,
.remove = of_isp1760_remove,
};
#endif
#ifdef CONFIG_USB_ISP1760_PCI
static u32 nxp_pci_io_base;
static u32 iolength;
static u32 pci_mem_phy0;
static u32 length;
static u8 *chip_addr;
static u8 *iobase;
static int __devinit isp1761_pci_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
u8 latency, limit;
__u32 reg_data;
int retry_count;
int length;
int status = 1;
struct usb_hcd *hcd;
if (usb_disabled())
return -ENODEV;
if (pci_enable_device(dev) < 0)
return -ENODEV;
if (!dev->irq)
return -ENODEV;
/* Grab the PLX PCI mem maped port start address we need */
nxp_pci_io_base = pci_resource_start(dev, 0);
iolength = pci_resource_len(dev, 0);
if (!request_mem_region(nxp_pci_io_base, iolength, "ISP1761 IO MEM")) {
printk(KERN_ERR "request region #1\n");
return -EBUSY;
}
iobase = ioremap_nocache(nxp_pci_io_base, iolength);
if (!iobase) {
printk(KERN_ERR "ioremap #1\n");
release_mem_region(nxp_pci_io_base, iolength);
return -ENOMEM;
}
/* Grab the PLX PCI shared memory of the ISP 1761 we need */
pci_mem_phy0 = pci_resource_start(dev, 3);
length = pci_resource_len(dev, 3);
if (length < 0xffff) {
printk(KERN_ERR "memory length for this resource is less than "
"required\n");
release_mem_region(nxp_pci_io_base, iolength);
iounmap(iobase);
return -ENOMEM;
}
if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) {
printk(KERN_ERR "host controller already in use\n");
release_mem_region(nxp_pci_io_base, iolength);
iounmap(iobase);
return -EBUSY;
}
/* bad pci latencies can contribute to overruns */
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
if (latency) {
pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
if (limit && limit < latency)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
}
/* Try to check whether we can access Scratch Register of
* Host Controller or not. The initial PCI access is retried until
* local init for the PCI bridge is completed
*/
retry_count = 20;
reg_data = 0;
while ((reg_data != 0xFACE) && retry_count) {
/*by default host is in 16bit mode, so
* io operations at this stage must be 16 bit
* */
writel(0xface, chip_addr + HC_SCRATCH_REG);
udelay(100);
reg_data = readl(chip_addr + HC_SCRATCH_REG);
retry_count--;
}
/* Host Controller presence is detected by writing to scratch register
* and reading back and checking the contents are same or not
*/
if (reg_data != 0xFACE) {
err("scratch register mismatch %x", reg_data);
goto clean;
}
pci_set_master(dev);
status = readl(iobase + 0x68);
status |= 0x900;
writel(status, iobase + 0x68);
dev->dev.dma_mask = NULL;
hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
pci_set_drvdata(dev, hcd);
if (!hcd)
return 0;
clean:
status = -ENODEV;
iounmap(iobase);
release_mem_region(pci_mem_phy0, length);
release_mem_region(nxp_pci_io_base, iolength);
return status;
}
static void isp1761_pci_remove(struct pci_dev *dev)
{
struct usb_hcd *hcd;
hcd = pci_get_drvdata(dev);
usb_remove_hcd(hcd);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
pci_disable_device(dev);
iounmap(iobase);
iounmap(chip_addr);
release_mem_region(nxp_pci_io_base, iolength);
release_mem_region(pci_mem_phy0, length);
}
static void isp1761_pci_shutdown(struct pci_dev *dev)
{
printk(KERN_ERR "ips1761_pci_shutdown\n");
}
static const struct pci_device_id isp1760_plx [] = { {
/* handle any USB 2.0 EHCI controller */
PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0),
.driver_data = 0,
},
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(pci, isp1760_plx);
static struct pci_driver isp1761_pci_driver = {
.name = "isp1760",
.id_table = isp1760_plx,
.probe = isp1761_pci_probe,
.remove = isp1761_pci_remove,
.shutdown = isp1761_pci_shutdown,
};
#endif
static int __init isp1760_init(void)
{
int ret;
init_kmem_once();
#ifdef CONFIG_USB_ISP1760_OF
ret = of_register_platform_driver(&isp1760_of_driver);
if (ret) {
deinit_kmem_cache();
return ret;
}
#endif
#ifdef CONFIG_USB_ISP1760_PCI
ret = pci_register_driver(&isp1761_pci_driver);
if (ret)
goto unreg_of;
#endif
return ret;
#ifdef CONFIG_USB_ISP1760_PCI
unreg_of:
#endif
#ifdef CONFIG_USB_ISP1760_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
deinit_kmem_cache();
return ret;
}
module_init(isp1760_init);
static void __exit isp1760_exit(void)
{
#ifdef CONFIG_USB_ISP1760_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
#ifdef CONFIG_USB_ISP1760_PCI
pci_unregister_driver(&isp1761_pci_driver);
#endif
deinit_kmem_cache();
}
module_exit(isp1760_exit);

View file

@ -613,7 +613,7 @@ static void start_hnp(struct ohci_hcd *ohci);
static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
u32 temp = 0;
u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC;
int limit_1 = DIV_ROUND_UP(PORT_RESET_MSEC, PORT_RESET_HW_MSEC);

View file

@ -234,7 +234,7 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
return 0;
}
static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
static int global_suspend_mode_is_broken(struct uhci_hcd *uhci)
{
int port;
const char *sys_info;
@ -261,27 +261,60 @@ __releases(uhci->lock)
__acquires(uhci->lock)
{
int auto_stop;
int int_enable, egsm_enable;
int int_enable, egsm_enable, wakeup_enable;
struct usb_device *rhdev = uhci_to_hcd(uhci)->self.root_hub;
auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
dev_dbg(&rhdev->dev, "%s%s\n", __func__,
(auto_stop ? " (auto-stop)" : ""));
/* Enable resume-detect interrupts if they work.
* Then enter Global Suspend mode if _it_ works, still configured.
/* Start off by assuming Resume-Detect interrupts and EGSM work
* and that remote wakeups should be enabled.
*/
egsm_enable = USBCMD_EGSM;
uhci->working_RD = 1;
uhci->RD_enable = 1;
int_enable = USBINTR_RESUME;
if (remote_wakeup_is_broken(uhci))
egsm_enable = 0;
if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
wakeup_enable = 1;
/* In auto-stop mode wakeups must always be detected, but
* Resume-Detect interrupts may be prohibited. (In the absence
* of CONFIG_PM, they are always disallowed.)
*/
if (auto_stop) {
if (!device_may_wakeup(&rhdev->dev))
int_enable = 0;
/* In bus-suspend mode wakeups may be disabled, but if they are
* allowed then so are Resume-Detect interrupts.
*/
} else {
#ifdef CONFIG_PM
(!auto_stop && !rhdev->do_remote_wakeup) ||
if (!rhdev->do_remote_wakeup)
wakeup_enable = 0;
#endif
(auto_stop && !device_may_wakeup(&rhdev->dev)))
uhci->working_RD = int_enable = 0;
}
/* EGSM causes the root hub to echo a 'K' signal (resume) out any
* port which requests a remote wakeup. According to the USB spec,
* every hub is supposed to do this. But if we are ignoring
* remote-wakeup requests anyway then there's no point to it.
* We also shouldn't enable EGSM if it's broken.
*/
if (!wakeup_enable || global_suspend_mode_is_broken(uhci))
egsm_enable = 0;
/* If we're ignoring wakeup events then there's no reason to
* enable Resume-Detect interrupts. We also shouldn't enable
* them if they are broken or disallowed.
*
* This logic may lead us to enabling RD but not EGSM. The UHCI
* spec foolishly says that RD works only when EGSM is on, but
* there's no harm in enabling it anyway -- perhaps some chips
* will implement it!
*/
if (!wakeup_enable || resume_detect_interrupts_are_broken(uhci) ||
!int_enable)
uhci->RD_enable = int_enable = 0;
outw(int_enable, uhci->io_addr + USBINTR);
outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD);
@ -308,7 +341,11 @@ __acquires(uhci->lock)
uhci->rh_state = new_state;
uhci->is_stopped = UHCI_IS_STOPPED;
uhci_to_hcd(uhci)->poll_rh = !int_enable;
/* If interrupts don't work and remote wakeup is enabled then
* the suspended root hub needs to be polled.
*/
uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable);
uhci_scan_schedule(uhci);
uhci_fsbr_off(uhci);
@ -344,9 +381,12 @@ __acquires(uhci->lock)
* for 20 ms.
*/
if (uhci->rh_state == UHCI_RH_SUSPENDED) {
unsigned egsm;
/* Keep EGSM on if it was set before */
egsm = inw(uhci->io_addr + USBCMD) & USBCMD_EGSM;
uhci->rh_state = UHCI_RH_RESUMING;
outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,
uhci->io_addr + USBCMD);
outw(USBCMD_FGR | USBCMD_CF | egsm, uhci->io_addr + USBCMD);
spin_unlock_irq(&uhci->lock);
msleep(20);
spin_lock_irq(&uhci->lock);
@ -801,8 +841,10 @@ static int uhci_pci_resume(struct usb_hcd *hcd)
spin_unlock_irq(&uhci->lock);
if (!uhci->working_RD) {
/* Suspended root hub needs to be polled */
/* If interrupts don't work and remote wakeup is enabled then
* the suspended root hub needs to be polled.
*/
if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) {
hcd->poll_rh = 1;
usb_hcd_poll_rh_status(hcd);
}

View file

@ -400,8 +400,9 @@ struct uhci_hcd {
unsigned int scan_in_progress:1; /* Schedule scan is running */
unsigned int need_rescan:1; /* Redo the schedule scan */
unsigned int dead:1; /* Controller has died */
unsigned int working_RD:1; /* Suspended root hub doesn't
need to be polled */
unsigned int RD_enable:1; /* Suspended root hub with
Resume-Detect interrupts
enabled */
unsigned int is_initialized:1; /* Data structure is usable */
unsigned int fsbr_is_on:1; /* FSBR is turned on */
unsigned int fsbr_is_wanted:1; /* Does any URB want FSBR? */

View file

@ -148,7 +148,7 @@ MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in
/* Structure to hold all of our device specific stuff */
struct ld_usb {
struct semaphore sem; /* locks this structure */
struct mutex mutex; /* locks this structure */
struct usb_interface* intf; /* save off the usb interface pointer */
int open_count; /* number of times this port has been opened */
@ -319,7 +319,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
return -ENODEV;
/* lock this device */
if (down_interruptible(&dev->sem))
if (mutex_lock_interruptible(&dev->mutex))
return -ERESTARTSYS;
/* allow opening only once */
@ -358,7 +358,7 @@ static int ld_usb_open(struct inode *inode, struct file *file)
file->private_data = dev;
unlock_exit:
up(&dev->sem);
mutex_unlock(&dev->mutex);
return retval;
}
@ -378,7 +378,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
goto exit;
}
if (down_interruptible(&dev->sem)) {
if (mutex_lock_interruptible(&dev->mutex)) {
retval = -ERESTARTSYS;
goto exit;
}
@ -389,7 +389,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
}
if (dev->intf == NULL) {
/* the device was unplugged before the file was released */
up(&dev->sem);
mutex_unlock(&dev->mutex);
/* unlock here as ld_usb_delete frees dev */
ld_usb_delete(dev);
goto exit;
@ -402,7 +402,7 @@ static int ld_usb_release(struct inode *inode, struct file *file)
dev->open_count = 0;
unlock_exit:
up(&dev->sem);
mutex_unlock(&dev->mutex);
exit:
return retval;
@ -448,7 +448,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
goto exit;
/* lock this object */
if (down_interruptible(&dev->sem)) {
if (mutex_lock_interruptible(&dev->mutex)) {
retval = -ERESTARTSYS;
goto exit;
}
@ -505,7 +505,7 @@ static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
unlock_exit:
/* unlock the device */
up(&dev->sem);
mutex_unlock(&dev->mutex);
exit:
return retval;
@ -528,7 +528,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
goto exit;
/* lock this object */
if (down_interruptible(&dev->sem)) {
if (mutex_lock_interruptible(&dev->mutex)) {
retval = -ERESTARTSYS;
goto exit;
}
@ -602,7 +602,7 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
unlock_exit:
/* unlock the device */
up(&dev->sem);
mutex_unlock(&dev->mutex);
exit:
return retval;
@ -651,7 +651,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
dev_err(&intf->dev, "Out of memory\n");
goto exit;
}
init_MUTEX(&dev->sem);
mutex_init(&dev->mutex);
spin_lock_init(&dev->rbsl);
dev->intf = intf;
init_waitqueue_head(&dev->read_wait);
@ -765,15 +765,15 @@ static void ld_usb_disconnect(struct usb_interface *intf)
/* give back our minor */
usb_deregister_dev(intf, &ld_usb_class);
down(&dev->sem);
mutex_lock(&dev->mutex);
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up(&dev->sem);
mutex_unlock(&dev->mutex);
ld_usb_delete(dev);
} else {
dev->intf = NULL;
up(&dev->sem);
mutex_unlock(&dev->mutex);
}
dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",

View file

@ -79,30 +79,10 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
/* set up all urbs so they can be used with either bulk or interrupt */
#define INTERRUPT_RATE 1 /* msec/transfer */
#define xprintk(tdev,level,fmt,args...) \
dev_printk(level , &(tdev)->intf->dev , fmt , ## args)
#ifdef DEBUG
#define DBG(dev,fmt,args...) \
xprintk(dev , KERN_DEBUG , fmt , ## args)
#else
#define DBG(dev,fmt,args...) \
do { } while (0)
#endif /* DEBUG */
#ifdef VERBOSE
#define VDBG DBG
#else
#define VDBG(dev,fmt,args...) \
do { } while (0)
#endif /* VERBOSE */
#define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
#define WARN(dev,fmt,args...) \
xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
#define ERROR(tdev, fmt, args...) \
dev_err(&(tdev)->intf->dev , fmt , ## args)
#define WARN(tdev, fmt, args...) \
dev_warn(&(tdev)->intf->dev , fmt , ## args)
/*-------------------------------------------------------------------------*/
@ -236,7 +216,7 @@ static struct urb *simple_alloc_urb (
static unsigned pattern = 0;
module_param (pattern, uint, S_IRUGO);
// MODULE_PARM_DESC (pattern, "i/o pattern (0 == zeroes)");
MODULE_PARM_DESC(pattern, "i/o pattern (0 == zeroes)");
static inline void simple_fill_buf (struct urb *urb)
{
@ -257,7 +237,7 @@ static inline void simple_fill_buf (struct urb *urb)
}
}
static inline int simple_check_buf (struct urb *urb)
static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
{
unsigned i;
u8 expected;
@ -285,7 +265,7 @@ static inline int simple_check_buf (struct urb *urb)
}
if (*buf == expected)
continue;
dbg ("buf[%d] = %d (not %d)", i, *buf, expected);
ERROR(tdev, "buf[%d] = %d (not %d)\n", i, *buf, expected);
return -EINVAL;
}
return 0;
@ -299,6 +279,7 @@ static void simple_free_urb (struct urb *urb)
}
static int simple_io (
struct usbtest_dev *tdev,
struct urb *urb,
int iterations,
int vary,
@ -324,7 +305,7 @@ static int simple_io (
retval = urb->status;
urb->dev = udev;
if (retval == 0 && usb_pipein (urb->pipe))
retval = simple_check_buf (urb);
retval = simple_check_buf(tdev, urb);
if (vary) {
int len = urb->transfer_buffer_length;
@ -341,7 +322,7 @@ static int simple_io (
urb->transfer_buffer_length = max;
if (expected != retval)
dev_dbg (&udev->dev,
dev_err(&udev->dev,
"%s failed, iterations left %d, status %d (not %d)\n",
label, iterations, retval, expected);
return retval;
@ -357,7 +338,7 @@ static int simple_io (
static void free_sglist (struct scatterlist *sg, int nents)
{
unsigned i;
if (!sg)
return;
for (i = 0; i < nents; i++) {
@ -415,7 +396,7 @@ alloc_sglist (int nents, int max, int vary)
}
static int perform_sglist (
struct usb_device *udev,
struct usbtest_dev *tdev,
unsigned iterations,
int pipe,
struct usb_sg_request *req,
@ -423,6 +404,7 @@ static int perform_sglist (
int nents
)
{
struct usb_device *udev = testdev_to_usbdev(tdev);
int retval = 0;
while (retval == 0 && iterations-- > 0) {
@ -431,7 +413,7 @@ static int perform_sglist (
? (INTERRUPT_RATE << 3)
: INTERRUPT_RATE,
sg, nents, 0, GFP_KERNEL);
if (retval)
break;
usb_sg_wait (req);
@ -446,7 +428,8 @@ static int perform_sglist (
// failure if retval is as we expected ...
if (retval)
dbg ("perform_sglist failed, iterations left %d, status %d",
ERROR(tdev, "perform_sglist failed, "
"iterations left %d, status %d\n",
iterations, retval);
return retval;
}
@ -505,28 +488,28 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
alternate);
}
static int is_good_config (char *buf, int len)
static int is_good_config(struct usbtest_dev *tdev, int len)
{
struct usb_config_descriptor *config;
if (len < sizeof *config)
return 0;
config = (struct usb_config_descriptor *) buf;
config = (struct usb_config_descriptor *) tdev->buf;
switch (config->bDescriptorType) {
case USB_DT_CONFIG:
case USB_DT_OTHER_SPEED_CONFIG:
if (config->bLength != 9) {
dbg ("bogus config descriptor length");
ERROR(tdev, "bogus config descriptor length\n");
return 0;
}
/* this bit 'must be 1' but often isn't */
if (!realworld && !(config->bmAttributes & 0x80)) {
dbg ("high bit of config attributes not set");
ERROR(tdev, "high bit of config attributes not set\n");
return 0;
}
if (config->bmAttributes & 0x1f) { /* reserved == 0 */
dbg ("reserved config bits set");
ERROR(tdev, "reserved config bits set\n");
return 0;
}
break;
@ -538,7 +521,7 @@ static int is_good_config (char *buf, int len)
return 1;
if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */
return 1;
dbg ("bogus config descriptor read size");
ERROR(tdev, "bogus config descriptor read size\n");
return 0;
}
@ -571,7 +554,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* 9.2.3 constrains the range here */
alt = iface->altsetting [i].desc.bAlternateSetting;
if (alt < 0 || alt >= iface->num_altsetting) {
dev_dbg (&iface->dev,
dev_err(&iface->dev,
"invalid alt [%d].bAltSetting = %d\n",
i, alt);
}
@ -583,7 +566,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* [9.4.10] set_interface */
retval = set_altsetting (dev, alt);
if (retval) {
dev_dbg (&iface->dev, "can't set_interface = %d, %d\n",
dev_err(&iface->dev, "can't set_interface = %d, %d\n",
alt, retval);
return retval;
}
@ -591,7 +574,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* [9.4.4] get_interface always works */
retval = get_altsetting (dev);
if (retval != alt) {
dev_dbg (&iface->dev, "get alt should be %d, was %d\n",
dev_err(&iface->dev, "get alt should be %d, was %d\n",
alt, retval);
return (retval < 0) ? retval : -EDOM;
}
@ -611,7 +594,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
USB_DIR_IN | USB_RECIP_DEVICE,
0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
if (retval != 1 || dev->buf [0] != expected) {
dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n",
dev_err(&iface->dev, "get config --> %d %d (1 %d)\n",
retval, dev->buf[0], expected);
return (retval < 0) ? retval : -EDOM;
}
@ -621,7 +604,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval = usb_get_descriptor (udev, USB_DT_DEVICE, 0,
dev->buf, sizeof udev->descriptor);
if (retval != sizeof udev->descriptor) {
dev_dbg (&iface->dev, "dev descriptor --> %d\n", retval);
dev_err(&iface->dev, "dev descriptor --> %d\n", retval);
return (retval < 0) ? retval : -EDOM;
}
@ -629,8 +612,8 @@ static int ch9_postconfig (struct usbtest_dev *dev)
for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
retval = usb_get_descriptor (udev, USB_DT_CONFIG, i,
dev->buf, TBUF_SIZE);
if (!is_good_config (dev->buf, retval)) {
dev_dbg (&iface->dev,
if (!is_good_config(dev, retval)) {
dev_err(&iface->dev,
"config [%d] descriptor --> %d\n",
i, retval);
return (retval < 0) ? retval : -EDOM;
@ -650,14 +633,14 @@ static int ch9_postconfig (struct usbtest_dev *dev)
sizeof (struct usb_qualifier_descriptor));
if (retval == -EPIPE) {
if (udev->speed == USB_SPEED_HIGH) {
dev_dbg (&iface->dev,
dev_err(&iface->dev,
"hs dev qualifier --> %d\n",
retval);
return (retval < 0) ? retval : -EDOM;
}
/* usb2.0 but not high-speed capable; fine */
} else if (retval != sizeof (struct usb_qualifier_descriptor)) {
dev_dbg (&iface->dev, "dev qualifier --> %d\n", retval);
dev_err(&iface->dev, "dev qualifier --> %d\n", retval);
return (retval < 0) ? retval : -EDOM;
} else
d = (struct usb_qualifier_descriptor *) dev->buf;
@ -669,8 +652,8 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval = usb_get_descriptor (udev,
USB_DT_OTHER_SPEED_CONFIG, i,
dev->buf, TBUF_SIZE);
if (!is_good_config (dev->buf, retval)) {
dev_dbg (&iface->dev,
if (!is_good_config(dev, retval)) {
dev_err(&iface->dev,
"other speed config --> %d\n",
retval);
return (retval < 0) ? retval : -EDOM;
@ -683,7 +666,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* [9.4.5] get_status always works */
retval = usb_get_status (udev, USB_RECIP_DEVICE, 0, dev->buf);
if (retval != 2) {
dev_dbg (&iface->dev, "get dev status --> %d\n", retval);
dev_err(&iface->dev, "get dev status --> %d\n", retval);
return (retval < 0) ? retval : -EDOM;
}
@ -693,11 +676,11 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval = usb_get_status (udev, USB_RECIP_INTERFACE,
iface->altsetting [0].desc.bInterfaceNumber, dev->buf);
if (retval != 2) {
dev_dbg (&iface->dev, "get interface status --> %d\n", retval);
dev_err(&iface->dev, "get interface status --> %d\n", retval);
return (retval < 0) ? retval : -EDOM;
}
// FIXME get status for each endpoint in the interface
return 0;
}
@ -752,8 +735,9 @@ static void ctrl_complete (struct urb *urb)
*/
if (subcase->number > 0) {
if ((subcase->number - ctx->last) != 1) {
dbg ("subcase %d completed out of order, last %d",
subcase->number, ctx->last);
ERROR(ctx->dev,
"subcase %d completed out of order, last %d\n",
subcase->number, ctx->last);
status = -EDOM;
ctx->last = subcase->number;
goto error;
@ -777,7 +761,7 @@ static void ctrl_complete (struct urb *urb)
else if (subcase->number == 12 && status == -EPIPE)
status = 0;
else
dbg ("subtest %d error, status %d",
ERROR(ctx->dev, "subtest %d error, status %d\n",
subcase->number, status);
}
@ -788,9 +772,12 @@ error:
int i;
ctx->status = status;
info ("control queue %02x.%02x, err %d, %d left",
ERROR(ctx->dev, "control queue %02x.%02x, err %d, "
"%d left, subcase %d, len %d/%d\n",
reqp->bRequestType, reqp->bRequest,
status, ctx->count);
status, ctx->count, subcase->number,
urb->actual_length,
urb->transfer_buffer_length);
/* FIXME this "unlink everything" exit route should
* be a separate test case.
@ -799,7 +786,8 @@ error:
/* unlink whatever's still pending */
for (i = 1; i < ctx->param->sglen; i++) {
struct urb *u = ctx->urb [
(i + subcase->number) % ctx->param->sglen];
(i + subcase->number)
% ctx->param->sglen];
if (u == urb || !u->dev)
continue;
@ -812,7 +800,8 @@ error:
case -EIDRM:
continue;
default:
dbg ("urb unlink --> %d", status);
ERROR(ctx->dev, "urb unlink --> %d\n",
status);
}
}
status = ctx->status;
@ -822,14 +811,15 @@ error:
/* resubmit if we need to, else mark this as done */
if ((status == 0) && (ctx->pending < ctx->count)) {
if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
dbg ("can't resubmit ctrl %02x.%02x, err %d",
ERROR(ctx->dev,
"can't resubmit ctrl %02x.%02x, err %d\n",
reqp->bRequestType, reqp->bRequest, status);
urb->dev = NULL;
} else
ctx->pending++;
} else
urb->dev = NULL;
/* signal completion when nothing's queued */
if (ctx->pending == 0)
complete (&ctx->complete);
@ -918,11 +908,11 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8);
// interface == 0
len = sizeof (struct usb_interface_descriptor);
expected = EPIPE;
expected = -EPIPE;
break;
// NOTE: two consecutive stalls in the queue here.
// that tests fault recovery a bit more aggressively.
case 8: // clear endpoint halt (USUALLY STALLS)
case 8: // clear endpoint halt (MAY STALL)
req.bRequest = USB_REQ_CLEAR_FEATURE;
req.bRequestType = USB_RECIP_ENDPOINT;
// wValue 0 == ep halt
@ -965,7 +955,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
break;
case 14: // short read; try to fill the last packet
req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
// device descriptor size == 18 bytes
/* device descriptor size == 18 bytes */
len = udev->descriptor.bMaxPacketSize0;
switch (len) {
case 8: len = 24; break;
@ -974,7 +964,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
expected = -EREMOTEIO;
break;
default:
err ("bogus number of ctrl queue testcases!");
ERROR(dev, "bogus number of ctrl queue testcases!\n");
context.status = -EINVAL;
goto cleanup;
}
@ -1003,7 +993,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
for (i = 0; i < param->sglen; i++) {
context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
if (context.status != 0) {
dbg ("can't submit urb[%d], status %d",
ERROR(dev, "can't submit urb[%d], status %d\n",
i, context.status);
context.count = context.pending;
break;
@ -1070,7 +1060,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
* due to errors, or is just NAKing requests.
*/
if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
dev_dbg (&dev->intf->dev, "submit fail %d\n", retval);
dev_err(&dev->intf->dev, "submit fail %d\n", retval);
return retval;
}
@ -1087,13 +1077,13 @@ retry:
* "normal" drivers would prevent resubmission, but
* since we're testing unlink paths, we can't.
*/
dev_dbg (&dev->intf->dev, "unlink retry\n");
ERROR(dev, "unlink retry\n");
goto retry;
}
} else
usb_kill_urb (urb);
if (!(retval == 0 || retval == -EINPROGRESS)) {
dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval);
dev_err(&dev->intf->dev, "unlink fail %d\n", retval);
return retval;
}
@ -1121,7 +1111,7 @@ static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
/*-------------------------------------------------------------------------*/
static int verify_not_halted (int ep, struct urb *urb)
static int verify_not_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
{
int retval;
u16 status;
@ -1129,20 +1119,21 @@ static int verify_not_halted (int ep, struct urb *urb)
/* shouldn't look or act halted */
retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
if (retval < 0) {
dbg ("ep %02x couldn't get no-halt status, %d", ep, retval);
ERROR(tdev, "ep %02x couldn't get no-halt status, %d\n",
ep, retval);
return retval;
}
if (status != 0) {
dbg ("ep %02x bogus status: %04x != 0", ep, status);
ERROR(tdev, "ep %02x bogus status: %04x != 0\n", ep, status);
return -EINVAL;
}
retval = simple_io (urb, 1, 0, 0, __func__);
retval = simple_io(tdev, urb, 1, 0, 0, __func__);
if (retval != 0)
return -EINVAL;
return 0;
}
static int verify_halted (int ep, struct urb *urb)
static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb)
{
int retval;
u16 status;
@ -1150,29 +1141,30 @@ static int verify_halted (int ep, struct urb *urb)
/* should look and act halted */
retval = usb_get_status (urb->dev, USB_RECIP_ENDPOINT, ep, &status);
if (retval < 0) {
dbg ("ep %02x couldn't get halt status, %d", ep, retval);
ERROR(tdev, "ep %02x couldn't get halt status, %d\n",
ep, retval);
return retval;
}
le16_to_cpus(&status);
if (status != 1) {
dbg ("ep %02x bogus status: %04x != 1", ep, status);
ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status);
return -EINVAL;
}
retval = simple_io (urb, 1, 0, -EPIPE, __func__);
retval = simple_io(tdev, urb, 1, 0, -EPIPE, __func__);
if (retval != -EPIPE)
return -EINVAL;
retval = simple_io (urb, 1, 0, -EPIPE, "verify_still_halted");
retval = simple_io(tdev, urb, 1, 0, -EPIPE, "verify_still_halted");
if (retval != -EPIPE)
return -EINVAL;
return 0;
}
static int test_halt (int ep, struct urb *urb)
static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
{
int retval;
/* shouldn't look or act halted now */
retval = verify_not_halted (ep, urb);
retval = verify_not_halted(tdev, ep, urb);
if (retval < 0)
return retval;
@ -1182,20 +1174,20 @@ static int test_halt (int ep, struct urb *urb)
USB_ENDPOINT_HALT, ep,
NULL, 0, USB_CTRL_SET_TIMEOUT);
if (retval < 0) {
dbg ("ep %02x couldn't set halt, %d", ep, retval);
ERROR(tdev, "ep %02x couldn't set halt, %d\n", ep, retval);
return retval;
}
retval = verify_halted (ep, urb);
retval = verify_halted(tdev, ep, urb);
if (retval < 0)
return retval;
/* clear halt (tests API + protocol), verify it worked */
retval = usb_clear_halt (urb->dev, urb->pipe);
if (retval < 0) {
dbg ("ep %02x couldn't clear halt, %d", ep, retval);
ERROR(tdev, "ep %02x couldn't clear halt, %d\n", ep, retval);
return retval;
}
retval = verify_not_halted (ep, urb);
retval = verify_not_halted(tdev, ep, urb);
if (retval < 0)
return retval;
@ -1217,7 +1209,7 @@ static int halt_simple (struct usbtest_dev *dev)
if (dev->in_pipe) {
ep = usb_pipeendpoint (dev->in_pipe) | USB_DIR_IN;
urb->pipe = dev->in_pipe;
retval = test_halt (ep, urb);
retval = test_halt(dev, ep, urb);
if (retval < 0)
goto done;
}
@ -1225,7 +1217,7 @@ static int halt_simple (struct usbtest_dev *dev)
if (dev->out_pipe) {
ep = usb_pipeendpoint (dev->out_pipe);
urb->pipe = dev->out_pipe;
retval = test_halt (ep, urb);
retval = test_halt(dev, ep, urb);
}
done:
simple_free_urb (urb);
@ -1275,7 +1267,7 @@ static int ctrl_out (struct usbtest_dev *dev,
if (retval != len) {
what = "write";
if (retval >= 0) {
INFO(dev, "ctrl_out, wlen %d (expected %d)\n",
ERROR(dev, "ctrl_out, wlen %d (expected %d)\n",
retval, len);
retval = -EBADMSG;
}
@ -1289,7 +1281,7 @@ static int ctrl_out (struct usbtest_dev *dev,
if (retval != len) {
what = "read";
if (retval >= 0) {
INFO(dev, "ctrl_out, rlen %d (expected %d)\n",
ERROR(dev, "ctrl_out, rlen %d (expected %d)\n",
retval, len);
retval = -EBADMSG;
}
@ -1299,7 +1291,7 @@ static int ctrl_out (struct usbtest_dev *dev,
/* fail if we can't verify */
for (j = 0; j < len; j++) {
if (buf [j] != (u8) (i + j)) {
INFO (dev, "ctrl_out, byte %d is %d not %d\n",
ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
j, buf [j], (u8) i + j);
retval = -EBADMSG;
break;
@ -1321,7 +1313,7 @@ static int ctrl_out (struct usbtest_dev *dev,
}
if (retval < 0)
INFO (dev, "ctrl_out %s failed, code %d, count %d\n",
ERROR (dev, "ctrl_out %s failed, code %d, count %d\n",
what, retval, i);
kfree (buf);
@ -1366,7 +1358,7 @@ static void iso_callback (struct urb *urb)
case 0:
goto done;
default:
dev_dbg (&ctx->dev->intf->dev,
dev_err(&ctx->dev->intf->dev,
"iso resubmit err %d\n",
status);
/* FALLTHROUGH */
@ -1381,7 +1373,7 @@ static void iso_callback (struct urb *urb)
ctx->pending--;
if (ctx->pending == 0) {
if (ctx->errors)
dev_dbg (&ctx->dev->intf->dev,
dev_err(&ctx->dev->intf->dev,
"iso test, %lu errors out of %lu\n",
ctx->errors, ctx->packet_count);
complete (&ctx->done);
@ -1458,7 +1450,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
memset (urbs, 0, sizeof urbs);
udev = testdev_to_usbdev (dev);
dev_dbg (&dev->intf->dev,
dev_info(&dev->intf->dev,
"... iso period %d %sframes, wMaxPacket %04x\n",
1 << (desc->bInterval - 1),
(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
@ -1475,7 +1467,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
urbs [i]->context = &context;
}
packets *= param->iterations;
dev_dbg (&dev->intf->dev,
dev_info(&dev->intf->dev,
"... total %lu msec (%lu packets)\n",
(packets * (1 << (desc->bInterval - 1)))
/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
@ -1537,6 +1529,13 @@ fail:
* except indirectly by consuming USB bandwidth and CPU resources for test
* threads and request completion. But the only way to know that for sure
* is to test when HC queues are in use by many devices.
*
* WARNING: Because usbfs grabs udev->dev.sem before calling this ioctl(),
* it locks out usbcore in certain code paths. Notably, if you disconnect
* the device-under-test, khubd will wait block forever waiting for the
* ioctl to complete ... so that usb_disconnect() can abort the pending
* urbs and then call usbtest_disconnect(). To abort a test, you're best
* off just killing the userspace task and waiting for it to exit.
*/
static int
@ -1575,7 +1574,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
* altsettings; force a default so most tests don't need to check.
*/
if (dev->info->alt >= 0) {
int res;
int res;
if (intf->altsetting->desc.bInterfaceNumber) {
mutex_unlock(&dev->lock);
@ -1604,7 +1603,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
switch (param->test_num) {
case 0:
dev_dbg (&intf->dev, "TEST 0: NOP\n");
dev_info(&intf->dev, "TEST 0: NOP\n");
retval = 0;
break;
@ -1612,7 +1611,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case 1:
if (dev->out_pipe == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 1: write %d bytes %u times\n",
param->length, param->iterations);
urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
@ -1621,13 +1620,13 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval = simple_io (urb, param->iterations, 0, 0, "test1");
retval = simple_io(dev, urb, param->iterations, 0, 0, "test1");
simple_free_urb (urb);
break;
case 2:
if (dev->in_pipe == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 2: read %d bytes %u times\n",
param->length, param->iterations);
urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
@ -1636,13 +1635,13 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval = simple_io (urb, param->iterations, 0, 0, "test2");
retval = simple_io(dev, urb, param->iterations, 0, 0, "test2");
simple_free_urb (urb);
break;
case 3:
if (dev->out_pipe == 0 || param->vary == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 3: write/%d 0..%d bytes %u times\n",
param->vary, param->length, param->iterations);
urb = simple_alloc_urb (udev, dev->out_pipe, param->length);
@ -1651,14 +1650,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval = simple_io (urb, param->iterations, param->vary,
retval = simple_io(dev, urb, param->iterations, param->vary,
0, "test3");
simple_free_urb (urb);
break;
case 4:
if (dev->in_pipe == 0 || param->vary == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 4: read/%d 0..%d bytes %u times\n",
param->vary, param->length, param->iterations);
urb = simple_alloc_urb (udev, dev->in_pipe, param->length);
@ -1667,7 +1666,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval = simple_io (urb, param->iterations, param->vary,
retval = simple_io(dev, urb, param->iterations, param->vary,
0, "test4");
simple_free_urb (urb);
break;
@ -1676,7 +1675,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case 5:
if (dev->out_pipe == 0 || param->sglen == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 5: write %d sglists %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
@ -1686,7 +1685,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval = perform_sglist (udev, param->iterations, dev->out_pipe,
retval = perform_sglist(dev, param->iterations, dev->out_pipe,
&req, sg, param->sglen);
free_sglist (sg, param->sglen);
break;
@ -1694,7 +1693,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case 6:
if (dev->in_pipe == 0 || param->sglen == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 6: read %d sglists %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
@ -1704,14 +1703,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval = perform_sglist (udev, param->iterations, dev->in_pipe,
retval = perform_sglist(dev, param->iterations, dev->in_pipe,
&req, sg, param->sglen);
free_sglist (sg, param->sglen);
break;
case 7:
if (dev->out_pipe == 0 || param->sglen == 0 || param->vary == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 7: write/%d %d sglists %d entries 0..%d bytes\n",
param->vary, param->iterations,
param->sglen, param->length);
@ -1721,14 +1720,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval = perform_sglist (udev, param->iterations, dev->out_pipe,
retval = perform_sglist(dev, param->iterations, dev->out_pipe,
&req, sg, param->sglen);
free_sglist (sg, param->sglen);
break;
case 8:
if (dev->in_pipe == 0 || param->sglen == 0 || param->vary == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 8: read/%d %d sglists %d entries 0..%d bytes\n",
param->vary, param->iterations,
param->sglen, param->length);
@ -1738,7 +1737,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval = perform_sglist (udev, param->iterations, dev->in_pipe,
retval = perform_sglist(dev, param->iterations, dev->in_pipe,
&req, sg, param->sglen);
free_sglist (sg, param->sglen);
break;
@ -1746,13 +1745,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
/* non-queued sanity tests for control (chapter 9 subset) */
case 9:
retval = 0;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 9: ch9 (subset) control tests, %d times\n",
param->iterations);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = ch9_postconfig (dev);
if (retval)
dbg ("ch9 subset failed, iterations left %d", i);
dev_err(&intf->dev, "ch9 subset failed, "
"iterations left %d\n", i);
break;
/* queued control messaging */
@ -1760,7 +1760,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (param->sglen == 0)
break;
retval = 0;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 10: queue %d control calls, %d times\n",
param->sglen,
param->iterations);
@ -1772,26 +1772,26 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (dev->in_pipe == 0 || !param->length)
break;
retval = 0;
dev_dbg (&intf->dev, "TEST 11: unlink %d reads of %d\n",
dev_info(&intf->dev, "TEST 11: unlink %d reads of %d\n",
param->iterations, param->length);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = unlink_simple (dev, dev->in_pipe,
param->length);
if (retval)
dev_dbg (&intf->dev, "unlink reads failed %d, "
dev_err(&intf->dev, "unlink reads failed %d, "
"iterations left %d\n", retval, i);
break;
case 12:
if (dev->out_pipe == 0 || !param->length)
break;
retval = 0;
dev_dbg (&intf->dev, "TEST 12: unlink %d writes of %d\n",
dev_info(&intf->dev, "TEST 12: unlink %d writes of %d\n",
param->iterations, param->length);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = unlink_simple (dev, dev->out_pipe,
param->length);
if (retval)
dev_dbg (&intf->dev, "unlink writes failed %d, "
dev_err(&intf->dev, "unlink writes failed %d, "
"iterations left %d\n", retval, i);
break;
@ -1800,24 +1800,24 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if (dev->out_pipe == 0 && dev->in_pipe == 0)
break;
retval = 0;
dev_dbg (&intf->dev, "TEST 13: set/clear %d halts\n",
dev_info(&intf->dev, "TEST 13: set/clear %d halts\n",
param->iterations);
for (i = param->iterations; retval == 0 && i--; /* NOP */)
retval = halt_simple (dev);
if (retval)
DBG (dev, "halts failed, iterations left %d\n", i);
ERROR(dev, "halts failed, iterations left %d\n", i);
break;
/* control write tests */
case 14:
if (!dev->info->ctrl_out)
break;
dev_dbg (&intf->dev, "TEST 14: %d ep0out, %d..%d vary %d\n",
dev_info(&intf->dev, "TEST 14: %d ep0out, %d..%d vary %d\n",
param->iterations,
realworld ? 1 : 0, param->length,
param->vary);
retval = ctrl_out (dev, param->iterations,
retval = ctrl_out(dev, param->iterations,
param->length, param->vary);
break;
@ -1825,7 +1825,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case 15:
if (dev->out_iso_pipe == 0 || param->sglen == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 15: write %d iso, %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
@ -1838,7 +1838,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case 16:
if (dev->in_iso_pipe == 0 || param->sglen == 0)
break;
dev_dbg (&intf->dev,
dev_info(&intf->dev,
"TEST 16: read %d iso, %d entries of %d bytes\n",
param->iterations,
param->sglen, param->length);
@ -1898,7 +1898,8 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV;
if (product && le16_to_cpu(udev->descriptor.idProduct) != (u16)product)
return -ENODEV;
dbg ("matched module params, vend=0x%04x prod=0x%04x",
dev_info(&intf->dev, "matched module params, "
"vend=0x%04x prod=0x%04x\n",
le16_to_cpu(udev->descriptor.idVendor),
le16_to_cpu(udev->descriptor.idProduct));
}
@ -1940,7 +1941,8 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
status = get_endpoints (dev, intf);
if (status < 0) {
dbg ("couldn't get endpoints, %d\n", status);
WARN(dev, "couldn't get endpoints, %d\n",
status);
return status;
}
/* may find bulk or ISO pipes */
@ -2082,21 +2084,9 @@ static struct usbtest_info generic_info = {
};
#endif
// FIXME remove this
static struct usbtest_info hact_info = {
.name = "FX2/hact",
//.ep_in = 6,
.ep_out = 2,
.alt = -1,
};
static struct usb_device_id id_table [] = {
{ USB_DEVICE (0x0547, 0x1002),
.driver_info = (unsigned long) &hact_info,
},
/*-------------------------------------------------------------*/
/* EZ-USB devices which download firmware to replace (or in our
@ -2185,7 +2175,7 @@ static int __init usbtest_init (void)
{
#ifdef GENERIC
if (vendor)
dbg ("params: vend=0x%04x prod=0x%04x", vendor, product);
pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product);
#endif
return usb_register (&usbtest_driver);
}

View file

@ -147,7 +147,7 @@ static void serial_buf_free(struct circ_buf *cb)
*/
static int serial_buf_data_avail(struct circ_buf *cb)
{
return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
return CIRC_CNT(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
}
/*
@ -171,7 +171,7 @@ static int serial_buf_put(struct circ_buf *cb, const char *buf, int count)
cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
buf += c;
count -= c;
ret= c;
ret = c;
}
return ret;
}
@ -197,7 +197,7 @@ static int serial_buf_get(struct circ_buf *cb, char *buf, int count)
cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
buf += c;
count -= c;
ret= c;
ret = c;
}
return ret;
}
@ -208,7 +208,7 @@ static void aircable_send(struct usb_serial_port *port)
{
int count, result;
struct aircable_private *priv = usb_get_serial_port_data(port);
unsigned char* buf;
unsigned char *buf;
__le16 *dbuf;
dbg("%s - port %d", __func__, port->number);
if (port->write_urb_busy)
@ -229,7 +229,8 @@ static void aircable_send(struct usb_serial_port *port)
buf[1] = TX_HEADER_1;
dbuf = (__le16 *)&buf[2];
*dbuf = cpu_to_le16((u16)count);
serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
serial_buf_get(priv->tx_buf, buf + HCI_HEADER_LENGTH,
MAX_HCI_FRAMESIZE);
memcpy(port->write_urb->transfer_buffer, buf,
count + HCI_HEADER_LENGTH);
@ -261,7 +262,7 @@ static void aircable_read(struct work_struct *work)
struct tty_struct *tty;
unsigned char *data;
int count;
if (priv->rx_flags & THROTTLED){
if (priv->rx_flags & THROTTLED) {
if (priv->rx_flags & ACTUALLY_THROTTLED)
schedule_work(&priv->rx_work);
return;
@ -282,10 +283,10 @@ static void aircable_read(struct work_struct *work)
count = min(64, serial_buf_data_avail(priv->rx_buf));
if (count <= 0)
return; //We have finished sending everything.
return; /* We have finished sending everything. */
tty_prepare_flip_string(tty, &data, count);
if (!data){
if (!data) {
err("%s- kzalloc(%d) failed.", __func__, count);
return;
}
@ -304,9 +305,10 @@ static void aircable_read(struct work_struct *work)
static int aircable_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
struct usb_host_interface *iface_desc = serial->interface->
cur_altsetting;
struct usb_endpoint_descriptor *endpoint;
int num_bulk_out=0;
int num_bulk_out = 0;
int i;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
@ -325,13 +327,13 @@ static int aircable_probe(struct usb_serial *serial,
return 0;
}
static int aircable_attach (struct usb_serial *serial)
static int aircable_attach(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
struct aircable_private *priv;
priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
if (!priv){
if (!priv) {
err("%s- kmalloc(%Zd) failed.", __func__,
sizeof(struct aircable_private));
return -ENOMEM;
@ -392,7 +394,7 @@ static int aircable_write(struct usb_serial_port *port,
usb_serial_debug_data(debug, &port->dev, __func__, count, source);
if (!count){
if (!count) {
dbg("%s - write request of 0 bytes", __func__);
return count;
}
@ -418,31 +420,31 @@ static void aircable_write_bulk_callback(struct urb *urb)
/* This has been taken from cypress_m8.c cypress_write_int_callback */
switch (status) {
case 0:
/* success */
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__func__, status);
port->write_urb_busy = 0;
case 0:
/* success */
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
__func__, status);
port->write_urb_busy = 0;
return;
default:
/* error in the urb, so we have to resubmit it */
dbg("%s - Overflow in write", __func__);
dbg("%s - nonzero write bulk status received: %d",
__func__, status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev,
"%s - failed resubmitting write urb, error %d\n",
__func__, result);
else
return;
default:
/* error in the urb, so we have to resubmit it */
dbg("%s - Overflow in write", __func__);
dbg("%s - nonzero write bulk status received: %d",
__func__, status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
dev_err(&urb->dev->dev,
"%s - failed resubmitting write urb, error %d\n",
__func__, result);
else
return;
}
port->write_urb_busy = 0;
@ -472,11 +474,11 @@ static void aircable_read_bulk_callback(struct urb *urb)
dbg("%s - caught -EPROTO, resubmitting the urb",
__func__);
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
aircable_read_bulk_callback, port);
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
aircable_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
@ -490,7 +492,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
}
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length,urb->transfer_buffer);
urb->actual_length, urb->transfer_buffer);
tty = port->tty;
if (tty && urb->actual_length) {
@ -507,9 +509,9 @@ static void aircable_read_bulk_callback(struct urb *urb)
no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
no_packages+=1;
no_packages++;
for (i = 0; i < no_packages ;i++) {
for (i = 0; i < no_packages; i++) {
if (remaining > (HCI_COMPLETE_FRAME))
package_length = HCI_COMPLETE_FRAME;
else
@ -529,7 +531,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
if (port->open_count) {
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
aircable_read_bulk_callback, port);
@ -602,7 +604,7 @@ static struct usb_serial_driver aircable_device = {
.unthrottle = aircable_unthrottle,
};
static int __init aircable_init (void)
static int __init aircable_init(void)
{
int retval;
retval = usb_serial_register(&aircable_device);
@ -619,7 +621,7 @@ failed_usb_register:
return retval;
}
static void __exit aircable_exit (void)
static void __exit aircable_exit(void)
{
usb_deregister(&aircable_driver);
usb_serial_deregister(&aircable_device);

View file

@ -68,8 +68,9 @@ static int airprime_send_setup(struct usb_serial_port *port)
val |= 0x02;
return usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
usb_rcvctrlpipe(serial->dev, 0),
0x22, 0x21, val, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
return 0;
@ -90,17 +91,19 @@ static void airprime_read_bulk_callback(struct urb *urb)
__func__, status);
return;
}
usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, data);
tty = port->tty;
if (tty && urb->actual_length) {
tty_insert_flip_string (tty, data, urb->actual_length);
tty_flip_buffer_push (tty);
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
result = usb_submit_urb (urb, GFP_ATOMIC);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
__func__, result);
return;
}
@ -115,7 +118,7 @@ static void airprime_write_bulk_callback(struct urb *urb)
dbg("%s - port %d", __func__, port->number);
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
kfree(urb->transfer_buffer);
if (status)
dbg("%s - nonzero write bulk status received: %d",
@ -171,7 +174,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
}
usb_fill_bulk_urb(urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_out_endpointAddress),
port->bulk_out_endpointAddress),
buffer, buffer_size,
airprime_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_KERNEL);
@ -183,7 +186,8 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
__func__, i, port->number, result);
goto errout;
}
/* remember this urb so we can kill it when the port is closed */
/* remember this urb so we can kill it when the
port is closed */
priv->read_urbp[i] = urb;
}
@ -192,22 +196,22 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp)
goto out;
errout:
/* some error happened, cancel any submitted urbs and clean up anything that
got allocated successfully */
/* some error happened, cancel any submitted urbs and clean up
anything that got allocated successfully */
while (i-- != 0) {
urb = priv->read_urbp[i];
buffer = urb->transfer_buffer;
usb_kill_urb (urb);
usb_free_urb (urb);
kfree (buffer);
usb_kill_urb(urb);
usb_free_urb(urb);
kfree(buffer);
}
out:
return result;
}
static void airprime_close(struct usb_serial_port *port, struct file * filp)
static void airprime_close(struct usb_serial_port *port, struct file *filp)
{
struct airprime_private *priv = usb_get_serial_port_data(port);
int i;
@ -220,16 +224,16 @@ static void airprime_close(struct usb_serial_port *port, struct file * filp)
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
airprime_send_setup(port);
mutex_lock(&port->serial->disc_mutex);
mutex_unlock(&port->serial->disc_mutex);
for (i = 0; i < NUM_READ_URBS; ++i) {
usb_kill_urb (priv->read_urbp[i]);
kfree (priv->read_urbp[i]->transfer_buffer);
usb_free_urb (priv->read_urbp[i]);
usb_kill_urb(priv->read_urbp[i]);
kfree(priv->read_urbp[i]->transfer_buffer);
usb_free_urb(priv->read_urbp[i]);
}
/* free up private structure */
kfree (priv);
kfree(priv);
usb_set_serial_port_data(port, NULL);
}
@ -259,10 +263,10 @@ static int airprime_write(struct usb_serial_port *port,
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
dev_err(&port->dev, "no more free urbs\n");
kfree (buffer);
kfree(buffer);
return -ENOMEM;
}
memcpy (buffer, buf, count);
memcpy(buffer, buf, count);
usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
@ -279,7 +283,7 @@ static int airprime_write(struct usb_serial_port *port,
"%s - usb_submit_urb(write bulk) failed with status = %d\n",
__func__, status);
count = status;
kfree (buffer);
kfree(buffer);
} else {
spin_lock_irqsave(&priv->lock, flags);
++priv->outstanding_urbs;
@ -287,7 +291,7 @@ static int airprime_write(struct usb_serial_port *port,
}
/* we are done with this urb, so let the host driver
* really free it when it is finished with it */
usb_free_urb (urb);
usb_free_urb(urb);
return count;
}
@ -315,8 +319,10 @@ static int __init airprime_init(void)
{
int retval;
airprime_device.num_ports =
(endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
airprime_device.num_ports = endpoints;
if (endpoints < 0 || endpoints >= MAX_BULK_EPS)
airprime_device.num_ports = NUM_BULK_EPS;
retval = usb_serial_register(&airprime_device);
if (retval)
return retval;
@ -341,6 +347,7 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled");
module_param(buffer_size, int, 0);
MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
MODULE_PARM_DESC(buffer_size,
"Size of the transfer buffers in bytes (default 4096)");
module_param(endpoints, int, 0);
MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");

View file

@ -24,7 +24,7 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
#include <linux/serial.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
static int debug;
@ -246,29 +246,29 @@ static void ark3116_set_termios(struct usb_serial_port *port,
baud = tty_get_baud_rate(port->tty);
switch (baud) {
case 75:
case 150:
case 300:
case 600:
case 1200:
case 1800:
case 2400:
case 4800:
case 9600:
case 19200:
case 38400:
case 57600:
case 115200:
case 230400:
case 460800:
/* Report the resulting rate back to the caller */
tty_encode_baud_rate(port->tty, baud, baud);
break;
/* set 9600 as default (if given baudrate is invalid for example) */
default:
tty_encode_baud_rate(port->tty, 9600, 9600);
case 0:
baud = 9600;
case 75:
case 150:
case 300:
case 600:
case 1200:
case 1800:
case 2400:
case 4800:
case 9600:
case 19200:
case 38400:
case 57600:
case 115200:
case 230400:
case 460800:
/* Report the resulting rate back to the caller */
tty_encode_baud_rate(port->tty, baud, baud);
break;
/* set 9600 as default (if given baudrate is invalid for example) */
default:
tty_encode_baud_rate(port->tty, 9600, 9600);
case 0:
baud = 9600;
}
/*
@ -380,19 +380,19 @@ static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) {
case TIOCGSERIAL:
/* XXX: Some of these values are probably wrong. */
memset(&serstruct, 0, sizeof (serstruct));
memset(&serstruct, 0, sizeof(serstruct));
serstruct.type = PORT_16654;
serstruct.line = port->serial->minor;
serstruct.port = port->number;
serstruct.custom_divisor = 0;
serstruct.baud_base = 460800;
if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
if (copy_to_user(user_arg, &serstruct, sizeof(serstruct)))
return -EFAULT;
return 0;
case TIOCSSERIAL:
if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
return -EFAULT;
return 0;
default:

View file

@ -130,7 +130,7 @@ static int ch341_get_status(struct usb_device *dev)
return -ENOMEM;
r = ch341_control_in(dev, 0x95, 0x0706, 0, buffer, size);
if ( r < 0)
if (r < 0)
goto out;
/* Not having the datasheet for the CH341, we ignore the bytes returned

View file

@ -133,6 +133,14 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_3_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_4_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_5_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_6_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_7_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },

View file

@ -40,6 +40,17 @@
/* AlphaMicro Components AMC-232USB01 device */
#define FTDI_AMC232_PID 0xFF00 /* Product Id */
/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
/* the VID is the standard ftdi vid (FTDI_VID) */
#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */
#define FTDI_SCS_DEVICE_1_PID 0xD011 /* SCS Tracker / DSP TNC */
#define FTDI_SCS_DEVICE_2_PID 0xD012
#define FTDI_SCS_DEVICE_3_PID 0xD013
#define FTDI_SCS_DEVICE_4_PID 0xD014
#define FTDI_SCS_DEVICE_5_PID 0xD015
#define FTDI_SCS_DEVICE_6_PID 0xD016
#define FTDI_SCS_DEVICE_7_PID 0xD017
/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */
#define FTDI_ACTZWAVE_PID 0xF2D0

View file

@ -1713,7 +1713,7 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
{
struct moschip_port *mos7840_port;
unsigned int mcr;
unsigned int status;
int status;
dbg("%s - port %d", __func__, port->number);
@ -1740,11 +1740,10 @@ static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
mos7840_port->shadowMCR = mcr;
status = 0;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
if (status < 0) {
dbg("setting MODEM_CONTROL_REGISTER Failed\n");
return -1;
return status;
}
return 0;

View file

@ -123,7 +123,8 @@ config USB_STORAGE_ALAUDA
config USB_STORAGE_ONETOUCH
bool "Support OneTouch Button on Maxtor Hard Drives"
depends on USB_STORAGE && INPUT_EVDEV
depends on USB_STORAGE
depends on INPUT=y || INPUT=USB_STORAGE
help
Say Y here to include additional code to support the Maxtor OneTouch
USB hard drive's onetouch button.

View file

@ -135,7 +135,7 @@ static int usu_probe(struct usb_interface *intf,
stat[type].fls |= USU_MOD_FL_THREAD;
spin_unlock_irqrestore(&usu_lock, flags);
task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type);
if (IS_ERR(task)) {
rc = PTR_ERR(task);
printk(KERN_WARNING "libusual: "

View file

@ -38,7 +38,7 @@
#include "onetouch.h"
#include "debug.h"
void onetouch_release_input(void *onetouch_);
static void onetouch_release_input(void *onetouch_);
struct usb_onetouch {
char name[128];
@ -223,7 +223,7 @@ int onetouch_connect_input(struct us_data *ss)
return error;
}
void onetouch_release_input(void *onetouch_)
static void onetouch_release_input(void *onetouch_)
{
struct usb_onetouch *onetouch = (struct usb_onetouch *) onetouch_;

View file

@ -44,7 +44,8 @@
* running with this patch.
* Send your submission to either Phil Dibowitz <phil@ipom.com> or
* Alan Stern <stern@rowland.harvard.edu>, and don't forget to CC: the
* USB development list <linux-usb-devel@lists.sourceforge.net>.
* USB development list <linux-usb@vger.kernel.org> and the USB storage list
* <usb-storage@lists.one-eyed-alien.net>
*/
/* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
@ -557,6 +558,13 @@ UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999,
US_FL_SINGLE_LUN),
#endif
/* Reported by Dmitry Khlystov <adminimus@gmail.com> */
UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220,
"Samsung",
"YP-U3",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64),
/* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
"Belkin",
@ -1200,6 +1208,17 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_BULK32),
/* Andrew Lunn <andrew@lunn.ch>
* PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL
* on LUN 4.
* Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera"
*/
UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200,
"PanDigital",
"Photo Frame",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_NOT_LOCKABLE),
/* Submitted by Jan De Luyck <lkml@kcore.org> */
UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
"CITIZEN",
@ -1342,6 +1361,13 @@ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
/* Reported by Rohan Hart <rohan.hart17@gmail.com> */
UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010,
"INTOVA",
"Pixtreme",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
/*
* Entry for Jenoptik JD 5200z3
*

View file

@ -539,7 +539,8 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id)
" has %s in unusual_devs.h (kernel"
" %s)\n"
" Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n",
"<linux-usb@vger.kernel.org> and "
"<usb-storage@lists.one-eyed-alien.net>\n",
le16_to_cpu(ddesc->idVendor),
le16_to_cpu(ddesc->idProduct),
le16_to_cpu(ddesc->bcdDevice),

View file

@ -0,0 +1,48 @@
/*
* usb_c67x00.h: platform definitions for the Cypress C67X00 USB chip
*
* Copyright (C) 2006-2008 Barco N.V.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
#ifndef _LINUX_USB_C67X00_H
#define _LINUX_USB_C67X00_H
/* SIE configuration */
#define C67X00_SIE_UNUSED 0
#define C67X00_SIE_HOST 1
#define C67X00_SIE_PERIPHERAL_A 2 /* peripheral on A port */
#define C67X00_SIE_PERIPHERAL_B 3 /* peripheral on B port */
#define c67x00_sie_config(config, n) (((config)>>(4*(n)))&0x3)
#define C67X00_SIE1_UNUSED (C67X00_SIE_UNUSED << 0)
#define C67X00_SIE1_HOST (C67X00_SIE_HOST << 0)
#define C67X00_SIE1_PERIPHERAL_A (C67X00_SIE_PERIPHERAL_A << 0)
#define C67X00_SIE1_PERIPHERAL_B (C67X00_SIE_PERIPHERAL_B << 0)
#define C67X00_SIE2_UNUSED (C67X00_SIE_UNUSED << 4)
#define C67X00_SIE2_HOST (C67X00_SIE_HOST << 4)
#define C67X00_SIE2_PERIPHERAL_A (C67X00_SIE_PERIPHERAL_A << 4)
#define C67X00_SIE2_PERIPHERAL_B (C67X00_SIE_PERIPHERAL_B << 4)
struct c67x00_platform_data {
int sie_config; /* SIEs config (C67X00_SIEx_*) */
unsigned long hpi_regstep; /* Step between HPI registers */
};
#endif /* _LINUX_USB_C67X00_H */

View file

@ -455,7 +455,7 @@ struct usb_encryption_descriptor {
/*-------------------------------------------------------------------------*/
/* USB_DT_BOS: group of wireless capabilities */
/* USB_DT_BOS: group of device-level capabilities */
struct usb_bos_descriptor {
__u8 bLength;
__u8 bDescriptorType;
@ -501,6 +501,16 @@ struct usb_wireless_cap_descriptor { /* Ultra Wide Band */
__u8 bReserved;
} __attribute__((packed));
#define USB_CAP_TYPE_EXT 2
struct usb_ext_cap_descriptor { /* Link Power Management */
__u8 bLength;
__u8 bDescriptorType;
__u8 bDevCapabilityType;
__u8 bmAttributes;
#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */
} __attribute__((packed));
/*-------------------------------------------------------------------------*/
/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with

View file

@ -114,6 +114,8 @@ struct usb_ep_ops {
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
int (*set_halt) (struct usb_ep *ep, int value);
int (*set_wedge) (struct usb_ep *ep);
int (*fifo_status) (struct usb_ep *ep);
void (*fifo_flush) (struct usb_ep *ep);
};
@ -348,6 +350,25 @@ static inline int usb_ep_clear_halt(struct usb_ep *ep)
return ep->ops->set_halt(ep, 0);
}
/**
* usb_ep_set_wedge - sets the halt feature and ignores clear requests
* @ep: the endpoint being wedged
*
* Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT)
* requests. If the gadget driver clears the halt status, it will
* automatically unwedge the endpoint.
*
* Returns zero on success, else negative errno.
*/
static inline int
usb_ep_set_wedge(struct usb_ep *ep)
{
if (ep->ops->set_wedge)
return ep->ops->set_wedge(ep);
else
return ep->ops->set_halt(ep, 1);
}
/**
* usb_ep_fifo_status - returns number of bytes in fifo, or error
* @ep: the endpoint whose fifo status is being checked.