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: (97 commits)
  USB: qcserial: add device id for HP devices
  USB: isp1760: Add a delay before reading the SKIPMAP registers in isp1760-hcd.c
  USB: allow malformed LANGID descriptors
  USB: pxa27x_udc: typo fixes and code cleanups
  USB: gadget: gadget zero uses new suspend/resume hooks
  USB: gadget: composite device-level suspend/resume hooks
  USB: r8a66597-hcd: suspend/resume support
  USB: more u32 conversion after transfer_buffer_length and actual_length
  USB: Fix cp2101 USB serial device driver termios functions for console use
  USB: CP2101 New Device ID
  USB: ipaq: handle 4 endpoint devices
  USB: S3C: Move usb-control.h to platform include
  USB: ohci-hcd: Add ARCH_S3C24XX to the ohci-s3c2410.c glue
  USB: pedantic: spelling correction in comment for ch9.h
  USB: host: fix sparse warning: Using plain integer as NULL pointer
  USB: ohci-s3c2410: fix name of bus clock
  USB: ohci-s3c2410: remove <mach/hardware.h> include
  USB: serial: rename cp2101 driver to cp210x
  USB: CP2101 Reduce Error Logging
  USB: CP2101 Support AN205 baud rates
  ...
This commit is contained in:
Linus Torvalds 2009-03-26 11:17:39 -07:00
Родитель 0c93ea4064 fd8345f8de
Коммит 61a091827e
157 изменённых файлов: 5228 добавлений и 3829 удалений

Просмотреть файл

@ -229,16 +229,26 @@ struct usbmon_packet {
int status; /* 28: */
unsigned int length; /* 32: Length of data (submitted or actual) */
unsigned int len_cap; /* 36: Delivered length */
unsigned char setup[8]; /* 40: Only for Control 'S' */
}; /* 48 bytes total */
union { /* 40: */
unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
struct iso_rec { /* Only for ISO */
int error_count;
int numdesc;
} iso;
} s;
int interval; /* 48: Only for Interrupt and ISO */
int start_frame; /* 52: For ISO */
unsigned int xfer_flags; /* 56: copy of URB's transfer_flags */
unsigned int ndesc; /* 60: Actual number of ISO descriptors */
}; /* 64 total length */
These events can be received from a character device by reading with read(2),
with an ioctl(2), or by accessing the buffer with mmap.
with an ioctl(2), or by accessing the buffer with mmap. However, read(2)
only returns first 48 bytes for compatibility reasons.
The character device is usually called /dev/usbmonN, where N is the USB bus
number. Number zero (/dev/usbmon0) is special and means "all buses".
However, this feature is not implemented yet. Note that specific naming
policy is set by your Linux distribution.
Note that specific naming policy is set by your Linux distribution.
If you create /dev/usbmon0 by hand, make sure that it is owned by root
and has mode 0600. Otherwise, unpriviledged users will be able to snoop
@ -279,9 +289,10 @@ size is out of [unspecified] bounds for this kernel, the call fails with
This call returns the current size of the buffer in bytes.
MON_IOCX_GET, defined as _IOW(MON_IOC_MAGIC, 6, struct mon_get_arg)
MON_IOCX_GETX, defined as _IOW(MON_IOC_MAGIC, 10, struct mon_get_arg)
This call waits for events to arrive if none were in the kernel buffer,
then returns the first event. Its argument is a pointer to the following
These calls wait for events to arrive if none were in the kernel buffer,
then return the first event. The argument is a pointer to the following
structure:
struct mon_get_arg {
@ -294,6 +305,8 @@ Before the call, hdr, data, and alloc should be filled. Upon return, the area
pointed by hdr contains the next event structure, and the data buffer contains
the data, if any. The event is removed from the kernel buffer.
The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes.
MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg)
This ioctl is primarily used when the application accesses the buffer

Просмотреть файл

@ -29,13 +29,14 @@
#include <mach/bast-map.h>
#include <mach/bast-irq.h>
#include <mach/usb-control.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <plat/usb-control.h>
#include <plat/devs.h>
#include "usb-simtec.h"
/* control power and monitor over-current events on various Simtec

Просмотреть файл

@ -1,9 +1,9 @@
/* arch/arm/mach-s3c2410/include/mach/usb-control.h
/* arch/arm/plat-s3c/include/plat/usb-control.h
*
* Copyright (c) 2004 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 - usb port information
* S3C - USB host port information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -11,7 +11,7 @@
*/
#ifndef __ASM_ARCH_USBCONTROL_H
#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h"
#define __ASM_ARCH_USBCONTROL_H
#define S3C_HCDFLG_USED (1)

Просмотреть файл

@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
*/
#ifdef CONFIG_USB_LIBUSUAL
#define ub_usb_ids storage_usb_ids
#define ub_usb_ids usb_storage_usb_ids
#else
static struct usb_device_id ub_usb_ids[] = {
@ -2146,10 +2146,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
ep = &altsetting->endpoint[i].desc;
/* Is it a BULK endpoint? */
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK) {
if (usb_endpoint_xfer_bulk(ep)) {
/* BULK in or out? */
if (ep->bEndpointAddress & USB_DIR_IN) {
if (usb_endpoint_dir_in(ep)) {
if (ep_in == NULL)
ep_in = ep;
} else {
@ -2168,9 +2167,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);
sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);
sc->send_bulk_pipe = usb_sndbulkpipe(dev,
ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
usb_endpoint_num(ep_out));
sc->recv_bulk_pipe = usb_rcvbulkpipe(dev,
ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
usb_endpoint_num(ep_in));
return 0;
}

Просмотреть файл

@ -19,6 +19,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_ISP1760_HCD) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/

Просмотреть файл

@ -880,16 +880,19 @@ static int usblp_wwait(struct usblp *usblp, int nonblock)
if (rc <= 0)
break;
if (usblp->flags & LP_ABORT) {
if (schedule_timeout(msecs_to_jiffies(5000)) == 0) {
if (schedule_timeout(msecs_to_jiffies(1500)) == 0) {
if (usblp->flags & LP_ABORT) {
err = usblp_check_status(usblp, err);
if (err == 1) { /* Paper out */
rc = -ENOSPC;
break;
}
} else {
/* Prod the printer, Gentoo#251237. */
mutex_lock(&usblp->mut);
usblp_read_status(usblp, usblp->statusbuf);
mutex_unlock(&usblp->mut);
}
} else {
schedule();
}
}
set_current_state(TASK_RUNNING);

Просмотреть файл

@ -187,7 +187,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
}
/* this isn't checking for illegal values */
switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
type = "Ctrl";
if (speed == USB_SPEED_HIGH) /* uframes per NAK */

Просмотреть файл

@ -104,7 +104,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
#define MAX_USBFS_BUFFER_SIZE 16384
static inline int connected(struct dev_state *ps)
static int connected(struct dev_state *ps)
{
return (!list_empty(&ps->list) &&
ps->dev->state != USB_STATE_NOTATTACHED);
@ -248,7 +248,7 @@ static void free_async(struct async *as)
kfree(as);
}
static inline void async_newpending(struct async *as)
static void async_newpending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
@ -258,7 +258,7 @@ static inline void async_newpending(struct async *as)
spin_unlock_irqrestore(&ps->lock, flags);
}
static inline void async_removepending(struct async *as)
static void async_removepending(struct async *as)
{
struct dev_state *ps = as->ps;
unsigned long flags;
@ -268,7 +268,7 @@ static inline void async_removepending(struct async *as)
spin_unlock_irqrestore(&ps->lock, flags);
}
static inline struct async *async_getcompleted(struct dev_state *ps)
static struct async *async_getcompleted(struct dev_state *ps)
{
unsigned long flags;
struct async *as = NULL;
@ -283,7 +283,7 @@ static inline struct async *async_getcompleted(struct dev_state *ps)
return as;
}
static inline struct async *async_getpending(struct dev_state *ps,
static struct async *async_getpending(struct dev_state *ps,
void __user *userurb)
{
unsigned long flags;
@ -302,7 +302,7 @@ static inline struct async *async_getpending(struct dev_state *ps,
static void snoop_urb(struct urb *urb, void __user *userurb)
{
int j;
unsigned j;
unsigned char *data = urb->transfer_buffer;
if (!usbfs_snoop)
@ -311,9 +311,9 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
dev_info(&urb->dev->dev, "direction=%s\n",
usb_urb_dir_in(urb) ? "IN" : "OUT");
dev_info(&urb->dev->dev, "userurb=%p\n", userurb);
dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n",
dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n",
urb->transfer_buffer_length);
dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length);
dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length);
dev_info(&urb->dev->dev, "data: ");
for (j = 0; j < urb->transfer_buffer_length; ++j)
printk("%02x ", data[j]);
@ -376,7 +376,7 @@ static void destroy_async_on_interface(struct dev_state *ps,
destroy_async(ps, &hitlist);
}
static inline void destroy_all_async(struct dev_state *ps)
static void destroy_all_async(struct dev_state *ps)
{
destroy_async(ps, &ps->async_pending);
}
@ -525,7 +525,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
{
int ret = 0;
if (ps->dev->state != USB_STATE_ADDRESS
if (ps->dev->state != USB_STATE_UNAUTHENTICATED
&& ps->dev->state != USB_STATE_ADDRESS
&& ps->dev->state != USB_STATE_CONFIGURED)
return -EHOSTUNREACH;
if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))

Просмотреть файл

@ -66,7 +66,7 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
struct ep_device *ep = to_ep_device(dev);
char *type = "unknown";
switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
switch (usb_endpoint_type(ep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
type = "Control";
break;
@ -94,7 +94,7 @@ static ssize_t show_ep_interval(struct device *dev,
in = (ep->desc->bEndpointAddress & USB_DIR_IN);
switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
switch (usb_endpoint_type(ep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
interval = ep->desc->bInterval;
@ -131,10 +131,9 @@ static ssize_t show_ep_direction(struct device *dev,
struct ep_device *ep = to_ep_device(dev);
char *direction;
if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_CONTROL)
if (usb_endpoint_xfer_control(ep->desc))
direction = "both";
else if (ep->desc->bEndpointAddress & USB_DIR_IN)
else if (usb_endpoint_dir_in(ep->desc))
direction = "in";
else
direction = "out";

Просмотреть файл

@ -279,9 +279,9 @@ static const u8 hs_rh_config_descriptor [] = {
* helper routine for returning string descriptors in UTF-16LE
* input can actually be ISO-8859-1; ASCII is its 7-bit subset
*/
static int ascii2utf (char *s, u8 *utf, int utfmax)
static unsigned ascii2utf(char *s, u8 *utf, int utfmax)
{
int retval;
unsigned retval;
for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
*utf++ = *s++;
@ -304,19 +304,15 @@ static int ascii2utf (char *s, u8 *utf, int utfmax)
* Produces either a manufacturer, product or serial number string for the
* virtual root hub device.
*/
static int rh_string (
int id,
struct usb_hcd *hcd,
u8 *data,
int len
) {
static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len)
{
char buf [100];
// language ids
if (id == 0) {
buf[0] = 4; buf[1] = 3; /* 4 bytes string data */
buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */
len = min (len, 4);
len = min_t(unsigned, len, 4);
memcpy (data, buf, len);
return len;
@ -332,10 +328,7 @@ static int rh_string (
} else if (id == 3) {
snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname,
init_utsname()->release, hcd->driver->description);
// unsupported IDs --> "protocol stall"
} else
return -EPIPE;
}
switch (len) { /* All cases fall through */
default:
@ -360,9 +353,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
u8 tbuf [sizeof (struct usb_hub_descriptor)]
__attribute__((aligned(4)));
const u8 *bufp = tbuf;
int len = 0;
unsigned len = 0;
int status;
int n;
u8 patch_wakeup = 0;
u8 patch_protocol = 0;
@ -456,10 +448,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
patch_wakeup = 1;
break;
case USB_DT_STRING << 8:
n = rh_string (wValue & 0xff, hcd, ubuf, wLength);
if (n < 0)
if ((wValue & 0xff) < 4)
urb->actual_length = rh_string(wValue & 0xff,
hcd, ubuf, wLength);
else /* unsupported IDs --> "protocol stall" */
goto error;
urb->actual_length = n;
break;
default:
goto error;
@ -629,7 +622,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
{
int retval;
unsigned long flags;
int len = 1 + (urb->dev->maxchild / 8);
unsigned len = 1 + (urb->dev->maxchild / 8);
spin_lock_irqsave (&hcd_root_hub_lock, flags);
if (hcd->status_urb || urb->transfer_buffer_length < len) {
@ -901,7 +894,7 @@ static int register_root_hub(struct usb_hcd *hcd)
mutex_lock(&usb_bus_list_lock);
usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
if (retval != sizeof usb_dev->descriptor) {
mutex_unlock(&usb_bus_list_lock);

Просмотреть файл

@ -392,7 +392,7 @@ static void hub_irq(struct urb *urb)
{
struct usb_hub *hub = urb->context;
int status = urb->status;
int i;
unsigned i;
unsigned long bits;
switch (status) {
@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev,
recursively_mark_NOTATTACHED(udev);
spin_unlock_irqrestore(&device_state_lock, flags);
}
EXPORT_SYMBOL_GPL(usb_set_device_state);
/*
* WUSB devices are simple: they have no hubs behind, so the mapping
@ -2471,20 +2472,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
*/
switch (udev->speed) {
case USB_SPEED_VARIABLE: /* fixed at 512 */
udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
break;
case USB_SPEED_HIGH: /* fixed at 64 */
udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
break;
case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
/* to determine the ep0 maxpacket size, try to read
* the device descriptor to get bMaxPacketSize0 and
* then correct our initial guess.
*/
udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
break;
case USB_SPEED_LOW: /* fixed at 8 */
udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
break;
default:
goto fail;
@ -3392,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
udev->descriptor = descriptor; /* for disconnect() calls */
goto re_enumerate;
}
/* Restore the device's previous configuration */
if (!udev->actconfig)
goto done;
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_SET_CONFIGURATION, 0,
udev->actconfig->desc.bConfigurationValue, 0,
@ -3408,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}
usb_set_device_state(udev, USB_STATE_CONFIGURED);
/* Put interfaces back into the same altsettings as before.
* Don't bother to send the Set-Interface request for interfaces
* that were already in altsetting 0; besides being unnecessary,
* many devices can't handle it. Instead just reset the host-side
* endpoint state.
*/
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *intf = udev->actconfig->interface[i];
struct usb_interface_descriptor *desc;
/* set_interface resets host side toggle even
* for altsetting zero. the interface may have no driver.
*/
desc = &intf->cur_altsetting->desc;
ret = usb_set_interface(udev, desc->bInterfaceNumber,
desc->bAlternateSetting);
if (desc->bAlternateSetting == 0) {
usb_disable_interface(udev, intf, true);
usb_enable_interface(udev, intf, true);
ret = 0;
} else {
ret = usb_set_interface(udev, desc->bInterfaceNumber,
desc->bAlternateSetting);
}
if (ret < 0) {
dev_err(&udev->dev, "failed to restore interface %d "
"altsetting %d (error=%d)\n",

Просмотреть файл

@ -59,7 +59,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
"%s timed out on ep%d%s len=%u/%u\n",
current->comm,
usb_endpoint_num(&urb->ep->desc),
usb_urb_dir_in(urb) ? "in" : "out",
@ -804,18 +804,16 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
dev_err(&dev->dev,
"string descriptor 0 read error: %d\n",
err);
goto errout;
} else if (err < 4) {
dev_err(&dev->dev, "string descriptor 0 too short\n");
err = -EINVAL;
goto errout;
} else {
dev->have_langid = 1;
dev->string_langid = tbuf[2] | (tbuf[3] << 8);
/* always use the first langid listed */
dev_dbg(&dev->dev, "default language 0x%04x\n",
dev->string_langid);
}
dev->have_langid = 1;
}
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
@ -1719,7 +1717,8 @@ free_interfaces:
}
kfree(new_interfaces);
if (cp->string == NULL)
if (cp->string == NULL &&
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
/* Now that all the interfaces are set up, register them

Просмотреть файл

@ -54,6 +54,10 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
USB_QUIRK_STRING_FETCH_255 },
/* Saitek Cyborg Gold Joystick */
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },

Просмотреть файл

@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h>
#include <linux/usb/quirks.h>
#include "usb.h"
/* Active configuration fields */
@ -813,7 +814,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
if (intf->sysfs_files_created || intf->unregistering)
return 0;
if (alt->string == NULL)
if (alt->string == NULL &&
!(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string)
retval = device_create_file(&intf->dev, &dev_attr_interface);

Просмотреть файл

@ -295,7 +295,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (!urb || urb->hcpriv || !urb->complete)
return -EINVAL;
dev = urb->dev;
if ((!dev) || (dev->state < USB_STATE_DEFAULT))
if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
return -ENODEV;
/* For now, get the endpoint from the pipe. Eventually drivers
@ -370,7 +370,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
}
/* the I/O buffer must be mapped/unmapped, except when length=0 */
if (urb->transfer_buffer_length < 0)
if (urb->transfer_buffer_length > INT_MAX)
return -EMSGSIZE;
#ifdef DEBUG

Просмотреть файл

@ -254,6 +254,7 @@ config USB_PXA25X_SMALL
config USB_GADGET_PXA27X
boolean "PXA 27x"
depends on ARCH_PXA && PXA27x
select USB_OTG_UTILS
help
Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller.

Просмотреть файл

@ -551,7 +551,7 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
dma_desc->status = AMD_ADDBITS(dma_desc->status,
UDC_DMA_STP_STS_BS_HOST_BUSY,
UDC_DMA_STP_STS_BS);
dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE);
dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE);
req->td_data = dma_desc;
req->td_data_last = NULL;
req->chain_len = 1;

Просмотреть файл

@ -1017,7 +1017,7 @@ static struct usb_endpoint_descriptor usba_ep0_desc = {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0,
.bmAttributes = USB_ENDPOINT_XFER_CONTROL,
.wMaxPacketSize = __constant_cpu_to_le16(64),
.wMaxPacketSize = cpu_to_le16(64),
/* FIXME: I have no idea what to put here */
.bInterval = 1,
};
@ -1207,21 +1207,21 @@ static int do_test_mode(struct usba_udc *udc)
/* Avoid overly long expressions */
static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq)
{
if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP))
return true;
return false;
}
static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq)
{
if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE))
if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE))
return true;
return false;
}
static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq)
{
if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT))
if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT))
return true;
return false;
}
@ -1239,7 +1239,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
status = cpu_to_le16(udc->devstatus);
} else if (crq->bRequestType
== (USB_DIR_IN | USB_RECIP_INTERFACE)) {
status = __constant_cpu_to_le16(0);
status = cpu_to_le16(0);
} else if (crq->bRequestType
== (USB_DIR_IN | USB_RECIP_ENDPOINT)) {
struct usba_ep *target;
@ -1250,12 +1250,12 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
status = 0;
if (is_stalled(udc, target))
status |= __constant_cpu_to_le16(1);
status |= cpu_to_le16(1);
} else
goto delegate;
/* Write directly to the FIFO. No queueing is done. */
if (crq->wLength != __constant_cpu_to_le16(sizeof(status)))
if (crq->wLength != cpu_to_le16(sizeof(status)))
goto stall;
ep->state = DATA_STAGE_IN;
__raw_writew(status, ep->fifo);
@ -1274,7 +1274,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
struct usba_ep *target;
if (crq->wLength != __constant_cpu_to_le16(0)
if (crq->wLength != cpu_to_le16(0)
|| !feature_is_ep_halt(crq))
goto stall;
target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex));
@ -1308,7 +1308,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep,
} else if (crq->bRequestType == USB_RECIP_ENDPOINT) {
struct usba_ep *target;
if (crq->wLength != __constant_cpu_to_le16(0)
if (crq->wLength != cpu_to_le16(0)
|| !feature_is_ep_halt(crq))
goto stall;
@ -1514,7 +1514,7 @@ restart:
*/
ep->state = DATA_STAGE_IN;
} else {
if (crq.crq.wLength != __constant_cpu_to_le16(0))
if (crq.crq.wLength != cpu_to_le16(0))
ep->state = DATA_STAGE_OUT;
else
ep->state = STATUS_STAGE_IN;

Просмотреть файл

@ -66,7 +66,7 @@ static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_COMM,
.bDeviceSubClass = 0,
@ -74,8 +74,8 @@ static struct usb_device_descriptor device_desc = {
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
.idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM),
.idVendor = cpu_to_le16(CDC_VENDOR_NUM),
.idProduct = cpu_to_le16(CDC_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@ -193,7 +193,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
gadget->name,
cdc_config_driver.label);
device_desc.bcdDevice =
__constant_cpu_to_le16(0x0300 | 0x0099);
cpu_to_le16(0x0300 | 0x0099);
}

Просмотреть файл

@ -56,7 +56,6 @@
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/kernel.h>

Просмотреть файл

@ -149,16 +149,17 @@ done:
int usb_function_deactivate(struct usb_function *function)
{
struct usb_composite_dev *cdev = function->config->cdev;
unsigned long flags;
int status = 0;
spin_lock(&cdev->lock);
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
status = usb_gadget_disconnect(cdev->gadget);
if (status == 0)
cdev->deactivations++;
spin_unlock(&cdev->lock);
spin_unlock_irqrestore(&cdev->lock, flags);
return status;
}
@ -1013,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget)
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_function *f;
/* REVISIT: should we have config and device level
/* REVISIT: should we have config level
* suspend/resume callbacks?
*/
DBG(cdev, "suspend\n");
@ -1023,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget)
f->suspend(f);
}
}
if (composite->suspend)
composite->suspend(cdev);
}
static void
@ -1031,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget)
struct usb_composite_dev *cdev = get_gadget_data(gadget);
struct usb_function *f;
/* REVISIT: should we have config and device level
/* REVISIT: should we have config level
* suspend/resume callbacks?
*/
DBG(cdev, "resume\n");
if (composite->resume)
composite->resume(cdev);
if (cdev->config) {
list_for_each_entry(f, &cdev->config->functions, list) {
if (f->resume)

Просмотреть файл

@ -1437,7 +1437,7 @@ restart:
}
if (urb->transfer_buffer_length > 1)
buf [1] = 0;
urb->actual_length = min (2,
urb->actual_length = min_t(u32, 2,
urb->transfer_buffer_length);
value = 0;
status = 0;
@ -1626,7 +1626,7 @@ static int dummy_hub_control (
hub_descriptor ((struct usb_hub_descriptor *) buf);
break;
case GetHubStatus:
*(__le32 *) buf = __constant_cpu_to_le32 (0);
*(__le32 *) buf = cpu_to_le32 (0);
break;
case GetPortStatus:
if (wIndex != 1)

Просмотреть файл

@ -148,7 +148,7 @@ ep_matches (
return 0;
/* BOTH: "high bandwidth" works only at high speed */
if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
if (!gadget->is_dualspeed)
return 0;
/* configure your hardware with enough buffering!! */

Просмотреть файл

@ -156,7 +156,7 @@ static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16 (0x0200),
.bcdUSB = cpu_to_le16 (0x0200),
.bDeviceClass = USB_CLASS_COMM,
.bDeviceSubClass = 0,
@ -167,8 +167,8 @@ static struct usb_device_descriptor device_desc = {
* we support. (As does bNumConfigurations.) These values can
* also be overridden by module parameters.
*/
.idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM),
.idVendor = cpu_to_le16 (CDC_VENDOR_NUM),
.idProduct = cpu_to_le16 (CDC_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@ -318,7 +318,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
gadget->name,
eth_config_driver.label);
device_desc.bcdDevice =
__constant_cpu_to_le16(0x0300 | 0x0099);
cpu_to_le16(0x0300 | 0x0099);
}

Просмотреть файл

@ -125,7 +125,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = {
.bLength = sizeof(acm_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_call_mgmt_descriptor
@ -159,7 +159,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
.bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
};
@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = {
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
.bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
};
@ -205,14 +205,14 @@ static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *acm_hs_function[] __initdata = {

Просмотреть файл

@ -130,7 +130,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = {
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_union_desc ecm_union_desc __initdata = {
@ -148,9 +148,9 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = {
/* this descriptor actually adds value, surprise! */
/* .iMACAddress = DYNAMIC */
.bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */
.wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN),
.wNumberMCFilters = __constant_cpu_to_le16(0),
.bmEthernetStatistics = cpu_to_le32(0), /* no statistics */
.wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN),
.wNumberMCFilters = cpu_to_le16(0),
.bNumberPowerFilters = 0,
};
@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT),
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
@ -245,7 +245,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
@ -254,7 +254,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = {
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *ecm_hs_function[] __initdata = {

Просмотреть файл

@ -100,7 +100,7 @@ static struct usb_endpoint_descriptor hs_loop_source_desc = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_loop_sink_desc = {
@ -108,7 +108,7 @@ static struct usb_endpoint_descriptor hs_loop_sink_desc = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *hs_loopback_descs[] = {
@ -359,7 +359,7 @@ static struct usb_configuration loopback_driver = {
* loopback_add - add a loopback testing configuration to a device
* @cdev: the device to support the loopback configuration
*/
int __init loopback_add(struct usb_composite_dev *cdev)
int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
{
int id;
@ -372,6 +372,10 @@ int __init loopback_add(struct usb_composite_dev *cdev)
loopback_intf.iInterface = id;
loopback_driver.iConfiguration = id;
/* support autoresume for remote wakeup testing */
if (autoresume)
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
loopback_driver.descriptors = otg_desc;

Просмотреть файл

@ -123,7 +123,7 @@ static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
.bLength = sizeof(obex_cdc_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0120),
.bcdCDC = cpu_to_le16(0x0120),
};
static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
@ -138,7 +138,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
.bLength = sizeof(obex_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_OBEX_TYPE,
.bcdVersion = __constant_cpu_to_le16(0x0100),
.bcdVersion = cpu_to_le16(0x0100),
};
/* High-Speed Support */
@ -149,7 +149,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
@ -158,7 +158,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *hs_function[] __initdata = {

Просмотреть файл

@ -79,7 +79,7 @@ pn_header_desc = {
.bLength = sizeof pn_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
.bcdCDC = cpu_to_le16(0x0110),
};
static const struct usb_cdc_header_desc
@ -87,7 +87,7 @@ pn_phonet_desc = {
.bLength = sizeof pn_phonet_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_PHONET_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x1505), /* ??? */
.bcdCDC = cpu_to_le16(0x1505), /* ??? */
};
static struct usb_cdc_union_desc
@ -138,7 +138,7 @@ pn_hs_sink_desc = {
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor
@ -157,7 +157,7 @@ pn_hs_source_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *fs_pn_function[] = {

Просмотреть файл

@ -137,7 +137,7 @@ static struct usb_cdc_header_desc header_desc __initdata = {
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
@ -187,7 +187,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
};
@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT),
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};
static struct usb_endpoint_descriptor hs_in_desc __initdata = {
@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_out_desc __initdata = {
@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *eth_hs_function[] __initdata = {
@ -437,7 +437,7 @@ invalid:
DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
w_value, w_index, w_length);
req->zero = 0;
req->zero = (value < w_length);
req->length = value;
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0)

Просмотреть файл

@ -89,14 +89,14 @@ static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *gser_hs_function[] __initdata = {

Просмотреть файл

@ -59,7 +59,6 @@ struct f_sourcesink {
struct usb_ep *in_ep;
struct usb_ep *out_ep;
struct timer_list resume;
};
static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@ -67,10 +66,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
return container_of(f, struct f_sourcesink, function);
}
static unsigned autoresume;
module_param(autoresume, uint, 0);
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
static unsigned pattern;
module_param(pattern, uint, 0);
MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 ");
@ -118,7 +113,7 @@ static struct usb_endpoint_descriptor hs_source_desc = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_sink_desc = {
@ -126,7 +121,7 @@ static struct usb_endpoint_descriptor hs_sink_desc = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *hs_source_sink_descs[] = {
@ -155,21 +150,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
/*-------------------------------------------------------------------------*/
static void sourcesink_autoresume(unsigned long _c)
{
struct usb_composite_dev *cdev = (void *)_c;
struct usb_gadget *g = cdev->gadget;
/* Normally the host would be woken up for something
* more significant than just a timer firing; likely
* because of some direct user request.
*/
if (g->speed != USB_SPEED_UNKNOWN) {
int status = usb_gadget_wakeup(g);
DBG(cdev, "%s --> %d\n", __func__, status);
}
}
static int __init
sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
{
@ -198,9 +178,6 @@ autoconf_fail:
goto autoconf_fail;
ss->out_ep->driver_data = cdev; /* claim */
setup_timer(&ss->resume, sourcesink_autoresume,
(unsigned long) c->cdev);
/* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_source_desc.bEndpointAddress =
@ -359,7 +336,6 @@ static void disable_source_sink(struct f_sourcesink *ss)
cdev = ss->function.config->cdev;
disable_endpoints(cdev, ss->in_ep, ss->out_ep);
del_timer(&ss->resume);
VDBG(cdev, "%s disabled\n", ss->function.name);
}
@ -426,30 +402,6 @@ static void sourcesink_disable(struct usb_function *f)
disable_source_sink(ss);
}
static void sourcesink_suspend(struct usb_function *f)
{
struct f_sourcesink *ss = func_to_ss(f);
struct usb_composite_dev *cdev = f->config->cdev;
if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
return;
if (autoresume) {
mod_timer(&ss->resume, jiffies + (HZ * autoresume));
DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
} else
DBG(cdev, "%s\n", __func__);
}
static void sourcesink_resume(struct usb_function *f)
{
struct f_sourcesink *ss = func_to_ss(f);
struct usb_composite_dev *cdev = f->config->cdev;
DBG(cdev, "%s\n", __func__);
del_timer(&ss->resume);
}
/*-------------------------------------------------------------------------*/
static int __init sourcesink_bind_config(struct usb_configuration *c)
@ -467,8 +419,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt;
ss->function.disable = sourcesink_disable;
ss->function.suspend = sourcesink_suspend;
ss->function.resume = sourcesink_resume;
status = usb_add_function(c, &ss->function);
if (status)
@ -559,7 +509,7 @@ static struct usb_configuration sourcesink_driver = {
* sourcesink_add - add a source/sink testing configuration to a device
* @cdev: the device to support the configuration
*/
int __init sourcesink_add(struct usb_composite_dev *cdev)
int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume)
{
int id;

Просмотреть файл

@ -108,7 +108,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = __constant_cpu_to_le16(0x0110),
.bcdCDC = cpu_to_le16(0x0110),
};
static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
@ -116,7 +116,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_MDLM_TYPE,
.bcdVersion = __constant_cpu_to_le16(0x0100),
.bcdVersion = cpu_to_le16(0x0100),
.bGUID = {
0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6,
0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f,
@ -144,9 +144,9 @@ static struct usb_cdc_ether_desc ether_desc __initdata = {
/* this descriptor actually adds value, surprise! */
/* .iMACAddress = DYNAMIC */
.bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */
.wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN),
.wNumberMCFilters = __constant_cpu_to_le16(0),
.bmEthernetStatistics = cpu_to_le32(0), /* no statistics */
.wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN),
.wNumberMCFilters = cpu_to_le16(0),
.bNumberPowerFilters = 0,
};
@ -186,7 +186,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
@ -194,7 +194,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *hs_eth_function[] __initdata = {

Просмотреть файл

@ -847,13 +847,13 @@ device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
/* The next three values can be overridden by module parameters */
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
.bcdDevice = __constant_cpu_to_le16(0xffff),
.idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
.idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
.bcdDevice = cpu_to_le16(0xffff),
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
@ -926,7 +926,7 @@ fs_intr_in_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(2),
.wMaxPacketSize = cpu_to_le16(2),
.bInterval = 32, // frames -> 32 ms
};
@ -954,7 +954,7 @@ dev_qualifier = {
.bLength = sizeof dev_qualifier,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bNumConfigurations = 1,
@ -967,7 +967,7 @@ hs_bulk_in_desc = {
/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor
@ -977,7 +977,7 @@ hs_bulk_out_desc = {
/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512),
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1, // NAK every 1 uframe
};
@ -988,7 +988,7 @@ hs_intr_in_desc = {
/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = __constant_cpu_to_le16(2),
.wMaxPacketSize = cpu_to_le16(2),
.bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms
};
@ -2646,7 +2646,7 @@ static int send_status(struct fsg_dev *fsg)
struct bulk_cs_wrap *csw = bh->buf;
/* Store and send the Bulk-only CSW */
csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
csw->Signature = cpu_to_le32(USB_BULK_CS_SIG);
csw->Tag = fsg->tag;
csw->Residue = cpu_to_le32(fsg->residue);
csw->Status = status;
@ -3089,7 +3089,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
/* Is the CBW valid? */
if (req->actual != USB_BULK_CB_WRAP_LEN ||
cbw->Signature != __constant_cpu_to_le32(
cbw->Signature != cpu_to_le32(
USB_BULK_CB_SIG)) {
DBG(fsg, "invalid CBW: len %u sig 0x%x\n",
req->actual,

Просмотреть файл

@ -1802,7 +1802,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
out:
if (retval)
printk("gadget driver register failed %d\n", retval);
printk(KERN_WARNING "gadget driver register failed %d\n",
retval);
return retval;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@ -1847,7 +1848,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc_controller->gadget.dev.driver = NULL;
udc_controller->driver = NULL;
printk("unregistered gadget driver '%s'\n", driver->driver.name);
printk(KERN_WARNING "unregistered gadget driver '%s'\n",
driver->driver.name);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
@ -2455,7 +2457,7 @@ module_init(udc_init);
static void __exit udc_exit(void)
{
platform_driver_unregister(&udc_driver);
printk("%s unregistered\n", driver_desc);
printk(KERN_WARNING "%s unregistered\n", driver_desc);
}
module_exit(udc_exit);

Просмотреть файл

@ -19,7 +19,7 @@ void disable_endpoints(struct usb_composite_dev *cdev,
struct usb_ep *in, struct usb_ep *out);
/* configuration-specific linkup */
int sourcesink_add(struct usb_composite_dev *cdev);
int loopback_add(struct usb_composite_dev *cdev);
int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
int loopback_add(struct usb_composite_dev *cdev, bool autoresume);
#endif /* __G_ZERO_H */

Просмотреть файл

@ -199,10 +199,10 @@ DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
.idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
.bNumConfigurations = 1,
@ -241,8 +241,8 @@ static const struct usb_ac_header_descriptor_1 ac_header_desc = {
.bLength = USB_DT_AC_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
.bcdADC = __constant_cpu_to_le16(0x0100),
.wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
.bcdADC = cpu_to_le16(0x0100),
.wTotalLength = cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)),
.bInCollection = 1,
.baInterfaceNr = {
[0] = GMIDI_MS_INTERFACE,
@ -265,8 +265,8 @@ static const struct usb_ms_header_descriptor ms_header_desc = {
.bLength = USB_DT_MS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = USB_MS_HEADER,
.bcdMSC = __constant_cpu_to_le16(0x0100),
.wTotalLength = __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE
.bcdMSC = cpu_to_le16(0x0100),
.wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE
+ 2*USB_DT_MIDI_IN_SIZE
+ 2*USB_DT_MIDI_OUT_SIZE(1)),
};
@ -1226,7 +1226,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 = cpu_to_le16(0x9999);
}

Просмотреть файл

@ -1472,7 +1472,7 @@ static void ep0_setup(struct goku_udc *dev)
/* active endpoint */
if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0))
goto stall;
if (ctrl.wIndex & __constant_cpu_to_le16(
if (ctrl.wIndex & cpu_to_le16(
USB_DIR_IN)) {
if (!dev->ep[tmp].is_in)
goto stall;
@ -1480,7 +1480,7 @@ static void ep0_setup(struct goku_udc *dev)
if (dev->ep[tmp].is_in)
goto stall;
}
if (ctrl.wValue != __constant_cpu_to_le16(
if (ctrl.wValue != cpu_to_le16(
USB_ENDPOINT_HALT))
goto stall;
if (tmp)
@ -1493,7 +1493,7 @@ succeed:
return;
case USB_RECIP_DEVICE:
/* device remote wakeup: always clear */
if (ctrl.wValue != __constant_cpu_to_le16(1))
if (ctrl.wValue != cpu_to_le16(1))
goto stall;
VDBG(dev, "clear dev remote wakeup\n");
goto succeed;
@ -1519,7 +1519,7 @@ succeed:
dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION
&& ctrl.bRequestType == USB_RECIP_DEVICE);
if (unlikely(dev->req_config))
dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0));
dev->configured = (ctrl.wValue != cpu_to_le16(0));
/* delegate everything to the gadget driver.
* it may respond after this irq handler returns.

Просмотреть файл

@ -1,7 +1,7 @@
/*
* driver/usb/gadget/imx_udc.c
*
* Copyright (C) 2005 Mike Lee(eemike@gmail.com)
* Copyright (C) 2005 Mike Lee <eemike@gmail.com>
* Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@ -51,7 +52,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb,
void imx_udc_enable(struct imx_udc_struct *imx_usb)
{
int temp = __raw_readl(imx_usb->base + USB_CTRL);
__raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL);
__raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA,
imx_usb->base + USB_CTRL);
imx_usb->gadget.speed = USB_SPEED_FULL;
}
@ -126,7 +128,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb)
for (j = 0; j < 5; j++) {
__raw_writeb(ep_conf[j],
imx_usb->base + USB_DDAT);
do {} while (__raw_readl(imx_usb->base + USB_DADR)
do {} while (__raw_readl(imx_usb->base
+ USB_DADR)
& DADR_BSY);
}
}
@ -183,7 +186,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb)
temp = (EP_DIR(imx_ep) << 7) | (max << 5)
| (imx_ep->bmAttributes << 3);
__raw_writel(temp, imx_usb->base + USB_EP_STAT(i));
__raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i));
__raw_writel(temp | EPSTAT_FLUSH,
imx_usb->base + USB_EP_STAT(i));
D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i,
__raw_readl(imx_usb->base + USB_EP_STAT(i)));
}
@ -278,15 +282,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
struct imx_udc_struct *imx_usb = imx_ep->imx_usb;
int temp, i;
D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
D_ERR(imx_usb->dev,
"<%s> Forced stall on %s\n", __func__, imx_ep->ep.name);
imx_flush(imx_ep);
/* Special care for ep0 */
if (EP_NO(imx_ep)) {
if (!EP_NO(imx_ep)) {
temp = __raw_readl(imx_usb->base + USB_CTRL);
__raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL);
do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER);
__raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR,
imx_usb->base + USB_CTRL);
do { } while (__raw_readl(imx_usb->base + USB_CTRL)
& CTRL_CMDOVER);
temp = __raw_readl(imx_usb->base + USB_CTRL);
__raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL);
}
@ -296,12 +303,13 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep)
imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
for (i = 0; i < 100; i ++) {
temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
temp = __raw_readl(imx_usb->base
+ USB_EP_STAT(EP_NO(imx_ep)));
if (!(temp & EPSTAT_STALL))
break;
udelay(20);
}
if (i == 50)
if (i == 100)
D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n",
__func__, imx_ep->ep.name);
}
@ -325,7 +333,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget)
*******************************************************************************
*/
static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
static void ep_add_request(struct imx_ep_struct *imx_ep,
struct imx_request *req)
{
if (unlikely(!req))
return;
@ -334,7 +343,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req
list_add_tail(&req->queue, &imx_ep->queue);
}
static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req)
static void ep_del_request(struct imx_ep_struct *imx_ep,
struct imx_request *req)
{
if (unlikely(!req))
return;
@ -343,7 +353,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req
req->in_use = 0;
}
static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status)
static void done(struct imx_ep_struct *imx_ep,
struct imx_request *req, int status)
{
ep_del_request(imx_ep, req);
@ -494,7 +505,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req)
__func__, imx_ep->ep.name, req,
completed ? "completed" : "not completed");
if (!EP_NO(imx_ep))
ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE);
ep0_chg_stat(__func__,
imx_ep->imx_usb, EP0_IDLE);
}
}
@ -539,10 +551,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep)
struct imx_request *req = NULL;
int ret = 0;
if (!list_empty(&imx_ep->queue))
if (!list_empty(&imx_ep->queue)) {
req = list_entry(imx_ep->queue.next, struct imx_request, queue);
if (req) {
switch (imx_ep->imx_usb->ep0state) {
case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */
@ -561,6 +572,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep)
}
}
else
D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n",
__func__, imx_ep->ep.name);
return ret;
}
@ -583,7 +598,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb)
"<%s> no setup packet received\n", __func__);
goto stall;
}
u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep)));
u.word[i] = __raw_readl(imx_usb->base
+ USB_EP_FDAT(EP_NO(imx_ep)));
}
temp = imx_ep_empty(imx_ep);
@ -759,7 +775,7 @@ static int imx_ep_queue
*/
if (imx_usb->set_config && !EP_NO(imx_ep)) {
imx_usb->set_config = 0;
D_EPX(imx_usb->dev,
D_ERR(imx_usb->dev,
"<%s> gadget reply set config\n", __func__);
return 0;
}
@ -779,28 +795,29 @@ static int imx_ep_queue
return -ESHUTDOWN;
}
local_irq_save(flags);
/* Debug */
D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n",
__func__, EP_NO(imx_ep),
((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length);
((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
== EP0_IN_DATA_PHASE)
|| (EP_NO(imx_ep) && EP_DIR(imx_ep)))
? "IN" : "OUT", usb_req->length);
dump_req(__func__, imx_ep, usb_req);
if (imx_ep->stopped) {
usb_req->status = -ESHUTDOWN;
ret = -ESHUTDOWN;
goto out;
return -ESHUTDOWN;
}
if (req->in_use) {
D_ERR(imx_usb->dev,
"<%s> refusing to queue req %p (already queued)\n",
__func__, req);
goto out;
return 0;
}
local_irq_save(flags);
usb_req->status = -EINPROGRESS;
usb_req->actual = 0;
@ -810,7 +827,7 @@ static int imx_ep_queue
ret = handle_ep0(imx_ep);
else
ret = handle_ep(imx_ep);
out:
local_irq_restore(flags);
return ret;
}
@ -997,71 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb,
*******************************************************************************
*/
static irqreturn_t imx_udc_irq(int irq, void *dev)
/*
* Called when timer expires.
* Timer is started when CFG_CHG is received.
*/
static void handle_config(unsigned long data)
{
struct imx_udc_struct *imx_usb = dev;
struct imx_udc_struct *imx_usb = (void *)data;
struct usb_ctrlrequest u;
int temp, cfg, intf, alt;
int intr = __raw_readl(imx_usb->base + USB_INTR);
if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
| INTR_RESET_STOP | INTR_CFG_CHG)) {
dump_intr(__func__, intr, imx_usb->dev);
dump_usb_stat(__func__, imx_usb);
}
local_irq_disable();
if (!imx_usb->driver) {
/*imx_udc_disable(imx_usb);*/
goto end_irq;
}
temp = __raw_readl(imx_usb->base + USB_STAT);
cfg = (temp & STAT_CFG) >> 5;
intf = (temp & STAT_INTF) >> 3;
alt = temp & STAT_ALTSET;
if (intr & INTR_WAKEUP) {
if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
&& imx_usb->driver && imx_usb->driver->resume)
imx_usb->driver->resume(&imx_usb->gadget);
imx_usb->set_config = 0;
imx_usb->gadget.speed = USB_SPEED_FULL;
}
D_REQ(imx_usb->dev,
"<%s> orig config C=%d, I=%d, A=%d / "
"req config C=%d, I=%d, A=%d\n",
__func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
cfg, intf, alt);
if (intr & INTR_SUSPEND) {
if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
&& imx_usb->driver && imx_usb->driver->suspend)
imx_usb->driver->suspend(&imx_usb->gadget);
imx_usb->set_config = 0;
imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
}
if (cfg == 1 || cfg == 2) {
if (intr & INTR_RESET_START) {
__raw_writel(intr, imx_usb->base + USB_INTR);
udc_stop_activity(imx_usb, imx_usb->driver);
imx_usb->set_config = 0;
imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
}
if (intr & INTR_RESET_STOP)
imx_usb->gadget.speed = USB_SPEED_FULL;
if (intr & INTR_CFG_CHG) {
__raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
temp = __raw_readl(imx_usb->base + USB_STAT);
cfg = (temp & STAT_CFG) >> 5;
intf = (temp & STAT_INTF) >> 3;
alt = temp & STAT_ALTSET;
D_REQ(imx_usb->dev,
"<%s> orig config C=%d, I=%d, A=%d / "
"req config C=%d, I=%d, A=%d\n",
__func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt,
cfg, intf, alt);
if (cfg != 1 && cfg != 2)
goto end_irq;
imx_usb->set_config = 0;
/* Config setup */
if (imx_usb->cfg != cfg) {
D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__);
u.bRequest = USB_REQ_SET_CONFIGURATION;
u.bRequestType = USB_DIR_OUT |
USB_TYPE_STANDARD |
@ -1070,14 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
u.wIndex = 0;
u.wLength = 0;
imx_usb->cfg = cfg;
imx_usb->set_config = 1;
imx_usb->driver->setup(&imx_usb->gadget, &u);
imx_usb->set_config = 0;
D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__);
}
if (imx_usb->intf != intf || imx_usb->alt != alt) {
D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__);
u.bRequest = USB_REQ_SET_INTERFACE;
u.bRequestType = USB_DIR_OUT |
USB_TYPE_STANDARD |
@ -1087,20 +1061,92 @@ static irqreturn_t imx_udc_irq(int irq, void *dev)
u.wLength = 0;
imx_usb->intf = intf;
imx_usb->alt = alt;
imx_usb->set_config = 1;
imx_usb->driver->setup(&imx_usb->gadget, &u);
imx_usb->set_config = 0;
D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__);
}
}
imx_usb->set_config = 0;
local_irq_enable();
}
static irqreturn_t imx_udc_irq(int irq, void *dev)
{
struct imx_udc_struct *imx_usb = dev;
int intr = __raw_readl(imx_usb->base + USB_INTR);
int temp;
if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START
| INTR_RESET_STOP | INTR_CFG_CHG)) {
dump_intr(__func__, intr, imx_usb->dev);
dump_usb_stat(__func__, imx_usb);
}
if (!imx_usb->driver)
goto end_irq;
if (intr & INTR_SOF) {
/* Copy from Freescale BSP.
We must enable SOF intr and set CMDOVER.
Datasheet don't specifiy this action, but it
is done in Freescale BSP, so just copy it.
*/
if (imx_usb->ep0state == EP0_IDLE) {
temp = __raw_readl(imx_usb->base + USB_CTRL);
__raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL);
__raw_writel(temp | CTRL_CMDOVER,
imx_usb->base + USB_CTRL);
}
}
if (intr & INTR_CFG_CHG) {
/* A workaround of serious IMX UDC bug.
Handling of CFG_CHG should be delayed for some time, because
IMX does not NACK the host when CFG_CHG interrupt is pending.
There is no time to handle current CFG_CHG
if next CFG_CHG or SETUP packed is send immediately.
We have to clear CFG_CHG, start the timer and
NACK the host by setting CTRL_CMDOVER
if it sends any SETUP packet.
When timer expires, handler is called to handle configuration
changes. While CFG_CHG is not handled (set_config=1),
we must NACK the host to every SETUP packed.
This delay prevents from going out of sync with host.
*/
__raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR);
imx_usb->set_config = 1;
mod_timer(&imx_usb->timer, jiffies + 5);
goto end_irq;
}
if (intr & INTR_WAKEUP) {
if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN
&& imx_usb->driver && imx_usb->driver->resume)
imx_usb->driver->resume(&imx_usb->gadget);
imx_usb->set_config = 0;
del_timer(&imx_usb->timer);
imx_usb->gadget.speed = USB_SPEED_FULL;
}
if (intr & INTR_SUSPEND) {
if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN
&& imx_usb->driver && imx_usb->driver->suspend)
imx_usb->driver->suspend(&imx_usb->gadget);
imx_usb->set_config = 0;
del_timer(&imx_usb->timer);
imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
}
if (intr & INTR_RESET_START) {
__raw_writel(intr, imx_usb->base + USB_INTR);
udc_stop_activity(imx_usb, imx_usb->driver);
imx_usb->set_config = 0;
del_timer(&imx_usb->timer);
imx_usb->gadget.speed = USB_SPEED_UNKNOWN;
}
if (intr & INTR_RESET_STOP)
imx_usb->gadget.speed = USB_SPEED_FULL;
end_irq:
__raw_writel(intr, imx_usb->base + USB_INTR);
return IRQ_HANDLED;
@ -1109,6 +1155,7 @@ end_irq:
static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
{
struct imx_udc_struct *imx_usb = dev;
struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0];
int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0));
dump_ep_intr(__func__, 0, intr, imx_usb->dev);
@ -1118,16 +1165,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev)
return IRQ_HANDLED;
}
/* DEVREQ IRQ has highest priority */
/* DEVREQ has highest priority */
if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ))
handle_ep0_devreq(imx_usb);
/* Seem i.MX is missing EOF interrupt sometimes.
* Therefore we monitor both EOF and FIFO_EMPTY interrups
* when transmiting, and both EOF and FIFO_FULL when
* receiving data.
* Therefore we don't monitor EOF.
* We call handle_ep0() only if a request is queued for ep0.
*/
else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL))
handle_ep0(&imx_usb->imx_ep[0]);
else if (!list_empty(&imx_ep->queue))
handle_ep0(imx_ep);
__raw_writel(intr, imx_usb->base + USB_EP_INTR(0));
@ -1318,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
udc_stop_activity(imx_usb, driver);
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);
driver->unbind(&imx_usb->gadget);
imx_usb->gadget.dev.driver = NULL;
@ -1435,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev)
usb_init_data(imx_usb);
imx_udc_init(imx_usb);
init_timer(&imx_usb->timer);
imx_usb->timer.function = handle_config;
imx_usb->timer.data = (unsigned long)imx_usb;
return 0;
fail3:
@ -1457,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
int i;
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);
for (i = 0; i < IMX_USB_NB_EP + 1; i++)
free_irq(imx_usb->usbd_int[i], imx_usb);

Просмотреть файл

@ -23,7 +23,8 @@
/* Helper macros */
#define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */
#define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0)
#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \
? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/
#define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0)
#define IMX_USB_NB_EP 6
@ -58,6 +59,7 @@ struct imx_udc_struct {
struct device *dev;
struct imx_ep_struct imx_ep[IMX_USB_NB_EP];
struct clk *clk;
struct timer_list timer;
enum ep0_state ep0state;
struct resource *res;
void __iomem *base;
@ -88,8 +90,8 @@ struct imx_udc_struct {
#define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */
#define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */
#define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */
#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */
#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */
#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */
#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */
#define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */
#define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */
#define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */
@ -170,7 +172,7 @@ struct imx_udc_struct {
/* #define DEBUG_IRQ */
/* #define DEBUG_EPIRQ */
/* #define DEBUG_DUMP */
#define DEBUG_ERR
/* #define DEBUG_ERR */
#ifdef DEBUG_REQ
#define D_REQ(dev, args...) dev_dbg(dev, ## args)
@ -228,7 +230,8 @@ struct imx_udc_struct {
#endif /* DEBUG_IRQ */
#ifdef DEBUG_EPIRQ
static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev)
static void dump_ep_intr(const char *label, int nr, int irqreg,
struct device *dev)
{
dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr,
(irqreg & EPINTR_FIFO_FULL) ? " full" : "",
@ -246,7 +249,8 @@ struct imx_udc_struct {
#endif /* DEBUG_IRQ */
#ifdef DEBUG_DUMP
static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb)
static void dump_usb_stat(const char *label,
struct imx_udc_struct *imx_usb)
{
int temp = __raw_readl(imx_usb->base + USB_STAT);
@ -259,12 +263,15 @@ struct imx_udc_struct {
(temp & STAT_ALTSET));
}
static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep)
static void dump_ep_stat(const char *label,
struct imx_ep_struct *imx_ep)
{
int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep)));
int temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_INTR(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
"<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n",
label, EP_NO(imx_ep),
(temp & EPINTR_FIFO_FULL) ? " full" : "",
(temp & EPINTR_FIFO_EMPTY) ? " fempty" : "",
(temp & EPINTR_FIFO_ERROR) ? " ferr" : "",
@ -275,18 +282,22 @@ struct imx_udc_struct {
(temp & EPINTR_DEVREQ) ? " devreq" : "",
(temp & EPINTR_EOT) ? " eot" : "");
temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep)));
temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_STAT(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep),
"<%s> EP%d_STAT=[%s%s bcount=%d]\n",
label, EP_NO(imx_ep),
(temp & EPSTAT_SIP) ? " sip" : "",
(temp & EPSTAT_STALL) ? " stall" : "",
(temp & EPSTAT_BCOUNT) >> 16);
temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep)));
temp = __raw_readl(imx_ep->imx_usb->base
+ USB_EP_FSTAT(EP_NO(imx_ep)));
dev_dbg(imx_ep->imx_usb->dev,
"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep),
"<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n",
label, EP_NO(imx_ep),
(temp & FSTAT_ERR) ? " ferr" : "",
(temp & FSTAT_UF) ? " funder" : "",
(temp & FSTAT_OF) ? " fover" : "",
@ -296,19 +307,23 @@ struct imx_udc_struct {
(temp & FSTAT_EMPTY) ? " fempty" : "");
}
static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req)
static void dump_req(const char *label, struct imx_ep_struct *imx_ep,
struct usb_request *req)
{
int i;
if (!req || !req->buf) {
dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label);
dev_dbg(imx_ep->imx_usb->dev,
"<%s> req or req buf is free\n", label);
return;
}
if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE)
if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state
== EP0_IN_DATA_PHASE)
|| (EP_NO(imx_ep) && EP_DIR(imx_ep))) {
dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label);
dev_dbg(imx_ep->imx_usb->dev,
"<%s> request dump <", label);
for (i = 0; i < req->length; i++)
printk("%02x-", *((u8 *)req->buf + i));
printk(">\n");

Просмотреть файл

@ -1334,7 +1334,7 @@ static void make_qualifier (struct dev_data *dev)
qual.bLength = sizeof qual;
qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER;
qual.bcdUSB = __constant_cpu_to_le16 (0x0200);
qual.bcdUSB = cpu_to_le16 (0x0200);
desc = dev->dev;
qual.bDeviceClass = desc->bDeviceClass;
@ -1908,7 +1908,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|| dev->dev->bNumConfigurations != 1)
goto fail;
dev->dev->bNumConfigurations = 1;
dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200);
dev->dev->bcdUSB = cpu_to_le16 (0x0200);
/* triggers gadgetfs_bind(); then we can enumerate. */
spin_unlock_irq (&dev->lock);

Просмотреть файл

@ -432,8 +432,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
device_add(&dev->gadget.dev);
retval = driver->bind(&dev->gadget);
if (retval) {
printk("%s: bind to driver %s --> error %d\n", dev->gadget.name,
driver->driver.name, retval);
printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
dev->gadget.name, driver->driver.name, retval);
device_del(&dev->gadget.dev);
dev->driver = 0;
@ -445,8 +445,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
* for set_configuration as well as eventual disconnect.
* NOTE: this shouldn't power up until later.
*/
printk("%s: registered gadget driver '%s'\n", dev->gadget.name,
driver->driver.name);
printk(KERN_WARNING "%s: registered gadget driver '%s'\n",
dev->gadget.name, driver->driver.name);
udc_enable(dev);
@ -581,7 +581,8 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
* discard the extra data.
*/
if (req->req.status != -EOVERFLOW)
printk("%s overflow %d\n", ep->ep.name, count);
printk(KERN_WARNING "%s overflow %d\n",
ep->ep.name, count);
req->req.status = -EOVERFLOW;
} else {
*buf++ = byte;
@ -831,7 +832,8 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
queue);
if (!req) {
printk("%s: NULL REQ %d\n",
printk(KERN_WARNING
"%s: NULL REQ %d\n",
__func__, ep_idx);
flush(ep);
break;
@ -844,7 +846,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
} else {
/* Throw packet away.. */
printk("%s: No descriptor?!?\n", __func__);
printk(KERN_WARNING "%s: No descriptor?!?\n", __func__);
flush(ep);
}
}

Просмотреть файл

@ -142,8 +142,8 @@ static char *type_string (u8 bmAttributes)
#include "net2280.h"
#define valid_bit __constant_cpu_to_le32 (1 << VALID_BIT)
#define dma_done_ie __constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
#define valid_bit cpu_to_le32 (1 << VALID_BIT)
#define dma_done_ie cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE)
/*-------------------------------------------------------------------------*/
@ -425,7 +425,7 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
return NULL;
}
td->dmacount = 0; /* not VALID */
td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
req->td = td;
}
@ -775,7 +775,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
fill_dma_desc (ep, req, 1);
if (!use_dma_chaining)
req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN);
req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN);
start_queue (ep, tmp, req->td_dma);
}
@ -2407,9 +2407,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if (readl (&e->regs->ep_rsp)
& (1 << SET_ENDPOINT_HALT))
status = __constant_cpu_to_le32 (1);
status = cpu_to_le32 (1);
else
status = __constant_cpu_to_le32 (0);
status = cpu_to_le32 (0);
/* don't bother with a request object! */
writel (0, &dev->epregs [0].ep_irqenb);
@ -2667,7 +2667,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
req = list_entry (ep->queue.next,
struct net2280_request, queue);
dmacount = req->td->dmacount;
dmacount &= __constant_cpu_to_le32 (
dmacount &= cpu_to_le32 (
(1 << VALID_BIT)
| DMA_BYTE_COUNT_MASK);
if (dmacount && (dmacount & valid_bit) == 0)
@ -2881,7 +2881,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
goto done;
}
td->dmacount = 0; /* not VALID */
td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
dev->ep [i].dummy = td;
}

Просмотреть файл

@ -225,12 +225,12 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.idVendor = __constant_cpu_to_le16(PRINTER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(PRINTER_PRODUCT_NUM),
.idVendor = cpu_to_le16(PRINTER_VENDOR_NUM),
.idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM),
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
.iSerialNumber = STRING_SERIALNUM,
@ -299,20 +299,20 @@ static struct usb_endpoint_descriptor hs_ep_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512)
.wMaxPacketSize = cpu_to_le16(512)
};
static struct usb_endpoint_descriptor hs_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = __constant_cpu_to_le16(512)
.wMaxPacketSize = cpu_to_le16(512)
};
static struct usb_qualifier_descriptor dev_qualifier = {
.bLength = sizeof dev_qualifier,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PRINTER,
.bNumConfigurations = 1
};
@ -1406,16 +1406,16 @@ printer_bind(struct usb_gadget *gadget)
gadget->name);
/* unrecognized, but safe unless bulk is REALLY quirky */
device_desc.bcdDevice =
__constant_cpu_to_le16(0xFFFF);
cpu_to_le16(0xFFFF);
}
snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
init_utsname()->sysname, init_utsname()->release,
gadget->name);
device_desc.idVendor =
__constant_cpu_to_le16(PRINTER_VENDOR_NUM);
cpu_to_le16(PRINTER_VENDOR_NUM);
device_desc.idProduct =
__constant_cpu_to_le16(PRINTER_PRODUCT_NUM);
cpu_to_le16(PRINTER_PRODUCT_NUM);
/* support optional vendor/distro customization */
if (idVendor) {

Просмотреть файл

@ -30,6 +30,7 @@
#include <linux/proc_fs.h>
#include <linux/clk.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <asm/byteorder.h>
#include <mach/hardware.h>
@ -278,7 +279,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc)
goto err_queues;
eps = debugfs_create_file("epstate", 0400, root, udc,
&eps_dbg_fops);
if (!queues)
if (!eps)
goto err_eps;
udc->debugfs_root = root;
@ -747,13 +748,13 @@ static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status)
}
/**
* ep_end_out_req - Ends control endpoint in request
* ep_end_out_req - Ends endpoint OUT request
* @ep: physical endpoint
* @req: pxa request
*
* Context: ep->lock held
*
* Ends endpoint in request (completes usb request).
* Ends endpoint OUT request (completes usb request).
*/
static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
{
@ -762,13 +763,13 @@ static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
}
/**
* ep0_end_out_req - Ends control endpoint in request (ends data stage)
* ep0_end_out_req - Ends control endpoint OUT request (ends data stage)
* @ep: physical endpoint
* @req: pxa request
*
* Context: ep->lock held
*
* Ends control endpoint in request (completes usb request), and puts
* Ends control endpoint OUT request (completes usb request), and puts
* control endpoint into idle state
*/
static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
@ -779,13 +780,13 @@ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req)
}
/**
* ep_end_in_req - Ends endpoint out request
* ep_end_in_req - Ends endpoint IN request
* @ep: physical endpoint
* @req: pxa request
*
* Context: ep->lock held
*
* Ends endpoint out request (completes usb request).
* Ends endpoint IN request (completes usb request).
*/
static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
{
@ -794,20 +795,18 @@ static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
}
/**
* ep0_end_in_req - Ends control endpoint out request (ends data stage)
* ep0_end_in_req - Ends control endpoint IN request (ends data stage)
* @ep: physical endpoint
* @req: pxa request
*
* Context: ep->lock held
*
* Ends control endpoint out request (completes usb request), and puts
* Ends control endpoint IN request (completes usb request), and puts
* control endpoint into status state
*/
static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req)
{
struct pxa_udc *udc = ep->dev;
set_ep0state(udc, IN_STATUS_STAGE);
set_ep0state(ep->dev, IN_STATUS_STAGE);
ep_end_in_req(ep, req);
}
@ -1167,7 +1166,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req,
ep_end_in_req(ep, req);
} else {
ep_err(ep, "got a request of %d bytes while"
"in state WATI_ACK_SET_CONF_INTERF\n",
"in state WAIT_ACK_SET_CONF_INTERF\n",
length);
ep_del_request(ep, req);
rc = -EL2HLT;
@ -1213,30 +1212,26 @@ static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
struct udc_usb_ep *udc_usb_ep;
struct pxa27x_request *req;
unsigned long flags;
int rc;
int rc = -EINVAL;
if (!_ep)
return -EINVAL;
return rc;
udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep);
ep = udc_usb_ep->pxa_ep;
if (!ep || is_ep0(ep))
return -EINVAL;
return rc;
spin_lock_irqsave(&ep->lock, flags);
/* make sure it's actually queued on this endpoint */
list_for_each_entry(req, &ep->queue, queue) {
if (&req->req == _req)
if (&req->req == _req) {
req_done(ep, req, -ECONNRESET);
rc = 0;
break;
}
}
rc = -EINVAL;
if (&req->req != _req)
goto out;
rc = 0;
req_done(ep, req, -ECONNRESET);
out:
spin_unlock_irqrestore(&ep->lock, flags);
return rc;
}
@ -1471,6 +1466,32 @@ static struct usb_ep_ops pxa_ep_ops = {
.fifo_flush = pxa_ep_fifo_flush,
};
/**
* dplus_pullup - Connect or disconnect pullup resistor to D+ pin
* @udc: udc device
* @on: 0 if disconnect pullup resistor, 1 otherwise
* Context: any
*
* Handle D+ pullup resistor, make the device visible to the usb bus, and
* declare it as a full speed usb device
*/
static void dplus_pullup(struct pxa_udc *udc, int on)
{
if (on) {
if (gpio_is_valid(udc->mach->gpio_pullup))
gpio_set_value(udc->mach->gpio_pullup,
!udc->mach->gpio_pullup_inverted);
if (udc->mach->udc_command)
udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
} else {
if (gpio_is_valid(udc->mach->gpio_pullup))
gpio_set_value(udc->mach->gpio_pullup,
udc->mach->gpio_pullup_inverted);
if (udc->mach->udc_command)
udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
udc->pullup_on = on;
}
/**
* pxa_udc_get_frame - Returns usb frame number
@ -1500,21 +1521,145 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget)
return 0;
}
static void udc_enable(struct pxa_udc *udc);
static void udc_disable(struct pxa_udc *udc);
/**
* should_enable_udc - Tells if UDC should be enabled
* @udc: udc device
* Context: any
*
* The UDC should be enabled if :
* - the pullup resistor is connected
* - and a gadget driver is bound
* - and vbus is sensed (or no vbus sense is available)
*
* Returns 1 if UDC should be enabled, 0 otherwise
*/
static int should_enable_udc(struct pxa_udc *udc)
{
int put_on;
put_on = ((udc->pullup_on) && (udc->driver));
put_on &= ((udc->vbus_sensed) || (!udc->transceiver));
return put_on;
}
/**
* should_disable_udc - Tells if UDC should be disabled
* @udc: udc device
* Context: any
*
* The UDC should be disabled if :
* - the pullup resistor is not connected
* - or no gadget driver is bound
* - or no vbus is sensed (when vbus sesing is available)
*
* Returns 1 if UDC should be disabled
*/
static int should_disable_udc(struct pxa_udc *udc)
{
int put_off;
put_off = ((!udc->pullup_on) || (!udc->driver));
put_off |= ((!udc->vbus_sensed) && (udc->transceiver));
return put_off;
}
/**
* pxa_udc_pullup - Offer manual D+ pullup control
* @_gadget: usb gadget using the control
* @is_active: 0 if disconnect, else connect D+ pullup resistor
* Context: !in_interrupt()
*
* Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup
*/
static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active)
{
struct pxa_udc *udc = to_gadget_udc(_gadget);
if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
return -EOPNOTSUPP;
dplus_pullup(udc, is_active);
if (should_enable_udc(udc))
udc_enable(udc);
if (should_disable_udc(udc))
udc_disable(udc);
return 0;
}
static void udc_enable(struct pxa_udc *udc);
static void udc_disable(struct pxa_udc *udc);
/**
* pxa_udc_vbus_session - Called by external transceiver to enable/disable udc
* @_gadget: usb gadget
* @is_active: 0 if should disable the udc, 1 if should enable
*
* Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the
* udc, and deactivates D+ pullup resistor.
*
* Returns 0
*/
static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
{
struct pxa_udc *udc = to_gadget_udc(_gadget);
udc->vbus_sensed = is_active;
if (should_enable_udc(udc))
udc_enable(udc);
if (should_disable_udc(udc))
udc_disable(udc);
return 0;
}
/**
* pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed
* @_gadget: usb gadget
* @mA: current drawn
*
* Context: !in_interrupt()
*
* Called after a configuration was chosen by a USB host, to inform how much
* current can be drawn by the device from VBus line.
*
* Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc
*/
static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
{
struct pxa_udc *udc;
udc = to_gadget_udc(_gadget);
if (udc->transceiver)
return otg_set_power(udc->transceiver, mA);
return -EOPNOTSUPP;
}
static const struct usb_gadget_ops pxa_udc_ops = {
.get_frame = pxa_udc_get_frame,
.wakeup = pxa_udc_wakeup,
/* current versions must always be self-powered */
.pullup = pxa_udc_pullup,
.vbus_session = pxa_udc_vbus_session,
.vbus_draw = pxa_udc_vbus_draw,
};
/**
* udc_disable - disable udc device controller
* @udc: udc device
* Context: any
*
* Disables the udc device : disables clocks, udc interrupts, control endpoint
* interrupts.
*/
static void udc_disable(struct pxa_udc *udc)
{
if (!udc->enabled)
return;
udc_writel(udc, UDCICR0, 0);
udc_writel(udc, UDCICR1, 0);
@ -1523,8 +1668,8 @@ static void udc_disable(struct pxa_udc *udc)
ep0_idle(udc);
udc->gadget.speed = USB_SPEED_UNKNOWN;
if (udc->mach->udc_command)
udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
udc->enabled = 0;
}
/**
@ -1555,10 +1700,9 @@ static __init void udc_init_data(struct pxa_udc *dev)
}
/* USB endpoints init */
for (i = 0; i < NR_USB_ENDPOINTS; i++)
if (i != 0)
list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
&dev->gadget.ep_list);
for (i = 1; i < NR_USB_ENDPOINTS; i++)
list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list,
&dev->gadget.ep_list);
}
/**
@ -1570,6 +1714,9 @@ static __init void udc_init_data(struct pxa_udc *dev)
*/
static void udc_enable(struct pxa_udc *udc)
{
if (udc->enabled)
return;
udc_writel(udc, UDCICR0, 0);
udc_writel(udc, UDCICR1, 0);
udc_clear_mask_UDCCR(udc, UDCCR_UDE);
@ -1598,9 +1745,7 @@ static void udc_enable(struct pxa_udc *udc)
/* enable ep0 irqs */
pio_irq_enable(&udc->pxa_ep[0]);
dev_info(udc->dev, "UDC connecting\n");
if (udc->mach->udc_command)
udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
udc->enabled = 1;
}
/**
@ -1612,6 +1757,9 @@ static void udc_enable(struct pxa_udc *udc)
* usb traffic follows until a disconnect is reported. Then a host may connect
* again, or the driver might get unbound.
*
* Note that the udc is not automatically enabled. Check function
* should_enable_udc().
*
* Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise
*/
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
@ -1630,6 +1778,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* first hook up the driver ... */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
dplus_pullup(udc, 1);
retval = device_add(&udc->gadget.dev);
if (retval) {
@ -1645,9 +1794,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
dev_dbg(udc->dev, "registered gadget driver '%s'\n",
driver->driver.name);
udc_enable(udc);
if (udc->transceiver) {
retval = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (retval) {
dev_err(udc->dev, "can't bind to transceiver\n");
goto transceiver_fail;
}
}
if (should_enable_udc(udc))
udc_enable(udc);
return 0;
transceiver_fail:
if (driver->unbind)
driver->unbind(&udc->gadget);
bind_fail:
device_del(&udc->gadget.dev);
add_fail:
@ -1699,14 +1860,17 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
stop_activity(udc, driver);
udc_disable(udc);
dplus_pullup(udc, 0);
driver->unbind(&udc->gadget);
udc->driver = NULL;
device_del(&udc->gadget.dev);
dev_info(udc->dev, "unregistered gadget driver '%s'\n",
driver->driver.name);
if (udc->transceiver)
return otg_set_peripheral(udc->transceiver, NULL);
return 0;
}
EXPORT_SYMBOL(usb_gadget_unregister_driver);
@ -1823,14 +1987,14 @@ static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq)
struct pxa27x_request *req = NULL;
int completed = 0;
if (!list_empty(&ep->queue))
req = list_entry(ep->queue.next, struct pxa27x_request, queue);
udccsr0 = udc_ep_readl(ep, UDCCSR);
ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n",
EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR),
(fifo_irq << 1 | opc_irq));
if (!list_empty(&ep->queue))
req = list_entry(ep->queue.next, struct pxa27x_request, queue);
if (udccsr0 & UDCCSR0_SST) {
ep_dbg(ep, "clearing stall status\n");
nuke(ep, -EPIPE);
@ -2212,7 +2376,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct pxa_udc *udc = &memory;
int retval;
int retval = 0, gpio;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs)
@ -2223,6 +2387,20 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
udc->dev = &pdev->dev;
udc->mach = pdev->dev.platform_data;
udc->transceiver = otg_get_transceiver();
gpio = udc->mach->gpio_pullup;
if (gpio_is_valid(gpio)) {
retval = gpio_request(gpio, "USB D+ pullup");
if (retval == 0)
gpio_direction_output(gpio,
udc->mach->gpio_pullup_inverted);
}
if (retval) {
dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n",
gpio, retval);
return retval;
}
udc->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->clk)) {
@ -2240,6 +2418,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
device_initialize(&udc->gadget.dev);
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = NULL;
udc->vbus_sensed = 0;
the_controller = udc;
platform_set_drvdata(pdev, udc);
@ -2273,14 +2452,21 @@ err_clk:
static int __exit pxa_udc_remove(struct platform_device *_dev)
{
struct pxa_udc *udc = platform_get_drvdata(_dev);
int gpio = udc->mach->gpio_pullup;
usb_gadget_unregister_driver(udc->driver);
free_irq(udc->irq, udc);
pxa_cleanup_debugfs(udc);
if (gpio_is_valid(gpio))
gpio_free(gpio);
otg_put_transceiver(udc->transceiver);
udc->transceiver = NULL;
platform_set_drvdata(_dev, NULL);
the_controller = NULL;
clk_put(udc->clk);
iounmap(udc->regs);
return 0;
}
@ -2319,6 +2505,8 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
}
udc_disable(udc);
udc->pullup_resume = udc->pullup_on;
dplus_pullup(udc, 0);
return 0;
}
@ -2346,7 +2534,9 @@ static int pxa_udc_resume(struct platform_device *_dev)
ep->udccsr_value, ep->udccr_value);
}
udc_enable(udc);
dplus_pullup(udc, udc->pullup_resume);
if (should_enable_udc(udc))
udc_enable(udc);
/*
* We do not handle OTG yet.
*

Просмотреть файл

@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/usb/otg.h>
/*
* Register definitions
@ -421,10 +422,14 @@ struct udc_stats {
* @driver: bound gadget (zero, g_ether, g_file_storage, ...)
* @dev: device
* @mach: machine info, used to activate specific GPIO
* @transceiver: external transceiver to handle vbus sense and D+ pullup
* @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
* @enabled: UDC was enabled by a previous udc_enable()
* @pullup_on: if pullup resistor connected to D+ pin
* @pullup_resume: if pullup resistor should be connected to D+ pin on resume
* @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
@ -443,6 +448,7 @@ struct pxa_udc {
struct usb_gadget_driver *driver;
struct device *dev;
struct pxa2xx_udc_mach_info *mach;
struct otg_transceiver *transceiver;
enum ep0_state ep0state;
struct udc_stats stats;
@ -450,6 +456,10 @@ struct pxa_udc {
struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS];
struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS];
unsigned enabled:1;
unsigned pullup_on:1;
unsigned pullup_resume:1;
unsigned vbus_sensed:1;
unsigned config:2;
unsigned last_interface:3;
unsigned last_alternate:3;

Просмотреть файл

@ -87,12 +87,12 @@ static struct usb_gadget_strings *dev_strings[] = {
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
/* .bDeviceClass = f(use_acm) */
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
/* .bMaxPacketSize0 = f(hardware) */
.idVendor = __constant_cpu_to_le16(GS_VENDOR_ID),
.idVendor = cpu_to_le16(GS_VENDOR_ID),
/* .idProduct = f(use_acm) */
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
@ -216,7 +216,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
pr_warning("gs_bind: controller '%s' not recognized\n",
gadget->name);
device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM | 0x0099);
cpu_to_le16(GS_VERSION_NUM | 0x0099);
}
if (gadget_is_otg(cdev->gadget)) {
@ -255,19 +255,19 @@ static int __init init(void)
serial_config_driver.bConfigurationValue = 2;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
__constant_cpu_to_le16(GS_CDC_PRODUCT_ID);
cpu_to_le16(GS_CDC_PRODUCT_ID);
} else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
serial_config_driver.bConfigurationValue = 3;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
__constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
} else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idProduct =
__constant_cpu_to_le16(GS_PRODUCT_ID);
cpu_to_le16(GS_PRODUCT_ID);
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;

Просмотреть файл

@ -1092,7 +1092,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count)
gs_tty_driver->init_termios.c_ispeed = 9600;
gs_tty_driver->init_termios.c_ospeed = 9600;
coding.dwDTERate = __constant_cpu_to_le32(9600);
coding.dwDTERate = cpu_to_le32(9600);
coding.bCharFormat = 8;
coding.bParityType = USB_CDC_NO_PARITY;
coding.bDataBits = USB_CDC_1_STOP_BITS;

Просмотреть файл

@ -102,22 +102,32 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
#ifndef CONFIG_USB_ZERO_HNPTEST
#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */
#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */
#define DEFAULT_AUTORESUME 0
#else
#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */
#define DRIVER_PRODUCT_NUM 0xbadd
#define DEFAULT_AUTORESUME 5
#endif
/* If the optional "autoresume" mode is enabled, it provides good
* functional coverage for the "USBCV" test harness from USB-IF.
* It's always set if OTG mode is enabled.
*/
unsigned autoresume = DEFAULT_AUTORESUME;
module_param(autoresume, uint, S_IRUGO);
MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
/*-------------------------------------------------------------------------*/
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = 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 = cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
.bNumConfigurations = 2,
};
@ -212,6 +222,47 @@ void disable_endpoints(struct usb_composite_dev *cdev,
/*-------------------------------------------------------------------------*/
static struct timer_list autoresume_timer;
static void zero_autoresume(unsigned long _c)
{
struct usb_composite_dev *cdev = (void *)_c;
struct usb_gadget *g = cdev->gadget;
/* unconfigured devices can't issue wakeups */
if (!cdev->config)
return;
/* Normally the host would be woken up for something
* more significant than just a timer firing; likely
* because of some direct user request.
*/
if (g->speed != USB_SPEED_UNKNOWN) {
int status = usb_gadget_wakeup(g);
INFO(cdev, "%s --> %d\n", __func__, status);
}
}
static void zero_suspend(struct usb_composite_dev *cdev)
{
if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
return;
if (autoresume) {
mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
} else
DBG(cdev, "%s\n", __func__);
}
static void zero_resume(struct usb_composite_dev *cdev)
{
DBG(cdev, "%s\n", __func__);
del_timer(&autoresume_timer);
}
/*-------------------------------------------------------------------------*/
static int __init zero_bind(struct usb_composite_dev *cdev)
{
int gcnum;
@ -239,17 +290,19 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
strings_dev[STRING_SERIAL_IDX].id = id;
device_desc.iSerialNumber = id;
setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
/* Register primary, then secondary configuration. Note that
* SH3 only allows one config...
*/
if (loopdefault) {
loopback_add(cdev);
loopback_add(cdev, autoresume != 0);
if (!gadget_is_sh(gadget))
sourcesink_add(cdev);
sourcesink_add(cdev, autoresume != 0);
} else {
sourcesink_add(cdev);
sourcesink_add(cdev, autoresume != 0);
if (!gadget_is_sh(gadget))
loopback_add(cdev);
loopback_add(cdev, autoresume != 0);
}
gcnum = usb_gadget_controller_number(gadget);
@ -265,7 +318,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
*/
pr_warning("%s: controller '%s' not recognized\n",
longname, gadget->name);
device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
device_desc.bcdDevice = cpu_to_le16(0x9999);
}
@ -278,11 +331,20 @@ static int __init zero_bind(struct usb_composite_dev *cdev)
return 0;
}
static int zero_unbind(struct usb_composite_dev *cdev)
{
del_timer_sync(&autoresume_timer);
return 0;
}
static struct usb_composite_driver zero_driver = {
.name = "zero",
.dev = &device_desc,
.strings = dev_strings,
.bind = zero_bind,
.unbind = zero_unbind,
.suspend = zero_suspend,
.resume = zero_resume,
};
MODULE_AUTHOR("David Brownell");

Просмотреть файл

@ -24,10 +24,7 @@ config USB_EHCI_HCD
The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
"high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
If your USB host controller supports USB 2.0, you will likely want to
configure this Host Controller Driver. At the time of this writing,
the primary implementation of EHCI is a chip from NEC, widely available
in add-on PCI cards, but implementations are in the works from other
vendors including Intel and Philips. Motherboard support is appearing.
configure this Host Controller Driver.
EHCI controllers are packaged with "companion" host controllers (OHCI
or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports
@ -123,7 +120,7 @@ config USB_ISP116X_HCD
config USB_ISP1760_HCD
tristate "ISP 1760 HCD support"
depends on USB && EXPERIMENTAL && (PCI || PPC_OF)
depends on USB && EXPERIMENTAL
---help---
The ISP1760 chip is a USB 2.0 host controller.

Просмотреть файл

@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
/*-------------------------------------------------------------------------*/
static void
timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
{
/* Don't override timeouts which shrink or (later) disable
* the async ring; just the I/O watchdog. Note that if a
* SHRINK were pending, OFF would never be requested.
*/
if (timer_pending(&ehci->watchdog)
&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
& ehci->actions))
return;
if (!test_and_set_bit(action, &ehci->actions)) {
unsigned long t;
switch (action) {
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
break;
case TIMER_ASYNC_OFF:
t = EHCI_ASYNC_JIFFIES;
break;
/* case TIMER_ASYNC_SHRINK: */
default:
/* add a jiffie since we synch against the
* 8 KHz uframe counter.
*/
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
mod_timer(&ehci->watchdog, t + jiffies);
}
}
/*-------------------------------------------------------------------------*/
/*
* handshake - spin reading hc until handshake completes or fails
* @ptr: address of hc register to be read

Просмотреть файл

@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
token = hc32_to_cpu(ehci, qtd->hw_token);
/* always clean up qtds the hc de-activated */
retry_xacterr:
if ((token & QTD_STS_ACTIVE) == 0) {
/* on STALL, error, and short reads this urb must
* complete and all its qtds must be recycled.
*/
if ((token & QTD_STS_HALT) != 0) {
/* retry transaction errors until we
* reach the software xacterr limit
*/
if ((token & QTD_STS_XACT) &&
QTD_CERR(token) == 0 &&
--qh->xacterrs > 0 &&
!urb->unlinked) {
ehci_dbg(ehci,
"detected XactErr len %zu/%zu retry %d\n",
qtd->length - QTD_LENGTH(token), qtd->length,
QH_XACTERR_MAX - qh->xacterrs);
/* reset the token in the qtd and the
* qh overlay (which still contains
* the qtd) so that we pick up from
* where we left off
*/
token &= ~QTD_STS_HALT;
token |= QTD_STS_ACTIVE |
(EHCI_TUNE_CERR << 10);
qtd->hw_token = cpu_to_hc32(ehci,
token);
wmb();
qh->hw_token = cpu_to_hc32(ehci, token);
goto retry_xacterr;
}
stopped = 1;
/* magic dummy for some short reads; qh won't advance.
@ -421,6 +449,9 @@ halt:
/* remove qtd; it's recycled after possible urb completion */
list_del (&qtd->qtd_list);
last = qtd;
/* reinit the xacterr counter for the next qtd */
qh->xacterrs = QH_XACTERR_MAX;
}
/* last urb's completion might still need calling */
@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
head->qh_next.qh = qh;
head->hw_next = dma;
qh->xacterrs = QH_XACTERR_MAX;
qh->qh_state = QH_STATE_LINKED;
/* qtd completions reported later by interrupt */
}

Просмотреть файл

@ -563,7 +563,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
// and this qh is active in the current uframe
// (and overlay token SplitXstate is false?)
// THEN
// qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */);
// qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */);
/* high bandwidth, or otherwise part of every microframe */
if ((period = qh->period) == 0)

Просмотреть файл

@ -190,40 +190,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action)
clear_bit (action, &ehci->actions);
}
static inline void
timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
{
/* Don't override timeouts which shrink or (later) disable
* the async ring; just the I/O watchdog. Note that if a
* SHRINK were pending, OFF would never be requested.
*/
if (timer_pending(&ehci->watchdog)
&& ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
& ehci->actions))
return;
if (!test_and_set_bit (action, &ehci->actions)) {
unsigned long t;
switch (action) {
case TIMER_IO_WATCHDOG:
t = EHCI_IO_JIFFIES;
break;
case TIMER_ASYNC_OFF:
t = EHCI_ASYNC_JIFFIES;
break;
// case TIMER_ASYNC_SHRINK:
default:
/* add a jiffie since we synch against the
* 8 KHz uframe counter.
*/
t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1;
break;
}
mod_timer(&ehci->watchdog, t + jiffies);
}
}
static void free_cached_itd_list(struct ehci_hcd *ehci);
/*-------------------------------------------------------------------------*/
@ -287,7 +253,7 @@ struct ehci_qtd {
/*
* Now the following defines are not converted using the
* __constant_cpu_to_le32() macro anymore, since we have to support
* cpu_to_le32() macro anymore, since we have to support
* "dynamic" switching between be and le support, so that the driver
* can be used on one system with SoC EHCI controller using big-endian
* descriptors as well as a normal little-endian PCI EHCI controller.
@ -376,6 +342,9 @@ struct ehci_qh {
#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */
#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
u8 xacterrs; /* XactErr retry counter */
#define QH_XACTERR_MAX 32 /* XactErr retry limit */
/* periodic schedule info */
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */

Просмотреть файл

@ -464,8 +464,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid,
port_idx << 8 | iface_no,
keyd, keyd_len, 1000 /* FIXME: arbitrary */);
memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */
kfree(keyd);
kzfree(keyd); /* clear keys etc. */
return result;
}

Просмотреть файл

@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
break;
case PIPE_INTERRUPT:
urb->interval = ep->period;
ep->length = min((int)ep->maxpacket,
ep->length = min_t(u32, ep->maxpacket,
urb->transfer_buffer_length);
/* urb submitted for already existing endpoint */

Просмотреть файл

@ -563,7 +563,7 @@ static void urb_dbg(struct urb *urb, char *msg)
*/
static inline void dump_ptd(struct ptd *ptd)
{
printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n",
printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d %x %x%x%x\n",
PTD_GET_CC(ptd), PTD_GET_FA(ptd),
PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
@ -576,7 +576,7 @@ static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf)
int k;
if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) {
printk("-> ");
printk(KERN_WARNING "-> ");
for (k = 0; k < PTD_GET_LEN(ptd); ++k)
printk("%02x ", ((u8 *) buf)[k]);
printk("\n");
@ -588,13 +588,13 @@ static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf)
int k;
if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) {
printk("<- ");
printk(KERN_WARNING "<- ");
for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
printk("%02x ", ((u8 *) buf)[k]);
printk("\n");
}
if (PTD_GET_LAST(ptd))
printk("-\n");
printk(KERN_WARNING "-\n");
}
#else

Просмотреть файл

@ -644,7 +644,7 @@ static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
if (urb->dev->speed != USB_SPEED_HIGH) {
/* split */
ptd->dw5 = __constant_cpu_to_le32(0x1c);
ptd->dw5 = cpu_to_le32(0x1c);
if (qh->period >= 32)
period = qh->period / 2;
@ -819,6 +819,13 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
u32 atl_regs, payload;
u32 buffstatus;
/*
* When this function is called from the interrupt handler to enqueue
* a follow-up packet, the SKIP register gets written and read back
* almost immediately. With ISP1761, this register requires a delay of
* 195ns between a write and subsequent read (see section 15.1.1.3).
*/
ndelay(195);
skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
BUG_ON(!skip_map);
@ -853,6 +860,13 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
u32 int_regs, payload;
u32 buffstatus;
/*
* When this function is called from the interrupt handler to enqueue
* a follow-up packet, the SKIP register gets written and read back
* almost immediately. With ISP1761, this register requires a delay of
* 195ns between a write and subsequent read (see section 15.1.1.3).
*/
ndelay(195);
skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
BUG_ON(!skip_map);
@ -1054,7 +1068,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
atl_regs, sizeof(ptd));
ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID);
ptd.dw0 |= cpu_to_le32(PTD_VALID);
priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
atl_regs, sizeof(ptd));
@ -2235,9 +2249,10 @@ void deinit_kmem_cache(void)
kmem_cache_destroy(qh_cachep);
}
struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq,
u64 irqflags, struct device *dev, const char *busname,
unsigned int devflags)
struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
int irq, unsigned long irqflags,
struct device *dev, const char *busname,
unsigned int devflags)
{
struct usb_hcd *hcd;
struct isp1760_hcd *priv;

Просмотреть файл

@ -2,9 +2,10 @@
#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,
unsigned int devflags);
struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len,
int irq, unsigned long irqflags,
struct device *dev, const char *busname,
unsigned int devflags);
int init_kmem_once(void);
void deinit_kmem_cache(void);

Просмотреть файл

@ -10,6 +10,7 @@
#include <linux/usb.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include "../core/hcd.h"
#include "isp1760-hcd.h"
@ -300,39 +301,101 @@ static struct pci_driver isp1761_pci_driver = {
};
#endif
static int __devinit isp1760_plat_probe(struct platform_device *pdev)
{
int ret = 0;
struct usb_hcd *hcd;
struct resource *mem_res;
struct resource *irq_res;
resource_size_t mem_size;
unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_res) {
pr_warning("isp1760: Memory resource not available\n");
ret = -ENODEV;
goto out;
}
mem_size = resource_size(mem_res);
if (!request_mem_region(mem_res->start, mem_size, "isp1760")) {
pr_warning("isp1760: Cannot reserve the memory resource\n");
ret = -EBUSY;
goto out;
}
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq_res) {
pr_warning("isp1760: IRQ resource not available\n");
return -ENODEV;
}
irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
irqflags, &pdev->dev, dev_name(&pdev->dev), 0);
if (IS_ERR(hcd)) {
pr_warning("isp1760: Failed to register the HCD device\n");
ret = -ENODEV;
goto cleanup;
}
pr_info("ISP1760 USB device initialised\n");
return ret;
cleanup:
release_mem_region(mem_res->start, mem_size);
out:
return ret;
}
static int __devexit isp1760_plat_remove(struct platform_device *pdev)
{
struct resource *mem_res;
resource_size_t mem_size;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
mem_size = resource_size(mem_res);
release_mem_region(mem_res->start, mem_size);
return 0;
}
static struct platform_driver isp1760_plat_driver = {
.probe = isp1760_plat_probe,
.remove = isp1760_plat_remove,
.driver = {
.name = "isp1760",
},
};
static int __init isp1760_init(void)
{
int ret;
int ret, any_ret = -ENODEV;
init_kmem_once();
ret = platform_driver_register(&isp1760_plat_driver);
if (!ret)
any_ret = 0;
#ifdef CONFIG_PPC_OF
ret = of_register_platform_driver(&isp1760_of_driver);
if (ret) {
deinit_kmem_cache();
return ret;
}
if (!ret)
any_ret = 0;
#endif
#ifdef CONFIG_PCI
ret = pci_register_driver(&isp1761_pci_driver);
if (ret)
goto unreg_of;
if (!ret)
any_ret = 0;
#endif
return ret;
#ifdef CONFIG_PCI
unreg_of:
#endif
#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif
deinit_kmem_cache();
return ret;
if (any_ret)
deinit_kmem_cache();
return any_ret;
}
module_init(isp1760_init);
static void __exit isp1760_exit(void)
{
platform_driver_unregister(&isp1760_plat_driver);
#ifdef CONFIG_PPC_OF
of_unregister_platform_driver(&isp1760_of_driver);
#endif

Просмотреть файл

@ -997,7 +997,7 @@ MODULE_LICENSE ("GPL");
#define SA1111_DRIVER ohci_hcd_sa1111_driver
#endif
#ifdef CONFIG_ARCH_S3C2410
#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX)
#include "ohci-s3c2410.c"
#define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
#endif

Просмотреть файл

@ -21,9 +21,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <mach/hardware.h>
#include <mach/usb-control.h>
#include <plat/usb-control.h>
#define valid_port(idx) ((idx) == 1 || (idx) == 2)
@ -372,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
usb_clk = clk_get(&dev->dev, "usb-bus-host");
if (IS_ERR(usb_clk)) {
dev_err(&dev->dev, "cannot get usb-host clock\n");
dev_err(&dev->dev, "cannot get usb-bus-host clock\n");
retval = -ENOENT;
goto err_clk;
}

Просмотреть файл

@ -845,14 +845,14 @@ static inline void qh_update(struct oxu_hcd *oxu,
is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) {
qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE);
qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE);
usb_settoggle(qh->dev, epnum, is_out, 1);
}
}
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
wmb();
qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING);
qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING);
}
/* If it weren't for a common silicon quirk (writing the dummy into the qh
@ -937,7 +937,7 @@ __acquires(oxu->lock)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
/* S-mask in a QH means it's an interrupt urb */
if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) {
if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) {
/* ... update hc-wide periodic stats (for usbfs) */
oxu_to_hcd(oxu)->self.bandwidth_int_reqs--;
@ -981,7 +981,7 @@ static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh);
static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh);
static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh);
#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
#define HALT_BIT cpu_to_le32(QTD_STS_HALT)
/* Process and free completed qtds for a qh, returning URBs to drivers.
* Chases up to qh->hw_current. Returns number of completions called,
@ -1160,7 +1160,7 @@ halt:
/* should be rare for periodic transfers,
* except maybe high bandwidth ...
*/
if ((__constant_cpu_to_le32(QH_SMASK)
if ((cpu_to_le32(QH_SMASK)
& qh->hw_info2) != 0) {
intr_deschedule(oxu, qh);
(void) qh_schedule(oxu, qh);
@ -1350,7 +1350,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu,
}
/* by default, enable interrupt on urb completion */
qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC);
qtd->hw_token |= cpu_to_le32(QTD_IOC);
return head;
cleanup:
@ -1539,7 +1539,7 @@ static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh)
/* qtd completions reported later by interrupt */
}
#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f)
#define QH_ADDR_MASK cpu_to_le32(0x7f)
/*
* For control/bulk/interrupt, return QH with these TDs appended.
@ -2012,7 +2012,7 @@ static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh)
* and this qh is active in the current uframe
* (and overlay token SplitXstate is false?)
* THEN
* qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore");
* qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore");
*/
/* high bandwidth, or otherwise part of every microframe */
@ -2057,7 +2057,7 @@ static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh)
* active high speed queues may need bigger delays...
*/
if (list_empty(&qh->qtd_list)
|| (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0)
|| (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0)
wait = 2;
else
wait = 55; /* worst case: 3 * 1024 */
@ -2183,10 +2183,10 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK));
qh->hw_info2 |= qh->period
? cpu_to_le32(1 << uframe)
: __constant_cpu_to_le32(QH_SMASK);
: cpu_to_le32(QH_SMASK);
qh->hw_info2 |= c_mask;
} else
oxu_dbg(oxu, "reused qh %p schedule\n", qh);
@ -2684,7 +2684,7 @@ static int oxu_reset(struct usb_hcd *hcd)
oxu->urb_len = 0;
/* FIMXE */
hcd->self.controller->dma_mask = 0UL;
hcd->self.controller->dma_mask = NULL;
if (oxu->is_otg) {
oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET;

Просмотреть файл

@ -235,21 +235,21 @@ struct ehci_qtd {
} __attribute__ ((aligned(32)));
/* mask NakCnt+T in qh->hw_alt_next */
#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
#define QTD_MASK cpu_to_le32 (~0x1f)
#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1)
/* Type tag from {qh, itd, sitd, fstn}->hw_next */
#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1))
/* values for that type tag */
#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1)
#define Q_TYPE_QH cpu_to_le32 (1 << 1)
/* next async queue entry, or pointer to interrupt/periodic QH */
#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
/* for periodic/async schedules and qtd lists, mark end of list */
#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */
#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */
/*
* Entries in periodic shadow table are pointers to one of four kinds

Просмотреть файл

@ -234,7 +234,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
*/
hcc_params = readl(base + EHCI_HCC_PARAMS);
offset = (hcc_params >> 8) & 0xff;
while (offset && count--) {
while (offset && --count) {
u32 cap;
int msec;

Просмотреть файл

@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
memset(array, 0, sizeof(array));
switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
switch (usb_endpoint_type(ep)) {
case USB_ENDPOINT_XFER_BULK:
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
if (usb_endpoint_dir_in(ep))
array[i++] = 4;
else {
array[i++] = 3;
@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
}
break;
case USB_ENDPOINT_XFER_INT:
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
if (usb_endpoint_dir_in(ep)) {
array[i++] = 6;
array[i++] = 7;
array[i++] = 8;
@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
array[i++] = 9;
break;
case USB_ENDPOINT_XFER_ISOC:
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
if (usb_endpoint_dir_in(ep))
array[i++] = 2;
else
array[i++] = 1;
@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
info.pipenum = get_empty_pipenum(r8a66597, ep);
info.address = get_urb_to_r8a66597_addr(r8a66597, urb);
info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
info.epnum = usb_endpoint_num(ep);
info.maxpacket = le16_to_cpu(ep->wMaxPacketSize);
info.type = get_r8a66597_type(ep->bmAttributes
& USB_ENDPOINT_XFERTYPE_MASK);
info.type = get_r8a66597_type(usb_endpoint_type(ep));
info.bufnum = get_bufnum(info.pipenum);
info.buf_bsize = get_buf_bsize(info.pipenum);
if (info.type == R8A66597_BULK) {
@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
info.interval = get_interval(urb, ep->bInterval);
info.timer_interval = get_timer_interval(urb, ep->bInterval);
}
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
if (usb_endpoint_dir_in(ep))
info.dir_in = 1;
else
info.dir_in = 0;
@ -1014,6 +1013,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
if (r8a66597->bus_suspended)
usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
}
/* this function must be called with interrupt disabled */
@ -1395,7 +1397,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
(int)urb->iso_frame_desc[td->iso_cnt].length);
} else {
buf = (u16 *)(urb->transfer_buffer + urb->actual_length);
size = min((int)bufsize,
size = min_t(u32, bufsize,
urb->transfer_buffer_length - urb->actual_length);
}
@ -1615,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
r8a66597_bclr(r8a66597, DTCHE, INTENB2);
r8a66597_usb_disconnect(r8a66597, 1);
}
if (mask2 & BCHG) {
r8a66597_write(r8a66597, ~BCHG, INTSTS2);
r8a66597_bclr(r8a66597, BCHGE, INTENB2);
usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
}
}
if (mask1) {
@ -1630,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
r8a66597_bclr(r8a66597, DTCHE, INTENB1);
r8a66597_usb_disconnect(r8a66597, 0);
}
if (mask1 & BCHG) {
r8a66597_write(r8a66597, ~BCHG, INTSTS1);
r8a66597_bclr(r8a66597, BCHGE, INTENB1);
usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
}
if (mask1 & SIGN) {
r8a66597_write(r8a66597, ~SIGN, INTSTS1);
status = get_urb_error(r8a66597, 0);
@ -2141,7 +2154,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
switch (wValue) {
case USB_PORT_FEAT_ENABLE:
rh->port &= (1 << USB_PORT_FEAT_POWER);
rh->port &= ~(1 << USB_PORT_FEAT_POWER);
break;
case USB_PORT_FEAT_SUSPEND:
break;
@ -2213,6 +2226,68 @@ error:
return ret;
}
#if defined(CONFIG_PM)
static int r8a66597_bus_suspend(struct usb_hcd *hcd)
{
struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
int port;
dbg("%s", __func__);
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
unsigned long dvstctr_reg = get_dvstctr_reg(port);
if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE)))
continue;
dbg("suspend port = %d", port);
r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */
rh->port |= 1 << USB_PORT_FEAT_SUSPEND;
if (rh->dev->udev->do_remote_wakeup) {
msleep(3); /* waiting last SOF */
r8a66597_bset(r8a66597, RWUPE, dvstctr_reg);
r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port));
r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port));
}
}
r8a66597->bus_suspended = 1;
return 0;
}
static int r8a66597_bus_resume(struct usb_hcd *hcd)
{
struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
int port;
dbg("%s", __func__);
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
unsigned long dvstctr_reg = get_dvstctr_reg(port);
if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND)))
continue;
dbg("resume port = %d", port);
rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND);
rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND;
r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg);
msleep(50);
r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg);
}
return 0;
}
#else
#define r8a66597_bus_suspend NULL
#define r8a66597_bus_resume NULL
#endif
static struct hc_driver r8a66597_hc_driver = {
.description = hcd_name,
.hcd_priv_size = sizeof(struct r8a66597),
@ -2243,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driver = {
*/
.hub_status_data = r8a66597_hub_status_data,
.hub_control = r8a66597_hub_control,
.bus_suspend = r8a66597_bus_suspend,
.bus_resume = r8a66597_bus_resume,
};
#if defined(CONFIG_PM)
static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
{
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
int port;
dbg("%s", __func__);
disable_controller(r8a66597);
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
rh->port = 0x00000000;
}
return 0;
}
static int r8a66597_resume(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
dbg("%s", __func__);
enable_controller(r8a66597);
usb_root_hub_lost_power(hcd->self.root_hub);
return 0;
}
#else /* if defined(CONFIG_PM) */

Просмотреть файл

@ -504,6 +504,8 @@ struct r8a66597 {
struct list_head child_device;
unsigned long child_connect_map[4];
unsigned bus_suspended:1;
};
static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)

Просмотреть файл

@ -230,7 +230,7 @@ static void in_packet(
writeb(usb_pipedevice(urb->pipe), data_reg);
sl811_write(sl811, bank + SL11H_HOSTCTLREG, control);
ep->length = min((int)len,
ep->length = min_t(u32, len,
urb->transfer_buffer_length - urb->actual_length);
PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "",
!!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len);
@ -255,7 +255,7 @@ static void out_packet(
buf = urb->transfer_buffer + urb->actual_length;
prefetch(buf);
len = min((int)ep->maxpacket,
len = min_t(u32, ep->maxpacket,
urb->transfer_buffer_length - urb->actual_length);
if (!(control & SL11H_HCTLMASK_ISOCH)

Просмотреть файл

@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space)
}
out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length,
(urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ?
"-8" : ""));
if (urbp->urb->unlinked)
out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked);

Просмотреть файл

@ -73,11 +73,11 @@
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F)
#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001)
#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002)
#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004)
#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000)
#define UHCI_PTR_BITS cpu_to_le32(0x000F)
#define UHCI_PTR_TERM cpu_to_le32(0x0001)
#define UHCI_PTR_QH cpu_to_le32(0x0002)
#define UHCI_PTR_DEPTH cpu_to_le32(0x0004)
#define UHCI_PTR_BREADTH cpu_to_le32(0x0000)
#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */
#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */

Просмотреть файл

@ -402,7 +402,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first)
/* Otherwise all the toggles in the URB have to be switched */
} else {
list_for_each_entry(td, &urbp->td_list, list) {
td->token ^= __constant_cpu_to_le32(
td->token ^= cpu_to_le32(
TD_TOKEN_TOGGLE);
toggle ^= 1;
}
@ -883,7 +883,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
wmb();
qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
qh->dummy_td = td;
/* Low-speed transfers get a different queue, and won't hog the bus.
@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
}
if (qh->state != QH_STATE_ACTIVE)
qh->skel = skel;
urb->actual_length = -8; /* Account for the SETUP packet */
return 0;
nomem:
@ -1003,7 +1001,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
* fast side but not enough to justify delaying an interrupt
* more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
* flag setting. */
td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
td->status |= cpu_to_le32(TD_CTRL_IOC);
/*
* Build the new dummy TD and activate the old one
@ -1015,7 +1013,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0);
wmb();
qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE);
qh->dummy_td = td;
usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
@ -1317,7 +1315,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
}
/* Set the interrupt-on-completion flag on the last packet. */
td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
td->status |= cpu_to_le32(TD_CTRL_IOC);
/* Add the TDs to the frame list */
frame = urb->start_frame;
@ -1494,11 +1492,10 @@ __acquires(uhci->lock)
if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
/* urb->actual_length < 0 means the setup transaction didn't
* complete successfully. Either it failed or the URB was
* unlinked first. Regardless, don't confuse people with a
* negative length. */
urb->actual_length = max(urb->actual_length, 0);
/* Subtract off the length of the SETUP packet from
* urb->actual_length.
*/
urb->actual_length -= min_t(u32, 8, urb->actual_length);
}
/* When giving back the first URB in an Isochronous queue,

Просмотреть файл

@ -188,7 +188,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] =
.bDescriptorType = 0,
.bEndpointAddress = 0x01,
.bmAttributes = 0x02,
.wMaxPacketSize = __constant_cpu_to_le16(8),
.wMaxPacketSize = cpu_to_le16(8),
.bInterval = 0,
.bRefresh = 0,
.bSynchAddress = 0,
@ -198,7 +198,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] =
.bDescriptorType = 0,
.bEndpointAddress = 0x82,
.bmAttributes = 0x03,
.wMaxPacketSize = __constant_cpu_to_le16(8),
.wMaxPacketSize = cpu_to_le16(8),
.bInterval = 0,
.bRefresh = 0,
.bSynchAddress = 0,
@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] =
.bDescriptorType = 0,
.bEndpointAddress = 0x03,
.bmAttributes = 0x02,
.wMaxPacketSize = __constant_cpu_to_le16(64),
.wMaxPacketSize = cpu_to_le16(64),
.bInterval = 0,
.bRefresh = 0,
.bSynchAddress = 0,
@ -218,7 +218,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] =
.bDescriptorType = 0,
.bEndpointAddress = 0x84,
.bmAttributes = 0x02,
.wMaxPacketSize = __constant_cpu_to_le16(64),
.wMaxPacketSize = cpu_to_le16(64),
.bInterval = 0,
.bRefresh = 0,
.bSynchAddress = 0,

Просмотреть файл

@ -135,45 +135,6 @@ config USB_CYTHERM
To compile this driver as a module, choose M here: the
module will be called cytherm.
config USB_PHIDGET
tristate "USB Phidgets drivers"
depends on USB
help
Say Y here to enable the various drivers for devices from
Phidgets inc.
config USB_PHIDGETKIT
tristate "USB PhidgetInterfaceKit support"
depends on USB_PHIDGET
help
Say Y here if you want to connect a PhidgetInterfaceKit USB device
from Phidgets Inc.
To compile this driver as a module, choose M here: the
module will be called phidgetkit.
config USB_PHIDGETMOTORCONTROL
tristate "USB PhidgetMotorControl support"
depends on USB_PHIDGET
help
Say Y here if you want to connect a PhidgetMotorControl USB device
from Phidgets Inc.
To compile this driver as a module, choose M here: the
module will be called phidgetmotorcontrol.
config USB_PHIDGETSERVO
tristate "USB PhidgetServo support"
depends on USB_PHIDGET
help
Say Y here if you want to connect an 1 or 4 Motor PhidgetServo
servo controller version 2.0 or 3.0.
Phidgets Inc. has a web page at <http://www.phidgets.com/>.
To compile this driver as a module, choose M here: the
module will be called phidgetservo.
config USB_IDMOUSE
tristate "Siemens ID USB Mouse Fingerprint sensor support"
depends on USB

Просмотреть файл

@ -18,10 +18,6 @@ obj-$(CONFIG_USB_LCD) += usblcd.o
obj-$(CONFIG_USB_LD) += ldusb.o
obj-$(CONFIG_USB_LED) += usbled.o
obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
obj-$(CONFIG_USB_PHIDGET) += phidget.o
obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o
obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o

Просмотреть файл

@ -1568,7 +1568,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
struct u132_target *target = &ftdi->target[ed];
struct u132_command *command = &ftdi->command[
COMMAND_MASK & ftdi->command_next];
int remaining_length = urb->transfer_buffer_length -
u32 remaining_length = urb->transfer_buffer_length -
urb->actual_length;
command->header = 0x82 | (ed << 5);
if (remaining_length == 0) {
@ -1702,7 +1702,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
| (address << 0);
command->width = usb_maxpacket(urb->dev, urb->pipe,
usb_pipeout(urb->pipe));
command->follows = min(1024,
command->follows = min_t(u32, 1024,
urb->transfer_buffer_length -
urb->actual_length);
command->value = 0;
@ -1766,7 +1766,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
mutex_lock(&ftdi->u132_lock);
command_size = ftdi->command_next - ftdi->command_head;
if (command_size < COMMAND_SIZE) {
int remaining_length = urb->transfer_buffer_length -
u32 remaining_length = urb->transfer_buffer_length -
urb->actual_length;
struct u132_target *target = &ftdi->target[ed];
struct u132_command *command = &ftdi->command[

Просмотреть файл

@ -1,43 +0,0 @@
/*
* USB Phidgets class
*
* Copyright (C) 2006 Sean Young <sean@mess.org>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/device.h>
struct class *phidget_class;
static int __init init_phidget(void)
{
phidget_class = class_create(THIS_MODULE, "phidget");
if (IS_ERR(phidget_class))
return PTR_ERR(phidget_class);
return 0;
}
static void __exit cleanup_phidget(void)
{
class_destroy(phidget_class);
}
EXPORT_SYMBOL_GPL(phidget_class);
module_init(init_phidget);
module_exit(cleanup_phidget);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sean Young <sean@mess.org>");
MODULE_DESCRIPTION("Container module for phidget class");

Просмотреть файл

@ -1,12 +0,0 @@
/*
* USB Phidgets class
*
* Copyright (C) 2006 Sean Young <sean@mess.org>
*
* 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.
*/
extern struct class *phidget_class;

Просмотреть файл

@ -1,740 +0,0 @@
/*
* USB PhidgetInterfaceKit driver 1.0
*
* Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
* Copyright (C) 2005 Daniel Saakes <daniel@saakes.net>
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This is a driver for the USB PhidgetInterfaceKit.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "phidget.h"
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_INTERFACEKIT004 0x0040
#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044
#define USB_DEVICE_ID_INTERFACEKIT888 0x0045
#define USB_DEVICE_ID_INTERFACEKIT047 0x0051
#define USB_DEVICE_ID_INTERFACEKIT088 0x0053
#define USB_VENDOR_ID_WISEGROUP 0x0925
#define USB_DEVICE_ID_INTERFACEKIT884 0x8201
#define MAX_INTERFACES 16
#define URB_INT_SIZE 8
struct driver_interfacekit {
int sensors;
int inputs;
int outputs;
int has_lcd;
int amnesiac;
};
#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \
{ \
.sensors = _sensors, \
.inputs = _inputs, \
.outputs = _outputs, \
.has_lcd = _lcd, \
.amnesiac = _amnesiac \
};
static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0);
static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1);
static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0);
static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0);
static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0);
static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0);
static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0);
static unsigned long device_no;
struct interfacekit {
struct usb_device *udev;
struct usb_interface *intf;
struct driver_interfacekit *ifkit;
struct device *dev;
unsigned long outputs;
int dev_no;
u8 inputs[MAX_INTERFACES];
u16 sensors[MAX_INTERFACES];
u8 lcd_files_on;
struct urb *irq;
unsigned char *data;
dma_addr_t data_dma;
struct delayed_work do_notify;
struct delayed_work do_resubmit;
unsigned long input_events;
unsigned long sensor_events;
};
static struct usb_device_id id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004),
.driver_info = (kernel_ulong_t)&ph_004},
{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814),
.driver_info = (kernel_ulong_t)&ph_888o},
{USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff),
.driver_info = (kernel_ulong_t)&ph_888n},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047),
.driver_info = (kernel_ulong_t)&ph_047},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
.driver_info = (kernel_ulong_t)&ph_088},
{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616),
.driver_info = (kernel_ulong_t)&ph_01616},
{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
.driver_info = (kernel_ulong_t)&ph_884},
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
static int set_outputs(struct interfacekit *kit)
{
u8 *buffer;
int retval;
buffer = kzalloc(4, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
buffer[0] = (u8)kit->outputs;
buffer[1] = (u8)(kit->outputs >> 8);
dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs);
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000);
if (retval != 4)
dev_err(&kit->udev->dev, "usb_control_msg returned %d\n",
retval);
kfree(buffer);
if (kit->ifkit->amnesiac)
schedule_delayed_work(&kit->do_resubmit, HZ / 2);
return retval < 0 ? retval : 0;
}
static int change_string(struct interfacekit *kit, const char *display, unsigned char row)
{
unsigned char *buffer;
unsigned char *form_buffer;
int retval = -ENOMEM;
int i,j, len, buf_ptr;
buffer = kmalloc(8, GFP_KERNEL);
form_buffer = kmalloc(30, GFP_KERNEL);
if ((!buffer) || (!form_buffer)) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
goto exit;
}
len = strlen(display);
if (len > 20)
len = 20;
dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display);
form_buffer[0] = row * 0x40 + 0x80;
form_buffer[1] = 0x02;
buf_ptr = 2;
for (i = 0; i<len; i++)
form_buffer[buf_ptr++] = display[i];
for (i = 0; i < (20 - len); i++)
form_buffer[buf_ptr++] = 0x20;
form_buffer[buf_ptr++] = 0x01;
form_buffer[buf_ptr++] = row * 0x40 + 0x80 + strlen(display);
for (i = 0; i < buf_ptr; i += 7) {
if ((buf_ptr - i) > 7)
len = 7;
else
len = (buf_ptr - i);
for (j = 0; j < len; j++)
buffer[j] = form_buffer[i + j];
buffer[7] = len;
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
}
retval = 0;
exit:
kfree(buffer);
kfree(form_buffer);
return retval;
}
#define set_lcd_line(number) \
static ssize_t lcd_line_##number(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct interfacekit *kit = dev_get_drvdata(dev); \
change_string(kit, buf, number - 1); \
return count; \
}
#define lcd_line_attr(number) \
__ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number)
set_lcd_line(1);
set_lcd_line(2);
static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct interfacekit *kit = dev_get_drvdata(dev);
int enabled;
unsigned char *buffer;
int retval = -ENOMEM;
buffer = kzalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&kit->udev->dev, "%s - out of memory\n", __func__);
goto exit;
}
if (sscanf(buf, "%d", &enabled) < 1) {
retval = -EINVAL;
goto exit;
}
if (enabled)
buffer[0] = 0x01;
buffer[7] = 0x11;
dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off");
retval = usb_control_msg(kit->udev,
usb_sndctrlpipe(kit->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval < 0)
goto exit;
retval = count;
exit:
kfree(buffer);
return retval;
}
static struct device_attribute dev_lcd_line_attrs[] = {
lcd_line_attr(1),
lcd_line_attr(2),
__ATTR(backlight, S_IWUGO, NULL, set_backlight)
};
static void remove_lcd_files(struct interfacekit *kit)
{
int i;
if (kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Removing lcd files\n");
for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++)
device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
}
}
static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct interfacekit *kit = dev_get_drvdata(dev);
int enable;
int i, rc;
if (kit->ifkit->has_lcd == 0)
return -ENODEV;
if (sscanf(buf, "%d", &enable) < 1)
return -EINVAL;
if (enable) {
if (!kit->lcd_files_on) {
dev_dbg(&kit->udev->dev, "Adding lcd files\n");
for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) {
rc = device_create_file(kit->dev,
&dev_lcd_line_attrs[i]);
if (rc)
goto out;
}
kit->lcd_files_on = 1;
}
} else {
if (kit->lcd_files_on) {
remove_lcd_files(kit);
kit->lcd_files_on = 0;
}
}
return count;
out:
while (i-- > 0)
device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
return rc;
}
static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
static void interfacekit_irq(struct urb *urb)
{
struct interfacekit *kit = urb->context;
unsigned char *buffer = kit->data;
int i, level, sensor;
int retval;
int status = urb->status;
switch (status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default: /* error */
goto resubmit;
}
/* digital inputs */
if (kit->ifkit->inputs == 16) {
for (i=0; i < 8; i++) {
level = (buffer[0] >> i) & 1;
if (kit->inputs[i] != level) {
kit->inputs[i] = level;
set_bit(i, &kit->input_events);
}
level = (buffer[1] >> i) & 1;
if (kit->inputs[8 + i] != level) {
kit->inputs[8 + i] = level;
set_bit(8 + i, &kit->input_events);
}
}
}
else if (kit->ifkit->inputs == 8) {
for (i=0; i < 8; i++) {
level = (buffer[1] >> i) & 1;
if (kit->inputs[i] != level) {
kit->inputs[i] = level;
set_bit(i, &kit->input_events);
}
}
}
/* analog inputs */
if (kit->ifkit->sensors) {
sensor = (buffer[0] & 1) ? 4 : 0;
level = buffer[2] + (buffer[3] & 0x0f) * 256;
if (level != kit->sensors[sensor]) {
kit->sensors[sensor] = level;
set_bit(sensor, &kit->sensor_events);
}
sensor++;
level = buffer[4] + (buffer[3] & 0xf0) * 16;
if (level != kit->sensors[sensor]) {
kit->sensors[sensor] = level;
set_bit(sensor, &kit->sensor_events);
}
sensor++;
level = buffer[5] + (buffer[6] & 0x0f) * 256;
if (level != kit->sensors[sensor]) {
kit->sensors[sensor] = level;
set_bit(sensor, &kit->sensor_events);
}
sensor++;
level = buffer[7] + (buffer[6] & 0xf0) * 16;
if (level != kit->sensors[sensor]) {
kit->sensors[sensor] = level;
set_bit(sensor, &kit->sensor_events);
}
}
if (kit->input_events || kit->sensor_events)
schedule_delayed_work(&kit->do_notify, 0);
resubmit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
err("can't resubmit intr, %s-%s/interfacekit0, retval %d",
kit->udev->bus->bus_name,
kit->udev->devpath, retval);
}
static void do_notify(struct work_struct *work)
{
struct interfacekit *kit =
container_of(work, struct interfacekit, do_notify.work);
int i;
char sysfs_file[8];
for (i=0; i<kit->ifkit->inputs; i++) {
if (test_and_clear_bit(i, &kit->input_events)) {
sprintf(sysfs_file, "input%d", i + 1);
sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
}
}
for (i=0; i<kit->ifkit->sensors; i++) {
if (test_and_clear_bit(i, &kit->sensor_events)) {
sprintf(sysfs_file, "sensor%d", i + 1);
sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
}
}
}
static void do_resubmit(struct work_struct *work)
{
struct interfacekit *kit =
container_of(work, struct interfacekit, do_resubmit.work);
set_outputs(kit);
}
#define show_set_output(value) \
static ssize_t set_output##value(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct interfacekit *kit = dev_get_drvdata(dev); \
int enable; \
int retval; \
\
if (sscanf(buf, "%d", &enable) < 1) \
return -EINVAL; \
\
if (enable) \
set_bit(value - 1, &kit->outputs); \
else \
clear_bit(value - 1, &kit->outputs); \
\
retval = set_outputs(kit); \
\
return retval ? retval : count; \
} \
\
static ssize_t show_output##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct interfacekit *kit = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
}
#define output_attr(value) \
__ATTR(output##value, S_IWUGO | S_IRUGO, \
show_output##value, set_output##value)
show_set_output(1);
show_set_output(2);
show_set_output(3);
show_set_output(4);
show_set_output(5);
show_set_output(6);
show_set_output(7);
show_set_output(8);
show_set_output(9);
show_set_output(10);
show_set_output(11);
show_set_output(12);
show_set_output(13);
show_set_output(14);
show_set_output(15);
show_set_output(16);
static struct device_attribute dev_output_attrs[] = {
output_attr(1), output_attr(2), output_attr(3), output_attr(4),
output_attr(5), output_attr(6), output_attr(7), output_attr(8),
output_attr(9), output_attr(10), output_attr(11), output_attr(12),
output_attr(13), output_attr(14), output_attr(15), output_attr(16)
};
#define show_input(value) \
static ssize_t show_input##value(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct interfacekit *kit = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \
}
#define input_attr(value) \
__ATTR(input##value, S_IRUGO, show_input##value, NULL)
show_input(1);
show_input(2);
show_input(3);
show_input(4);
show_input(5);
show_input(6);
show_input(7);
show_input(8);
show_input(9);
show_input(10);
show_input(11);
show_input(12);
show_input(13);
show_input(14);
show_input(15);
show_input(16);
static struct device_attribute dev_input_attrs[] = {
input_attr(1), input_attr(2), input_attr(3), input_attr(4),
input_attr(5), input_attr(6), input_attr(7), input_attr(8),
input_attr(9), input_attr(10), input_attr(11), input_attr(12),
input_attr(13), input_attr(14), input_attr(15), input_attr(16)
};
#define show_sensor(value) \
static ssize_t show_sensor##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct interfacekit *kit = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \
}
#define sensor_attr(value) \
__ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL)
show_sensor(1);
show_sensor(2);
show_sensor(3);
show_sensor(4);
show_sensor(5);
show_sensor(6);
show_sensor(7);
show_sensor(8);
static struct device_attribute dev_sensor_attrs[] = {
sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4),
sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8)
};
static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct interfacekit *kit;
struct driver_interfacekit *ifkit;
int pipe, maxp, rc = -ENOMEM;
int bit, value, i;
ifkit = (struct driver_interfacekit *)id->driver_info;
if (!ifkit)
return -ENODEV;
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
* bmAttributes
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
kit = kzalloc(sizeof(*kit), GFP_KERNEL);
if (!kit)
goto out;
kit->dev_no = -1;
kit->ifkit = ifkit;
kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma);
if (!kit->data)
goto out;
kit->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!kit->irq)
goto out;
kit->udev = usb_get_dev(dev);
kit->intf = intf;
INIT_DELAYED_WORK(&kit->do_notify, do_notify);
INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit);
usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
interfacekit_irq, kit, endpoint->bInterval);
kit->irq->transfer_dma = kit->data_dma;
kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_set_intfdata(intf, kit);
do {
bit = find_first_zero_bit(&device_no, sizeof(device_no));
value = test_and_set_bit(bit, &device_no);
} while(value);
kit->dev_no = bit;
kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0),
kit, "interfacekit%d", kit->dev_no);
if (IS_ERR(kit->dev)) {
rc = PTR_ERR(kit->dev);
kit->dev = NULL;
goto out;
}
if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
rc = -EIO;
goto out;
}
for (i=0; i<ifkit->outputs; i++ ) {
rc = device_create_file(kit->dev, &dev_output_attrs[i]);
if (rc)
goto out2;
}
for (i=0; i<ifkit->inputs; i++ ) {
rc = device_create_file(kit->dev, &dev_input_attrs[i]);
if (rc)
goto out3;
}
for (i=0; i<ifkit->sensors; i++ ) {
rc = device_create_file(kit->dev, &dev_sensor_attrs[i]);
if (rc)
goto out4;
}
if (ifkit->has_lcd) {
rc = device_create_file(kit->dev, &dev_attr_lcd);
if (rc)
goto out4;
}
dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
ifkit->sensors, ifkit->inputs, ifkit->outputs);
return 0;
out4:
while (i-- > 0)
device_remove_file(kit->dev, &dev_sensor_attrs[i]);
i = ifkit->inputs;
out3:
while (i-- > 0)
device_remove_file(kit->dev, &dev_input_attrs[i]);
i = ifkit->outputs;
out2:
while (i-- > 0)
device_remove_file(kit->dev, &dev_output_attrs[i]);
out:
if (kit) {
usb_free_urb(kit->irq);
if (kit->data)
usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
if (kit->dev)
device_unregister(kit->dev);
if (kit->dev_no >= 0)
clear_bit(kit->dev_no, &device_no);
kfree(kit);
}
return rc;
}
static void interfacekit_disconnect(struct usb_interface *interface)
{
struct interfacekit *kit;
int i;
kit = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!kit)
return;
usb_kill_urb(kit->irq);
usb_free_urb(kit->irq);
usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
cancel_delayed_work(&kit->do_notify);
cancel_delayed_work(&kit->do_resubmit);
for (i=0; i<kit->ifkit->outputs; i++)
device_remove_file(kit->dev, &dev_output_attrs[i]);
for (i=0; i<kit->ifkit->inputs; i++)
device_remove_file(kit->dev, &dev_input_attrs[i]);
for (i=0; i<kit->ifkit->sensors; i++)
device_remove_file(kit->dev, &dev_sensor_attrs[i]);
if (kit->ifkit->has_lcd) {
device_remove_file(kit->dev, &dev_attr_lcd);
remove_lcd_files(kit);
}
device_unregister(kit->dev);
dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
usb_put_dev(kit->udev);
clear_bit(kit->dev_no, &device_no);
kfree(kit);
}
static struct usb_driver interfacekit_driver = {
.name = "phidgetkit",
.probe = interfacekit_probe,
.disconnect = interfacekit_disconnect,
.id_table = id_table
};
static int __init interfacekit_init(void)
{
int retval = 0;
retval = usb_register(&interfacekit_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit interfacekit_exit(void)
{
usb_deregister(&interfacekit_driver);
}
module_init(interfacekit_init);
module_exit(interfacekit_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

Просмотреть файл

@ -1,465 +0,0 @@
/*
* USB Phidget MotorControl driver
*
* Copyright (C) 2006 Sean Young <sean@mess.org>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "phidget.h"
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetMotorControl Driver"
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_MOTORCONTROL 0x0058
#define URB_INT_SIZE 8
static unsigned long device_no;
struct motorcontrol {
struct usb_device *udev;
struct usb_interface *intf;
struct device *dev;
int dev_no;
u8 inputs[4];
s8 desired_speed[2];
s8 speed[2];
s16 _current[2];
s8 acceleration[2];
struct urb *irq;
unsigned char *data;
dma_addr_t data_dma;
struct delayed_work do_notify;
unsigned long input_events;
unsigned long speed_events;
unsigned long exceed_events;
};
static struct usb_device_id id_table[] = {
{ USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
static int set_motor(struct motorcontrol *mc, int motor)
{
u8 *buffer;
int speed, speed2, acceleration;
int retval;
buffer = kzalloc(8, GFP_KERNEL);
if (!buffer) {
dev_err(&mc->intf->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
acceleration = mc->acceleration[motor] * 10;
/* -127 <= speed <= 127 */
speed = (mc->desired_speed[motor] * 127) / 100;
/* -0x7300 <= speed2 <= 0x7300 */
speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;
buffer[0] = motor;
buffer[1] = speed;
buffer[2] = acceleration >> 8;
buffer[3] = acceleration;
buffer[4] = speed2 >> 8;
buffer[5] = speed2;
retval = usb_control_msg(mc->udev,
usb_sndctrlpipe(mc->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
if (retval != 8)
dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
retval);
kfree(buffer);
return retval < 0 ? retval : 0;
}
static void motorcontrol_irq(struct urb *urb)
{
struct motorcontrol *mc = urb->context;
unsigned char *buffer = mc->data;
int i, level;
int retval;
int status = urb->status;;
switch (status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default: /* error */
goto resubmit;
}
/* digital inputs */
for (i=0; i<4; i++) {
level = (buffer[0] >> i) & 1;
if (mc->inputs[i] != level) {
mc->inputs[i] = level;
set_bit(i, &mc->input_events);
}
}
/* motor speed */
if (buffer[2] == 0) {
for (i=0; i<2; i++) {
level = ((s8)buffer[4+i]) * 100 / 127;
if (mc->speed[i] != level) {
mc->speed[i] = level;
set_bit(i, &mc->speed_events);
}
}
} else {
int index = buffer[3] & 1;
level = ((s8)buffer[4] << 8) | buffer[5];
level = level * 100 / 29440;
if (mc->speed[index] != level) {
mc->speed[index] = level;
set_bit(index, &mc->speed_events);
}
level = ((s8)buffer[6] << 8) | buffer[7];
mc->_current[index] = level * 100 / 1572;
}
if (buffer[1] & 1)
set_bit(0, &mc->exceed_events);
if (buffer[1] & 2)
set_bit(1, &mc->exceed_events);
if (mc->input_events || mc->exceed_events || mc->speed_events)
schedule_delayed_work(&mc->do_notify, 0);
resubmit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&mc->intf->dev,
"can't resubmit intr, %s-%s/motorcontrol0, retval %d\n",
mc->udev->bus->bus_name,
mc->udev->devpath, retval);
}
static void do_notify(struct work_struct *work)
{
struct motorcontrol *mc =
container_of(work, struct motorcontrol, do_notify.work);
int i;
char sysfs_file[8];
for (i=0; i<4; i++) {
if (test_and_clear_bit(i, &mc->input_events)) {
sprintf(sysfs_file, "input%d", i);
sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
}
}
for (i=0; i<2; i++) {
if (test_and_clear_bit(i, &mc->speed_events)) {
sprintf(sysfs_file, "speed%d", i);
sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
}
}
for (i=0; i<2; i++) {
if (test_and_clear_bit(i, &mc->exceed_events))
dev_warn(&mc->intf->dev,
"motor #%d exceeds 1.5 Amp current limit\n", i);
}
}
#define show_set_speed(value) \
static ssize_t set_speed##value(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
int speed; \
int retval; \
\
if (sscanf(buf, "%d", &speed) < 1) \
return -EINVAL; \
\
if (speed < -100 || speed > 100) \
return -EINVAL; \
\
mc->desired_speed[value] = speed; \
\
retval = set_motor(mc, value); \
\
return retval ? retval : count; \
} \
\
static ssize_t show_speed##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", mc->speed[value]); \
}
#define speed_attr(value) \
__ATTR(speed##value, S_IWUGO | S_IRUGO, \
show_speed##value, set_speed##value)
show_set_speed(0);
show_set_speed(1);
#define show_set_acceleration(value) \
static ssize_t set_acceleration##value(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
int acceleration; \
int retval; \
\
if (sscanf(buf, "%d", &acceleration) < 1) \
return -EINVAL; \
\
if (acceleration < 0 || acceleration > 100) \
return -EINVAL; \
\
mc->acceleration[value] = acceleration; \
\
retval = set_motor(mc, value); \
\
return retval ? retval : count; \
} \
\
static ssize_t show_acceleration##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", mc->acceleration[value]); \
}
#define acceleration_attr(value) \
__ATTR(acceleration##value, S_IWUGO | S_IRUGO, \
show_acceleration##value, set_acceleration##value)
show_set_acceleration(0);
show_set_acceleration(1);
#define show_current(value) \
static ssize_t show_current##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
\
return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \
}
#define current_attr(value) \
__ATTR(current##value, S_IRUGO, show_current##value, NULL)
show_current(0);
show_current(1);
#define show_input(value) \
static ssize_t show_input##value(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct motorcontrol *mc = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d\n", (int)mc->inputs[value]); \
}
#define input_attr(value) \
__ATTR(input##value, S_IRUGO, show_input##value, NULL)
show_input(0);
show_input(1);
show_input(2);
show_input(3);
static struct device_attribute dev_attrs[] = {
input_attr(0),
input_attr(1),
input_attr(2),
input_attr(3),
speed_attr(0),
speed_attr(1),
acceleration_attr(0),
acceleration_attr(1),
current_attr(0),
current_attr(1)
};
static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *interface;
struct usb_endpoint_descriptor *endpoint;
struct motorcontrol *mc;
int pipe, maxp, rc = -ENOMEM;
int bit, value, i;
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
* bmAttributes
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
mc = kzalloc(sizeof(*mc), GFP_KERNEL);
if (!mc)
goto out;
mc->dev_no = -1;
mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma);
if (!mc->data)
goto out;
mc->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!mc->irq)
goto out;
mc->udev = usb_get_dev(dev);
mc->intf = intf;
mc->acceleration[0] = mc->acceleration[1] = 10;
INIT_DELAYED_WORK(&mc->do_notify, do_notify);
usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
motorcontrol_irq, mc, endpoint->bInterval);
mc->irq->transfer_dma = mc->data_dma;
mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_set_intfdata(intf, mc);
do {
bit = find_first_zero_bit(&device_no, sizeof(device_no));
value = test_and_set_bit(bit, &device_no);
} while(value);
mc->dev_no = bit;
mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc,
"motorcontrol%d", mc->dev_no);
if (IS_ERR(mc->dev)) {
rc = PTR_ERR(mc->dev);
mc->dev = NULL;
goto out;
}
if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
rc = -EIO;
goto out;
}
for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
rc = device_create_file(mc->dev, &dev_attrs[i]);
if (rc)
goto out2;
}
dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
return 0;
out2:
while (i-- > 0)
device_remove_file(mc->dev, &dev_attrs[i]);
out:
if (mc) {
usb_free_urb(mc->irq);
if (mc->data)
usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
if (mc->dev)
device_unregister(mc->dev);
if (mc->dev_no >= 0)
clear_bit(mc->dev_no, &device_no);
kfree(mc);
}
return rc;
}
static void motorcontrol_disconnect(struct usb_interface *interface)
{
struct motorcontrol *mc;
int i;
mc = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!mc)
return;
usb_kill_urb(mc->irq);
usb_free_urb(mc->irq);
usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);
cancel_delayed_work(&mc->do_notify);
for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
device_remove_file(mc->dev, &dev_attrs[i]);
device_unregister(mc->dev);
usb_put_dev(mc->udev);
clear_bit(mc->dev_no, &device_no);
kfree(mc);
dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
}
static struct usb_driver motorcontrol_driver = {
.name = "phidgetmotorcontrol",
.probe = motorcontrol_probe,
.disconnect = motorcontrol_disconnect,
.id_table = id_table
};
static int __init motorcontrol_init(void)
{
int retval = 0;
retval = usb_register(&motorcontrol_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit motorcontrol_exit(void)
{
usb_deregister(&motorcontrol_driver);
}
module_init(motorcontrol_init);
module_exit(motorcontrol_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

Просмотреть файл

@ -1,375 +0,0 @@
/*
* USB PhidgetServo driver 1.0
*
* Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
*
* 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 is a driver for the USB PhidgetServo version 2.0 and 3.0 servo
* controllers available at: http://www.phidgets.com/
*
* Note that the driver takes input as: degrees.minutes
*
* CAUTION: Generally you should use 0 < degrees < 180 as anything else
* is probably beyond the range of your servo and may damage it.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "phidget.h"
#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
#define DRIVER_DESC "USB PhidgetServo Driver"
#define VENDOR_ID_GLAB 0x06c2
#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038
#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039
#define VENDOR_ID_WISEGROUP 0x0925
#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101
#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104
#define SERVO_VERSION_30 0x01
#define SERVO_COUNT_QUAD 0x02
static struct usb_device_id id_table[] = {
{
USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD),
.driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD
},
{
USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI),
.driver_info = SERVO_VERSION_30
},
{
USB_DEVICE(VENDOR_ID_WISEGROUP,
VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD),
.driver_info = SERVO_COUNT_QUAD
},
{
USB_DEVICE(VENDOR_ID_WISEGROUP,
VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI),
.driver_info = 0
},
{}
};
MODULE_DEVICE_TABLE(usb, id_table);
static int unsigned long device_no;
struct phidget_servo {
struct usb_device *udev;
struct device *dev;
int dev_no;
ulong type;
int pulse[4];
int degrees[4];
int minutes[4];
};
static int
change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
int minutes)
{
int retval;
unsigned char *buffer;
if (degrees < -23 || degrees > 362)
return -EINVAL;
buffer = kmalloc(6, GFP_KERNEL);
if (!buffer) {
dev_err(&servo->udev->dev, "%s - out of memory\n",
__func__);
return -ENOMEM;
}
/*
* pulse = 0 - 4095
* angle = 0 - 180 degrees
*
* pulse = angle * 10.6 + 243.8
*/
servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600;
servo->degrees[servo_no]= degrees;
servo->minutes[servo_no]= minutes;
/*
* The PhidgetServo v3.0 is controlled by sending 6 bytes,
* 4 * 12 bits for each servo.
*
* low = lower 8 bits pulse
* high = higher 4 bits pulse
*
* offset bits
* +---+-----------------+
* | 0 | low 0 |
* +---+--------+--------+
* | 1 | high 1 | high 0 |
* +---+--------+--------+
* | 2 | low 1 |
* +---+-----------------+
* | 3 | low 2 |
* +---+--------+--------+
* | 4 | high 3 | high 2 |
* +---+--------+--------+
* | 5 | low 3 |
* +---+-----------------+
*/
buffer[0] = servo->pulse[0] & 0xff;
buffer[1] = (servo->pulse[0] >> 8 & 0x0f)
| (servo->pulse[1] >> 4 & 0xf0);
buffer[2] = servo->pulse[1] & 0xff;
buffer[3] = servo->pulse[2] & 0xff;
buffer[4] = (servo->pulse[2] >> 8 & 0x0f)
| (servo->pulse[3] >> 4 & 0xf0);
buffer[5] = servo->pulse[3] & 0xff;
dev_dbg(&servo->udev->dev,
"data: %02x %02x %02x %02x %02x %02x\n",
buffer[0], buffer[1], buffer[2],
buffer[3], buffer[4], buffer[5]);
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000);
kfree(buffer);
return retval;
}
static int
change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
int minutes)
{
int retval;
unsigned char *buffer;
if (degrees < -23 || degrees > 278)
return -EINVAL;
buffer = kmalloc(2, GFP_KERNEL);
if (!buffer) {
dev_err(&servo->udev->dev, "%s - out of memory\n",
__func__);
return -ENOMEM;
}
/*
* angle = 0 - 180 degrees
* pulse = angle + 23
*/
servo->pulse[servo_no]= degrees + 23;
servo->degrees[servo_no]= degrees;
servo->minutes[servo_no]= 0;
/*
* The PhidgetServo v2.0 is controlled by sending two bytes. The
* first byte is the servo number xor'ed with 2:
*
* servo 0 = 2
* servo 1 = 3
* servo 2 = 0
* servo 3 = 1
*
* The second byte is the position.
*/
buffer[0] = servo_no ^ 2;
buffer[1] = servo->pulse[servo_no];
dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
retval = usb_control_msg(servo->udev,
usb_sndctrlpipe(servo->udev, 0),
0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000);
kfree(buffer);
return retval;
}
#define show_set(value) \
static ssize_t set_servo##value (struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
int degrees, minutes, retval; \
struct phidget_servo *servo = dev_get_drvdata(dev); \
\
minutes = 0; \
/* must at least convert degrees */ \
if (sscanf(buf, "%d.%d", &degrees, &minutes) < 1) { \
return -EINVAL; \
} \
\
if (minutes < 0 || minutes > 59) \
return -EINVAL; \
\
if (servo->type & SERVO_VERSION_30) \
retval = change_position_v30(servo, value, degrees, \
minutes); \
else \
retval = change_position_v20(servo, value, degrees, \
minutes); \
\
return retval < 0 ? retval : count; \
} \
\
static ssize_t show_servo##value (struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct phidget_servo *servo = dev_get_drvdata(dev); \
\
return sprintf(buf, "%d.%02d\n", servo->degrees[value], \
servo->minutes[value]); \
}
#define servo_attr(value) \
__ATTR(servo##value, S_IWUGO | S_IRUGO, \
show_servo##value, set_servo##value)
show_set(0);
show_set(1);
show_set(2);
show_set(3);
static struct device_attribute dev_attrs[] = {
servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
};
static int
servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct phidget_servo *dev;
int bit, value, rc;
int servo_count, i;
dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
if (dev == NULL) {
dev_err(&interface->dev, "%s - out of memory\n", __func__);
rc = -ENOMEM;
goto out;
}
dev->udev = usb_get_dev(udev);
dev->type = id->driver_info;
dev->dev_no = -1;
usb_set_intfdata(interface, dev);
do {
bit = find_first_zero_bit(&device_no, sizeof(device_no));
value = test_and_set_bit(bit, &device_no);
} while (value);
dev->dev_no = bit;
dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0),
dev, "servo%d", dev->dev_no);
if (IS_ERR(dev->dev)) {
rc = PTR_ERR(dev->dev);
dev->dev = NULL;
goto out;
}
servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
for (i=0; i<servo_count; i++) {
rc = device_create_file(dev->dev, &dev_attrs[i]);
if (rc)
goto out2;
}
dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
if (!(dev->type & SERVO_VERSION_30))
dev_info(&interface->dev,
"WARNING: v2.0 not tested! Please report if it works.\n");
return 0;
out2:
while (i-- > 0)
device_remove_file(dev->dev, &dev_attrs[i]);
out:
if (dev) {
if (dev->dev)
device_unregister(dev->dev);
if (dev->dev_no >= 0)
clear_bit(dev->dev_no, &device_no);
kfree(dev);
}
return rc;
}
static void
servo_disconnect(struct usb_interface *interface)
{
struct phidget_servo *dev;
int servo_count, i;
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!dev)
return;
servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
for (i=0; i<servo_count; i++)
device_remove_file(dev->dev, &dev_attrs[i]);
device_unregister(dev->dev);
usb_put_dev(dev->udev);
dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
clear_bit(dev->dev_no, &device_no);
kfree(dev);
}
static struct usb_driver servo_driver = {
.name = "phidgetservo",
.probe = servo_probe,
.disconnect = servo_disconnect,
.id_table = id_table
};
static int __init
phidget_servo_init(void)
{
int retval;
retval = usb_register(&servo_driver);
if (retval)
err("usb_register failed. Error number %d", retval);
return retval;
}
static void __exit
phidget_servo_exit(void)
{
usb_deregister(&servo_driver);
}
module_init(phidget_servo_init);
module_exit(phidget_servo_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

Просмотреть файл

@ -37,10 +37,13 @@
#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
/* #9 was MON_IOCT_SETAPI */
#define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get)
#ifdef CONFIG_COMPAT
#define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
#define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
#define MON_IOCX_GETX32 _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32)
#endif
/*
@ -92,7 +95,29 @@ struct mon_bin_hdr {
int status;
unsigned int len_urb; /* Length of data (submitted or actual) */
unsigned int len_cap; /* Delivered length */
unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
union {
unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
struct iso_rec {
int error_count;
int numdesc;
} iso;
} s;
int interval;
int start_frame;
unsigned int xfer_flags;
unsigned int ndesc; /* Actual number of ISO descriptors */
};
/*
* ISO vector, packed into the head of data stream.
* This has to take 16 bytes to make sure that the end of buffer
* wrap is not happening in the middle of a descriptor.
*/
struct mon_bin_isodesc {
int iso_status;
unsigned int iso_off;
unsigned int iso_len;
u32 _pad;
};
/* per file statistic */
@ -102,7 +127,7 @@ struct mon_bin_stats {
};
struct mon_bin_get {
struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */
struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */
void __user *data;
size_t alloc; /* Length of data (can be zero) */
};
@ -131,6 +156,11 @@ struct mon_bin_mfetch32 {
#define PKT_ALIGN 64
#define PKT_SIZE 64
#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */
#define PKT_SZ_API1 64 /* API 1 size: extra fields */
#define ISODESC_MAX 128 /* Same number as usbfs allows, 2048 bytes. */
/* max number of USB bus supported */
#define MON_BIN_MAX_MINOR 128
@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb,
const struct urb *urb, char ev_type)
{
if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S')
return '-';
if (urb->setup_packet == NULL)
return 'Z';
memcpy(setupb, urb->setup_packet, SETUP_LEN);
return 0;
}
@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp,
return 0;
}
static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
{
struct mon_bin_isodesc *dp;
struct usb_iso_packet_descriptor *fp;
fp = urb->iso_frame_desc;
while (ndesc-- != 0) {
dp = (struct mon_bin_isodesc *)
(rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
dp->iso_status = fp->status;
dp->iso_off = fp->offset;
dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
dp->_pad = 0;
if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
offset = 0;
fp++;
}
}
static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
char ev_type, int status)
{
@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
unsigned int urb_length;
unsigned int offset;
unsigned int length;
unsigned int ndesc, lendesc;
unsigned char dir;
struct mon_bin_hdr *ep;
char data_tag = 0;
@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
/*
* Find the maximum allowable length, then allocate space.
*/
if (usb_endpoint_xfer_isoc(epd)) {
if (urb->number_of_packets < 0) {
ndesc = 0;
} else if (urb->number_of_packets >= ISODESC_MAX) {
ndesc = ISODESC_MAX;
} else {
ndesc = urb->number_of_packets;
}
} else {
ndesc = 0;
}
lendesc = ndesc*sizeof(struct mon_bin_isodesc);
urb_length = (ev_type == 'S') ?
urb->transfer_buffer_length : urb->actual_length;
length = urb_length;
@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
dir = 0;
}
if (rp->mmap_active)
offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE);
else
offset = mon_buff_area_alloc(rp, length + PKT_SIZE);
if (rp->mmap_active) {
offset = mon_buff_area_alloc_contiguous(rp,
length + PKT_SIZE + lendesc);
} else {
offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
}
if (offset == ~0) {
rp->cnt_lost++;
spin_unlock_irqrestore(&rp->b_lock, flags);
@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
ep->ts_usec = ts.tv_usec;
ep->status = status;
ep->len_urb = urb_length;
ep->len_cap = length;
ep->len_cap = length + lendesc;
ep->xfer_flags = urb->transfer_flags;
if (usb_endpoint_xfer_int(epd)) {
ep->interval = urb->interval;
} else if (usb_endpoint_xfer_isoc(epd)) {
ep->interval = urb->interval;
ep->start_frame = urb->start_frame;
ep->s.iso.error_count = urb->error_count;
ep->s.iso.numdesc = urb->number_of_packets;
}
if (usb_endpoint_xfer_control(epd) && ev_type == 'S') {
ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
} else {
ep->flag_setup = '-';
}
if (ndesc != 0) {
ep->ndesc = ndesc;
mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
if ((offset += lendesc) >= rp->b_size)
offset -= rp->b_size;
}
ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type);
if (length != 0) {
ep->flag_data = mon_bin_get_data(rp, offset, urb, length);
if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */
@ -592,7 +676,8 @@ err_alloc:
* Returns zero or error.
*/
static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes)
struct mon_bin_hdr __user *hdr, unsigned int hdrbytes,
void __user *data, unsigned int nbytes)
{
unsigned long flags;
struct mon_bin_hdr *ep;
@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
ep = MON_OFF2HDR(rp, rp->b_out);
if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) {
if (copy_to_user(hdr, ep, hdrbytes)) {
mutex_unlock(&rp->fetch_lock);
return -EFAULT;
}
@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct mon_reader_bin *rp = file->private_data;
unsigned int hdrbytes = PKT_SZ_API0;
unsigned long flags;
struct mon_bin_hdr *ep;
unsigned int offset;
@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
ep = MON_OFF2HDR(rp, rp->b_out);
if (rp->b_read < sizeof(struct mon_bin_hdr)) {
step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read);
if (rp->b_read < hdrbytes) {
step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
ptr = ((char *)ep) + rp->b_read;
if (step_len && copy_to_user(buf, ptr, step_len)) {
mutex_unlock(&rp->fetch_lock);
@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
done += step_len;
}
if (rp->b_read >= sizeof(struct mon_bin_hdr)) {
if (rp->b_read >= hdrbytes) {
step_len = ep->len_cap;
step_len -= rp->b_read - sizeof(struct mon_bin_hdr);
step_len -= rp->b_read - hdrbytes;
if (step_len > nbytes)
step_len = nbytes;
offset = rp->b_out + PKT_SIZE;
offset += rp->b_read - sizeof(struct mon_bin_hdr);
offset += rp->b_read - hdrbytes;
if (offset >= rp->b_size)
offset -= rp->b_size;
if (copy_from_buf(rp, offset, buf, step_len)) {
@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
/*
* Check if whole packet was read, and if so, jump to the next one.
*/
if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) {
if (rp->b_read >= hdrbytes + ep->len_cap) {
spin_lock_irqsave(&rp->b_lock, flags);
mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
spin_unlock_irqrestore(&rp->b_lock, flags);
@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
break;
case MON_IOCX_GET:
case MON_IOCX_GETX:
{
struct mon_bin_get getb;
@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file,
if (getb.alloc > 0x10000000) /* Want to cast to u32 */
return -EINVAL;
ret = mon_bin_get_event(file, rp,
getb.hdr, getb.data, (unsigned int)getb.alloc);
ret = mon_bin_get_event(file, rp, getb.hdr,
(cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1,
getb.data, (unsigned int)getb.alloc);
}
break;
@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file,
switch (cmd) {
case MON_IOCX_GET32: {
case MON_IOCX_GET32:
case MON_IOCX_GETX32:
{
struct mon_bin_get32 getb;
if (copy_from_user(&getb, (void __user *)arg,
sizeof(struct mon_bin_get32)))
return -EFAULT;
ret = mon_bin_get_event(file, rp,
compat_ptr(getb.hdr32), compat_ptr(getb.data32),
getb.alloc32);
ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
(cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
compat_ptr(getb.data32), getb.alloc32);
if (ret < 0)
return ret;
}

Просмотреть файл

@ -20,8 +20,8 @@ config USB_MUSB_HDRC
it's being used with, including the USB peripheral role,
or the USB host role, or both.
Texas Instruments parts using this IP include DaVinci 644x,
OMAP 243x, OMAP 343x, and TUSB 6010.
Texas Instruments familiies using this IP include DaVinci
(35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010.
Analog Devices parts using this IP include Blackfin BF54x,
BF525 and BF527.
@ -40,7 +40,7 @@ config USB_MUSB_SOC
default y if (BF54x && !BF544)
default y if (BF52x && !BF522 && !BF523)
comment "DaVinci 644x USB support"
comment "DaVinci 35x and 644x USB support"
depends on USB_MUSB_HDRC && ARCH_DAVINCI
comment "OMAP 243x high speed USB support"

Просмотреть файл

@ -48,6 +48,9 @@
#include "cppi_dma.h"
#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR)
#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR)
/* REVISIT (PM) we should be able to keep the PHY in low power mode most
* of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0
* and, when in host mode, autosuspending idle root ports... PHYPLLON
@ -56,20 +59,26 @@
static inline void phy_on(void)
{
/* start the on-chip PHY and its PLL */
__raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON,
(void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR));
while ((__raw_readl((void __force __iomem *)
IO_ADDRESS(USBPHY_CTL_PADDR))
& USBPHY_PHYCLKGD) == 0)
u32 phy_ctrl = __raw_readl(USB_PHY_CTRL);
/* power everything up; start the on-chip PHY and its PLL */
phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN);
phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON;
__raw_writel(phy_ctrl, USB_PHY_CTRL);
/* wait for PLL to lock before proceeding */
while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0)
cpu_relax();
}
static inline void phy_off(void)
{
/* powerdown the on-chip PHY and its oscillator */
__raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *)
IO_ADDRESS(USBPHY_CTL_PADDR));
u32 phy_ctrl = __raw_readl(USB_PHY_CTRL);
/* powerdown the on-chip PHY, its PLL, and the OTG block */
phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON);
phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN;
__raw_writel(phy_ctrl, USB_PHY_CTRL);
}
static int dma_off = 1;
@ -126,10 +135,6 @@ void musb_platform_disable(struct musb *musb)
}
/* REVISIT it's not clear whether DaVinci can support full OTG. */
static int vbus_state = -1;
#ifdef CONFIG_USB_MUSB_HDRC_HCD
#define portstate(stmt) stmt
#else
@ -137,10 +142,19 @@ static int vbus_state = -1;
#endif
/* VBUS SWITCHING IS BOARD-SPECIFIC */
/*
* VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM,
* which doesn't wire DRVVBUS to the FET that switches it. Unclear
* if that's a problem with the DM6446 chip or just with that board.
*
* In either case, the DM355 EVM automates DRVVBUS the normal way,
* when J10 is out, and TI documents it as handling OTG.
*/
#ifdef CONFIG_MACH_DAVINCI_EVM
static int vbus_state = -1;
/* I2C operations are always synchronous, and require a task context.
* With unloaded systems, using the shared workqueue seems to suffice
* to satisfy the 100msec A_WAIT_VRISE timeout...
@ -150,12 +164,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored)
gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
vbus_state = !vbus_state;
}
static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
#endif /* EVM */
static void davinci_source_power(struct musb *musb, int is_on, int immediate)
{
#ifdef CONFIG_MACH_DAVINCI_EVM
if (is_on)
is_on = 1;
@ -163,16 +177,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate)
return;
vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */
#ifdef CONFIG_MACH_DAVINCI_EVM
if (machine_is_davinci_evm()) {
static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus);
if (immediate)
gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state);
else
schedule_work(&evm_vbus_work);
}
#endif
if (immediate)
vbus_state = is_on;
#endif
}
static void davinci_set_vbus(struct musb *musb, int is_on)
@ -391,6 +406,17 @@ int __init musb_platform_init(struct musb *musb)
musb->board_set_vbus = davinci_set_vbus;
davinci_source_power(musb, 0, 1);
/* dm355 EVM swaps D+/D- for signal integrity, and
* is clocked from the main 24 MHz crystal.
*/
if (machine_is_davinci_dm355_evm()) {
u32 phy_ctrl = __raw_readl(USB_PHY_CTRL);
phy_ctrl &= ~(3 << 9);
phy_ctrl |= USBPHY_DATAPOL;
__raw_writel(phy_ctrl, USB_PHY_CTRL);
}
/* reset the controller */
musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
@ -401,8 +427,7 @@ int __init musb_platform_init(struct musb *musb)
/* NOTE: irqs are in mixed mode, not bypass to pure-musb */
pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n",
revision, __raw_readl((void __force __iomem *)
IO_ADDRESS(USBPHY_CTL_PADDR)),
revision, __raw_readl(USB_PHY_CTRL),
musb_readb(tibase, DAVINCI_USB_CTRL_REG));
musb->isr = davinci_interrupt;

Просмотреть файл

@ -15,14 +15,21 @@
*/
/* Integrated highspeed/otg PHY */
#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
#define USBPHY_PHYCLKGD (1 << 8)
#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */
#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */
#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */
#define USBPHY_CLKO1SEL (1 << 3)
#define USBPHY_OSCPDWN (1 << 2)
#define USBPHY_PHYPDWN (1 << 0)
#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34)
#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */
#define USBPHY_PHYCLKGD BIT(8)
#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */
#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */
#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */
#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */
#define USBPHY_CLKO1SEL BIT(3)
#define USBPHY_OSCPDWN BIT(2)
#define USBPHY_OTGPDWN BIT(1)
#define USBPHY_PHYPDWN BIT(0)
#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48)
#define DRVVBUS_FORCE BIT(2)
#define DRVVBUS_OVERRIDE BIT(1)
/* For now include usb OTG module registers here */
#define DAVINCI_USB_VERSION_REG 0x00

Просмотреть файл

@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_A_SUSPEND:
usb_hcd_resume_root_hub(musb_to_hcd(musb));
musb_root_disconnect(musb);
if (musb->a_wait_bcon != 0)
if (musb->a_wait_bcon != 0 && is_otg_enabled(musb))
musb_platform_try_idle(musb, jiffies
+ msecs_to_jiffies(musb->a_wait_bcon));
break;

Просмотреть файл

@ -331,7 +331,6 @@ struct musb {
struct list_head control; /* of musb_qh */
struct list_head in_bulk; /* of musb_qh */
struct list_head out_bulk; /* of musb_qh */
struct musb_qh *periodic[32]; /* tree of interrupt+iso */
#endif
/* called with IRQs blocked; ON/nonzero implies starting a session,
@ -479,10 +478,11 @@ static inline void musb_configure_ep0(struct musb *musb)
static inline int musb_read_fifosize(struct musb *musb,
struct musb_hw_ep *hw_ep, u8 epnum)
{
void *mbase = musb->mregs;
u8 reg = 0;
/* read from core using indexed model */
reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE);
reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE));
/* 0's returned when no more endpoints */
if (!reg)
return -ENODEV;
@ -509,6 +509,7 @@ static inline void musb_configure_ep0(struct musb *musb)
{
musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
musb->endpoints[0].is_shared_fifo = true;
}
#endif /* CONFIG_BLACKFIN */

Просмотреть файл

@ -64,11 +64,8 @@
*
* - DMA (Mentor/OMAP) ...has at least toggle update problems
*
* - Still no traffic scheduling code to make NAKing for bulk or control
* transfers unable to starve other requests; or to make efficient use
* of hardware with periodic transfers. (Note that network drivers
* commonly post bulk reads that stay pending for a long time; these
* would make very visible trouble.)
* - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet
* starvation ... nothing yet for TX, interrupt, or bulk.
*
* - Not tested with HNP, but some SRP paths seem to behave.
*
@ -88,11 +85,8 @@
*
* CONTROL transfers all go through ep0. BULK ones go through dedicated IN
* and OUT endpoints ... hardware is dedicated for those "async" queue(s).
*
* (Yes, bulk _could_ use more of the endpoints than that, and would even
* benefit from it ... one remote device may easily be NAKing while others
* need to perform transfers in that same direction. The same thing could
* be done in software though, assuming dma cooperates.)
* benefit from it.)
*
* INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints.
* So far that scheduling is both dumb and optimistic: the endpoint will be
@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh)
len = urb->iso_frame_desc[0].length;
break;
default: /* bulk, interrupt */
buf = urb->transfer_buffer;
len = urb->transfer_buffer_length;
/* actual_length may be nonzero on retry paths */
buf = urb->transfer_buffer + urb->actual_length;
len = urb->transfer_buffer_length - urb->actual_length;
}
DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n",
@ -395,7 +390,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
* de-allocated if it's tracked and allocated;
* and where we'd update the schedule tree...
*/
musb->periodic[ep->epnum] = NULL;
kfree(qh);
qh = NULL;
break;
@ -1045,7 +1039,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb)
/* NOTE: this code path would be a good place to PAUSE a
* control transfer, if another one is queued, so that
* ep0 is more likely to stay busy.
* ep0 is more likely to stay busy. That's already done
* for bulk RX transfers.
*
* if (qh->ring.next != &musb->control), then
* we have a candidate... NAKing is *NOT* an error
@ -1197,6 +1192,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
/* NOTE: this code path would be a good place to PAUSE a
* transfer, if there's some other (nonperiodic) tx urb
* that could use this fifo. (dma complicates it...)
* That's already done for bulk RX transfers.
*
* if (bulk && qh->ring.next != &musb->out_bulk), then
* we have a candidate... NAKing is *NOT* an error
@ -1358,6 +1354,50 @@ finish:
#endif
/* Schedule next QH from musb->in_bulk and move the current qh to
* the end; avoids starvation for other endpoints.
*/
static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep)
{
struct dma_channel *dma;
struct urb *urb;
void __iomem *mbase = musb->mregs;
void __iomem *epio = ep->regs;
struct musb_qh *cur_qh, *next_qh;
u16 rx_csr;
musb_ep_select(mbase, ep->epnum);
dma = is_dma_capable() ? ep->rx_channel : NULL;
/* clear nak timeout bit */
rx_csr = musb_readw(epio, MUSB_RXCSR);
rx_csr |= MUSB_RXCSR_H_WZC_BITS;
rx_csr &= ~MUSB_RXCSR_DATAERROR;
musb_writew(epio, MUSB_RXCSR, rx_csr);
cur_qh = first_qh(&musb->in_bulk);
if (cur_qh) {
urb = next_urb(cur_qh);
if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) {
dma->status = MUSB_DMA_STATUS_CORE_ABORT;
musb->dma_controller->channel_abort(dma);
urb->actual_length += dma->actual_len;
dma->actual_len = 0L;
}
musb_save_toggle(ep, 1, urb);
/* move cur_qh to end of queue */
list_move_tail(&cur_qh->ring, &musb->in_bulk);
/* get the next qh from musb->in_bulk */
next_qh = first_qh(&musb->in_bulk);
/* set rx_reinit and schedule the next qh */
ep->rx_reinit = 1;
musb_start_urb(musb, 1, next_qh);
}
}
/*
* Service an RX interrupt for the given IN endpoint; docs cover bulk, iso,
* and high-bandwidth IN transfer cases.
@ -1421,18 +1461,26 @@ void musb_host_rx(struct musb *musb, u8 epnum)
} else if (rx_csr & MUSB_RXCSR_DATAERROR) {
if (USB_ENDPOINT_XFER_ISOC != qh->type) {
/* NOTE this code path would be a good place to PAUSE a
* transfer, if there's some other (nonperiodic) rx urb
* that could use this fifo. (dma complicates it...)
*
* if (bulk && qh->ring.next != &musb->in_bulk), then
* we have a candidate... NAKing is *NOT* an error
*/
DBG(6, "RX end %d NAK timeout\n", epnum);
/* NOTE: NAKing is *NOT* an error, so we want to
* continue. Except ... if there's a request for
* another QH, use that instead of starving it.
*
* Devices like Ethernet and serial adapters keep
* reads posted at all times, which will starve
* other devices without this logic.
*/
if (usb_pipebulk(urb->pipe)
&& qh->mux == 1
&& !list_is_singular(&musb->in_bulk)) {
musb_bulk_rx_nak_timeout(musb, hw_ep);
return;
}
musb_ep_select(mbase, epnum);
musb_writew(epio, MUSB_RXCSR,
MUSB_RXCSR_H_WZC_BITS
| MUSB_RXCSR_H_REQPKT);
rx_csr |= MUSB_RXCSR_H_WZC_BITS;
rx_csr &= ~MUSB_RXCSR_DATAERROR;
musb_writew(epio, MUSB_RXCSR, rx_csr);
goto finish;
} else {
@ -1711,31 +1759,27 @@ static int musb_schedule(
/* else, periodic transfers get muxed to other endpoints */
/* FIXME this doesn't consider direction, so it can only
* work for one half of the endpoint hardware, and assumes
* the previous cases handled all non-shared endpoints...
*/
/* we know this qh hasn't been scheduled, so all we need to do
/*
* We know this qh hasn't been scheduled, so all we need to do
* is choose which hardware endpoint to put it on ...
*
* REVISIT what we really want here is a regular schedule tree
* like e.g. OHCI uses, but for now musb->periodic is just an
* array of the _single_ logical endpoint associated with a
* given physical one (identity mapping logical->physical).
*
* that simplistic approach makes TT scheduling a lot simpler;
* there is none, and thus none of its complexity...
* like e.g. OHCI uses.
*/
best_diff = 4096;
best_end = -1;
for (epnum = 1; epnum < musb->nr_endpoints; epnum++) {
for (epnum = 1, hw_ep = musb->endpoints + 1;
epnum < musb->nr_endpoints;
epnum++, hw_ep++) {
int diff;
if (musb->periodic[epnum])
if (is_in || hw_ep->is_shared_fifo) {
if (hw_ep->in_qh != NULL)
continue;
} else if (hw_ep->out_qh != NULL)
continue;
hw_ep = &musb->endpoints[epnum];
if (hw_ep == musb->bulk_ep)
continue;
@ -1756,6 +1800,17 @@ static int musb_schedule(
head = &musb->in_bulk;
else
head = &musb->out_bulk;
/* Enable bulk RX NAK timeout scheme when bulk requests are
* multiplexed. This scheme doen't work in high speed to full
* speed scenario as NAK interrupts are not coming from a
* full speed device connected to a high speed device.
* NAK timeout interval is 8 (128 uframe or 16ms) for HS and
* 4 (8 frame or 8ms) for FS device.
*/
if (is_in && qh->dev)
qh->intv_reg =
(USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
goto success;
} else if (best_end < 0) {
return -ENOSPC;
@ -1764,7 +1819,6 @@ static int musb_schedule(
idle = 1;
qh->mux = 0;
hw_ep = musb->endpoints + best_end;
musb->periodic[best_end] = qh;
DBG(4, "qh %p periodic slot %d\n", qh, best_end);
success:
if (head) {
@ -1888,13 +1942,11 @@ static int musb_urb_enqueue(
*
* The downside of disabling this is that transfer scheduling
* gets VERY unfair for nonperiodic transfers; a misbehaving
* peripheral could make that hurt. Or for reads, one that's
* perfectly normal: network and other drivers keep reads
* posted at all times, having one pending for a week should
* be perfectly safe.
* peripheral could make that hurt. That's perfectly normal
* for reads from network or serial adapters ... so we have
* partial NAKlimit support for bulk RX.
*
* The upside of disabling it is avoidng transfer scheduling
* code to put this aside for while.
* The upside of disabling it is simpler transfer scheduling.
*/
interval = 0;
}

Просмотреть файл

@ -285,7 +285,7 @@ int musb_hub_control(
desc->bDescLength = 9;
desc->bDescriptorType = 0x29;
desc->bNbrPorts = 1;
desc->wHubCharacteristics = __constant_cpu_to_le16(
desc->wHubCharacteristics = cpu_to_le16(
0x0001 /* per-port power switching */
| 0x0010 /* no overcurrent reporting */
);

Просмотреть файл

@ -43,7 +43,7 @@ config ISP1301_OMAP
config TWL4030_USB
tristate "TWL4030 USB Transceiver Driver"
depends on TWL4030_CORE
depends on TWL4030_CORE && REGULATOR_TWL4030
select USB_OTG_UTILS
help
Enable this to support the USB OTG transceiver on TWL4030
@ -51,4 +51,12 @@ config TWL4030_USB
This transceiver supports high and full speed devices plus,
in host mode, low speed.
config NOP_USB_XCEIV
tristate "NOP USB Transceiver Driver"
select USB_OTG_UTILS
help
this driver is to be used by all the usb transceiver which are either
built-in with usb ip or which are autonomous and doesn't require any
phy programming such as ISP1x04 etc.
endif # USB || OTG

Просмотреть файл

@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o
obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG
ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG

Просмотреть файл

@ -13,6 +13,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <linux/regulator/consumer.h>
@ -34,6 +35,7 @@ struct gpio_vbus_data {
struct regulator *vbus_draw;
int vbus_draw_enabled;
unsigned mA;
struct work_struct work;
};
@ -76,24 +78,26 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
gpio_vbus->mA = mA;
}
/* VBUS change IRQ handler */
static irqreturn_t gpio_vbus_irq(int irq, void *data)
static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
{
struct platform_device *pdev = data;
struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
int gpio, vbus;
int vbus;
vbus = gpio_get_value(pdata->gpio_vbus);
if (pdata->gpio_vbus_inverted)
vbus = !vbus;
dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
vbus ? "supplied" : "inactive",
gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
return vbus;
}
static void gpio_vbus_work(struct work_struct *work)
{
struct gpio_vbus_data *gpio_vbus =
container_of(work, struct gpio_vbus_data, work);
struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
int gpio;
if (!gpio_vbus->otg.gadget)
return IRQ_HANDLED;
return;
/* Peripheral controllers which manage the pullup themselves won't have
* gpio_pullup configured here. If it's configured here, we'll do what
@ -101,7 +105,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data)
* that may complicate usb_gadget_{,dis}connect() support.
*/
gpio = pdata->gpio_pullup;
if (vbus) {
if (is_vbus_powered(pdata)) {
gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
usb_gadget_vbus_connect(gpio_vbus->otg.gadget);
@ -121,6 +125,21 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data)
usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
gpio_vbus->otg.state = OTG_STATE_B_IDLE;
}
}
/* VBUS change IRQ handler */
static irqreturn_t gpio_vbus_irq(int irq, void *data)
{
struct platform_device *pdev = data;
struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
is_vbus_powered(pdata) ? "supplied" : "inactive",
gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
if (gpio_vbus->otg.gadget)
schedule_work(&gpio_vbus->work);
return IRQ_HANDLED;
}
@ -257,6 +276,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
irq, err);
goto err_irq;
}
INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
/* only active when a gadget is registered */
err = otg_set_transceiver(&gpio_vbus->otg);

Просмотреть файл

@ -0,0 +1,180 @@
/*
* drivers/usb/otg/nop-usb-xceiv.c
*
* NOP USB transceiver for all USB transceiver which are either built-in
* into USB IP or which are mostly autonomous.
*
* Copyright (C) 2009 Texas Instruments Inc
* Author: Ajay Kumar Gupta <ajay.gupta@ti.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Current status:
* this is to add "nop" transceiver for all those phy which is
* autonomous such as isp1504 etc.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/otg.h>
struct nop_usb_xceiv {
struct otg_transceiver otg;
struct device *dev;
};
static u64 nop_xceiv_dmamask = DMA_32BIT_MASK;
static struct platform_device nop_xceiv_device = {
.name = "nop_usb_xceiv",
.id = -1,
.dev = {
.dma_mask = &nop_xceiv_dmamask,
.coherent_dma_mask = DMA_32BIT_MASK,
.platform_data = NULL,
},
};
void usb_nop_xceiv_register(void)
{
if (platform_device_register(&nop_xceiv_device) < 0) {
printk(KERN_ERR "Unable to register usb nop transceiver\n");
return;
}
}
void usb_nop_xceiv_unregister(void)
{
platform_device_unregister(&nop_xceiv_device);
}
static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x)
{
return container_of(x, struct nop_usb_xceiv, otg);
}
static int nop_set_suspend(struct otg_transceiver *x, int suspend)
{
return 0;
}
static int nop_set_peripheral(struct otg_transceiver *x,
struct usb_gadget *gadget)
{
struct nop_usb_xceiv *nop;
if (!x)
return -ENODEV;
nop = xceiv_to_nop(x);
if (!gadget) {
nop->otg.gadget = NULL;
return -ENODEV;
}
nop->otg.gadget = gadget;
nop->otg.state = OTG_STATE_B_IDLE;
return 0;
}
static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host)
{
struct nop_usb_xceiv *nop;
if (!x)
return -ENODEV;
nop = xceiv_to_nop(x);
if (!host) {
nop->otg.host = NULL;
return -ENODEV;
}
nop->otg.host = host;
return 0;
}
static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop;
int err;
nop = kzalloc(sizeof *nop, GFP_KERNEL);
if (!nop)
return -ENOMEM;
nop->dev = &pdev->dev;
nop->otg.dev = nop->dev;
nop->otg.label = "nop-xceiv";
nop->otg.state = OTG_STATE_UNDEFINED;
nop->otg.set_host = nop_set_host;
nop->otg.set_peripheral = nop_set_peripheral;
nop->otg.set_suspend = nop_set_suspend;
err = otg_set_transceiver(&nop->otg);
if (err) {
dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
err);
goto exit;
}
platform_set_drvdata(pdev, nop);
return 0;
exit:
kfree(nop);
return err;
}
static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
{
struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
otg_set_transceiver(NULL);
platform_set_drvdata(pdev, NULL);
kfree(nop);
return 0;
}
static struct platform_driver nop_usb_xceiv_driver = {
.probe = nop_usb_xceiv_probe,
.remove = __devexit_p(nop_usb_xceiv_remove),
.driver = {
.name = "nop_usb_xceiv",
.owner = THIS_MODULE,
},
};
static int __init nop_usb_xceiv_init(void)
{
return platform_driver_register(&nop_usb_xceiv_driver);
}
subsys_initcall(nop_usb_xceiv_init);
static void __exit nop_usb_xceiv_exit(void)
{
platform_driver_unregister(&nop_usb_xceiv_driver);
}
module_exit(nop_usb_xceiv_exit);
MODULE_ALIAS("platform:nop_usb_xceiv");
MODULE_AUTHOR("Texas Instruments Inc");
MODULE_DESCRIPTION("NOP USB Transceiver driver");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -34,6 +34,8 @@
#include <linux/delay.h>
#include <linux/usb/otg.h>
#include <linux/i2c/twl4030.h>
#include <linux/regulator/consumer.h>
#include <linux/err.h>
/* Register defines */
@ -246,6 +248,11 @@ struct twl4030_usb {
struct otg_transceiver otg;
struct device *dev;
/* TWL4030 internal USB regulator supplies */
struct regulator *usb1v5;
struct regulator *usb1v8;
struct regulator *usb3v1;
/* for vbus reporting with irqs disabled */
spinlock_t lock;
@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
pwr = twl4030_usb_read(twl, PHY_PWR_CTRL);
if (on) {
regulator_enable(twl->usb3v1);
regulator_enable(twl->usb1v8);
/*
* Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
* in twl4030) resets the VUSB_DEDICATED2 register. This reset
* enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to
* SLEEP. We work around this by clearing the bit after usv3v1
* is re-activated. This ensures that VUSB3V1 is really active.
*/
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
VUSB_DEDICATED2);
regulator_enable(twl->usb1v5);
pwr &= ~PHY_PWR_PHYPWD;
WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
twl4030_usb_write(twl, PHY_CLK_CTRL,
@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
} else {
pwr |= PHY_PWR_PHYPWD;
WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0);
regulator_disable(twl->usb1v5);
regulator_disable(twl->usb1v8);
regulator_disable(twl->usb3v1);
}
}
@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
twl->asleep = 0;
}
static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
{
/* Enable writing to power configuration registers */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY);
@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl)
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
/* turn on 3.1V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP);
/* Initialize 3.1V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
if (IS_ERR(twl->usb3v1))
return -ENODEV;
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
/* turn on 1.5V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP);
/* Initialize 1.5V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
if (IS_ERR(twl->usb1v5))
goto fail1;
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
/* turn on 1.8V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP);
/* Initialize 1.8V regulator */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
if (IS_ERR(twl->usb1v8))
goto fail2;
twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
/* disable access to power configuration registers */
twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY);
return 0;
fail2:
regulator_put(twl->usb1v5);
twl->usb1v5 = NULL;
fail1:
regulator_put(twl->usb3v1);
twl->usb3v1 = NULL;
return -ENODEV;
}
static ssize_t twl4030_usb_vbus_show(struct device *dev,
@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
{
struct twl4030_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
int status;
int status, err;
if (!pdata) {
dev_dbg(&pdev->dev, "platform_data not available\n");
@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev)
/* init spinlock for workqueue */
spin_lock_init(&twl->lock);
twl4030_usb_ldo_init(twl);
err = twl4030_usb_ldo_init(twl);
if (err) {
dev_err(&pdev->dev, "ldo init failed\n");
kfree(twl);
return err;
}
otg_set_transceiver(&twl->otg);
platform_set_drvdata(pdev, twl);
@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
twl4030_phy_power(twl, 0);
regulator_put(twl->usb1v5);
regulator_put(twl->usb1v8);
regulator_put(twl->usb3v1);
kfree(twl);

Просмотреть файл

@ -116,14 +116,14 @@ config USB_SERIAL_DIGI_ACCELEPORT
To compile this driver as a module, choose M here: the
module will be called digi_acceleport.
config USB_SERIAL_CP2101
tristate "USB CP2101 UART Bridge Controller"
config USB_SERIAL_CP210X
tristate "USB CP210x family of UART Bridge Controllers"
help
Say Y here if you want to use a CP2101/CP2102 based USB to RS232
converter.
Say Y here if you want to use a CP2101/CP2102/CP2103 based USB
to RS232 converters.
To compile this driver as a module, choose M here: the
module will be called cp2101.
module will be called cp210x.
config USB_SERIAL_CYPRESS_M8
tristate "USB Cypress M8 USB Serial Driver"
@ -472,6 +472,15 @@ config USB_SERIAL_OTI6858
To compile this driver as a module, choose M here: the
module will be called oti6858.
config USB_SERIAL_QUALCOMM
tristate "USB Qualcomm Serial modem"
help
Say Y here if you have a Qualcomm USB modem device. These are
usually wireless cellular modems.
To compile this driver as a module, choose M here: the
module will be called qcserial.
config USB_SERIAL_SPCP8X5
tristate "USB SPCP8x5 USB To Serial Driver"
help
@ -515,6 +524,15 @@ config USB_SERIAL_SIERRAWIRELESS
To compile this driver as a module, choose M here: the
module will be called sierra.
config USB_SERIAL_SYMBOL
tristate "USB Symbol Barcode driver (serial mode)"
help
Say Y here if you want to use a Symbol USB Barcode device
in serial emulation mode.
To compile this driver as a module, choose M here: the
module will be called symbolserial.
config USB_SERIAL_TI
tristate "USB TI 3410/5052 Serial Driver"
help

Просмотреть файл

@ -15,7 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o
@ -45,10 +45,12 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o
obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o
obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o

Просмотреть файл

@ -1,5 +1,7 @@
/*
* Copyright 2007, Frank A Kingswood <frank@kingswood-consulting.co.uk>
* Copyright 2007, Werner Cornelius <werner@cornelius-consult.de>
* Copyright 2009, Boris Hajduk <boris@hajduk.org>
*
* ch341.c implements a serial port driver for the Winchiphead CH341.
*
@ -21,9 +23,39 @@
#include <linux/usb/serial.h>
#include <linux/serial.h>
#define DEFAULT_BAUD_RATE 2400
#define DEFAULT_BAUD_RATE 9600
#define DEFAULT_TIMEOUT 1000
/* flags for IO-Bits */
#define CH341_BIT_RTS (1 << 6)
#define CH341_BIT_DTR (1 << 5)
/******************************/
/* interrupt pipe definitions */
/******************************/
/* always 4 interrupt bytes */
/* first irq byte normally 0x08 */
/* second irq byte base 0x7d + below */
/* third irq byte base 0x94 + below */
/* fourth irq byte normally 0xee */
/* second interrupt byte */
#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */
/* status returned in third interrupt answer byte, inverted in data
from irq */
#define CH341_BIT_CTS 0x01
#define CH341_BIT_DSR 0x02
#define CH341_BIT_RI 0x04
#define CH341_BIT_DCD 0x08
#define CH341_BITS_MODEM_STAT 0x0f /* all bits */
/*******************************/
/* baudrate calculation factor */
/*******************************/
#define CH341_BAUDBASE_FACTOR 1532620800
#define CH341_BAUDBASE_DIVMAX 3
static int debug;
static struct usb_device_id id_table [] = {
@ -34,9 +66,12 @@ static struct usb_device_id id_table [] = {
MODULE_DEVICE_TABLE(usb, id_table);
struct ch341_private {
unsigned baud_rate;
u8 dtr;
u8 rts;
spinlock_t lock; /* access lock */
wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
unsigned baud_rate; /* set baud rate */
u8 line_control; /* set line control value RTS/DTR */
u8 line_status; /* active status of modem control inputs */
u8 multi_status_change; /* status changed multiple since last call */
};
static int ch341_control_out(struct usb_device *dev, u8 request,
@ -72,37 +107,28 @@ static int ch341_set_baudrate(struct usb_device *dev,
{
short a, b;
int r;
unsigned long factor;
short divisor;
dbg("ch341_set_baudrate(%d)", priv->baud_rate);
switch (priv->baud_rate) {
case 2400:
a = 0xd901;
b = 0x0038;
break;
case 4800:
a = 0x6402;
b = 0x001f;
break;
case 9600:
a = 0xb202;
b = 0x0013;
break;
case 19200:
a = 0xd902;
b = 0x000d;
break;
case 38400:
a = 0x6403;
b = 0x000a;
break;
case 115200:
a = 0xcc03;
b = 0x0008;
break;
default:
if (!priv->baud_rate)
return -EINVAL;
factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate);
divisor = CH341_BAUDBASE_DIVMAX;
while ((factor > 0xfff0) && divisor) {
factor >>= 3;
divisor--;
}
if (factor > 0xfff0)
return -EINVAL;
factor = 0x10000 - factor;
a = (factor & 0xff00) | divisor;
b = factor & 0xff;
r = ch341_control_out(dev, 0x9a, 0x1312, a);
if (!r)
r = ch341_control_out(dev, 0x9a, 0x0f2c, b);
@ -110,19 +136,18 @@ static int ch341_set_baudrate(struct usb_device *dev,
return r;
}
static int ch341_set_handshake(struct usb_device *dev,
struct ch341_private *priv)
static int ch341_set_handshake(struct usb_device *dev, u8 control)
{
dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts);
return ch341_control_out(dev, 0xa4,
~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0);
dbg("ch341_set_handshake(0x%02x)", control);
return ch341_control_out(dev, 0xa4, ~control, 0);
}
static int ch341_get_status(struct usb_device *dev)
static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv)
{
char *buffer;
int r;
const unsigned size = 8;
unsigned long flags;
dbg("ch341_get_status()");
@ -134,10 +159,15 @@ static int ch341_get_status(struct usb_device *dev)
if (r < 0)
goto out;
/* Not having the datasheet for the CH341, we ignore the bytes returned
* from the device. Return error if the device did not respond in time.
*/
r = 0;
/* setup the private status if available */
if (r == 2) {
r = 0;
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT;
priv->multi_status_change = 0;
spin_unlock_irqrestore(&priv->lock, flags);
} else
r = -EPROTO;
out: kfree(buffer);
return r;
@ -180,7 +210,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
goto out;
/* expect 0xff 0xee */
r = ch341_get_status(dev);
r = ch341_get_status(dev, priv);
if (r < 0)
goto out;
@ -192,12 +222,12 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv)
if (r < 0)
goto out;
r = ch341_set_handshake(dev, priv);
r = ch341_set_handshake(dev, priv->line_control);
if (r < 0)
goto out;
/* expect 0x9f 0xee */
r = ch341_get_status(dev);
r = ch341_get_status(dev, priv);
out: kfree(buffer);
return r;
@ -216,9 +246,10 @@ static int ch341_attach(struct usb_serial *serial)
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->delta_msr_wait);
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->dtr = 1;
priv->rts = 1;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
r = ch341_configure(serial->dev, priv);
if (r < 0)
@ -231,6 +262,35 @@ error: kfree(priv);
return r;
}
static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int c_cflag;
dbg("%s - port %d", __func__, port->number);
/* shutdown our urbs */
dbg("%s - shutting down urbs", __func__);
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
if (tty) {
c_cflag = tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_handshake(port->serial->dev, 0);
}
}
wake_up_interruptible(&priv->delta_msr_wait);
}
/* open this device, set default parameters */
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
@ -242,14 +302,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
dbg("ch341_open()");
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->dtr = 1;
priv->rts = 1;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
r = ch341_configure(serial->dev, priv);
if (r)
goto out;
r = ch341_set_handshake(serial->dev, priv);
r = ch341_set_handshake(serial->dev, priv->line_control);
if (r)
goto out;
@ -257,6 +316,16 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
if (r)
goto out;
dbg("%s - submitting interrupt urb", __func__);
port->interrupt_in_urb->dev = serial->dev;
r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (r) {
dev_err(&port->dev, "%s - failed submitting interrupt urb,"
" error %d\n", __func__, r);
ch341_close(tty, port, NULL);
return -EPROTO;
}
r = usb_serial_generic_open(tty, port, filp);
out: return r;
@ -270,46 +339,224 @@ static void ch341_set_termios(struct tty_struct *tty,
{
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned baud_rate;
unsigned long flags;
dbg("ch341_set_termios()");
if (!tty || !tty->termios)
return;
baud_rate = tty_get_baud_rate(tty);
switch (baud_rate) {
case 2400:
case 4800:
case 9600:
case 19200:
case 38400:
case 115200:
priv->baud_rate = baud_rate;
break;
default:
dbg("Rate %d not supported, using %d",
baud_rate, DEFAULT_BAUD_RATE);
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->baud_rate = baud_rate;
if (baud_rate) {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS);
spin_unlock_irqrestore(&priv->lock, flags);
ch341_set_baudrate(port->serial->dev, priv);
} else {
spin_lock_irqsave(&priv->lock, flags);
priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS);
spin_unlock_irqrestore(&priv->lock, flags);
}
ch341_set_baudrate(port->serial->dev, priv);
ch341_set_handshake(port->serial->dev, priv->line_control);
/* Unimplemented:
* (cflag & CSIZE) : data bits [5, 8]
* (cflag & PARENB) : parity {NONE, EVEN, ODD}
* (cflag & CSTOPB) : stop bits [1, 2]
*/
}
/* Copy back the old hardware settings */
tty_termios_copy_hw(tty->termios, old_termios);
/* And re-encode with the new baud */
tty_encode_baud_rate(tty, baud_rate, baud_rate);
static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 control;
spin_lock_irqsave(&priv->lock, flags);
if (set & TIOCM_RTS)
priv->line_control |= CH341_BIT_RTS;
if (set & TIOCM_DTR)
priv->line_control |= CH341_BIT_DTR;
if (clear & TIOCM_RTS)
priv->line_control &= ~CH341_BIT_RTS;
if (clear & TIOCM_DTR)
priv->line_control &= ~CH341_BIT_DTR;
control = priv->line_control;
spin_unlock_irqrestore(&priv->lock, flags);
return ch341_set_handshake(port->serial->dev, control);
}
static void ch341_read_int_callback(struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
unsigned char *data = urb->transfer_buffer;
unsigned int actual_length = urb->actual_length;
int status;
dbg("%s (%d)", __func__, port->number);
switch (urb->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__,
urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d", __func__,
urb->status);
goto exit;
}
usb_serial_debug_data(debug, &port->dev, __func__,
urb->actual_length, urb->transfer_buffer);
if (actual_length >= 4) {
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT;
if ((data[1] & CH341_MULT_STAT))
priv->multi_status_change = 1;
spin_unlock_irqrestore(&priv->lock, flags);
wake_up_interruptible(&priv->delta_msr_wait);
}
exit:
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
dev_err(&urb->dev->dev,
"%s - usb_submit_urb failed with result %d\n",
__func__, status);
}
static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 prevstatus;
u8 status;
u8 changed;
u8 multi_change = 0;
spin_lock_irqsave(&priv->lock, flags);
prevstatus = priv->line_status;
priv->multi_status_change = 0;
spin_unlock_irqrestore(&priv->lock, flags);
while (!multi_change) {
interruptible_sleep_on(&priv->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
multi_change = priv->multi_status_change;
spin_unlock_irqrestore(&priv->lock, flags);
changed = prevstatus ^ status;
if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) ||
((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) ||
((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) ||
((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) {
return 0;
}
prevstatus = status;
}
return 0;
}
/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/
static int ch341_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd);
switch (cmd) {
case TIOCMIWAIT:
dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
return wait_modem_info(port, arg);
default:
dbg("%s not supported = 0x%04x", __func__, cmd);
break;
}
return -ENOIOCTLCMD;
}
static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
{
struct usb_serial_port *port = tty->driver_data;
struct ch341_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
u8 mcr;
u8 status;
unsigned int result;
dbg("%s (%d)", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags);
mcr = priv->line_control;
status = priv->line_status;
spin_unlock_irqrestore(&priv->lock, flags);
result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0)
| ((mcr & CH341_BIT_RTS) ? TIOCM_RTS : 0)
| ((status & CH341_BIT_CTS) ? TIOCM_CTS : 0)
| ((status & CH341_BIT_DSR) ? TIOCM_DSR : 0)
| ((status & CH341_BIT_RI) ? TIOCM_RI : 0)
| ((status & CH341_BIT_DCD) ? TIOCM_CD : 0);
dbg("%s - result = %x", __func__, result);
return result;
}
static int ch341_reset_resume(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev(intf);
struct usb_serial *serial = NULL;
struct ch341_private *priv;
serial = usb_get_intfdata(intf);
priv = usb_get_serial_port_data(serial->port[0]);
/*reconfigure ch341 serial port after bus-reset*/
ch341_configure(dev, priv);
usb_serial_resume(intf);
return 0;
}
static struct usb_driver ch341_driver = {
.name = "ch341",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
.reset_resume = ch341_reset_resume,
.id_table = id_table,
.no_dynamic_id = 1,
.supports_autosuspend = 1,
};
static struct usb_serial_driver ch341_device = {
@ -317,12 +564,17 @@ static struct usb_serial_driver ch341_device = {
.owner = THIS_MODULE,
.name = "ch341-uart",
},
.id_table = id_table,
.usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
.set_termios = ch341_set_termios,
.attach = ch341_attach,
.id_table = id_table,
.usb_driver = &ch341_driver,
.num_ports = 1,
.open = ch341_open,
.close = ch341_close,
.ioctl = ch341_ioctl,
.set_termios = ch341_set_termios,
.tiocmget = ch341_tiocmget,
.tiocmset = ch341_tiocmset,
.read_int_callback = ch341_read_int_callback,
.attach = ch341_attach,
};
static int __init ch341_init(void)

Просмотреть файл

@ -11,10 +11,6 @@
* thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
* control thanks to Munir Nassar nassarmu@real-time.com
*
* Outstanding Issues:
* Buffers are not flushed when the port is opened.
* Multiple calls to write() may fail with "Resource temporarily unavailable"
*
*/
#include <linux/kernel.h>
@ -31,7 +27,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.07"
#define DRIVER_VERSION "v0.08"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
@ -42,17 +38,21 @@ static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
static void cp2101_cleanup(struct usb_serial_port *);
static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
struct file*);
static void cp2101_get_termios(struct tty_struct *);
static void cp2101_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp2101_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp2101_tiocmget(struct tty_struct *, struct file *);
static int cp2101_tiocmset(struct tty_struct *, struct file *,
unsigned int, unsigned int);
static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *,
unsigned int, unsigned int);
static void cp2101_break_ctl(struct tty_struct *, int);
static int cp2101_startup(struct usb_serial *);
static void cp2101_shutdown(struct usb_serial *);
static int debug;
static struct usb_device_id id_table [] = {
@ -91,6 +91,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
@ -225,7 +226,7 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request,
kfree(buf);
if (result != size) {
dev_err(&port->dev, "%s - Unable to send config request, "
dbg("%s - Unable to send config request, "
"request=0x%x size=%d result=%d\n",
__func__, request, size, result);
return -EPROTO;
@ -276,7 +277,7 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request,
kfree(buf);
if ((size > 2 && result != size) || result < 0) {
dev_err(&port->dev, "%s - Unable to send request, "
dbg("%s - Unable to send request, "
"request=0x%x size=%d result=%d\n",
__func__, request, size, result);
return -EPROTO;
@ -301,6 +302,47 @@ static inline int cp2101_set_config_single(struct usb_serial_port *port,
return cp2101_set_config(port, request, &data, 2);
}
/*
* cp2101_quantise_baudrate
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp2101_quantise_baudrate(unsigned int baud) {
if (baud <= 56) baud = 0;
else if (baud <= 300) baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
else if (baud <= 2400) baud = 2400;
else if (baud <= 4000) baud = 4000;
else if (baud <= 4803) baud = 4800;
else if (baud <= 7207) baud = 7200;
else if (baud <= 9612) baud = 9600;
else if (baud <= 14428) baud = 14400;
else if (baud <= 16062) baud = 16000;
else if (baud <= 19250) baud = 19200;
else if (baud <= 28912) baud = 28800;
else if (baud <= 38601) baud = 38400;
else if (baud <= 51558) baud = 51200;
else if (baud <= 56280) baud = 56000;
else if (baud <= 58053) baud = 57600;
else if (baud <= 64111) baud = 64000;
else if (baud <= 77608) baud = 76800;
else if (baud <= 117028) baud = 115200;
else if (baud <= 129347) baud = 128000;
else if (baud <= 156868) baud = 153600;
else if (baud <= 237832) baud = 230400;
else if (baud <= 254234) baud = 250000;
else if (baud <= 273066) baud = 256000;
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
else if (baud <= 1053257) baud = 921600;
else if (baud <= 1474560) baud = 1228800;
else if (baud <= 2457600) baud = 1843200;
else baud = 3686400;
return baud;
}
static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
struct file *filp)
{
@ -331,10 +373,12 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port,
}
/* Configure the termios structure */
cp2101_get_termios(tty);
cp2101_get_termios(tty, port);
/* Set the DTR and RTS pins low */
cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0);
cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data
: port,
NULL, TIOCM_DTR | TIOCM_RTS, 0);
return 0;
}
@ -376,9 +420,31 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
* from the device, corrects any unsupported values, and configures the
* termios structure to reflect the state of the device
*/
static void cp2101_get_termios (struct tty_struct *tty)
static void cp2101_get_termios(struct tty_struct *tty,
struct usb_serial_port *port)
{
unsigned int baud;
if (tty) {
cp2101_get_termios_port(tty->driver_data,
&tty->termios->c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
}
else {
unsigned int cflag;
cflag = 0;
cp2101_get_termios_port(port, &cflag, &baud);
}
}
/*
* cp2101_get_termios_port
* This is the heart of cp2101_get_termios which always uses a &usb_serial_port.
*/
static void cp2101_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int cflag, modem_ctl[4];
unsigned int baud;
unsigned int bits;
@ -388,12 +454,12 @@ static void cp2101_get_termios (struct tty_struct *tty)
cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
/* Convert to baudrate */
if (baud)
baud = BAUD_RATE_GEN_FREQ / baud;
baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
tty_encode_baud_rate(tty, baud, baud);
cflag = tty->termios->c_cflag;
cflag = *cflagp;
cp2101_get_config(port, CP2101_BITS, &bits, 2);
cflag &= ~CSIZE;
@ -499,7 +565,7 @@ static void cp2101_get_termios (struct tty_struct *tty)
cflag &= ~CRTSCTS;
}
tty->termios->c_cflag = cflag;
*cflagp = cflag;
}
static void cp2101_set_termios(struct tty_struct *tty,
@ -517,46 +583,16 @@ static void cp2101_set_termios(struct tty_struct *tty,
tty->termios->c_cflag &= ~CMSPAR;
cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
baud = tty_get_baud_rate(tty);
baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty));
/* If the baud rate is to be updated*/
if (baud != tty_termios_baud_rate(old_termios)) {
switch (baud) {
case 0:
case 600:
case 1200:
case 1800:
case 2400:
case 4800:
case 7200:
case 9600:
case 14400:
case 19200:
case 28800:
case 38400:
case 55854:
case 57600:
case 115200:
case 127117:
case 230400:
case 460800:
case 921600:
case 3686400:
break;
default:
baud = 9600;
break;
}
if (baud) {
dbg("%s - Setting baud rate to %d baud", __func__,
baud);
if (cp2101_set_config_single(port, CP2101_BAUDRATE,
(BAUD_RATE_GEN_FREQ / baud))) {
dev_err(&port->dev, "Baud rate requested not "
"supported by device\n");
baud = tty_termios_baud_rate(old_termios);
}
if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
dbg("%s - Setting baud rate to %d baud", __func__,
baud);
if (cp2101_set_config_single(port, CP2101_BAUDRATE,
((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
dbg("Baud rate requested not supported by device\n");
baud = tty_termios_baud_rate(old_termios);
}
}
/* Report back the resulting baud rate */
@ -588,14 +624,14 @@ static void cp2101_set_termios(struct tty_struct *tty,
dbg("%s - data bits = 9", __func__);
break;*/
default:
dev_err(&port->dev, "cp2101 driver does not "
dbg("cp2101 driver does not "
"support the number of bits requested,"
" using 8 bit mode\n");
bits |= BITS_DATA_8;
break;
}
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Number of data bits requested "
dbg("Number of data bits requested "
"not supported by device\n");
}
@ -612,7 +648,7 @@ static void cp2101_set_termios(struct tty_struct *tty,
}
}
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Parity mode not supported "
dbg("Parity mode not supported "
"by device\n");
}
@ -627,7 +663,7 @@ static void cp2101_set_termios(struct tty_struct *tty,
dbg("%s - stop bits = 1", __func__);
}
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Number of stop bits requested "
dbg("Number of stop bits requested "
"not supported by device\n");
}
@ -661,6 +697,12 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
return cp2101_tiocmset_port(port, file, set, clear);
}
static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
unsigned int control = 0;
dbg("%s - port %d", __func__, port->number);
@ -685,7 +727,6 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file,
dbg("%s - control = 0x%.4x", __func__, control);
return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
}
static int cp2101_tiocmget (struct tty_struct *tty, struct file *file)

Просмотреть файл

@ -1938,18 +1938,16 @@ static void ftdi_process_read(struct work_struct *work)
/* Compare new line status to the old one, signal if different/
N.B. packet may be processed more than once, but differences
are only processed once. */
if (priv != NULL) {
char new_status = data[packet_offset + 0] &
FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
priv->diff_status |=
new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
char new_status = data[packet_offset + 0] &
FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
priv->diff_status |=
new_status ^ priv->prev_status;
wake_up_interruptible(&priv->delta_msr_wait);
priv->prev_status = new_status;
}
length = min(PKTSZ, urb->actual_length-packet_offset)-2;
length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2;
if (length < 0) {
dev_err(&port->dev, "%s - bad packet length: %d\n",
__func__, length+2);
@ -2294,11 +2292,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, 0,
buf, 1, WDR_TIMEOUT);
if (ret < 0) {
dbg("%s Could not get modem status of device - err: %d", __func__,
ret);
if (ret < 0)
return ret;
}
break;
case FT8U232AM:
case FT232BM:
@ -2313,15 +2308,11 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
0, priv->interface,
buf, 2, WDR_TIMEOUT);
if (ret < 0) {
dbg("%s Could not get modem status of device - err: %d", __func__,
ret);
if (ret < 0)
return ret;
}
break;
default:
return -EFAULT;
break;
}
return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |

Просмотреть файл

@ -177,14 +177,6 @@ int usb_serial_generic_resume(struct usb_serial *serial)
struct usb_serial_port *port;
int i, c = 0, r;
#ifdef CONFIG_PM
/*
* If this is an autoresume, don't submit URBs.
* They will be submitted in the open function instead.
*/
if (serial->dev->auto_pm)
return 0;
#endif
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
if (port->port.count && port->read_urb) {
@ -196,6 +188,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
return c ? -EIO : 0;
}
EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
void usb_serial_generic_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp)

Просмотреть файл

@ -78,6 +78,7 @@ static int ipaq_open(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static void ipaq_close(struct tty_struct *tty,
struct usb_serial_port *port, struct file *filp);
static int ipaq_calc_num_ports(struct usb_serial *serial);
static int ipaq_startup(struct usb_serial *serial);
static void ipaq_shutdown(struct usb_serial *serial);
static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port,
@ -572,15 +573,10 @@ static struct usb_serial_driver ipaq_device = {
.description = "PocketPC PDA",
.usb_driver = &ipaq_driver,
.id_table = ipaq_id_table,
/*
* some devices have an extra endpoint, which
* must be ignored as it would make the core
* create a second port which oopses when used
*/
.num_ports = 1,
.open = ipaq_open,
.close = ipaq_close,
.attach = ipaq_startup,
.calc_num_ports = ipaq_calc_num_ports,
.shutdown = ipaq_shutdown,
.write = ipaq_write,
.write_room = ipaq_write_room,
@ -956,14 +952,49 @@ static void ipaq_destroy_lists(struct usb_serial_port *port)
}
static int ipaq_calc_num_ports(struct usb_serial *serial)
{
/*
* some devices have 3 endpoints, the 3rd of which
* must be ignored as it would make the core
* create a second port which oopses when used
*/
int ipaq_num_ports = 1;
dbg("%s - numberofendpoints: %d", __FUNCTION__,
(int)serial->interface->cur_altsetting->desc.bNumEndpoints);
/*
* a few devices have 4 endpoints, seemingly Yakuma devices,
* and we need the second pair, so let them have 2 ports
*
* TODO: can we drop port 1 ?
*/
if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) {
ipaq_num_ports = 2;
}
return ipaq_num_ports;
}
static int ipaq_startup(struct usb_serial *serial)
{
dbg("%s", __func__);
if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
/*
* FIXME: HP iPaq rx3715, possibly others, have 1 config that
* is labeled as 2
*/
dev_err(&serial->dev->dev, "active config #%d != 1 ??\n",
serial->dev->actconfig->desc.bConfigurationValue);
return -ENODEV;
}
dbg("%s - iPAQ module configured for %d ports",
__FUNCTION__, serial->num_ports);
return usb_reset_configuration(serial->dev);
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше