summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/Kconfig2
-rw-r--r--drivers/usb/atm/cxacru.c12
-rw-r--r--drivers/usb/atm/speedtch.c19
-rw-r--r--drivers/usb/atm/ueagle-atm.c18
-rw-r--r--drivers/usb/class/cdc-acm.c12
-rw-r--r--drivers/usb/class/usblp.c55
-rw-r--r--drivers/usb/core/Kconfig15
-rw-r--r--drivers/usb/core/buffer.c2
-rw-r--r--drivers/usb/core/devices.c9
-rw-r--r--drivers/usb/core/devio.c10
-rw-r--r--drivers/usb/core/driver.c304
-rw-r--r--drivers/usb/core/endpoint.c98
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c259
-rw-r--r--drivers/usb/core/hub.h41
-rw-r--r--drivers/usb/core/inode.c4
-rw-r--r--drivers/usb/core/message.c17
-rw-r--r--drivers/usb/core/usb.c169
-rw-r--r--drivers/usb/core/usb.h9
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/at91_udc.c238
-rw-r--r--drivers/usb/gadget/at91_udc.h7
-rw-r--r--drivers/usb/gadget/dummy_hcd.c7
-rw-r--r--drivers/usb/gadget/ether.c10
-rw-r--r--drivers/usb/gadget/file_storage.c20
-rw-r--r--drivers/usb/gadget/gmidi.c14
-rw-r--r--drivers/usb/gadget/goku_udc.c14
-rw-r--r--drivers/usb/gadget/inode.c6
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c14
-rw-r--r--drivers/usb/gadget/net2280.c21
-rw-r--r--drivers/usb/gadget/net2280.h3
-rw-r--r--drivers/usb/gadget/omap_udc.c260
-rw-r--r--drivers/usb/gadget/omap_udc.h3
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c9
-rw-r--r--drivers/usb/gadget/serial.c8
-rw-r--r--drivers/usb/gadget/zero.c2
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-dbg.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c16
-rw-r--r--drivers/usb/host/ehci-hub.c104
-rw-r--r--drivers/usb/host/ehci-pci.c40
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/host/hc_crisv10.c18
-rw-r--r--drivers/usb/host/ohci-at91.c3
-rw-r--r--drivers/usb/host/ohci-au1xxx.c4
-rw-r--r--drivers/usb/host/ohci-dbg.c10
-rw-r--r--drivers/usb/host/ohci-ep93xx.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c125
-rw-r--r--drivers/usb/host/ohci-hub.c193
-rw-r--r--drivers/usb/host/ohci-lh7a404.c8
-rw-r--r--drivers/usb/host/ohci-mem.c10
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-pci.c16
-rw-r--r--drivers/usb/host/ohci-pnx4008.c6
-rw-r--r--drivers/usb/host/ohci-pnx8550.c258
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c8
-rw-r--r--drivers/usb/host/ohci-pxa27x.c10
-rw-r--r--drivers/usb/host/ohci-q.c103
-rw-r--r--drivers/usb/host/ohci-s3c2410.c4
-rw-r--r--drivers/usb/host/ohci-sa1111.c8
-rw-r--r--drivers/usb/host/ohci.h92
-rw-r--r--drivers/usb/host/sl811_cs.c15
-rw-r--r--drivers/usb/host/u132-hcd.c168
-rw-r--r--drivers/usb/host/uhci-hcd.c35
-rw-r--r--drivers/usb/host/uhci-hub.c14
-rw-r--r--drivers/usb/host/uhci-q.c2
-rw-r--r--drivers/usb/image/microtek.c8
-rw-r--r--drivers/usb/input/Kconfig30
-rw-r--r--drivers/usb/input/Makefile3
-rw-r--r--drivers/usb/input/acecad.c2
-rw-r--r--drivers/usb/input/aiptek.c2
-rw-r--r--drivers/usb/input/appletouch.c95
-rw-r--r--drivers/usb/input/ati_remote.c13
-rw-r--r--drivers/usb/input/ati_remote2.c3
-rw-r--r--drivers/usb/input/hid-core.c1480
-rw-r--r--drivers/usb/input/hid-debug.h757
-rw-r--r--drivers/usb/input/hid-ff.c8
-rw-r--r--drivers/usb/input/hid-input.c868
-rw-r--r--drivers/usb/input/hid-lgff.c7
-rw-r--r--drivers/usb/input/hid-pidff.c58
-rw-r--r--drivers/usb/input/hid-tmff.c5
-rw-r--r--drivers/usb/input/hid-zpff.c7
-rw-r--r--drivers/usb/input/hid.h538
-rw-r--r--drivers/usb/input/hiddev.c37
-rw-r--r--drivers/usb/input/keyspan_remote.c2
-rw-r--r--drivers/usb/input/mtouchusb.c2
-rw-r--r--drivers/usb/input/powermate.c4
-rw-r--r--drivers/usb/input/touchkitusb.c2
-rw-r--r--drivers/usb/input/usbhid.h84
-rw-r--r--drivers/usb/input/usbkbd.c18
-rw-r--r--drivers/usb/input/usbmouse.c8
-rw-r--r--drivers/usb/input/usbtouchscreen.c98
-rw-r--r--drivers/usb/input/wacom.h1
-rw-r--r--drivers/usb/input/wacom_sys.c6
-rw-r--r--drivers/usb/input/wacom_wac.c26
-rw-r--r--drivers/usb/input/xpad.c2
-rw-r--r--drivers/usb/input/yealink.c12
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/appledisplay.c18
-rw-r--r--drivers/usb/misc/auerswald.c17
-rw-r--r--drivers/usb/misc/emi26.c3
-rw-r--r--drivers/usb/misc/emi62.c3
-rw-r--r--drivers/usb/misc/ftdi-elan.c698
-rw-r--r--drivers/usb/misc/idmouse.c22
-rw-r--r--drivers/usb/misc/legousbtower.c31
-rw-r--r--drivers/usb/misc/phidgetkit.c30
-rw-r--r--drivers/usb/misc/phidgetmotorcontrol.c20
-rw-r--r--drivers/usb/misc/phidgetservo.c1
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c2
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c12
-rw-r--r--drivers/usb/misc/trancevibrator.c2
-rw-r--r--drivers/usb/misc/usb_u132.h6
-rw-r--r--drivers/usb/misc/usbtest.c40
-rw-r--r--drivers/usb/misc/uss720.c2
-rw-r--r--drivers/usb/mon/mon_text.c10
-rw-r--r--drivers/usb/net/asix.c8
-rw-r--r--drivers/usb/net/catc.c14
-rw-r--r--drivers/usb/net/cdc_ether.c3
-rw-r--r--drivers/usb/net/gl620a.c154
-rw-r--r--drivers/usb/net/kaweth.c9
-rw-r--r--drivers/usb/net/net1080.c6
-rw-r--r--drivers/usb/net/pegasus.c9
-rw-r--r--drivers/usb/net/pegasus.h2
-rw-r--r--drivers/usb/net/rndis_host.c2
-rw-r--r--drivers/usb/net/rtl8150.c8
-rw-r--r--drivers/usb/net/usbnet.c15
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c22
-rw-r--r--drivers/usb/serial/airprime.c4
-rw-r--r--drivers/usb/serial/ark3116.c7
-rw-r--r--drivers/usb/serial/belkin_sa.c4
-rw-r--r--drivers/usb/serial/console.c8
-rw-r--r--drivers/usb/serial/cp2101.c5
-rw-r--r--drivers/usb/serial/cypress_m8.c36
-rw-r--r--drivers/usb/serial/digi_acceleport.c26
-rw-r--r--drivers/usb/serial/empeg.c4
-rw-r--r--drivers/usb/serial/ezusb.c3
-rw-r--r--drivers/usb/serial/ftdi_sio.c27
-rw-r--r--drivers/usb/serial/ftdi_sio.h5
-rw-r--r--drivers/usb/serial/funsoft.c27
-rw-r--r--drivers/usb/serial/garmin_gps.c3
-rw-r--r--drivers/usb/serial/io_edgeport.c12
-rw-r--r--drivers/usb/serial/io_ti.c8
-rw-r--r--drivers/usb/serial/ipaq.c2
-rw-r--r--drivers/usb/serial/ipw.c3
-rw-r--r--drivers/usb/serial/ir-usb.c4
-rw-r--r--drivers/usb/serial/keyspan.c20
-rw-r--r--drivers/usb/serial/keyspan.h2
-rw-r--r--drivers/usb/serial/keyspan_pda.c24
-rw-r--r--drivers/usb/serial/kl5kusb105.c74
-rw-r--r--drivers/usb/serial/kobil_sct.c23
-rw-r--r--drivers/usb/serial/mct_u232.c10
-rw-r--r--drivers/usb/serial/mos7720.c6
-rw-r--r--drivers/usb/serial/mos7840.c17
-rw-r--r--drivers/usb/serial/navman.c3
-rw-r--r--drivers/usb/serial/option.c10
-rw-r--r--drivers/usb/serial/pl2303.c6
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c11
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h1
-rw-r--r--drivers/usb/serial/usb-serial.c21
-rw-r--r--drivers/usb/serial/usb_debug.c65
-rw-r--r--drivers/usb/serial/visor.c7
-rw-r--r--drivers/usb/serial/whiteheat.c25
-rw-r--r--drivers/usb/storage/onetouch.c9
-rw-r--r--drivers/usb/storage/sddr09.c2
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/storage/unusual_devs.h43
-rw-r--r--drivers/usb/storage/usb.c10
170 files changed, 3375 insertions, 5552 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index f9b1719b9a37..9980a4ddfed9 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI
default y if ARCH_S3C2410
default y if PXA27x
default y if ARCH_EP93XX
- default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
+ default y if ARCH_AT91
default y if ARCH_PNX4008
# PPC:
default y if STB03xxx
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index e6565633ba0f..3dfa3e40e148 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -158,7 +158,7 @@ struct cxacru_data {
const struct cxacru_modem_type *modem_type;
int line_status;
- struct work_struct poll_work;
+ struct delayed_work poll_work;
/* contol handles */
struct mutex cm_serialize;
@@ -347,7 +347,7 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0;
}
-static void cxacru_poll_status(struct cxacru_data *instance);
+static void cxacru_poll_status(struct work_struct *work);
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
@@ -376,12 +376,14 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
}
/* Start status polling */
- cxacru_poll_status(instance);
+ cxacru_poll_status(&instance->poll_work.work);
return 0;
}
-static void cxacru_poll_status(struct cxacru_data *instance)
+static void cxacru_poll_status(struct work_struct *work)
{
+ struct cxacru_data *instance =
+ container_of(work, struct cxacru_data, poll_work.work);
u32 buf[CXINF_MAX] = {};
struct usbatm_data *usbatm = instance->usbatm;
struct atm_dev *atm_dev = usbatm->atm_dev;
@@ -720,7 +722,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
mutex_init(&instance->cm_serialize);
- INIT_WORK(&instance->poll_work, (void *)cxacru_poll_status, instance);
+ INIT_DELAYED_WORK(&instance->poll_work, cxacru_poll_status);
usbatm_instance->driver_data = instance;
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index c870c804470f..8ed6c75adf0f 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -142,7 +142,7 @@ struct speedtch_instance_data {
struct speedtch_params params; /* set in probe, constant afterwards */
- struct work_struct status_checker;
+ struct delayed_work status_checker;
unsigned char last_status;
@@ -498,8 +498,11 @@ static int speedtch_start_synchro(struct speedtch_instance_data *instance)
return ret;
}
-static void speedtch_check_status(struct speedtch_instance_data *instance)
+static void speedtch_check_status(struct work_struct *work)
{
+ struct speedtch_instance_data *instance =
+ container_of(work, struct speedtch_instance_data,
+ status_checker.work);
struct usbatm_data *usbatm = instance->usbatm;
struct atm_dev *atm_dev = usbatm->atm_dev;
unsigned char *buf = instance->scratch_buffer;
@@ -576,7 +579,7 @@ static void speedtch_status_poll(unsigned long data)
{
struct speedtch_instance_data *instance = (void *)data;
- schedule_work(&instance->status_checker);
+ schedule_delayed_work(&instance->status_checker, 0);
/* The following check is racy, but the race is harmless */
if (instance->poll_delay < MAX_POLL_DELAY)
@@ -596,7 +599,7 @@ static void speedtch_resubmit_int(unsigned long data)
if (int_urb) {
ret = usb_submit_urb(int_urb, GFP_ATOMIC);
if (!ret)
- schedule_work(&instance->status_checker);
+ schedule_delayed_work(&instance->status_checker, 0);
else {
atm_dbg(instance->usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
mod_timer(&instance->resubmit_timer, jiffies + msecs_to_jiffies(RESUBMIT_DELAY));
@@ -640,7 +643,7 @@ static void speedtch_handle_int(struct urb *int_urb)
if ((int_urb = instance->int_urb)) {
ret = usb_submit_urb(int_urb, GFP_ATOMIC);
- schedule_work(&instance->status_checker);
+ schedule_delayed_work(&instance->status_checker, 0);
if (ret < 0) {
atm_dbg(usbatm, "%s: usb_submit_urb failed with result %d\n", __func__, ret);
goto fail;
@@ -834,8 +837,8 @@ static int speedtch_bind(struct usbatm_data *usbatm,
const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
if ((endpoint_desc->bEndpointAddress == target_address)) {
- use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_ISOC;
+ use_isoc =
+ usb_endpoint_xfer_isoc(endpoint_desc);
break;
}
}
@@ -855,7 +858,7 @@ static int speedtch_bind(struct usbatm_data *usbatm,
usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
- INIT_WORK(&instance->status_checker, (void *)speedtch_check_status, instance);
+ INIT_DELAYED_WORK(&instance->status_checker, speedtch_check_status);
instance->status_checker.timer.function = speedtch_status_poll;
instance->status_checker.timer.data = (unsigned long)instance;
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index f6b9f7e1f716..dae4ef1e8fe5 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -64,6 +64,8 @@
#include <linux/kthread.h>
#include <linux/version.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
+
#include <asm/unaligned.h>
#include "usbatm.h"
@@ -401,9 +403,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
int ret = -ENOMEM;
u8 *xfer_buff;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(buff, size, GFP_KERNEL);
if (xfer_buff) {
- memcpy(xfer_buff, buff, size);
ret = usb_control_msg(usb,
usb_sndctrlpipe(usb, 0),
LOAD_INTERNAL,
@@ -595,14 +596,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
u8 *xfer_buff;
int bytes_read;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret;
}
- memcpy(xfer_buff, data, size);
-
ret = usb_bulk_msg(sc->usb_dev,
usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
xfer_buff, size, &bytes_read, BULK_TIMEOUT);
@@ -658,9 +657,9 @@ static int request_dsp(struct uea_softc *sc)
/*
* The uea_load_page() function must be called within a process context
*/
-static void uea_load_page(void *xsc)
+static void uea_load_page(struct work_struct *work)
{
- struct uea_softc *sc = xsc;
+ struct uea_softc *sc = container_of(work, struct uea_softc, task);
u16 pageno = sc->pageno;
u16 ovl = sc->ovl;
struct block_info bi;
@@ -765,12 +764,11 @@ static int uea_request(struct uea_softc *sc,
u8 *xfer_buff;
int ret = -ENOMEM;
- xfer_buff = kmalloc(size, GFP_KERNEL);
+ xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret;
}
- memcpy(xfer_buff, data, size);
ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
UCDC_SEND_ENCAPSULATED_COMMAND,
@@ -1352,7 +1350,7 @@ static int uea_boot(struct uea_softc *sc)
uea_enters(INS_TO_USBDEV(sc));
- INIT_WORK(&sc->task, uea_load_page, sc);
+ INIT_WORK(&sc->task, uea_load_page);
init_waitqueue_head(&sc->sync_q);
init_waitqueue_head(&sc->cmv_ack_wait);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9a9012fd284b..98199628e394 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -421,9 +421,9 @@ static void acm_write_bulk(struct urb *urb)
schedule_work(&acm->work);
}
-static void acm_softint(void *private)
+static void acm_softint(struct work_struct *work)
{
- struct acm *acm = private;
+ struct acm *acm = container_of(work, struct acm, work);
dbg("Entering acm_softint.");
if (!ACM_READY(acm))
@@ -677,10 +677,10 @@ static const __u8 acm_tty_size[] = {
5, 6, 7, 8
};
-static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old)
{
struct acm *acm = tty->driver_data;
- struct termios *termios = tty->termios;
+ struct ktermios *termios = tty->termios;
struct usb_cdc_line_coding newline;
int newctrl = acm->ctrlout;
@@ -892,7 +892,7 @@ skip_normal_probe:
/* workaround for switched endpoints */
- if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
+ if (!usb_endpoint_dir_in(epread)) {
/* descriptors are swapped */
struct usb_endpoint_descriptor *t;
dev_dbg(&intf->dev,"The data interface has switched endpoints");
@@ -927,7 +927,7 @@ skip_normal_probe:
acm->rx_buflimit = num_rx_buf;
acm->urb_task.func = acm_rx_tasklet;
acm->urb_task.data = (unsigned long) acm;
- INIT_WORK(&acm->work, acm_softint, acm);
+ INIT_WORK(&acm->work, acm_softint);
spin_lock_init(&acm->throttle_lock);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 6303970e93c1..6377db1b446d 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -130,7 +130,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
struct usblp {
struct usb_device *dev; /* USB device */
- struct semaphore sem; /* locks this struct, especially "dev" */
+ struct mutex mut; /* locks this struct, especially "dev" */
char *writebuf; /* write transfer_buffer */
char *readbuf; /* read transfer_buffer */
char *statusbuf; /* status transfer_buffer */
@@ -217,6 +217,7 @@ static const struct quirk_printer_struct quirk_printers[] = {
{ 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */
{ 0x0409, 0xf0be, USBLP_QUIRK_BIDIR }, /* NEC Picty920 (HP OEM) */
{ 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */
+ { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@zut.de> */
{ 0, 0 }
};
@@ -465,7 +466,7 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int twoints[2];
int retval = 0;
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
if (!usblp->present) {
retval = -ENODEV;
goto done;
@@ -644,14 +645,14 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
done:
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return retval;
}
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int timeout, rv, err = 0, transfer_length = 0;
+ int timeout, intr, rv, err = 0, transfer_length = 0;
size_t writecount = 0;
while (writecount < count) {
@@ -668,14 +669,16 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (rv < 0)
return writecount ? writecount : -EINTR;
}
- down (&usblp->sem);
+ intr = mutex_lock_interruptible (&usblp->mut);
+ if (intr)
+ return writecount ? writecount : -EINTR;
if (!usblp->present) {
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return -ENODEV;
}
if (usblp->sleeping) {
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return writecount ? writecount : -ENODEV;
}
@@ -687,10 +690,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
err = usblp->writeurb->status;
} else
err = usblp_check_status(usblp, err);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
/* if the fault was due to disconnect, let khubd's
- * call to usblp_disconnect() grab usblp->sem ...
+ * call to usblp_disconnect() grab usblp->mut ...
*/
schedule ();
continue;
@@ -702,7 +705,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
*/
writecount += transfer_length;
if (writecount == count) {
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
break;
}
@@ -714,7 +717,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
if (copy_from_user(usblp->writeurb->transfer_buffer,
buffer + writecount, transfer_length)) {
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
return writecount ? writecount : -EFAULT;
}
@@ -727,10 +730,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
count = -EIO;
else
count = writecount ? writecount : -ENOMEM;
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
break;
}
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
}
return count;
@@ -739,12 +742,14 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int rv;
+ int rv, intr;
if (!usblp->bidir)
return -EINVAL;
- down (&usblp->sem);
+ intr = mutex_lock_interruptible (&usblp->mut);
+ if (intr)
+ return -EINTR;
if (!usblp->present) {
count = -ENODEV;
goto done;
@@ -757,9 +762,9 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
count = -EAGAIN;
goto done;
}
- up(&usblp->sem);
+ mutex_unlock(&usblp->mut);
rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
- down(&usblp->sem);
+ mutex_lock(&usblp->mut);
if (rv < 0) {
count = -EINTR;
goto done;
@@ -807,7 +812,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
}
done:
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
return count;
}
@@ -886,7 +891,7 @@ static int usblp_probe(struct usb_interface *intf,
goto abort;
}
usblp->dev = dev;
- init_MUTEX (&usblp->sem);
+ mutex_init (&usblp->mut);
init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usblp->intf = intf;
@@ -1178,7 +1183,7 @@ static void usblp_disconnect(struct usb_interface *intf)
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
usblp->present = 0;
usb_set_intfdata (intf, NULL);
@@ -1187,7 +1192,7 @@ static void usblp_disconnect(struct usb_interface *intf)
usblp->writebuf, usblp->writeurb->transfer_dma);
usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
usblp->readbuf, usblp->readurb->transfer_dma);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
if (!usblp->used)
usblp_cleanup (usblp);
@@ -1200,11 +1205,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
/* this races against normal access and open */
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
/* we take no more IO */
usblp->sleeping = 1;
usblp_unlink_urbs(usblp);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return 0;
@@ -1216,12 +1221,12 @@ static int usblp_resume (struct usb_interface *intf)
int r;
mutex_lock (&usblp_mutex);
- down (&usblp->sem);
+ mutex_lock (&usblp->mut);
usblp->sleeping = 0;
r = handle_bidir (usblp);
- up (&usblp->sem);
+ mutex_unlock (&usblp->mut);
mutex_unlock (&usblp_mutex);
return r;
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 6e3b5358a760..f8324d8d06ac 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -72,6 +72,21 @@ config USB_SUSPEND
If you are unsure about this, say N here.
+config USB_MULTITHREAD_PROBE
+ bool "USB Multi-threaded probe (EXPERIMENTAL)"
+ depends on USB && EXPERIMENTAL
+ default n
+ help
+ Say Y here if you want the USB core to spawn a new thread for
+ every USB device that is probed. This can cause a small speedup
+ in boot times on systems with a lot of different USB devices.
+
+ This option should be safe to enable, but if any odd probing
+ problems are found, please disable it, or dynamically turn it
+ off in the /sys/module/usbcore/parameters/multithread_probe
+ file
+
+ When in doubt, say N.
config USB_OTG
bool
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 840442a25b61..c3915dc28608 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -93,7 +93,7 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
}
-/* sometimes alloc/free could use kmalloc with SLAB_DMA, for
+/* sometimes alloc/free could use kmalloc with GFP_DMA, for
* better sharing and to leverage mm/slab.c intelligence.
*/
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 3538c2fdadfe..ea398e5d50af 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor (
)
{
char dir, unit, *type;
- unsigned interval, in, bandwidth = 1;
+ unsigned interval, bandwidth = 1;
if (start > end)
return start;
- in = (desc->bEndpointAddress & USB_DIR_IN);
- dir = in ? 'I' : 'O';
+
+ dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
+
if (speed == USB_SPEED_HIGH) {
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break;
@@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
break;
case USB_ENDPOINT_XFER_BULK:
type = "Bulk";
- if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+ if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
interval = desc->bInterval;
else
interval = 0;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index fed92be63b5e..4b3a6ab29bd3 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
dev = inode->i_private;
if (!dev)
goto out;
- ret = usb_autoresume_device(dev, 1);
+ ret = usb_autoresume_device(dev);
if (ret)
goto out;
@@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
releaseintf(ps, ifnum);
}
destroy_all_async(ps);
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
usb_unlock_device(dev);
usb_put_dev(dev);
put_pid(ps->disc_pid);
@@ -962,7 +962,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
kfree(dr);
return -EFAULT;
}
- snoop(&ps->dev->dev, "control urb\n");
+ snoop(&ps->dev->dev, "control urb: bRequest=%02x "
+ "bRrequestType=%02x wValue=%04x "
+ "wIndex=%04x wLength=%04x\n",
+ dr->bRequest, dr->bRequestType, dr->wValue,
+ dr->wIndex, dr->wLength);
break;
case USBDEVFS_URB_TYPE_BULK:
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 113e484c763e..d6eb5ce1dd1d 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
if (id) {
dev_dbg(dev, "%s - got id\n", __FUNCTION__);
- error = usb_autoresume_device(udev, 1);
+ error = usb_autoresume_device(udev);
if (error)
return error;
@@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
} else
intf->condition = USB_INTERFACE_BOUND;
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
}
return error;
@@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
/* Autoresume for set_interface call below */
udev = interface_to_usbdev(intf);
- error = usb_autoresume_device(udev, 1);
+ error = usb_autoresume_device(udev);
/* release all urbs for this interface */
usb_disable_interface(interface_to_usbdev(intf), intf);
@@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev)
intf->needs_remote_wakeup = 0;
if (!error)
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
return 0;
}
@@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0;
+ /* The interface class, subclass, and protocol should never be
+ * checked for a match if the device class is Vendor Specific,
+ * unless the match record specifies the Vendor ID. */
+ if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
+ !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
+ (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
+ USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
+ return 0;
+
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0;
@@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface,
* most general; they let drivers bind to any interface on a
* multiple-function device. Use the USB_INTERFACE_INFO
* macro, or its siblings, to match class-per-interface style
- * devices (as recorded in bDeviceClass).
+ * devices (as recorded in bInterfaceClass).
+ *
+ * Note that an entry created by USB_INTERFACE_INFO won't match
+ * any interface if the device class is set to Vendor-Specific.
+ * This is deliberate; according to the USB spec the meanings of
+ * the interface class/subclass/protocol for these devices are also
+ * vendor-specific, and hence matching against a standard product
+ * class wouldn't work anyway. If you really want to use an
+ * interface-based match for such a device, create a match record
+ * that also specifies the vendor ID. (Unforunately there isn't a
+ * standard macro for creating records like this.)
*
* Within those groups, remember that not all combinations are
* meaningful. For example, don't give a product version range
@@ -505,7 +525,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
}
EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
-int usb_device_match(struct device *dev, struct device_driver *drv)
+static int usb_device_match(struct device *dev, struct device_driver *drv)
{
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
@@ -790,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
#ifdef CONFIG_PM
/* Caller has locked udev's pm_mutex */
-static int suspend_device(struct usb_device *udev, pm_message_t msg)
+static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
{
struct usb_device_driver *udriver;
int status = 0;
@@ -817,7 +837,7 @@ done:
}
/* Caller has locked udev's pm_mutex */
-static int resume_device(struct usb_device *udev)
+static int usb_resume_device(struct usb_device *udev)
{
struct usb_device_driver *udriver;
int status = 0;
@@ -843,7 +863,7 @@ done:
}
/* Caller has locked intf's usb_device's pm mutex */
-static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
{
struct usb_driver *driver;
int status = 0;
@@ -880,7 +900,7 @@ done:
}
/* Caller has locked intf's usb_device's pm_mutex */
-static int resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf)
{
struct usb_driver *driver;
int status = 0;
@@ -920,6 +940,44 @@ done:
return status;
}
+#ifdef CONFIG_USB_SUSPEND
+
+/* Internal routine to check whether we may autosuspend a device. */
+static int autosuspend_check(struct usb_device *udev)
+{
+ int i;
+ struct usb_interface *intf;
+
+ /* For autosuspend, fail fast if anything is in use.
+ * Also fail if any interfaces require remote wakeup but it
+ * isn't available. */
+ udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+ if (udev->pm_usage_cnt > 0)
+ return -EBUSY;
+ if (udev->actconfig) {
+ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+ intf = udev->actconfig->interface[i];
+ if (!is_active(intf))
+ continue;
+ if (intf->pm_usage_cnt > 0)
+ return -EBUSY;
+ if (intf->needs_remote_wakeup &&
+ !udev->do_remote_wakeup) {
+ dev_dbg(&udev->dev, "remote wakeup needed "
+ "for autosuspend\n");
+ return -EOPNOTSUPP;
+ }
+ }
+ }
+ return 0;
+}
+
+#else
+
+#define autosuspend_check(udev) 0
+
+#endif
+
/**
* usb_suspend_both - suspend a USB device and its interfaces
* @udev: the usb_device to suspend
@@ -971,52 +1029,34 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
- /* For autosuspend, fail fast if anything is in use.
- * Also fail if any interfaces require remote wakeup but it
- * isn't available. */
if (udev->auto_pm) {
- if (udev->pm_usage_cnt > 0)
- return -EBUSY;
- if (udev->actconfig) {
- for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
- intf = udev->actconfig->interface[i];
- if (!is_active(intf))
- continue;
- if (intf->pm_usage_cnt > 0)
- return -EBUSY;
- if (intf->needs_remote_wakeup &&
- !udev->do_remote_wakeup) {
- dev_dbg(&udev->dev,
- "remote wakeup needed for autosuspend\n");
- return -EOPNOTSUPP;
- }
- }
- i = 0;
- }
+ status = autosuspend_check(udev);
+ if (status < 0)
+ return status;
}
/* Suspend all the interfaces and then udev itself */
if (udev->actconfig) {
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
- status = suspend_interface(intf, msg);
+ status = usb_suspend_interface(intf, msg);
if (status != 0)
break;
}
}
if (status == 0)
- status = suspend_device(udev, msg);
+ status = usb_suspend_device(udev, msg);
/* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) {
while (--i >= 0) {
intf = udev->actconfig->interface[i];
- resume_interface(intf);
+ usb_resume_interface(intf);
}
/* If the suspend succeeded, propagate it up the tree */
} else if (parent)
- usb_autosuspend_device(parent, 0);
+ usb_autosuspend_device(parent);
// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
return status;
@@ -1064,9 +1104,25 @@ int usb_resume_both(struct usb_device *udev)
/* Propagate the resume up the tree, if necessary */
if (udev->state == USB_STATE_SUSPENDED) {
if (parent) {
- usb_pm_lock(parent);
- parent->auto_pm = 1;
- status = usb_resume_both(parent);
+ status = usb_autoresume_device(parent);
+ if (status == 0) {
+ status = usb_resume_device(udev);
+ if (status) {
+ usb_autosuspend_device(parent);
+
+ /* It's possible usb_resume_device()
+ * failed after the port was
+ * unsuspended, causing udev to be
+ * logically disconnected. We don't
+ * want usb_disconnect() to autosuspend
+ * the parent again, so tell it that
+ * udev disconnected while still
+ * suspended. */
+ if (udev->state ==
+ USB_STATE_NOTATTACHED)
+ udev->discon_suspended = 1;
+ }
+ }
} else {
/* We can't progagate beyond the USB subsystem,
@@ -1075,24 +1131,20 @@ int usb_resume_both(struct usb_device *udev)
if (udev->dev.parent->power.power_state.event !=
PM_EVENT_ON)
status = -EHOSTUNREACH;
- }
- if (status == 0)
- status = resume_device(udev);
- if (parent)
- usb_pm_unlock(parent);
+ else
+ status = usb_resume_device(udev);
+ }
} else {
/* Needed only for setting udev->dev.power.power_state.event
* and for possible debugging message. */
- status = resume_device(udev);
+ status = usb_resume_device(udev);
}
- /* Now the parent won't suspend until we are finished */
-
if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
- resume_interface(intf);
+ usb_resume_interface(intf);
}
}
@@ -1102,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev)
#ifdef CONFIG_USB_SUSPEND
+/* Internal routine to adjust a device's usage counter and change
+ * its autosuspend state.
+ */
+static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
+{
+ int status = 0;
+
+ usb_pm_lock(udev);
+ udev->pm_usage_cnt += inc_usage_cnt;
+ WARN_ON(udev->pm_usage_cnt < 0);
+ if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
+ udev->auto_pm = 1;
+ status = usb_resume_both(udev);
+ if (status != 0)
+ udev->pm_usage_cnt -= inc_usage_cnt;
+ } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ USB_AUTOSUSPEND_DELAY);
+ usb_pm_unlock(udev);
+ return status;
+}
+
/**
* usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
* @udev: the usb_device to autosuspend
- * @dec_usage_cnt: flag to decrement @udev's PM-usage counter
*
* This routine should be called when a core subsystem is finished using
* @udev and wants to allow it to autosuspend. Examples would be when
* @udev's device file in usbfs is closed or after a configuration change.
*
- * @dec_usage_cnt should be 1 if the subsystem previously incremented
- * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
- * otherwise it should be 0.
- *
- * If the usage counter for @udev or any of its active interfaces is greater
- * than 0, the autosuspend request will not be queued. (If an interface
- * driver does not support autosuspend then its usage counter is permanently
- * positive.) Likewise, if an interface driver requires remote-wakeup
- * capability during autosuspend but remote wakeup is disabled, the
- * autosuspend will fail.
+ * @udev's usage counter is decremented. If it or any of the usage counters
+ * for an active interface is greater than 0, no autosuspend request will be
+ * queued. (If an interface driver does not support autosuspend then its
+ * usage counter is permanently positive.) Furthermore, if an interface
+ * driver requires remote-wakeup capability during autosuspend but remote
+ * wakeup is disabled, the autosuspend will fail.
*
* Often the caller will hold @udev's device lock, but this is not
* necessary.
*
* This routine can run only in process context.
*/
-void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+void usb_autosuspend_device(struct usb_device *udev)
{
- usb_pm_lock(udev);
- udev->pm_usage_cnt -= dec_usage_cnt;
- if (udev->pm_usage_cnt <= 0)
- queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
- USB_AUTOSUSPEND_DELAY);
- usb_pm_unlock(udev);
+ int status;
+
+ status = usb_autopm_do_device(udev, -1);
// dev_dbg(&udev->dev, "%s: cnt %d\n",
// __FUNCTION__, udev->pm_usage_cnt);
}
@@ -1142,44 +1208,59 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
/**
* usb_autoresume_device - immediately autoresume a USB device and its interfaces
* @udev: the usb_device to autoresume
- * @inc_usage_cnt: flag to increment @udev's PM-usage counter
*
* This routine should be called when a core subsystem wants to use @udev
- * and needs to guarantee that it is not suspended. In addition, the
- * caller can prevent @udev from being autosuspended subsequently. (Note
- * that this will not prevent suspend events originating in the PM core.)
- * Examples would be when @udev's device file in usbfs is opened (autosuspend
- * should be prevented until the file is closed) or when a remote-wakeup
- * request is received (later autosuspends should not be prevented).
+ * and needs to guarantee that it is not suspended. No autosuspend will
+ * occur until usb_autosuspend_device is called. (Note that this will not
+ * prevent suspend events originating in the PM core.) Examples would be
+ * when @udev's device file in usbfs is opened or when a remote-wakeup
+ * request is received.
*
- * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
- * autosuspends. This prevention will persist until the usage counter is
- * decremented again (such as by passing 1 to usb_autosuspend_device).
- * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
- * Regardless, if the autoresume fails then the usage counter is not
- * incremented.
+ * @udev's usage counter is incremented to prevent subsequent autosuspends.
+ * However if the autoresume fails then the usage counter is re-decremented.
*
* Often the caller will hold @udev's device lock, but this is not
* necessary (and attempting it might cause deadlock).
*
* This routine can run only in process context.
*/
-int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+int usb_autoresume_device(struct usb_device *udev)
{
int status;
- usb_pm_lock(udev);
- udev->pm_usage_cnt += inc_usage_cnt;
- udev->auto_pm = 1;
- status = usb_resume_both(udev);
- if (status != 0)
- udev->pm_usage_cnt -= inc_usage_cnt;
- usb_pm_unlock(udev);
+ status = usb_autopm_do_device(udev, 1);
// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, udev->pm_usage_cnt);
return status;
}
+/* Internal routine to adjust an interface's usage counter and change
+ * its device's autosuspend state.
+ */
+static int usb_autopm_do_interface(struct usb_interface *intf,
+ int inc_usage_cnt)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ int status = 0;
+
+ usb_pm_lock(udev);
+ if (intf->condition == USB_INTERFACE_UNBOUND)
+ status = -ENODEV;
+ else {
+ intf->pm_usage_cnt += inc_usage_cnt;
+ if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
+ udev->auto_pm = 1;
+ status = usb_resume_both(udev);
+ if (status != 0)
+ intf->pm_usage_cnt -= inc_usage_cnt;
+ } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
+ queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
+ USB_AUTOSUSPEND_DELAY);
+ }
+ usb_pm_unlock(udev);
+ return status;
+}
+
/**
* usb_autopm_put_interface - decrement a USB interface's PM-usage counter
* @intf: the usb_interface whose counter should be decremented
@@ -1213,17 +1294,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
*/
void usb_autopm_put_interface(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
+ int status;
- usb_pm_lock(udev);
- if (intf->condition != USB_INTERFACE_UNBOUND &&
- --intf->pm_usage_cnt <= 0) {
- queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
- USB_AUTOSUSPEND_DELAY);
- }
- usb_pm_unlock(udev);
- // dev_dbg(&intf->dev, "%s: cnt %d\n",
- // __FUNCTION__, intf->pm_usage_cnt);
+ status = usb_autopm_do_interface(intf, -1);
+ // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ // __FUNCTION__, status, intf->pm_usage_cnt);
}
EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
@@ -1260,26 +1335,37 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
*/
int usb_autopm_get_interface(struct usb_interface *intf)
{
- struct usb_device *udev = interface_to_usbdev(intf);
- int status;
+ int status;
- usb_pm_lock(udev);
- if (intf->condition == USB_INTERFACE_UNBOUND)
- status = -ENODEV;
- else {
- ++intf->pm_usage_cnt;
- udev->auto_pm = 1;
- status = usb_resume_both(udev);
- if (status != 0)
- --intf->pm_usage_cnt;
- }
- usb_pm_unlock(udev);
+ status = usb_autopm_do_interface(intf, 1);
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, intf->pm_usage_cnt);
return status;
}
EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+/**
+ * usb_autopm_set_interface - set a USB interface's autosuspend state
+ * @intf: the usb_interface whose state should be set
+ *
+ * This routine sets the autosuspend state of @intf's device according
+ * to @intf's usage counter, which the caller must have set previously.
+ * If the counter is <= 0, the device is autosuspended (if it isn't
+ * already suspended and if nothing else prevents the autosuspend). If
+ * the counter is > 0, the device is autoresumed (if it isn't already
+ * awake).
+ */
+int usb_autopm_set_interface(struct usb_interface *intf)
+{
+ int status;
+
+ status = usb_autopm_do_interface(intf, 0);
+ // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+ // __FUNCTION__, status, intf->pm_usage_cnt);
+ return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
+
#endif /* CONFIG_USB_SUSPEND */
static int usb_suspend(struct device *dev, pm_message_t message)
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 3b2d137912be..5e628ae3aec7 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -10,15 +10,20 @@
*/
#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
#include <linux/usb.h>
#include "usb.h"
-/* endpoint stuff */
+#define MAX_ENDPOINT_MINORS (64*128*32)
+static int usb_endpoint_major;
+static DEFINE_IDR(endpoint_idr);
struct ep_device {
struct usb_endpoint_descriptor *desc;
struct usb_device *udev;
struct device dev;
+ int minor;
};
#define to_ep_device(_dev) \
container_of(_dev, struct ep_device, dev)
@@ -152,6 +157,55 @@ static struct attribute_group ep_dev_attr_grp = {
.attrs = ep_dev_attrs,
};
+static int usb_endpoint_major_init(void)
+{
+ dev_t dev;
+ int error;
+
+ error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
+ "usb_endpoint");
+ if (error) {
+ err("unable to get a dynamic major for usb endpoints");
+ return error;
+ }
+ usb_endpoint_major = MAJOR(dev);
+
+ return error;
+}
+
+static void usb_endpoint_major_cleanup(void)
+{
+ unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
+ MAX_ENDPOINT_MINORS);
+}
+
+static int endpoint_get_minor(struct ep_device *ep_dev)
+{
+ static DEFINE_MUTEX(minor_lock);
+ int retval = -ENOMEM;
+ int id;
+
+ mutex_lock(&minor_lock);
+ if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
+ goto exit;
+
+ retval = idr_get_new(&endpoint_idr, ep_dev, &id);
+ if (retval < 0) {
+ if (retval == -EAGAIN)
+ retval = -ENOMEM;
+ goto exit;
+ }
+ ep_dev->minor = id & MAX_ID_MASK;
+exit:
+ mutex_unlock(&minor_lock);
+ return retval;
+}
+
+static void endpoint_free_minor(struct ep_device *ep_dev)
+{
+ idr_remove(&endpoint_idr, ep_dev->minor);
+}
+
static struct endpoint_class {
struct kref kref;
struct class *class;
@@ -176,11 +230,20 @@ static int init_endpoint_class(void)
ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
if (IS_ERR(ep_class->class)) {
result = IS_ERR(ep_class->class);
- kfree(ep_class);
- ep_class = NULL;
- goto exit;
+ goto class_create_error;
}
+ result = usb_endpoint_major_init();
+ if (result)
+ goto endpoint_major_error;
+
+ goto exit;
+
+endpoint_major_error:
+ class_destroy(ep_class->class);
+class_create_error:
+ kfree(ep_class);
+ ep_class = NULL;
exit:
return result;
}
@@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref)
class_destroy(ep_class->class);
kfree(ep_class);
ep_class = NULL;
+ usb_endpoint_major_cleanup();
}
static void destroy_endpoint_class(void)
@@ -204,6 +268,7 @@ static void ep_device_release(struct device *dev)
struct ep_device *ep_dev = to_ep_device(dev);
dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+ endpoint_free_minor(ep_dev);
kfree(ep_dev);
}
@@ -213,7 +278,6 @@ int usb_create_ep_files(struct device *parent,
{
char name[8];
struct ep_device *ep_dev;
- int minor;
int retval;
retval = init_endpoint_class();
@@ -226,12 +290,16 @@ int usb_create_ep_files(struct device *parent,
goto error_alloc;
}
- /* fun calculation to determine the minor of this endpoint */
- minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
+ retval = endpoint_get_minor(ep_dev);
+ if (retval) {
+ dev_err(parent, "can not allocate minor number for %s",
+ ep_dev->dev.bus_id);
+ goto error_register;
+ }
ep_dev->desc = &endpoint->desc;
ep_dev->udev = udev;
- ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number...
+ ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
ep_dev->dev.class = ep_class->class;
ep_dev->dev.parent = parent;
ep_dev->dev.release = ep_device_release;
@@ -241,7 +309,7 @@ int usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev);
if (retval)
- goto error_register;
+ goto error_chrdev;
retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
if (retval)
goto error_group;
@@ -261,6 +329,9 @@ error_group:
destroy_endpoint_class();
return retval;
+error_chrdev:
+ endpoint_free_minor(ep_dev);
+
error_register:
kfree(ep_dev);
error_alloc:
@@ -271,14 +342,15 @@ exit:
void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
{
+ struct ep_device *ep_dev = endpoint->ep_dev;
- if (endpoint->ep_dev) {
+ if (ep_dev) {
char name[8];
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
- sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
- sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
- device_unregister(&endpoint->ep_dev->dev);
+ sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
+ sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+ device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL;
destroy_endpoint_class();
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index afa2dd203329..10064af65d17 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = {
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
+ * see hub.c:hub_configure() for details. */
+ (USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */
};
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ba165aff9ea4..2651c2e2a89f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -22,6 +22,7 @@
#include <linux/usbdevice_fs.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
+#include <linux/freezer.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -31,6 +32,47 @@
#include "hcd.h"
#include "hub.h"
+struct usb_hub {
+ struct device *intfdev; /* the "interface" device */
+ struct usb_device *hdev;
+ struct urb *urb; /* for interrupt polling pipe */
+
+ /* buffer for urb ... with extra space in case of babble */
+ char (*buffer)[8];
+ dma_addr_t buffer_dma; /* DMA address for buffer */
+ union {
+ struct usb_hub_status hub;
+ struct usb_port_status port;
+ } *status; /* buffer for status reports */
+
+ int error; /* last reported error */
+ int nerrors; /* track consecutive errors */
+
+ struct list_head event_list; /* hubs w/data or errs ready */
+ unsigned long event_bits[1]; /* status change bitmask */
+ unsigned long change_bits[1]; /* ports with logical connect
+ status change */
+ unsigned long busy_bits[1]; /* ports being reset or
+ resumed */
+#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
+#error event_bits[] is too short!
+#endif
+
+ struct usb_hub_descriptor *descriptor; /* class descriptor */
+ struct usb_tt tt; /* Transaction Translator */
+
+ unsigned mA_per_port; /* current for each child */
+
+ unsigned limited_power:1;
+ unsigned quiescing:1;
+ unsigned activating:1;
+
+ unsigned has_indicators:1;
+ u8 indicator[USB_MAXCHILDREN];
+ struct delayed_work leds;
+};
+
+
/* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -45,6 +87,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task;
+/* multithreaded probe logic */
+static int multithread_probe =
+#ifdef CONFIG_USB_MULTITHREAD_PROBE
+ 1;
+#else
+ 0;
+#endif
+module_param(multithread_probe, bool, S_IRUGO);
+MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
+
/* cycle leds on hubs that aren't blinking for attention */
static int blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO);
@@ -167,9 +219,10 @@ static void set_port_led(
#define LED_CYCLE_PERIOD ((2*HZ)/3)
-static void led_work (void *__hub)
+static void led_work (struct work_struct *work)
{
- struct usb_hub *hub = __hub;
+ struct usb_hub *hub =
+ container_of(work, struct usb_hub, leds.work);
struct usb_device *hdev = hub->hdev;
unsigned i;
unsigned changed = 0;
@@ -276,6 +329,9 @@ static void kick_khubd(struct usb_hub *hub)
{
unsigned long flags;
+ /* Suppress autosuspend until khubd runs */
+ to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
+
spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
@@ -351,9 +407,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
* talking to TTs must queue control transfers (not just bulk and iso), so
* both can talk to the same hub concurrently.
*/
-static void hub_tt_kevent (void *arg)
+static void hub_tt_kevent (struct work_struct *work)
{
- struct usb_hub *hub = arg;
+ struct usb_hub *hub =
+ container_of(work, struct usb_hub, tt.kevent);
unsigned long flags;
spin_lock_irqsave (&hub->tt.lock, flags);
@@ -404,7 +461,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
* since each TT has "at least two" buffers that can need it (and
* there can be many TTs per hub). even if they're uncommon.
*/
- if ((clear = kmalloc (sizeof *clear, SLAB_ATOMIC)) == NULL) {
+ if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
/* FIXME recover somehow ... RESET_TT? */
return;
@@ -457,7 +514,6 @@ static void hub_quiesce(struct usb_hub *hub)
/* (nonblocking) khubd and related activity won't re-trigger */
hub->quiescing = 1;
hub->activating = 0;
- hub->resume_root_hub = 0;
/* (blocking) stop khubd and related activity */
usb_kill_urb(hub->urb);
@@ -473,7 +529,7 @@ static void hub_activate(struct usb_hub *hub)
hub->quiescing = 0;
hub->activating = 1;
- hub->resume_root_hub = 0;
+
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -641,7 +697,7 @@ static int hub_configure(struct usb_hub *hub,
spin_lock_init (&hub->tt.lock);
INIT_LIST_HEAD (&hub->tt.clear_list);
- INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub);
+ INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
switch (hdev->descriptor.bDeviceProtocol) {
case 0:
break;
@@ -759,7 +815,12 @@ static int hub_configure(struct usb_hub *hub,
dev_dbg(hub_dev, "%sover-current condition exists\n",
(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
- /* set up the interrupt endpoint */
+ /* set up the interrupt endpoint
+ * We use the EP's maxpacket size instead of (PORTS+1+7)/8
+ * bytes as USB2.0[11.12.3] says because some hubs are known
+ * to send more data (and thus cause overflow). For root hubs,
+ * maxpktsize is defined in hcd.c's fake endpoint descriptors
+ * to be big enough for at least USB_MAXCHILDREN ports. */
pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
@@ -880,9 +941,10 @@ descriptor_error:
INIT_LIST_HEAD(&hub->event_list);
hub->intfdev = &intf->dev;
hub->hdev = hdev;
- INIT_WORK(&hub->leds, led_work, hub);
+ INIT_DELAYED_WORK(&hub->leds, led_work);
usb_set_intfdata (intf, hub);
+ intf->needs_remote_wakeup = 1;
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs++;
@@ -980,6 +1042,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
if (udev->children[i])
recursively_mark_NOTATTACHED(udev->children[i]);
}
+ if (udev->state == USB_STATE_SUSPENDED)
+ udev->discon_suspended = 1;
udev->state = USB_STATE_NOTATTACHED;
}
@@ -1169,6 +1233,14 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
spin_unlock_irq(&device_state_lock);
+ /* Decrement the parent's count of unsuspended children */
+ if (udev->parent) {
+ usb_pm_lock(udev);
+ if (!udev->discon_suspended)
+ usb_autosuspend_device(udev->parent);
+ usb_pm_unlock(udev);
+ }
+
put_device(&udev->dev);
}
@@ -1191,29 +1263,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
static int __usb_port_suspend(struct usb_device *, int port1);
#endif
-/**
- * usb_new_device - perform initial device setup (usbcore-internal)
- * @udev: newly addressed device (in ADDRESS state)
- *
- * This is called with devices which have been enumerated, but not yet
- * configured. The device descriptor is available, but not descriptors
- * for any device configuration. The caller must have locked either
- * the parent hub (if udev is a normal device) or else the
- * usb_bus_list_lock (if udev is a root hub). The parent's pointer to
- * udev has already been installed, but udev is not yet visible through
- * sysfs or other filesystem code.
- *
- * Returns 0 for success (device is configured and listed, with its
- * interfaces, in sysfs); else a negative errno value.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- *
- * Only the hub driver or root-hub registrar should ever call this.
- */
-int usb_new_device(struct usb_device *udev)
+static int __usb_new_device(void *void_data)
{
+ struct usb_device *udev = void_data;
int err;
+ /* Lock ourself into memory in order to keep a probe sequence
+ * sleeping in a new thread from allowing us to be unloaded.
+ */
+ if (!try_module_get(THIS_MODULE))
+ return -EINVAL;
+
err = usb_get_configuration(udev);
if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n",
@@ -1309,13 +1369,56 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}
- return 0;
+ /* Increment the parent's count of unsuspended children */
+ if (udev->parent)
+ usb_autoresume_device(udev->parent);
+
+exit:
+ module_put(THIS_MODULE);
+ return err;
fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
- return err;
+ goto exit;
}
+/**
+ * usb_new_device - perform initial device setup (usbcore-internal)
+ * @udev: newly addressed device (in ADDRESS state)
+ *
+ * This is called with devices which have been enumerated, but not yet
+ * configured. The device descriptor is available, but not descriptors
+ * for any device configuration. The caller must have locked either
+ * the parent hub (if udev is a normal device) or else the
+ * usb_bus_list_lock (if udev is a root hub). The parent's pointer to
+ * udev has already been installed, but udev is not yet visible through
+ * sysfs or other filesystem code.
+ *
+ * The return value for this function depends on if the
+ * multithread_probe variable is set or not. If it's set, it will
+ * return a if the probe thread was successfully created or not. If the
+ * variable is not set, it will return if the device is configured
+ * properly or not. interfaces, in sysfs); else a negative errno value.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only the hub driver or root-hub registrar should ever call this.
+ */
+int usb_new_device(struct usb_device *udev)
+{
+ struct task_struct *probe_task;
+ int ret = 0;
+
+ if (multithread_probe) {
+ probe_task = kthread_run(__usb_new_device, udev,
+ "usb-probe-%s", udev->devnum);
+ if (IS_ERR(probe_task))
+ ret = PTR_ERR(probe_task);
+ } else
+ ret = __usb_new_device(udev);
+
+ return ret;
+}
static int hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change)
@@ -1323,10 +1426,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
int ret;
ret = get_port_status(hub->hdev, port1, &hub->status->port);
- if (ret < 0)
+ if (ret < 4) {
dev_err (hub->intfdev,
"%s failed (err = %d)\n", __FUNCTION__, ret);
- else {
+ if (ret >= 0)
+ ret = -EIO;
+ } else {
*status = le16_to_cpu(hub->status->port.wPortStatus);
*change = le16_to_cpu(hub->status->port.wPortChange);
ret = 0;
@@ -1674,6 +1779,12 @@ static int
hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
{
int status;
+ u16 portchange, portstatus;
+
+ /* Skip the initial Clear-Suspend step for a remote wakeup */
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+ if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
+ goto SuspendCleared;
// dev_dbg(hub->intfdev, "resume port %d\n", port1);
@@ -1687,9 +1798,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
"can't resume port %d, status %d\n",
port1, status);
} else {
- u16 devstatus;
- u16 portchange;
-
/* drive resume for at least 20 msec */
if (udev)
dev_dbg(&udev->dev, "usb %sresume\n",
@@ -1704,16 +1812,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
* stop resume signaling. Then finish the resume
* sequence.
*/
- devstatus = portchange = 0;
- status = hub_port_status(hub, port1,
- &devstatus, &portchange);
+ status = hub_port_status(hub, port1, &portstatus, &portchange);
+SuspendCleared:
if (status < 0
- || (devstatus & LIVE_FLAGS) != LIVE_FLAGS
- || (devstatus & USB_PORT_STAT_SUSPEND) != 0
+ || (portstatus & LIVE_FLAGS) != LIVE_FLAGS
+ || (portstatus & USB_PORT_STAT_SUSPEND) != 0
) {
dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n",
- port1, portchange, devstatus, status);
+ port1, portchange, portstatus, status);
if (status >= 0)
status = -ENODEV;
} else {
@@ -1774,23 +1881,16 @@ static int remote_wakeup(struct usb_device *udev)
{
int status = 0;
- /* All this just to avoid sending a port-resume message
- * to the parent hub! */
-
usb_lock_device(udev);
- usb_pm_lock(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
- /* TRSMRCY = 10 msec */
- msleep(10);
- status = finish_port_resume(udev);
+ status = usb_autoresume_device(udev);
+
+ /* Give the interface drivers a chance to do something,
+ * then autosuspend the device again. */
if (status == 0)
- udev->dev.power.power_state.event = PM_EVENT_ON;
+ usb_autosuspend_device(udev);
}
- usb_pm_unlock(udev);
-
- if (status == 0)
- usb_autoresume_device(udev, 0);
usb_unlock_device(udev);
return status;
}
@@ -1854,6 +1954,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
}
}
+ dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
/* "global suspend" of the downstream HC-to-USB interface */
if (!hdev->parent) {
struct usb_bus *bus = hdev->bus;
@@ -1876,10 +1978,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
static int hub_resume(struct usb_interface *intf)
{
- struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_get_intfdata (intf);
+ struct usb_device *hdev = hub->hdev;
int status;
+ dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
+
/* "global resume" of the downstream HC-to-USB interface */
if (!hdev->parent) {
struct usb_bus *bus = hdev->bus;
@@ -1918,7 +2022,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
{
struct usb_hub *hub = hdev_to_hub(hdev);
- hub->resume_root_hub = 1;
kick_khubd(hub);
}
@@ -2269,7 +2372,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
struct usb_qualifier_descriptor *qual;
int status;
- qual = kmalloc (sizeof *qual, SLAB_KERNEL);
+ qual = kmalloc (sizeof *qual, GFP_KERNEL);
if (qual == NULL)
return;
@@ -2281,7 +2384,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
/* hub LEDs are probably harder to miss than syslog */
if (hub->has_indicators) {
hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
- schedule_work (&hub->leds);
+ schedule_delayed_work (&hub->leds, 0);
}
}
kfree(qual);
@@ -2455,7 +2558,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (hub->has_indicators) {
hub->indicator[port1-1] =
INDICATOR_AMBER_BLINK;
- schedule_work (&hub->leds);
+ schedule_delayed_work (&hub->leds, 0);
}
status = -ENOTCONN; /* Don't retry */
goto loop_disable;
@@ -2555,16 +2658,13 @@ static void hub_events(void)
intf = to_usb_interface(hub->intfdev);
hub_dev = &intf->dev;
- i = hub->resume_root_hub;
-
- dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
+ dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
hdev->state, hub->descriptor
? hub->descriptor->bNbrPorts
: 0,
/* NOTE: expects max 15 ports... */
(u16) hub->change_bits[0],
- (u16) hub->event_bits[0],
- i ? ", resume root" : "");
+ (u16) hub->event_bits[0]);
usb_get_intf(intf);
spin_unlock_irq(&hub_event_lock);
@@ -2585,16 +2685,16 @@ static void hub_events(void)
goto loop;
}
- /* Is this is a root hub wanting to reactivate the downstream
- * ports? If so, be sure the interface resumes even if its
- * stub "device" node was never suspended.
- */
- if (i)
- usb_autoresume_device(hdev, 0);
+ /* Autoresume */
+ ret = usb_autopm_get_interface(intf);
+ if (ret) {
+ dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
+ goto loop;
+ }
- /* If this is an inactive or suspended hub, do nothing */
+ /* If this is an inactive hub, do nothing */
if (hub->quiescing)
- goto loop;
+ goto loop_autopm;
if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n",
@@ -2604,7 +2704,7 @@ static void hub_events(void)
if (ret) {
dev_dbg (hub_dev,
"error resetting hub: %d\n", ret);
- goto loop;
+ goto loop_autopm;
}
hub->nerrors = 0;
@@ -2732,6 +2832,10 @@ static void hub_events(void)
if (!hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hdev->bus);
+loop_autopm:
+ /* Allow autosuspend if we're not going to run again */
+ if (list_empty(&hub->event_list))
+ usb_autopm_enable(intf);
loop:
usb_unlock_device(hdev);
usb_put_intf(intf);
@@ -2773,6 +2877,7 @@ static struct usb_driver hub_driver = {
.post_reset = hub_post_reset,
.ioctl = hub_ioctl,
.id_table = hub_id_table,
+ .supports_autosuspend = 1,
};
int usb_hub_init(void)
@@ -2818,7 +2923,7 @@ static int config_descriptors_changed(struct usb_device *udev)
if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
len = le16_to_cpu(udev->config[index].desc.wTotalLength);
}
- buf = kmalloc (len, SLAB_KERNEL);
+ buf = kmalloc (len, GFP_KERNEL);
if (buf == NULL) {
dev_err(&udev->dev, "no mem to re-read configs after reset\n");
/* assume the worst */
@@ -2997,7 +3102,7 @@ int usb_reset_composite_device(struct usb_device *udev,
}
/* Prevent autosuspend during the reset */
- usb_autoresume_device(udev, 1);
+ usb_autoresume_device(udev);
if (iface && iface->condition != USB_INTERFACE_BINDING)
iface = NULL;
@@ -3040,7 +3145,7 @@ int usb_reset_composite_device(struct usb_device *udev,
}
}
- usb_autosuspend_device(udev, 1);
+ usb_autosuspend_device(udev);
return ret;
}
EXPORT_SYMBOL(usb_reset_composite_device);
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 0f8e82a4d480..cf9559c6c9b6 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -192,45 +192,4 @@ struct usb_tt_clear {
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
-struct usb_hub {
- struct device *intfdev; /* the "interface" device */
- struct usb_device *hdev;
- struct urb *urb; /* for interrupt polling pipe */
-
- /* buffer for urb ... with extra space in case of babble */
- char (*buffer)[8];
- dma_addr_t buffer_dma; /* DMA address for buffer */
- union {
- struct usb_hub_status hub;
- struct usb_port_status port;
- } *status; /* buffer for status reports */
-
- int error; /* last reported error */
- int nerrors; /* track consecutive errors */
-
- struct list_head event_list; /* hubs w/data or errs ready */
- unsigned long event_bits[1]; /* status change bitmask */
- unsigned long change_bits[1]; /* ports with logical connect
- status change */
- unsigned long busy_bits[1]; /* ports being reset or
- resumed */
-#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
-#error event_bits[] is too short!
-#endif
-
- struct usb_hub_descriptor *descriptor; /* class descriptor */
- struct usb_tt tt; /* Transaction Translator */
-
- unsigned mA_per_port; /* current for each child */
-
- unsigned limited_power:1;
- unsigned quiescing:1;
- unsigned activating:1;
- unsigned resume_root_hub:1;
-
- unsigned has_indicators:1;
- enum hub_led_mode indicator[USB_MAXCHILDREN];
- struct work_struct leds;
-};
-
#endif /* __LINUX_HUB_H */
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index b5d6a79af0be..11dad22da41c 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -379,7 +379,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
{
loff_t retval = -EINVAL;
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
+ mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
switch(orig) {
case 0:
if (offset > 0) {
@@ -396,7 +396,7 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
default:
break;
}
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return retval;
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 7729c0744886..149aa8bfb1fe 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -488,7 +488,7 @@ void usb_sg_wait (struct usb_sg_request *io)
int retval;
io->urbs [i]->dev = io->dev;
- retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC);
+ retval = usb_submit_urb (io->urbs [i], GFP_ATOMIC);
/* after we submit, let completions or cancelations fire;
* we handshake using io->status.
@@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
err = -EINVAL;
goto errout;
} else {
- dev->have_langid = -1;
+ 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",
@@ -1398,7 +1398,7 @@ free_interfaces:
}
/* Wake up the device so we can send it the Set-Config request */
- ret = usb_autoresume_device(dev, 1);
+ ret = usb_autoresume_device(dev);
if (ret)
goto free_interfaces;
@@ -1421,7 +1421,7 @@ free_interfaces:
dev->actconfig = cp;
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
goto free_interfaces;
}
usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1490,7 +1490,7 @@ free_interfaces:
usb_create_sysfs_intf_files (intf);
}
- usb_autosuspend_device(dev, 1);
+ usb_autosuspend_device(dev);
return 0;
}
@@ -1501,9 +1501,10 @@ struct set_config_request {
};
/* Worker routine for usb_driver_set_configuration() */
-static void driver_set_config_work(void *_req)
+static void driver_set_config_work(struct work_struct *work)
{
- struct set_config_request *req = _req;
+ struct set_config_request *req =
+ container_of(work, struct set_config_request, work);
usb_lock_device(req->udev);
usb_set_configuration(req->udev, req->config);
@@ -1541,7 +1542,7 @@ int usb_driver_set_configuration(struct usb_device *udev, int config)
return -ENOMEM;
req->udev = udev;
req->config = config;
- INIT_WORK(&req->work, driver_set_config_work, req);
+ INIT_WORK(&req->work, driver_set_config_work);
usb_get_dev(udev);
if (!schedule_work(&req->work)) {
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 467cb02832f3..02426d0b9a34 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -200,19 +200,13 @@ static void ksuspend_usb_cleanup(void)
destroy_workqueue(ksuspend_usb_wq);
}
-#else
-
-#define ksuspend_usb_init() 0
-#define ksuspend_usb_cleanup() do {} while (0)
-
-#endif
-
#ifdef CONFIG_USB_SUSPEND
/* usb_autosuspend_work - callback routine to autosuspend a USB device */
-static void usb_autosuspend_work(void *_udev)
+static void usb_autosuspend_work(struct work_struct *work)
{
- struct usb_device *udev = _udev;
+ struct usb_device *udev =
+ container_of(work, struct usb_device, autosuspend.work);
usb_pm_lock(udev);
udev->auto_pm = 1;
@@ -222,10 +216,17 @@ static void usb_autosuspend_work(void *_udev)
#else
-static void usb_autosuspend_work(void *_udev)
+static void usb_autosuspend_work(struct work_struct *work)
{}
-#endif
+#endif /* CONFIG_USB_SUSPEND */
+
+#else
+
+#define ksuspend_usb_init() 0
+#define ksuspend_usb_cleanup() do {} while (0)
+
+#endif /* CONFIG_PM */
/**
* usb_alloc_dev - usb device constructor (usbcore-internal)
@@ -304,7 +305,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
#ifdef CONFIG_PM
mutex_init(&dev->pm_mutex);
- INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
+ INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work);
#endif
return dev;
}
@@ -537,138 +538,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
return usb_hcd_get_frame_number (dev);
}
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
-{
- return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
-{
- return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
-}
-
/*-------------------------------------------------------------------*/
/*
* __usb_get_extra_descriptor() finds a descriptor of specific type in the
@@ -1102,18 +971,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number);
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
-EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
-EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
-
EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 13322e33f912..17830a81be14 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
#define USB_AUTOSUSPEND_DELAY (HZ*2)
-extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
-extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+extern void usb_autosuspend_device(struct usb_device *udev);
+extern int usb_autoresume_device(struct usb_device *udev);
#else
-#define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0)
-static inline int usb_autoresume_device(struct usb_device *udev,
- int inc_busy_cnt)
+#define usb_autosuspend_device(udev) do {} while (0)
+static inline int usb_autoresume_device(struct usb_device *udev)
{
return 0;
}
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index bbbc82a8336a..4097a86c4b5e 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -189,7 +189,7 @@ config USB_OTG
config USB_GADGET_AT91
boolean "AT91 USB Device Port"
- depends on ARCH_AT91RM9200
+ depends on ARCH_AT91
select USB_GADGET_SELECTED
help
Many Atmel AT91 processors (such as the AT91RM2000) have a
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 72f3db99ff94..812c733ba8ce 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -43,14 +43,16 @@
#include <linux/usb_gadget.h>
#include <asm/byteorder.h>
+#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
-#include <asm/arch/hardware.h>
#include <asm/arch/gpio.h>
#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/at91sam9261_matrix.h>
#include "at91_udc.h"
@@ -78,27 +80,11 @@
static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0";
-/*-------------------------------------------------------------------------*/
-/*
- * Read from a UDP register.
- */
-static inline unsigned long at91_udp_read(unsigned int reg)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- return __raw_readl(udp_base + reg);
-}
-
-/*
- * Write to a UDP register.
- */
-static inline void at91_udp_write(unsigned int reg, unsigned long value)
-{
- void __iomem *udp_base = (void __iomem *)AT91_VA_BASE_UDP;
-
- __raw_writel(value, udp_base + reg);
-}
+#define at91_udp_read(dev, reg) \
+ __raw_readl((dev)->udp_baseaddr + (reg))
+#define at91_udp_write(dev, reg, val) \
+ __raw_writel((val), (dev)->udp_baseaddr + (reg))
/*-------------------------------------------------------------------------*/
@@ -210,13 +196,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
return 0;
}
- tmp = at91_udp_read(AT91_UDP_FRM_NUM);
+ tmp = at91_udp_read(udc, AT91_UDP_FRM_NUM);
seq_printf(s, "frame %05x:%s%s frame=%d\n", tmp,
(tmp & AT91_UDP_FRM_OK) ? " ok" : "",
(tmp & AT91_UDP_FRM_ERR) ? " err" : "",
(tmp & AT91_UDP_NUM));
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
seq_printf(s, "glbstate %02x:%s" FOURBITS "\n", tmp,
(tmp & AT91_UDP_RMWUPE) ? " rmwupe" : "",
(tmp & AT91_UDP_RSMINPR) ? " rsminpr" : "",
@@ -224,13 +210,13 @@ static int proc_udc_show(struct seq_file *s, void *unused)
(tmp & AT91_UDP_CONFG) ? " confg" : "",
(tmp & AT91_UDP_FADDEN) ? " fadden" : "");
- tmp = at91_udp_read(AT91_UDP_FADDR);
+ tmp = at91_udp_read(udc, AT91_UDP_FADDR);
seq_printf(s, "faddr %03x:%s fadd=%d\n", tmp,
(tmp & AT91_UDP_FEN) ? " fen" : "",
(tmp & AT91_UDP_FADD));
- proc_irq_show(s, "imr ", at91_udp_read(AT91_UDP_IMR));
- proc_irq_show(s, "isr ", at91_udp_read(AT91_UDP_ISR));
+ proc_irq_show(s, "imr ", at91_udp_read(udc, AT91_UDP_IMR));
+ proc_irq_show(s, "isr ", at91_udp_read(udc, AT91_UDP_ISR));
if (udc->enabled && udc->vbus) {
proc_ep_show(s, &udc->ep[0]);
@@ -286,6 +272,7 @@ static inline void remove_debug_file(struct at91_udc *udc) {}
static void done(struct at91_ep *ep, struct at91_request *req, int status)
{
unsigned stopped = ep->stopped;
+ struct at91_udc *udc = ep->udc;
list_del_init(&req->queue);
if (req->req.status == -EINPROGRESS)
@@ -301,7 +288,7 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status)
/* ep0 is always ready; other endpoints need a non-empty queue */
if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
- at91_udp_write(AT91_UDP_IDR, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
}
/*-------------------------------------------------------------------------*/
@@ -554,8 +541,8 @@ ok:
* reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
* since endpoint resets don't reset hw pingpong state.
*/
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(dev, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_RST_EP, 0);
local_irq_restore(flags);
return 0;
@@ -564,6 +551,7 @@ ok:
static int at91_ep_disable (struct usb_ep * _ep)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
unsigned long flags;
if (ep == &ep->udc->ep[0])
@@ -579,8 +567,8 @@ static int at91_ep_disable (struct usb_ep * _ep)
/* reset fifos and endpoint */
if (ep->udc->clocked) {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
__raw_writel(0, ep->creg);
}
@@ -598,7 +586,7 @@ at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags)
{
struct at91_request *req;
- req = kcalloc(1, sizeof (struct at91_request), gfp_flags);
+ req = kzalloc(sizeof (struct at91_request), gfp_flags);
if (!req)
return NULL;
@@ -695,10 +683,10 @@ static int at91_ep_queue(struct usb_ep *_ep,
* reconfigures the endpoints.
*/
if (dev->wait_for_config_ack) {
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(dev, AT91_UDP_GLB_STAT);
tmp ^= AT91_UDP_CONFG;
VDBG("toggle config\n");
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(dev, AT91_UDP_GLB_STAT, tmp);
}
if (req->req.length == 0) {
ep0_in_status:
@@ -727,7 +715,7 @@ ep0_in_status:
if (req && !status) {
list_add_tail (&req->queue, &ep->queue);
- at91_udp_write(AT91_UDP_IER, ep->int_mask);
+ at91_udp_write(dev, AT91_UDP_IER, ep->int_mask);
}
done:
local_irq_restore(flags);
@@ -758,6 +746,7 @@ static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
static int at91_ep_set_halt(struct usb_ep *_ep, int value)
{
struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
u32 __iomem *creg;
u32 csr;
unsigned long flags;
@@ -785,8 +774,8 @@ static int at91_ep_set_halt(struct usb_ep *_ep, int value)
csr |= AT91_UDP_FORCESTALL;
VDBG("halt %s\n", ep->ep.name);
} else {
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
csr &= ~AT91_UDP_FORCESTALL;
}
__raw_writel(csr, creg);
@@ -813,9 +802,11 @@ static struct usb_ep_ops at91_ep_ops = {
static int at91_get_frame(struct usb_gadget *gadget)
{
+ struct at91_udc *udc = to_udc(gadget);
+
if (!to_udc(gadget)->clocked)
return -EINVAL;
- return at91_udp_read(AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+ return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
}
static int at91_wakeup(struct usb_gadget *gadget)
@@ -833,11 +824,11 @@ static int at91_wakeup(struct usb_gadget *gadget)
/* NOTE: some "early versions" handle ESR differently ... */
- glbstate = at91_udp_read(AT91_UDP_GLB_STAT);
+ glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
if (!(glbstate & AT91_UDP_ESR))
goto done;
glbstate |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, glbstate);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
done:
local_irq_restore(flags);
@@ -861,6 +852,7 @@ static void udc_reinit(struct at91_udc *udc)
ep->stopped = 0;
ep->fifo_bank = 0;
ep->ep.maxpacket = ep->maxpacket;
+ ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
// initialiser une queue par endpoint
INIT_LIST_HEAD(&ep->queue);
}
@@ -915,14 +907,41 @@ static void pullup(struct at91_udc *udc, int is_on)
if (!udc->enabled || !udc->vbus)
is_on = 0;
DBG("%sactive\n", is_on ? "" : "in");
+
if (is_on) {
clk_on(udc);
- at91_udp_write(AT91_UDP_TXVC, 0);
- at91_set_gpio_value(udc->board.pullup_pin, 1);
- } else {
+ at91_udp_write(udc, AT91_UDP_TXVC, 0);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 1);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc |= AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
+ } else {
stop_activity(udc);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_set_gpio_value(udc->board.pullup_pin, 0);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ if (cpu_is_at91rm9200())
+ at91_set_gpio_value(udc->board.pullup_pin, 0);
+ else if (cpu_is_at91sam9260()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc &= ~AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261()) {
+ u32 usbpucr;
+
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
clk_off(udc);
}
}
@@ -936,7 +955,10 @@ static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
// VDBG("vbus %s\n", is_active ? "on" : "off");
local_irq_save(flags);
udc->vbus = (is_active != 0);
- pullup(udc, is_active);
+ if (udc->driver)
+ pullup(udc, is_active);
+ else
+ pullup(udc, 0);
local_irq_restore(flags);
return 0;
}
@@ -1086,7 +1108,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_SET_CONFIGURATION:
- tmp = at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
if (pkt.r.wValue)
udc->wait_for_config_ack = (tmp == 0);
else
@@ -1103,7 +1125,7 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_GET_STATUS:
tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
- if (at91_udp_read(AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+ if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
PACKET("get device status\n");
__raw_writeb(tmp, dreg);
@@ -1114,17 +1136,17 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
| USB_REQ_SET_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp |= AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
| USB_REQ_CLEAR_FEATURE:
if (w_value != USB_DEVICE_REMOTE_WAKEUP)
goto stall;
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_ESR;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
goto succeed;
/*
@@ -1206,8 +1228,8 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
} else if (ep->is_in)
goto stall;
- at91_udp_write(AT91_UDP_RST_EP, ep->int_mask);
- at91_udp_write(AT91_UDP_RST_EP, 0);
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
tmp = __raw_readl(ep->creg);
tmp |= CLR_FX;
tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
@@ -1222,7 +1244,10 @@ static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
#undef w_length
/* pass request up to the gadget driver */
- status = udc->driver->setup(&udc->gadget, &pkt.r);
+ if (udc->driver)
+ status = udc->driver->setup(&udc->gadget, &pkt.r);
+ else
+ status = -ENODEV;
if (status < 0) {
stall:
VDBG("req %02x.%02x protocol STALL; stat %d\n",
@@ -1300,13 +1325,13 @@ static void handle_ep0(struct at91_udc *udc)
if (udc->wait_for_addr_ack) {
u32 tmp;
- at91_udp_write(AT91_UDP_FADDR,
+ at91_udp_write(udc, AT91_UDP_FADDR,
AT91_UDP_FEN | udc->addr);
- tmp = at91_udp_read(AT91_UDP_GLB_STAT);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
tmp &= ~AT91_UDP_FADDEN;
if (udc->addr)
tmp |= AT91_UDP_FADDEN;
- at91_udp_write(AT91_UDP_GLB_STAT, tmp);
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
udc->wait_for_addr_ack = 0;
VDBG("address %d\n", udc->addr);
@@ -1374,28 +1399,28 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
while (rescans--) {
u32 status;
- status = at91_udp_read(AT91_UDP_ISR)
- & at91_udp_read(AT91_UDP_IMR);
+ status = at91_udp_read(udc, AT91_UDP_ISR)
+ & at91_udp_read(udc, AT91_UDP_IMR);
if (!status)
break;
/* USB reset irq: not maskable */
if (status & AT91_UDP_ENDBUSRES) {
- at91_udp_write(AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
- at91_udp_write(AT91_UDP_IER, MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+ at91_udp_write(udc, AT91_UDP_IER, MINIMUS_INTERRUPTUS);
/* Atmel code clears this irq twice */
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
VDBG("end bus reset\n");
udc->addr = 0;
stop_activity(udc);
/* enable ep0 */
- at91_udp_write(AT91_UDP_CSR(0),
+ at91_udp_write(udc, AT91_UDP_CSR(0),
AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
udc->gadget.speed = USB_SPEED_FULL;
udc->suspended = 0;
- at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0));
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_EP(0));
/*
* NOTE: this driver keeps clocks off unless the
@@ -1406,9 +1431,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated suspend (3+ms bus idle) */
} else if (status & AT91_UDP_RXSUSP) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
// VDBG("bus suspend\n");
if (udc->suspended)
continue;
@@ -1425,9 +1450,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/* host initiated resume */
} else if (status & AT91_UDP_RXRSM) {
- at91_udp_write(AT91_UDP_IDR, AT91_UDP_RXRSM);
- at91_udp_write(AT91_UDP_IER, AT91_UDP_RXSUSP);
- at91_udp_write(AT91_UDP_ICR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_IER, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
// VDBG("bus resume\n");
if (!udc->suspended)
continue;
@@ -1485,8 +1510,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(0)),
.int_mask = 1 << 0,
},
.ep[1] = {
@@ -1497,8 +1520,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(1)),
.int_mask = 1 << 1,
},
.ep[2] = {
@@ -1509,8 +1530,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(2)),
.int_mask = 1 << 2,
},
.ep[3] = {
@@ -1521,8 +1540,6 @@ static struct at91_udc controller = {
},
.udc = &controller,
.maxpacket = 8,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(3)),
.int_mask = 1 << 3,
},
.ep[4] = {
@@ -1533,8 +1550,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(4)),
.int_mask = 1 << 4,
},
.ep[5] = {
@@ -1545,8 +1560,6 @@ static struct at91_udc controller = {
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
- .creg = (void __iomem *)(AT91_VA_BASE_UDP
- + AT91_UDP_CSR(5)),
.int_mask = 1 << 5,
},
/* ep6 and ep7 are also reserved (custom silicon might use them) */
@@ -1572,9 +1585,8 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
int retval;
if (!driver
- || driver->speed != USB_SPEED_FULL
+ || driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->setup) {
DBG("bad parameter.\n");
return -EINVAL;
@@ -1595,6 +1607,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (retval) {
DBG("driver->bind() returned %d\n", retval);
udc->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ udc->gadget.dev.driver_data = NULL;
+ udc->enabled = 0;
+ udc->selfpowered = 0;
return retval;
}
@@ -1611,12 +1627,12 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
{
struct at91_udc *udc = &controller;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
udc->enabled = 0;
- at91_udp_write(AT91_UDP_IDR, ~0);
+ at91_udp_write(udc, AT91_UDP_IDR, ~0);
pullup(udc, 0);
local_irq_enable();
@@ -1641,6 +1657,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct at91_udc *udc;
int retval;
+ struct resource *res;
if (!dev->platform_data) {
/* small (so we copy it) but critical! */
@@ -1658,7 +1675,13 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
return -ENODEV;
}
- if (!request_mem_region(AT91RM9200_BASE_UDP, SZ_16K, driver_name)) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ if (!request_mem_region(res->start,
+ res->end - res->start + 1,
+ driver_name)) {
DBG("someone's using UDC memory\n");
return -EBUSY;
}
@@ -1668,15 +1691,23 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
udc->gadget.dev.parent = dev;
udc->board = *(struct at91_udc_data *) dev->platform_data;
udc->pdev = pdev;
- udc_reinit(udc);
udc->enabled = 0;
+ udc->udp_baseaddr = ioremap(res->start, res->end - res->start + 1);
+ if (!udc->udp_baseaddr) {
+ release_mem_region(res->start, res->end - res->start + 1);
+ return -ENOMEM;
+ }
+
+ udc_reinit(udc);
+
/* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk");
udc->fclk = clk_get(dev, "udpck");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
DBG("clocks missing\n");
- return -ENODEV;
+ retval = -ENODEV;
+ goto fail0;
}
retval = device_register(&udc->gadget.dev);
@@ -1685,8 +1716,10 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
/* don't do anything until we have both gadget driver and VBUS */
clk_enable(udc->iclk);
- at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
- at91_udp_write(AT91_UDP_IDR, 0xffffffff);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+ /* Clear all pending interrupts - UDP may be used by bootloader. */
+ at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
clk_disable(udc->iclk);
/* request UDC and maybe VBUS irqs */
@@ -1698,6 +1731,11 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
goto fail1;
}
if (udc->board.vbus_pin > 0) {
+ /*
+ * Get the initial state of VBUS - we cannot expect
+ * a pending interrupt.
+ */
+ udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
IRQF_DISABLED, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
@@ -1720,7 +1758,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev)
fail1:
device_unregister(&udc->gadget.dev);
fail0:
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+ release_mem_region(res->start, res->end - res->start + 1);
DBG("%s probe failed, %d\n", driver_name, retval);
return retval;
}
@@ -1728,13 +1766,14 @@ fail0:
static int __devexit at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
+ struct resource *res;
DBG("remove\n");
- pullup(udc, 0);
+ if (udc->driver)
+ return -EBUSY;
- if (udc->driver != 0)
- usb_gadget_unregister_driver(udc->driver);
+ pullup(udc, 0);
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
@@ -1742,7 +1781,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev)
free_irq(udc->board.vbus_pin, udc);
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
- release_mem_region(AT91RM9200_BASE_UDP, SZ_16K);
+
+ iounmap(udc->udp_baseaddr);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
clk_put(udc->iclk);
clk_put(udc->fclk);
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
index 882af42e86cc..677089baa59d 100644
--- a/drivers/usb/gadget/at91_udc.h
+++ b/drivers/usb/gadget/at91_udc.h
@@ -51,10 +51,10 @@
#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */
#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */
#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */
-#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */
+#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */
#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */
-#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */
+#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */
#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */
@@ -84,7 +84,7 @@
#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */
-
+#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */
/*-------------------------------------------------------------------------*/
@@ -141,6 +141,7 @@ struct at91_udc {
struct clk *iclk, *fclk;
struct platform_device *pdev;
struct proc_dir_entry *pde;
+ void __iomem *udp_baseaddr;
int udp_irq;
};
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index f1f32d7be5f9..3c2bc075ef4f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -779,7 +779,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
return -EINVAL;
if (dum->driver)
return -EBUSY;
- if (!driver->bind || !driver->unbind || !driver->setup
+ if (!driver->bind || !driver->setup
|| driver->speed == USB_SPEED_UNKNOWN)
return -EINVAL;
@@ -837,7 +837,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
err_bind_driver:
driver_unregister (&driver->driver);
err_register:
- driver->unbind (&dum->gadget);
+ if (driver->unbind)
+ driver->unbind (&dum->gadget);
spin_lock_irq (&dum->lock);
dum->pullup = 0;
set_link_state (dum);
@@ -857,7 +858,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dum)
return -ENODEV;
- if (!driver || driver != dum->driver)
+ if (!driver || driver != dum->driver || !driver->unbind)
return -EINVAL;
dev_dbg (udc_dev(dum), "unregister gadget driver '%s'\n",
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 1c17d26d03b8..d15bf22b9a03 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -1833,9 +1833,9 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags)
spin_unlock_irqrestore(&dev->req_lock, flags);
}
-static void eth_work (void *_dev)
+static void eth_work (struct work_struct *work)
{
- struct eth_dev *dev = _dev;
+ struct eth_dev *dev = container_of(work, struct eth_dev, work);
if (test_and_clear_bit (WORK_RX_MEMORY, &dev->todo)) {
if (netif_running (dev->net))
@@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
if (!eth_is_promisc (dev)) {
u8 *dest = skb->data;
- if (dest [0] & 0x01) {
+ if (is_multicast_ether_addr(dest)) {
u16 type;
/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
* SET_ETHERNET_MULTICAST_FILTERS requests
*/
- if (memcmp (dest, net->broadcast, ETH_ALEN) == 0)
+ if (is_broadcast_ether_addr(dest))
type = USB_CDC_PACKET_TYPE_BROADCAST;
else
type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
@@ -2398,7 +2398,7 @@ autoconf_fail:
dev = netdev_priv(net);
spin_lock_init (&dev->lock);
spin_lock_init (&dev->req_lock);
- INIT_WORK (&dev->work, eth_work, dev);
+ INIT_WORK (&dev->work, eth_work);
INIT_LIST_HEAD (&dev->tx_reqs);
INIT_LIST_HEAD (&dev->rx_reqs);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 8b975d15538d..72f2ae96fbf3 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -250,7 +250,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
#include <linux/utsname.h>
#include <linux/usb_ch9.h>
@@ -1909,10 +1909,10 @@ static int fsync_sub(struct lun *curlun)
if (!filp->f_op->fsync)
return -EINVAL;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
mutex_lock(&inode->i_mutex);
rc = filemap_fdatawrite(inode->i_mapping);
- err = filp->f_op->fsync(filp, filp->f_dentry, 1);
+ err = filp->f_op->fsync(filp, filp->f_path.dentry, 1);
if (!rc)
rc = err;
err = filemap_fdatawait(inode->i_mapping);
@@ -1950,7 +1950,7 @@ static int do_synchronize_cache(struct fsg_dev *fsg)
static void invalidate_sub(struct lun *curlun)
{
struct file *filp = curlun->filp;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
unsigned long rc;
rc = invalidate_inode_pages(inode->i_mapping);
@@ -3526,8 +3526,8 @@ static int open_backing_file(struct lun *curlun, const char *filename)
if (!(filp->f_mode & FMODE_WRITE))
ro = 1;
- if (filp->f_dentry)
- inode = filp->f_dentry->d_inode;
+ if (filp->f_path.dentry)
+ inode = filp->f_path.dentry->d_inode;
if (inode && S_ISBLK(inode->i_mode)) {
if (bdev_read_only(inode->i_bdev))
ro = 1;
@@ -3606,7 +3606,7 @@ static ssize_t show_file(struct device *dev, struct device_attribute *attr, char
down_read(&fsg->filesem);
if (backing_file_is_open(curlun)) { // Get the complete pathname
- p = d_path(curlun->filp->f_dentry, curlun->filp->f_vfsmnt,
+ p = d_path(curlun->filp->f_path.dentry, curlun->filp->f_path.mnt,
buf, PAGE_SIZE - 1);
if (IS_ERR(p))
rc = PTR_ERR(p);
@@ -4030,8 +4030,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
if (backing_file_is_open(curlun)) {
p = NULL;
if (pathbuf) {
- p = d_path(curlun->filp->f_dentry,
- curlun->filp->f_vfsmnt,
+ p = d_path(curlun->filp->f_path.dentry,
+ curlun->filp->f_path.mnt,
pathbuf, PATH_MAX);
if (IS_ERR(p))
p = NULL;
@@ -4100,7 +4100,7 @@ static struct usb_gadget_driver fsg_driver = {
#endif
.function = (char *) longname,
.bind = fsg_bind,
- .unbind = __exit_p(fsg_unbind),
+ .unbind = fsg_unbind,
.disconnect = fsg_disconnect,
.setup = fsg_setup,
.suspend = fsg_suspend,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index 64554acad63f..f1a679656c96 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -123,7 +123,7 @@ struct gmidi_device {
struct usb_request *req; /* for control responses */
u8 config;
struct usb_ep *in_ep, *out_ep;
- struct snd_card *card;
+ struct snd_card *card;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_substream *in_substream;
struct snd_rawmidi_substream *out_substream;
@@ -490,7 +490,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
int status = req->status;
switch (status) {
- case 0: /* normal completion */
+ case 0: /* normal completion */
if (ep == dev->out_ep) {
/* we received stuff.
req is queued again, below */
@@ -505,7 +505,7 @@ static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
break;
/* this endpoint is normally active while we're configured */
- case -ECONNABORTED: /* hardware forced ep reset */
+ case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */
VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
@@ -656,7 +656,7 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
case USB_SPEED_LOW: speed = "low"; break;
case USB_SPEED_FULL: speed = "full"; break;
case USB_SPEED_HIGH: speed = "high"; break;
- default: speed = "?"; break;
+ default: speed = "?"; break;
}
dev->config = number;
@@ -1236,7 +1236,7 @@ autoconf_fail:
/* ok, we made sense of the hardware ... */
- dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
return -ENOMEM;
}
@@ -1308,7 +1308,7 @@ static struct usb_gadget_driver gmidi_driver = {
.speed = USB_SPEED_FULL,
.function = (char *)longname,
.bind = gmidi_bind,
- .unbind = __exit_p(gmidi_unbind),
+ .unbind = gmidi_unbind,
.setup = gmidi_setup,
.disconnect = gmidi_disconnect,
@@ -1316,7 +1316,7 @@ static struct usb_gadget_driver gmidi_driver = {
.suspend = gmidi_suspend,
.resume = gmidi_resume,
- .driver = {
+ .driver = {
.name = (char *)shortname,
.owner = THIS_MODULE,
},
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index a3076da3f4eb..d0ef1d6b3fac 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1432,7 +1432,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1495,7 +1494,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -1808,13 +1807,8 @@ static void goku_remove(struct pci_dev *pdev)
struct goku_udc *dev = pci_get_drvdata(pdev);
DBG(dev, "%s\n", __FUNCTION__);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN(dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver(dev->driver);
- }
+
+ BUG_ON(dev->driver);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
remove_proc_entry(proc_node_name, NULL);
@@ -1864,7 +1858,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* alloc, and start init */
- dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+ dev = kmalloc (sizeof *dev, GFP_KERNEL);
if (dev == NULL){
pr_debug("enomem %s\n", pci_name(pdev));
retval = -ENOMEM;
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 86924f9cdd7e..3fb1044a4db0 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -412,7 +412,7 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
/* FIXME readahead for O_NONBLOCK and poll(); careful with ZLPs */
value = -ENOMEM;
- kbuf = kmalloc (len, SLAB_KERNEL);
+ kbuf = kmalloc (len, GFP_KERNEL);
if (unlikely (!kbuf))
goto free1;
@@ -456,7 +456,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* FIXME writebehind for O_NONBLOCK and poll(), qlen = 1 */
value = -ENOMEM;
- kbuf = kmalloc (len, SLAB_KERNEL);
+ kbuf = kmalloc (len, GFP_KERNEL);
if (!kbuf)
goto free1;
if (copy_from_user (kbuf, buf, len)) {
@@ -1898,7 +1898,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
buf += 4;
length -= 4;
- kbuf = kmalloc (length, SLAB_KERNEL);
+ kbuf = kmalloc (length, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
if (copy_from_user (kbuf, buf, length)) {
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index 179259664c18..a0a73c08a344 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -83,7 +83,6 @@ static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int);
static int lh7a40x_fifo_status(struct usb_ep *ep);
-static int lh7a40x_fifo_status(struct usb_ep *ep);
static void lh7a40x_fifo_flush(struct usb_ep *ep);
static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
@@ -423,9 +422,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
DEBUG("%s: %s\n", __FUNCTION__, driver->driver.name);
if (!driver
- || driver->speed != USB_SPEED_FULL
- || !driver->bind
- || !driver->unbind || !driver->disconnect || !driver->setup)
+ || driver->speed != USB_SPEED_FULL
+ || !driver->bind
+ || !driver->disconnect
+ || !driver->setup)
return -EINVAL;
if (!dev)
return -ENODEV;
@@ -472,7 +472,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave(&dev->lock, flags);
@@ -2126,9 +2126,11 @@ static int lh7a40x_udc_remove(struct platform_device *pdev)
DEBUG("%s: %p\n", __FUNCTION__, pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
free_irq(IRQ_USBINTR, dev);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3acc896a5d4c..569eb8ccf232 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
} /* else the irq handler advances the queue. */
+ ep->responded = 1;
if (req)
list_add_tail (&req->queue, &ep->queue);
done:
@@ -2019,7 +2020,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
if (!driver
|| driver->speed != USB_SPEED_HIGH
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
if (!dev)
@@ -2106,7 +2106,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
spin_lock_irqsave (&dev->lock, flags);
@@ -2188,7 +2188,8 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && !ep->stopped)
+ } else if (ep->responded &&
+ !req && !ep->stopped)
write_fifo (ep, NULL);
}
} else {
@@ -2203,7 +2204,7 @@ static void handle_ep_small (struct net2280_ep *ep)
} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
&& req
&& req->req.actual == req->req.length)
- || !req) {
+ || (ep->responded && !req)) {
ep->dev->protocol_stall = 1;
set_halt (ep);
ep->stopped = 1;
@@ -2469,6 +2470,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* we made the hardware handle most lowlevel requests;
* everything else goes uplevel to the gadget code.
*/
+ ep->responded = 1;
switch (u.r.bRequest) {
case USB_REQ_GET_STATUS: {
struct net2280_ep *e;
@@ -2537,6 +2539,7 @@ delegate:
u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length,
readl (&ep->regs->ep_cfg));
+ ep->responded = 0;
spin_unlock (&dev->lock);
tmp = dev->driver->setup (&dev->gadget, &u.r);
spin_lock (&dev->lock);
@@ -2799,13 +2802,7 @@ static void net2280_remove (struct pci_dev *pdev)
{
struct net2280 *dev = pci_get_drvdata (pdev);
- /* start with the driver above us */
- if (dev->driver) {
- /* should have been done already by driver model core */
- WARN (dev, "pci remove, driver '%s' is still registered\n",
- dev->driver->driver.name);
- usb_gadget_unregister_driver (dev->driver);
- }
+ BUG_ON(dev->driver);
/* then clean up the resources we allocated during probe() */
net2280_led_shutdown (dev);
@@ -2857,7 +2854,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
}
/* alloc, and start init */
- dev = kzalloc (sizeof *dev, SLAB_KERNEL);
+ dev = kzalloc (sizeof *dev, GFP_KERNEL);
if (dev == NULL){
retval = -ENOMEM;
goto done;
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 957d6df34015..44ca139983d8 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -110,7 +110,8 @@ struct net2280_ep {
out_overflow : 1,
stopped : 1,
is_in : 1,
- is_iso : 1;
+ is_iso : 1,
+ responded : 1;
};
static inline void allow_status (struct net2280_ep *ep)
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 48a09fd89d18..cdcfd42843d4 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -42,6 +42,7 @@
#include <linux/usb_gadget.h>
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
+#include <linux/clk.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -60,6 +61,11 @@
/* bulk DMA seems to be behaving for both IN and OUT */
#define USE_DMA
+/* FIXME: OMAP2 currently has some problem in DMA mode */
+#ifdef CONFIG_ARCH_OMAP2
+#undef USE_DMA
+#endif
+
/* ISO too */
#define USE_ISO
@@ -99,7 +105,7 @@ static unsigned fifo_mode = 0;
* boot parameter "omap_udc:fifo_mode=42"
*/
module_param (fifo_mode, uint, 0);
-MODULE_PARM_DESC (fifo_mode, "endpoint setup (0 == default)");
+MODULE_PARM_DESC (fifo_mode, "endpoint configuration");
#ifdef USE_DMA
static unsigned use_dma = 1;
@@ -122,7 +128,7 @@ static const char driver_desc [] = DRIVER_DESC;
/*-------------------------------------------------------------------------*/
/* there's a notion of "current endpoint" for modifying endpoint
- * state, and PIO access to its FIFO.
+ * state, and PIO access to its FIFO.
*/
static void use_ep(struct omap_ep *ep, u16 select)
@@ -391,7 +397,7 @@ done(struct omap_ep *ep, struct omap_req *req, int status)
#define FIFO_EMPTY (UDC_NON_ISO_FIFO_EMPTY | UDC_ISO_FIFO_EMPTY)
#define FIFO_UNREADABLE (UDC_EP_HALTED | FIFO_EMPTY)
-static inline int
+static inline int
write_packet(u8 *buf, struct omap_req *req, unsigned max)
{
unsigned len;
@@ -456,7 +462,7 @@ static int write_fifo(struct omap_ep *ep, struct omap_req *req)
return is_last;
}
-static inline int
+static inline int
read_packet(u8 *buf, struct omap_req *req, unsigned avail)
{
unsigned len;
@@ -542,9 +548,9 @@ static inline dma_addr_t dma_csac(unsigned lch)
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- csac = omap_readw(OMAP_DMA_CSAC(lch));
+ csac = OMAP_DMA_CSAC_REG(lch);
if (csac == 0)
- csac = omap_readw(OMAP_DMA_CSAC(lch));
+ csac = OMAP_DMA_CSAC_REG(lch);
return csac;
}
@@ -555,9 +561,9 @@ static inline dma_addr_t dma_cdac(unsigned lch)
/* omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is
* read before the DMA controller finished disabling the channel.
*/
- cdac = omap_readw(OMAP_DMA_CDAC(lch));
+ cdac = OMAP_DMA_CDAC_REG(lch);
if (cdac == 0)
- cdac = omap_readw(OMAP_DMA_CDAC(lch));
+ cdac = OMAP_DMA_CDAC_REG(lch);
return cdac;
}
@@ -582,7 +588,7 @@ static u16 dma_src_len(struct omap_ep *ep, dma_addr_t start)
}
#define DMA_DEST_LAST(x) (cpu_is_omap15xx() \
- ? omap_readw(OMAP_DMA_CSAC(x)) /* really: CPC */ \
+ ? OMAP_DMA_CSAC_REG(x) /* really: CPC */ \
: dma_cdac(x))
static u16 dma_dest_len(struct omap_ep *ep, dma_addr_t start)
@@ -620,17 +626,19 @@ static void next_in_dma(struct omap_ep *ep, struct omap_req *req)
|| (cpu_is_omap15xx() && length < ep->maxpacket)) {
txdma_ctrl = UDC_TXN_EOT | length;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S8,
- length, 1, sync_mode);
+ length, 1, sync_mode, 0, 0);
} else {
length = min(length / ep->maxpacket,
(unsigned) UDC_TXN_TSC + 1);
- txdma_ctrl = length;
+ txdma_ctrl = length;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
- ep->ep.maxpacket >> 1, length, sync_mode);
+ ep->ep.maxpacket >> 1, length, sync_mode,
+ 0, 0);
length *= ep->maxpacket;
}
omap_set_dma_src_params(ep->lch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+ OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+ 0, 0);
omap_start_dma(ep->lch);
ep->dma_counter = dma_csac(ep->lch);
@@ -675,9 +683,11 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
req->dma_bytes = packets * ep->ep.maxpacket;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
ep->ep.maxpacket >> 1, packets,
- OMAP_DMA_SYNC_ELEMENT);
+ OMAP_DMA_SYNC_ELEMENT,
+ 0, 0);
omap_set_dma_dest_params(ep->lch, OMAP_DMA_PORT_EMIFF,
- OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual);
+ OMAP_DMA_AMODE_POST_INC, req->req.dma + req->req.actual,
+ 0, 0);
ep->dma_counter = DMA_DEST_LAST(ep->lch);
UDC_RXDMA_REG(ep->dma_channel) = UDC_RXN_STOP | (packets - 1);
@@ -820,7 +830,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_dest_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+ (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+ 0, 0);
}
} else {
status = omap_request_dma(OMAP_DMA_USB_W2FC_RX0 - 1 + channel,
@@ -831,7 +842,8 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
omap_set_dma_src_params(ep->lch,
OMAP_DMA_PORT_TIPB,
OMAP_DMA_AMODE_CONSTANT,
- (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG));
+ (unsigned long) io_v2p((u32)&UDC_DATA_DMA_REG),
+ 0, 0);
/* EMIFF */
omap_set_dma_dest_burst_mode(ep->lch,
OMAP_DMA_DATA_BURST_4);
@@ -846,7 +858,7 @@ static void dma_channel_claim(struct omap_ep *ep, unsigned channel)
/* channel type P: hw synch (fifo) */
if (!cpu_is_omap15xx())
- omap_writew(2, OMAP_DMA_LCH_CTRL(ep->lch));
+ OMAP1_DMA_LCH_CTRL_REG(ep->lch) = 2;
}
just_restart:
@@ -893,7 +905,7 @@ static void dma_channel_release(struct omap_ep *ep)
else
req = NULL;
- active = ((1 << 7) & omap_readl(OMAP_DMA_CCR(ep->lch))) != 0;
+ active = ((1 << 7) & OMAP_DMA_CCR_REG(ep->lch)) != 0;
DBG("%s release %s %cxdma%d %p\n", ep->ep.name,
active ? "active" : "idle",
@@ -1117,7 +1129,7 @@ static int omap_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
*/
dma_channel_release(ep);
dma_channel_claim(ep, channel);
- } else
+ } else
done(ep, req, -ECONNRESET);
spin_unlock_irqrestore(&ep->udc->lock, flags);
return 0;
@@ -1153,7 +1165,7 @@ static int omap_ep_set_halt(struct usb_ep *_ep, int value)
/* IN endpoints must already be idle */
if ((ep->bEndpointAddress & USB_DIR_IN)
- && !list_empty(&ep->queue)) {
+ && !list_empty(&ep->queue)) {
status = -EAGAIN;
goto done;
}
@@ -1298,6 +1310,23 @@ static void pullup_disable(struct omap_udc *udc)
UDC_SYSCON1_REG &= ~UDC_PULLUP_EN;
}
+static struct omap_udc *udc;
+
+static void omap_udc_enable_clock(int enable)
+{
+ if (udc == NULL || udc->dc_clk == NULL || udc->hhc_clk == NULL)
+ return;
+
+ if (enable) {
+ clk_enable(udc->dc_clk);
+ clk_enable(udc->hhc_clk);
+ udelay(100);
+ } else {
+ clk_disable(udc->hhc_clk);
+ clk_disable(udc->dc_clk);
+ }
+}
+
/*
* Called by whatever detects VBUS sessions: external transceiver
* driver, or maybe GPIO0 VBUS IRQ. May request 48 MHz clock.
@@ -1318,10 +1347,22 @@ static int omap_vbus_session(struct usb_gadget *gadget, int is_active)
else
FUNC_MUX_CTRL_0_REG &= ~VBUS_CTRL_1510;
}
+ if (udc->dc_clk != NULL && is_active) {
+ if (!udc->clk_requested) {
+ omap_udc_enable_clock(1);
+ udc->clk_requested = 1;
+ }
+ }
if (can_pullup(udc))
pullup_enable(udc);
else
pullup_disable(udc);
+ if (udc->dc_clk != NULL && !is_active) {
+ if (udc->clk_requested) {
+ omap_udc_enable_clock(0);
+ udc->clk_requested = 0;
+ }
+ }
spin_unlock_irqrestore(&udc->lock, flags);
return 0;
}
@@ -1441,7 +1482,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
}
}
- /* IN/OUT packets mean we're in the DATA or STATUS stage.
+ /* IN/OUT packets mean we're in the DATA or STATUS stage.
* This driver uses only uses protocol stalls (ep0 never halts),
* and if we got this far the gadget driver already had a
* chance to stall. Tries to be forgiving of host oddities.
@@ -1509,7 +1550,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
} else if (stat == 0)
UDC_CTRL_REG = UDC_SET_FIFO_EN;
UDC_EP_NUM_REG = 0;
-
+
/* activate status stage */
if (stat == 1) {
done(ep0, req, 0);
@@ -1866,7 +1907,7 @@ static void pio_out_timer(unsigned long _ep)
spin_lock_irqsave(&ep->udc->lock, flags);
if (!list_empty(&ep->queue) && ep->ackwait) {
- use_ep(ep, 0);
+ use_ep(ep, UDC_EP_SEL);
stat_flg = UDC_STAT_FLG_REG;
if ((stat_flg & UDC_ACK) && (!(stat_flg & UDC_FIFO_EN)
@@ -1876,12 +1917,12 @@ static void pio_out_timer(unsigned long _ep)
VDBG("%s: lose, %04x\n", ep->ep.name, stat_flg);
req = container_of(ep->queue.next,
struct omap_req, queue);
- UDC_EP_NUM_REG = ep->bEndpointAddress | UDC_EP_SEL;
(void) read_fifo(ep, req);
UDC_EP_NUM_REG = ep->bEndpointAddress;
UDC_CTRL_REG = UDC_SET_FIFO_EN;
ep->ackwait = 1 + ep->double_buf;
- }
+ } else
+ deselect_ep();
}
mod_timer(&ep->timer, PIO_OUT_TIMEOUT);
spin_unlock_irqrestore(&ep->udc->lock, flags);
@@ -2028,7 +2069,17 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev)
/*-------------------------------------------------------------------------*/
-static struct omap_udc *udc;
+static inline int machine_needs_vbus_session(void)
+{
+ return (machine_is_omap_innovator()
+ || machine_is_omap_osk()
+ || machine_is_omap_apollon()
+#ifndef CONFIG_MACH_OMAP_H4_OTG
+ || machine_is_omap_h4()
+#endif
+ || machine_is_sx1()
+ );
+}
int usb_gadget_register_driver (struct usb_gadget_driver *driver)
{
@@ -2043,7 +2094,6 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
// FIXME if otg, check: driver->is_otg
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->setup)
return -EINVAL;
@@ -2071,6 +2121,9 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(1);
+
status = driver->bind (&udc->gadget);
if (status) {
DBG("bind to %s --> %d\n", driver->driver.name, status);
@@ -2087,9 +2140,11 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
status = otg_set_peripheral(udc->transceiver, &udc->gadget);
if (status < 0) {
ERR("can't bind to transceiver\n");
- driver->unbind (&udc->gadget);
- udc->gadget.dev.driver = NULL;
- udc->driver = NULL;
+ if (driver->unbind) {
+ driver->unbind (&udc->gadget);
+ udc->gadget.dev.driver = NULL;
+ udc->driver = NULL;
+ }
goto done;
}
} else {
@@ -2102,10 +2157,12 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
/* boards that don't have VBUS sensing can't autogate 48MHz;
* can't enter deep sleep while a gadget driver is active.
*/
- if (machine_is_omap_innovator() || machine_is_omap_osk())
+ if (machine_needs_vbus_session())
omap_vbus_session(&udc->gadget, 1);
done:
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(0);
return status;
}
EXPORT_SYMBOL(usb_gadget_register_driver);
@@ -2117,10 +2174,13 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
if (!udc)
return -ENODEV;
- if (!driver || driver != udc->driver)
+ if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
- if (machine_is_omap_innovator() || machine_is_omap_osk())
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(1);
+
+ if (machine_needs_vbus_session())
omap_vbus_session(&udc->gadget, 0);
if (udc->transceiver)
@@ -2136,6 +2196,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
+ if (udc->dc_clk != NULL)
+ omap_udc_enable_clock(0);
DBG("unregistered driver '%s'\n", driver->driver.name);
return status;
}
@@ -2218,7 +2280,7 @@ static char *trx_mode(unsigned m, int enabled)
case 0: return enabled ? "*6wire" : "unused";
case 1: return "4wire";
case 2: return "3wire";
- case 3: return "6wire";
+ case 3: return "6wire";
default: return "unknown";
}
}
@@ -2227,11 +2289,18 @@ static int proc_otg_show(struct seq_file *s)
{
u32 tmp;
u32 trans;
+ char *ctrl_name;
tmp = OTG_REV_REG;
- trans = USB_TRANSCEIVER_CTRL_REG;
- seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n",
- tmp >> 4, tmp & 0xf, trans);
+ if (cpu_is_omap24xx()) {
+ ctrl_name = "control_devconf";
+ trans = CONTROL_DEVCONF_REG;
+ } else {
+ ctrl_name = "tranceiver_ctrl";
+ trans = USB_TRANSCEIVER_CTRL_REG;
+ }
+ seq_printf(s, "\nOTG rev %d.%d, %s %05x\n",
+ tmp >> 4, tmp & 0xf, ctrl_name, trans);
tmp = OTG_SYSCON_1_REG;
seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
FOURBITS "\n", tmp,
@@ -2306,7 +2375,7 @@ static int proc_udc_show(struct seq_file *s, void *_)
driver_desc,
use_dma ? " (dma)" : "");
- tmp = UDC_REV_REG & 0xff;
+ tmp = UDC_REV_REG & 0xff;
seq_printf(s,
"UDC rev %d.%d, fifo mode %d, gadget %s\n"
"hmc %d, transceiver %s\n",
@@ -2314,11 +2383,16 @@ static int proc_udc_show(struct seq_file *s, void *_)
fifo_mode,
udc->driver ? udc->driver->driver.name : "(none)",
HMC,
- udc->transceiver ? udc->transceiver->label : "(none)");
- seq_printf(s, "ULPD control %04x req %04x status %04x\n",
- __REG16(ULPD_CLOCK_CTRL),
- __REG16(ULPD_SOFT_REQ),
- __REG16(ULPD_STATUS_REQ));
+ udc->transceiver
+ ? udc->transceiver->label
+ : ((cpu_is_omap1710() || cpu_is_omap24xx())
+ ? "external" : "(none)"));
+ if (cpu_class_is_omap1()) {
+ seq_printf(s, "ULPD control %04x req %04x status %04x\n",
+ __REG16(ULPD_CLOCK_CTRL),
+ __REG16(ULPD_SOFT_REQ),
+ __REG16(ULPD_STATUS_REQ));
+ }
/* OTG controller registers */
if (!cpu_is_omap15xx())
@@ -2503,9 +2577,10 @@ omap_ep_setup(char *name, u8 addr, u8 type,
dbuf = 1;
} else {
/* double-buffering "not supported" on 15xx,
- * and ignored for PIO-IN on 16xx
+ * and ignored for PIO-IN on newer chips
+ * (for more reliable behavior)
*/
- if (!use_dma || cpu_is_omap15xx())
+ if (!use_dma || cpu_is_omap15xx() || cpu_is_omap24xx())
dbuf = 0;
switch (maxp) {
@@ -2548,7 +2623,7 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->bEndpointAddress = addr;
ep->bmAttributes = type;
ep->double_buf = dbuf;
- ep->udc = udc;
+ ep->udc = udc;
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
@@ -2581,7 +2656,7 @@ omap_udc_setup(struct platform_device *odev, struct otg_transceiver *xceiv)
/* UDC_PULLUP_EN gates the chip clock */
// OTG_SYSCON_1_REG |= DEV_IDLE_EN;
- udc = kzalloc(sizeof(*udc), SLAB_KERNEL);
+ udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
return -ENOMEM;
@@ -2708,15 +2783,37 @@ static int __init omap_udc_probe(struct platform_device *pdev)
struct otg_transceiver *xceiv = NULL;
const char *type = NULL;
struct omap_usb_config *config = pdev->dev.platform_data;
+ struct clk *dc_clk;
+ struct clk *hhc_clk;
/* NOTE: "knows" the order of the resources! */
- if (!request_mem_region(pdev->resource[0].start,
+ if (!request_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1,
driver_name)) {
DBG("request_mem_region failed\n");
return -EBUSY;
}
+ if (cpu_is_omap16xx()) {
+ dc_clk = clk_get(&pdev->dev, "usb_dc_ck");
+ hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck");
+ BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+ /* can't use omap_udc_enable_clock yet */
+ clk_enable(dc_clk);
+ clk_enable(hhc_clk);
+ udelay(100);
+ }
+
+ if (cpu_is_omap24xx()) {
+ dc_clk = clk_get(&pdev->dev, "usb_fck");
+ hhc_clk = clk_get(&pdev->dev, "usb_l4_ick");
+ BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk));
+ /* can't use omap_udc_enable_clock yet */
+ clk_enable(dc_clk);
+ clk_enable(hhc_clk);
+ udelay(100);
+ }
+
INFO("OMAP UDC rev %d.%d%s\n",
UDC_REV_REG >> 4, UDC_REV_REG & 0xf,
config->otg ? ", Mini-AB" : "");
@@ -2726,7 +2823,7 @@ static int __init omap_udc_probe(struct platform_device *pdev)
hmc = HMC_1510;
type = "(unknown)";
- if (machine_is_omap_innovator()) {
+ if (machine_is_omap_innovator() || machine_is_sx1()) {
/* just set up software VBUS detect, and then
* later rig it so we always report VBUS.
* FIXME without really sensing VBUS, we can't
@@ -2755,6 +2852,15 @@ static int __init omap_udc_probe(struct platform_device *pdev)
}
hmc = HMC_1610;
+
+ if (cpu_is_omap24xx()) {
+ /* this could be transceiverless in one of the
+ * "we don't need to know" modes.
+ */
+ type = "external";
+ goto known;
+ }
+
switch (hmc) {
case 0: /* POWERUP DEFAULT == 0 */
case 4:
@@ -2793,6 +2899,7 @@ bad_on_1710:
goto cleanup0;
}
}
+known:
INFO("hmc mode %d, %s transceiver\n", hmc, type);
/* a "gadget" abstracts/virtualizes the controller */
@@ -2817,8 +2924,8 @@ bad_on_1710:
status = request_irq(pdev->resource[1].start, omap_udc_irq,
IRQF_SAMPLE_RANDOM, driver_name, udc);
if (status != 0) {
- ERR( "can't get irq %ld, err %d\n",
- pdev->resource[1].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[1].start, status);
goto cleanup1;
}
@@ -2826,24 +2933,41 @@ bad_on_1710:
status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
if (status != 0) {
- ERR( "can't get irq %ld, err %d\n",
- pdev->resource[2].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[2].start, status);
goto cleanup2;
}
#ifdef USE_ISO
status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
IRQF_DISABLED, "omap_udc iso", udc);
if (status != 0) {
- ERR("can't get irq %ld, err %d\n",
- pdev->resource[3].start, status);
+ ERR("can't get irq %d, err %d\n",
+ (int) pdev->resource[3].start, status);
goto cleanup3;
}
#endif
+ if (cpu_is_omap16xx()) {
+ udc->dc_clk = dc_clk;
+ udc->hhc_clk = hhc_clk;
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+ }
+
+ if (cpu_is_omap24xx()) {
+ udc->dc_clk = dc_clk;
+ udc->hhc_clk = hhc_clk;
+ /* FIXME OMAP2 don't release hhc & dc clock */
+#if 0
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+#endif
+ }
create_proc_file();
- device_add(&udc->gadget.dev);
- return 0;
-
+ status = device_add(&udc->gadget.dev);
+ if (!status)
+ return status;
+ /* If fail, fall through */
#ifdef USE_ISO
cleanup3:
free_irq(pdev->resource[2].start, udc);
@@ -2859,8 +2983,17 @@ cleanup1:
cleanup0:
if (xceiv)
put_device(xceiv->dev);
+
+ if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+ clk_disable(hhc_clk);
+ clk_disable(dc_clk);
+ clk_put(hhc_clk);
+ clk_put(dc_clk);
+ }
+
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
+
return status;
}
@@ -2870,6 +3003,8 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
if (!udc)
return -ENODEV;
+ if (udc->driver)
+ return -EBUSY;
udc->done = &done;
@@ -2888,6 +3023,13 @@ static int __exit omap_udc_remove(struct platform_device *pdev)
free_irq(pdev->resource[2].start, udc);
free_irq(pdev->resource[1].start, udc);
+ if (udc->dc_clk) {
+ if (udc->clk_requested)
+ omap_udc_enable_clock(0);
+ clk_put(udc->hhc_clk);
+ clk_put(udc->dc_clk);
+ }
+
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
diff --git a/drivers/usb/gadget/omap_udc.h b/drivers/usb/gadget/omap_udc.h
index 652ee4627344..1dc398bb9ab2 100644
--- a/drivers/usb/gadget/omap_udc.h
+++ b/drivers/usb/gadget/omap_udc.h
@@ -175,6 +175,9 @@ struct omap_udc {
unsigned ep0_reset_config:1;
unsigned ep0_setup:1;
struct completion *done;
+ struct clk *dc_clk;
+ struct clk *hhc_clk;
+ unsigned clk_requested:1;
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 671c24bc6d75..b78de9694665 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1623,7 +1623,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
if (!driver
|| driver->speed < USB_SPEED_FULL
|| !driver->bind
- || !driver->unbind
|| !driver->disconnect
|| !driver->setup)
return -EINVAL;
@@ -1694,7 +1693,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
if (!dev)
return -ENODEV;
- if (!driver || driver != dev->driver)
+ if (!driver || driver != dev->driver || !driver->unbind)
return -EINVAL;
local_irq_disable();
@@ -2472,6 +2471,7 @@ static struct pxa2xx_udc memory = {
#define PXA210_B1 0x00000123
#define PXA210_B0 0x00000122
#define IXP425_A0 0x000001c1
+#define IXP425_B0 0x000001f1
#define IXP465_AD 0x00000200
/*
@@ -2509,6 +2509,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
break;
#elif defined(CONFIG_ARCH_IXP4XX)
case IXP425_A0:
+ case IXP425_B0:
case IXP465_AD:
dev->has_cfr = 1;
out_dma = 0;
@@ -2636,9 +2637,11 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
{
struct pxa2xx_udc *dev = platform_get_drvdata(pdev);
+ if (dev->driver)
+ return -EBUSY;
+
udc_disable(dev);
remove_proc_files();
- usb_gadget_unregister_driver(dev->driver);
if (dev->got_irq) {
free_irq(IRQ_USB, dev);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 208e55a667ac..f8a3ec64635d 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -200,7 +200,7 @@ static void gs_unthrottle(struct tty_struct * tty);
static void gs_break(struct tty_struct *tty, int break_state);
static int gs_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
-static void gs_set_termios(struct tty_struct *tty, struct termios *old);
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old);
static int gs_send(struct gs_dev *dev);
static int gs_send_packet(struct gs_dev *dev, char *packet,
@@ -296,7 +296,7 @@ static struct usb_gadget_driver gs_gadget_driver = {
#endif /* CONFIG_USB_GADGET_DUALSPEED */
.function = GS_LONG_NAME,
.bind = gs_bind,
- .unbind = __exit_p(gs_unbind),
+ .unbind = gs_unbind,
.setup = gs_setup,
.disconnect = gs_disconnect,
.driver = {
@@ -1077,7 +1077,7 @@ static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd,
/*
* gs_set_termios
*/
-static void gs_set_termios(struct tty_struct *tty, struct termios *old)
+static void gs_set_termios(struct tty_struct *tty, struct ktermios *old)
{
}
@@ -2195,7 +2195,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
if (size == 0)
return NULL;
- gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
+ gb = kmalloc(sizeof(struct gs_buf), kmalloc_flags);
if (gb == NULL)
return NULL;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 0f809dd68492..40710ea1b490 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -1190,7 +1190,7 @@ autoconf_fail:
/* ok, we made sense of the hardware ... */
- dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
spin_lock_init (&dev->lock);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index cf10cbc98f80..cc60759083bf 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -153,7 +153,7 @@ config USB_U132_HCD
adapter will *NOT* work with PC cards that do not contain an OHCI
controller.
- For those PC cards that contain multiple OHCI controllers only ther
+ For those PC cards that contain multiple OHCI controllers only the
first one is used.
The driver consists of two modules, the "ftdi-elan" module is a
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 34b7a31cd85b..56349d21e6ea 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -492,7 +492,7 @@ show_periodic (struct class_device *class_dev, char *buf)
unsigned i;
__le32 tag;
- if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
+ if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
return 0;
seen_count = 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 9030994aba98..025d33313681 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -126,6 +126,11 @@ static unsigned park = 0;
module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc = 0;
+module_param (ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
+
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
/*-------------------------------------------------------------------------*/
@@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci,
- "USB %x.%x started, EHCI %x.%02x, driver %s\n",
+ "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
- temp >> 8, temp & 0xff, DRIVER_VERSION);
+ temp >> 8, temp & 0xff, DRIVER_VERSION,
+ ignore_oc ? ", overcurrent ignored" : "");
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
@@ -613,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
- status = readl (&ehci->regs->command);
- if (!(status & CMD_RUN))
- writel (status | CMD_RUN, &ehci->regs->command);
+ if (!(readl(&ehci->regs->command) & CMD_RUN))
+ usb_hcd_resume_root_hub(hcd);
while (i--) {
int pstatus = readl (&ehci->regs->port_status [i]);
@@ -632,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
*/
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
- usb_hcd_resume_root_hub(hcd);
}
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1b20722c102b..bfe5f307cba6 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int port;
+ int mask;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
@@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->reclaim_ready = 1;
ehci_work(ehci);
- /* suspend any active/unsuspended ports, maybe allow wakeup */
+ /* Unlike other USB host controller types, EHCI doesn't have
+ * any notion of "global" or bus-wide suspend. The driver has
+ * to manually suspend all the active unsuspended ports, and
+ * then manually resume them in the bus_resume() routine.
+ */
+ ehci->bus_suspended = 0;
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = readl (reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
- if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
+ /* keep track of which ports we suspend */
+ if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
+ !(t1 & PORT_SUSPEND)) {
t2 |= PORT_SUSPEND;
+ set_bit(port, &ehci->bus_suspended);
+ }
+
+ /* enable remote wakeup on all ports */
if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
@@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci_halt (ehci);
hcd->state = HC_STATE_SUSPENDED;
+ /* allow remote wakeup */
+ mask = INTR_MASK;
+ if (!device_may_wakeup(&hcd->self.root_hub->dev))
+ mask &= ~STS_PCD;
+ writel(mask, &ehci->regs->intr_enable);
+ readl(&ehci->regs->intr_enable);
+
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
return 0;
@@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
int i;
- int intr_enable;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
@@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
* the last user of the controller, not reset/pm hardware keeping
* state we gave to it.
*/
+ temp = readl(&ehci->regs->intr_enable);
+ ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
- /* re-init operational registers in case we lost power */
- if (readl (&ehci->regs->intr_enable) == 0) {
- /* at least some APM implementations will try to deliver
- * IRQs right away, so delay them until we're ready.
- */
- intr_enable = 1;
- writel (0, &ehci->regs->segment);
- writel (ehci->periodic_dma, &ehci->regs->frame_list);
- writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
- } else
- intr_enable = 0;
- ehci_dbg(ehci, "resume root hub%s\n",
- intr_enable ? " after power loss" : "");
+ /* at least some APM implementations will try to deliver
+ * IRQs right away, so delay them until we're ready.
+ */
+ writel(0, &ehci->regs->intr_enable);
+
+ /* re-init operational registers */
+ writel(0, &ehci->regs->segment);
+ writel(ehci->periodic_dma, &ehci->regs->frame_list);
+ writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
/* restore CMD_RUN, framelist size, and irq threshold */
writel (ehci->command, &ehci->regs->command);
- /* take ports out of suspend */
+ /* manually resume the ports we suspended during bus_suspend() */
i = HCS_N_PORTS (ehci->hcs_params);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS
| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
- if (temp & PORT_SUSPEND) {
+ if (test_bit(i, &ehci->bus_suspended) &&
+ (temp & PORT_SUSPEND)) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME;
}
@@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
mdelay (20);
while (i--) {
temp = readl (&ehci->regs->port_status [i]);
- if ((temp & PORT_SUSPEND) == 0)
- continue;
- temp &= ~(PORT_RWC_BITS | PORT_RESUME);
- writel (temp, &ehci->regs->port_status [i]);
- ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ if (test_bit(i, &ehci->bus_suspended) &&
+ (temp & PORT_SUSPEND)) {
+ temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+ writel (temp, &ehci->regs->port_status [i]);
+ ehci_vdbg (ehci, "resumed port %d\n", i + 1);
+ }
}
(void) readl (&ehci->regs->command);
@@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
/* Now we can safely re-enable irqs */
- if (intr_enable)
- writel (INTR_MASK, &ehci->regs->intr_enable);
+ writel(INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
return 0;
@@ -218,6 +235,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp, status = 0;
+ u32 mask;
int ports, i, retval = 1;
unsigned long flags;
@@ -233,6 +251,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
retval++;
}
+ /* Some boards (mostly VIA?) report bogus overcurrent indications,
+ * causing massive log spam unless we completely ignore them. It
+ * may be relevant that VIA VT8235 controlers, where PORT_POWER is
+ * always set, seem to clear PORT_OCC and PORT_CSC when writing to
+ * PORT_POWER; that's surprising, but maybe within-spec.
+ */
+ if (!ignore_oc)
+ mask = PORT_CSC | PORT_PEC | PORT_OCC;
+ else
+ mask = PORT_CSC | PORT_PEC;
+ // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
+
/* no hub change reports (bit 0) for now (power, ...) */
/* port N changes (bit N)? */
@@ -250,8 +280,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
if (!(temp & PORT_CONNECT))
ehci->reset_done [i] = 0;
- if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
- // PORT_STAT_C_SUSPEND?
+ if ((temp & mask) != 0
|| ((temp & PORT_RESUME) != 0
&& time_after (jiffies,
ehci->reset_done [i]))) {
@@ -319,6 +348,7 @@ static int ehci_hub_control (
u32 temp, status;
unsigned long flags;
int retval = 0;
+ unsigned selector;
/*
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -417,7 +447,7 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
if (temp & PORT_PEC)
status |= 1 << USB_PORT_FEAT_C_ENABLE;
- if (temp & PORT_OCC)
+ if ((temp & PORT_OCC) && !ignore_oc)
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
/* whoever resumes must GetPortStatus to complete it!! */
@@ -506,6 +536,8 @@ static int ehci_hub_control (
}
break;
case SetPortFeature:
+ selector = wIndex >> 8;
+ wIndex &= 0xff;
if (!wIndex || wIndex > ports)
goto error;
wIndex--;
@@ -559,6 +591,22 @@ static int ehci_hub_control (
}
writel (temp, &ehci->regs->port_status [wIndex]);
break;
+
+ /* For downstream facing ports (these): one hub port is put
+ * into test mode according to USB2 11.24.2.13, then the hub
+ * must be reset (which for root hub now means rmmod+modprobe,
+ * or else system reboot). See EHCI 2.3.9 and 4.14 for info
+ * about the EHCI-specific stuff.
+ */
+ case USB_PORT_FEAT_TEST:
+ if (!selector || selector > 5)
+ goto error;
+ ehci_quiesce(ehci);
+ ehci_halt(ehci);
+ temp |= selector << 16;
+ writel (temp, &ehci->regs->port_status [wIndex]);
+ break;
+
default:
goto error;
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e51c1ed81ac4..4bc7970ba3ef 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
static int ehci_pci_resume(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- unsigned port;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
- int retval = -EINVAL;
// maybe restore FLADJ
@@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
/* Mark hardware accessible again as we are out of D3 state by now */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- /* If CF is clear, we lost PCI Vaux power and need to restart. */
- if (readl(&ehci->regs->configured_flag) != FLAG_CF)
- goto restart;
-
- /* If any port is suspended (or owned by the companion),
- * we know we can/must resume the HC (and mustn't reset it).
- * We just defer that to the root hub code.
+ /* If CF is still set, we maintained PCI Vaux power.
+ * Just undo the effect of ehci_pci_suspend().
*/
- for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
- u32 status;
- port--;
- status = readl(&ehci->regs->port_status [port]);
- if (!(status & PORT_POWER))
- continue;
- if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
- usb_hcd_resume_root_hub(hcd);
- return 0;
- }
+ if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
+ int mask = INTR_MASK;
+
+ if (!device_may_wakeup(&hcd->self.root_hub->dev))
+ mask &= ~STS_PCD;
+ writel(mask, &ehci->regs->intr_enable);
+ readl(&ehci->regs->intr_enable);
+ return 0;
}
-restart:
ehci_dbg(ehci, "lost power, restarting\n");
usb_root_hub_lost_power(hcd->self.root_hub);
@@ -307,13 +297,15 @@ restart:
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);
- /* restart; khubd will disconnect devices */
- retval = ehci_run(hcd);
-
/* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1);
- return retval;
+ writel(ehci->command, &ehci->regs->command);
+ writel(FLAG_CF, &ehci->regs->configured_flag);
+ readl(&ehci->regs->command); /* unblock posted writes */
+
+ hcd->state = HC_STATE_SUSPENDED;
+ return 0;
}
#endif
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..74dbc6c8228f 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
/* per root hub port */
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
+ unsigned long bus_suspended;
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 87eca6aeacf2..282d82efc0b0 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -188,7 +188,7 @@ static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
-#define SLAB_FLAG (in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL)
+#define SLAB_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
#define KMALLOC_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
/* Most helpful debugging aid */
@@ -275,13 +275,13 @@ static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
static int zout_buffer[4] __attribute__ ((aligned (4)));
/* Cache for allocating new EP and SB descriptors. */
-static kmem_cache_t *usb_desc_cache;
+static struct kmem_cache *usb_desc_cache;
/* Cache for the registers allocated in the top half. */
-static kmem_cache_t *top_half_reg_cache;
+static struct kmem_cache *top_half_reg_cache;
/* Cache for the data allocated in the isoc descr top half. */
-static kmem_cache_t *isoc_compl_cache;
+static struct kmem_cache *isoc_compl_cache;
static struct usb_bus *etrax_usb_bus;
@@ -365,7 +365,7 @@ static inline struct urb *urb_list_first(int epid)
/* Adds an urb_entry last in the list for this epid. */
static inline void urb_list_add(struct urb *urb, int epid)
{
- urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
+ urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
assert(urb_entry);
urb_entry->urb = urb;
@@ -1743,7 +1743,7 @@ static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc)
*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
- comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, SLAB_ATOMIC);
+ comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC);
assert(comp_data != NULL);
INIT_WORK(&comp_data->usb_bh, etrax_usb_isoc_descr_interrupt_bottom_half, comp_data);
@@ -3010,7 +3010,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid)
if (!urb->iso_frame_desc[i].length)
continue;
- next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC);
+ next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
assert(next_sb_desc != NULL);
if (urb->iso_frame_desc[i].length > 0) {
@@ -3063,7 +3063,7 @@ static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid)
if (TxIsocEPList[epid].sub == 0) {
dbg_isoc("Isoc traffic not already running, allocating SB");
- next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_ATOMIC);
+ next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC);
assert(next_sb_desc != NULL);
next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) |
@@ -3317,7 +3317,7 @@ static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc)
restore_flags(flags);
- reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, SLAB_ATOMIC);
+ reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, GFP_ATOMIC);
assert(reg != NULL);
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index b466581beb4a..cc405512fa1c 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -187,7 +187,6 @@ ohci_at91_start (struct usb_hcd *hcd)
{
struct at91_usbh_data *board = hcd->self.controller->platform_data;
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- struct usb_device *root = hcd->self.root_hub;
int ret;
if ((ret = ohci_init(ohci)) < 0)
@@ -221,7 +220,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
*/
.start = ohci_at91_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 24e23c5783d8..e70b2430e2a9 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -269,7 +269,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.start = ohci_au1xxx_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -336,7 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_au1xxx_driver = {
.probe = ohci_hcd_au1xxx_drv_probe,
.remove = ohci_hcd_au1xxx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_au1xxx_drv_suspend, */
/*.resume = ohci_hcd_au1xxx_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 8293c1d4be3f..273d5ddb72be 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -16,7 +16,7 @@
case PIPE_CONTROL: temp = "ctrl"; break; \
case PIPE_BULK: temp = "bulk"; break; \
case PIPE_INTERRUPT: temp = "intr"; break; \
- default: temp = "isoc"; break; \
+ default: temp = "isoc"; break; \
}; temp;})
#define pipestring(pipe) edstring(usb_pipetype(pipe))
@@ -205,13 +205,13 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
- \
+ \
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
- \
+ \
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@@ -505,7 +505,7 @@ show_periodic (struct class_device *class_dev, char *buf)
char *next;
unsigned i;
- if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
+ if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
return 0;
seen_count = 0;
@@ -563,7 +563,7 @@ show_periodic (struct class_device *class_dev, char *buf)
(info & ED_SKIP) ? " K" : "",
(ed->hwHeadP &
cpu_to_hc32(ohci, ED_H)) ?
- " H" : "");
+ " H" : "");
size -= temp;
next += temp;
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 1bf5e7a4e735..43ae696b2ec2 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -204,7 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ep93xx_driver = {
.probe = ohci_hcd_ep93xx_drv_probe,
.remove = ohci_hcd_ep93xx_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_hcd_ep93xx_drv_suspend,
.resume = ohci_hcd_ep93xx_drv_resume,
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ea4714e557e4..c1c1d871aba4 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -3,77 +3,21 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
- *
- *
+ *
+ *
* OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller
* interfaces (though some non-x86 Intel chips use it). It supports
* smarter hardware than UHCI. A download link for the spec available
* through the http://www.usb.org website.
*
- * History:
- *
- * 2004/03/24 LH7A404 support (Durgesh Pattamatta & Marc Singer)
- * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
- * 2003/02/24 show registers in sysfs (Kevin Brosius)
- *
- * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
- * bandwidth accounting; if debugging, show schedules in driverfs
- * 2002/07/19 fixes to management of ED and schedule state.
- * 2002/06/09 SA-1111 support (Christopher Hoover)
- * 2002/06/01 remember frame when HC won't see EDs any more; use that info
- * to fix urb unlink races caused by interrupt latency assumptions;
- * minor ED field and function naming updates
- * 2002/01/18 package as a patch for 2.5.3; this should match the
- * 2.4.17 kernel modulo some bugs being fixed.
- *
- * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
- * from post-2.4.5 patches.
- * 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning
- * 2001/09/07 match PCI PM changes, errnos from Linus' tree
- * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
- * pbook pci quirks gone (please fix pbook pci sw!) (db)
- *
- * 2001/04/08 Identify version on module load (gb)
- * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
- pci_map_single (db)
- * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
- * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
- *
- * 2000/09/26 fixed races in removing the private portion of the urb
- * 2000/09/07 disable bulk and control lists when unlinking the last
- * endpoint descriptor in order to avoid unrecoverable errors on
- * the Lucent chips. (rwc@sgi)
- * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
- * urb unlink probs, indentation fixes
- * 2000/08/11 various oops fixes mostly affecting iso and cleanup from
- * device unplugs.
- * 2000/06/28 use PCI hotplug framework, for better power management
- * and for Cardbus support (David Brownell)
- * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling
- * when the controller loses power; handle UE; cleanup; ...
- *
- * v5.2 1999/12/07 URB 3rd preview,
- * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
- * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume
- * i386: HUB, Keyboard, Mouse, Printer
- *
- * v4.3 1999/10/27 multiple HCs, bulk_request
- * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
- * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
- * v4.0 1999/08/18
- * v3.0 1999/06/25
- * v2.1 1999/05/09 code clean up
- * v2.0 1999/05/04
- * v1.0 1999/04/27 initial release
- *
* This file is licenced under the GPL.
*/
-
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@@ -89,7 +33,7 @@
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/usb/otg.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/reboot.h>
@@ -183,11 +127,11 @@ static int ohci_urb_enqueue (
int i, size = 0;
unsigned long flags;
int retval = 0;
-
+
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "SUB", usb_pipein (pipe));
#endif
-
+
/* every endpoint has a ed, locate and maybe (re)initialize it */
if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval)))
return -ENOMEM;
@@ -232,7 +176,7 @@ static int ohci_urb_enqueue (
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
INIT_LIST_HEAD (&urb_priv->pending);
urb_priv->length = size;
- urb_priv->ed = ed;
+ urb_priv->ed = ed;
/* allocate the TDs (deferring hash chain updates) */
for (i = 0; i < size; i++) {
@@ -242,7 +186,7 @@ static int ohci_urb_enqueue (
urb_free_priv (ohci, urb_priv);
return -ENOMEM;
}
- }
+ }
spin_lock_irqsave (&ohci->lock, flags);
@@ -313,13 +257,13 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
unsigned long flags;
-
+
#ifdef OHCI_VERBOSE_DEBUG
urb_print (urb, "UNLINK", 1);
-#endif
+#endif
spin_lock_irqsave (&ohci->lock, flags);
- if (HC_IS_RUNNING(hcd->state)) {
+ if (HC_IS_RUNNING(hcd->state)) {
urb_priv_t *urb_priv;
/* Unless an IRQ completed the unlink while it was being
@@ -512,11 +456,11 @@ static int ohci_init (struct ohci_hcd *ohci)
/* Start an OHCI controller, set the BUS operational
* resets USB and controller
- * enable interrupts
+ * enable interrupts
*/
static int ohci_run (struct ohci_hcd *ohci)
{
- u32 mask, temp;
+ u32 mask, temp;
int first = ohci->fminterval == 0;
struct usb_hcd *hcd = ohci_to_hcd(ohci);
@@ -534,7 +478,7 @@ static int ohci_run (struct ohci_hcd *ohci)
/* also: power/overcurrent flags in roothub.a */
}
- /* Reset USB nearly "by the book". RemoteWakeupConnected was
+ /* Reset USB nearly "by the book". RemoteWakeupConnected was
* saved if boot firmware (BIOS/SMM/...) told us it's connected,
* or if bus glue did the same (e.g. for PCI add-in cards with
* PCI PM support).
@@ -729,6 +673,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
ohci->next_statechange = jiffies + STATECHANGE_DELAY;
ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
&regs->intrstatus);
+
+ /* NOTE: Vendors didn't always make the same implementation
+ * choices for RHSC. Many followed the spec; RHSC triggers
+ * on an edge, like setting and maybe clearing a port status
+ * change bit. With others it's level-triggered, active
+ * until khubd clears all the port status change bits. We'll
+ * always disable it here and rely on polling until khubd
+ * re-enables it.
+ */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &regs->intrdisable);
usb_hcd_poll_rh_status(hcd);
}
@@ -755,9 +709,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
dl_done_list (ohci);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state))
- ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
+ ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
}
-
+
/* could track INTR_SO to reduce available PCI/... bandwidth */
/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
@@ -768,12 +722,12 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
finish_unlinks (ohci, ohci_frame_no(ohci));
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
&& HC_IS_RUNNING(hcd->state))
- ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
+ ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
if (HC_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
- ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
+ ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);
}
@@ -784,7 +738,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
static void ohci_stop (struct usb_hcd *hcd)
-{
+{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
@@ -802,8 +756,8 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
if (ohci->hcca) {
- dma_free_coherent (hcd->self.controller,
- sizeof *ohci->hcca,
+ dma_free_coherent (hcd->self.controller,
+ sizeof *ohci->hcca,
ohci->hcca, ohci->hcca_dma);
ohci->hcca = NULL;
ohci->hcca_dma = 0;
@@ -826,7 +780,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
* recycle any "live" eds/tds (and urbs) right away.
* later, khubd disconnect processing will recycle the other state,
* (either as disconnect/reconnect, or maybe someday as a reset).
- */
+ */
spin_lock_irq(&ohci->lock);
disable (ohci);
usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
@@ -865,11 +819,11 @@ static int ohci_restart (struct ohci_hcd *ohci)
/* empty the interrupt branches */
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
-
+
/* no EDs to remove */
ohci->ed_rm_list = NULL;
- /* empty control and bulk lists */
+ /* empty control and bulk lists */
ohci->ed_controltail = NULL;
ohci->ed_bulktail = NULL;
@@ -931,11 +885,15 @@ MODULE_LICENSE ("GPL");
#include "ohci-au1xxx.c"
#endif
+#ifdef CONFIG_PNX8550
+#include "ohci-pnx8550.c"
+#endif
+
#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
#include "ohci-ppc-soc.c"
#endif
-#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
+#ifdef CONFIG_ARCH_AT91
#include "ohci-at91.c"
#endif
@@ -952,8 +910,7 @@ MODULE_LICENSE ("GPL");
|| defined (CONFIG_ARCH_EP93XX) \
|| defined (CONFIG_SOC_AU1X00) \
|| defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
- || defined (CONFIG_ARCH_AT91RM9200) \
- || defined (CONFIG_ARCH_AT91SAM9261) \
+ || defined (CONFIG_ARCH_AT91) \
|| defined (CONFIG_ARCH_PNX4008) \
)
#error "missing bus glue for ohci-hcd"
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 6995ea36f2e8..216c9c9d4d6d 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
- *
+ *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* This file is licenced under GPL
*/
@@ -23,13 +23,13 @@
(temp & RH_PS_PSSC) ? " PSSC" : "", \
(temp & RH_PS_PESC) ? " PESC" : "", \
(temp & RH_PS_CSC) ? " CSC" : "", \
- \
+ \
(temp & RH_PS_LSDA) ? " LSDA" : "", \
(temp & RH_PS_PPS) ? " PPS" : "", \
(temp & RH_PS_PRS) ? " PRS" : "", \
(temp & RH_PS_POCI) ? " POCI" : "", \
(temp & RH_PS_PSS) ? " PSS" : "", \
- \
+ \
(temp & RH_PS_PES) ? " PES" : "", \
(temp & RH_PS_CCS) ? " CCS" : "" \
);
@@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ spin_lock_irq(&ohci->lock);
+ if (!ohci->autostop)
+ del_timer(&hcd->rh_timer); /* Prevent next poll */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ spin_unlock_irq(&ohci->lock);
}
#define OHCI_SCHED_ENABLES \
@@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
static void dl_done_list (struct ohci_hcd *);
static void finish_unlinks (struct ohci_hcd *, u16);
+#ifdef CONFIG_PM
+static int ohci_restart(struct ohci_hcd *ohci);
+
static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
__releases(ohci->lock)
__acquires(ohci->lock)
@@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
return ed;
}
-static int ohci_restart (struct ohci_hcd *ohci);
-
/* caller has locked the root hub */
static int ohci_rh_resume (struct ohci_hcd *ohci)
__releases(ohci->lock)
@@ -169,7 +174,7 @@ __acquires(ohci->lock)
break;
case OHCI_USB_RESUME:
/* HCFS changes sometime after INTR_RD */
- ohci_info(ohci, "%swakeup\n",
+ ohci_dbg(ohci, "%swakeup root hub\n",
autostopped ? "auto-" : "");
break;
case OHCI_USB_OPER:
@@ -181,7 +186,6 @@ __acquires(ohci->lock)
ohci_dbg (ohci, "lost power\n");
status = -EBUSY;
}
-#ifdef CONFIG_PM
if (status == -EBUSY) {
if (!autostopped) {
spin_unlock_irq (&ohci->lock);
@@ -191,25 +195,12 @@ __acquires(ohci->lock)
}
return status;
}
-#endif
if (status != -EINPROGRESS)
return status;
if (autostopped)
goto skip_resume;
spin_unlock_irq (&ohci->lock);
- temp = ohci->num_ports;
- while (temp--) {
- u32 stat = ohci_readl (ohci,
- &ohci->regs->roothub.portstatus [temp]);
-
- /* force global, not selective, resume */
- if (!(stat & RH_PS_PSS))
- continue;
- ohci_writel (ohci, RH_PS_POCI,
- &ohci->regs->roothub.portstatus [temp]);
- }
-
/* Some controllers (lucent erratum) need extra-long delays */
msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
@@ -217,6 +208,7 @@ __acquires(ohci->lock)
temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n");
+ spin_lock_irq(&ohci->lock);
return -EBUSY;
}
@@ -296,8 +288,6 @@ skip_resume:
return 0;
}
-#ifdef CONFIG_PM
-
static int ohci_bus_suspend (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
return rc;
}
+/* Carry out polling-, autostop-, and autoresume-related state changes */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+{
+ int poll_rh = 1;
+
+ switch (ohci->hc_control & OHCI_CTRL_HCFS) {
+
+ case OHCI_USB_OPER:
+ /* keep on polling until we know a device is connected
+ * and RHSC is enabled */
+ if (!ohci->autostop) {
+ if (any_connected ||
+ !device_may_wakeup(&ohci_to_hcd(ohci)
+ ->self.root_hub->dev)) {
+ if (ohci_readl(ohci, &ohci->regs->intrenable) &
+ OHCI_INTR_RHSC)
+ poll_rh = 0;
+ } else {
+ ohci->autostop = 1;
+ ohci->next_statechange = jiffies + HZ;
+ }
+
+ /* if no devices have been attached for one second, autostop */
+ } else {
+ if (changed || any_connected) {
+ ohci->autostop = 0;
+ ohci->next_statechange = jiffies +
+ STATECHANGE_DELAY;
+ } else if (time_after_eq(jiffies,
+ ohci->next_statechange)
+ && !ohci->ed_rm_list
+ && !(ohci->hc_control &
+ OHCI_SCHED_ENABLES)) {
+ ohci_rh_suspend(ohci, 1);
+ }
+ }
+ break;
+
+ /* if there is a port change, autostart or ask to be resumed */
+ case OHCI_USB_SUSPEND:
+ case OHCI_USB_RESUME:
+ if (changed) {
+ if (ohci->autostop)
+ ohci_rh_resume(ohci);
+ else
+ usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+ } else {
+ /* everything is idle, no need for polling */
+ poll_rh = 0;
+ }
+ break;
+ }
+ return poll_rh;
+}
+
+#else /* CONFIG_PM */
+
+static inline int ohci_rh_resume(struct ohci_hcd *ohci)
+{
+ return 0;
+}
+
+/* Carry out polling-related state changes.
+ * autostop isn't used when CONFIG_PM is turned off.
+ */
+static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
+ int any_connected)
+{
+ int poll_rh = 1;
+
+ /* keep on polling until RHSC is enabled */
+ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
+ poll_rh = 0;
+ return poll_rh;
+}
+
#endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/
@@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
- int any_connected = 0, rhsc_enabled = 1;
+ int any_connected = 0;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -387,67 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
}
}
- /* NOTE: vendors didn't always make the same implementation
- * choices for RHSC. Sometimes it triggers on an edge (like
- * setting and maybe clearing a port status change bit); and
- * it's level-triggered on other silicon, active until khubd
- * clears all active port status change bits. If it's still
- * set (level-triggered) we must disable it and rely on
- * polling until khubd re-enables it.
- */
- if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
- ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
- (void) ohci_readl (ohci, &ohci->regs->intrdisable);
- rhsc_enabled = 0;
- }
- hcd->poll_rh = 1;
-
- /* carry out appropriate state changes */
- switch (ohci->hc_control & OHCI_CTRL_HCFS) {
-
- case OHCI_USB_OPER:
- /* keep on polling until we know a device is connected
- * and RHSC is enabled */
- if (!ohci->autostop) {
- if (any_connected) {
- if (rhsc_enabled)
- hcd->poll_rh = 0;
- } else {
- ohci->autostop = 1;
- ohci->next_statechange = jiffies + HZ;
- }
-
- /* if no devices have been attached for one second, autostop */
- } else {
- if (changed || any_connected) {
- ohci->autostop = 0;
- ohci->next_statechange = jiffies +
- STATECHANGE_DELAY;
- } else if (device_may_wakeup(&hcd->self.root_hub->dev)
- && time_after_eq(jiffies,
- ohci->next_statechange)
- && !ohci->ed_rm_list
- && !(ohci->hc_control &
- OHCI_SCHED_ENABLES)) {
- ohci_rh_suspend (ohci, 1);
- }
- }
- break;
-
- /* if there is a port change, autostart or ask to be resumed */
- case OHCI_USB_SUSPEND:
- case OHCI_USB_RESUME:
- if (changed) {
- if (ohci->autostop)
- ohci_rh_resume (ohci);
- else
- usb_hcd_resume_root_hub (hcd);
- } else {
- /* everything is idle, no need for polling */
- hcd->poll_rh = 0;
- }
- break;
- }
+ hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
+ any_connected);
done:
spin_unlock_irqrestore (&ohci->lock, flags);
@@ -476,7 +484,7 @@ ohci_hub_descriptor (
temp = 0;
if (rh & RH_A_NPS) /* no power switching? */
temp |= 0x0002;
- if (rh & RH_A_PSM) /* per-port power switching? */
+ if (rh & RH_A_PSM) /* per-port power switching? */
temp |= 0x0001;
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
temp |= 0x0010;
@@ -547,7 +555,7 @@ static void start_hnp(struct ohci_hcd *ohci);
#define tick_before(t1,t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
/* called from some task, normally khubd */
-static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
+static inline int root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
@@ -562,10 +570,13 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
/* spin until any current reset finishes */
for (;;) {
temp = ohci_readl (ohci, portstat);
+ /* handle e.g. CardBus eject */
+ if (temp == ~(u32)0)
+ return -ESHUTDOWN;
if (!(temp & RH_PS_PRS))
break;
udelay (500);
- }
+ }
if (!(temp & RH_PS_CCS))
break;
@@ -578,6 +589,8 @@ static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
now = ohci_readl(ohci, &ohci->regs->fmnumber);
} while (tick_before(now, reset_done));
/* caller synchronizes using PRSC */
+
+ return 0;
}
static int ohci_hub_control (
@@ -694,7 +707,7 @@ static int ohci_hub_control (
&ohci->regs->roothub.portstatus [wIndex]);
break;
case USB_PORT_FEAT_RESET:
- root_port_reset (ohci, wIndex);
+ retval = root_port_reset (ohci, wIndex);
break;
default:
goto error;
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index e121d97ed91c..e9807cf73a2f 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -38,7 +38,7 @@ static void lh7a404_start_hc(struct platform_device *dev)
CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
udelay(1000);
USBH_CMDSTATUS = OHCI_HCR;
-
+
printk(KERN_DEBUG __FILE__
": Clock to USB host has been enabled \n");
}
@@ -89,7 +89,7 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
retval = -EBUSY;
goto err1;
}
-
+
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
pr_debug("ioremap failed");
@@ -174,7 +174,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.start = ohci_lh7a404_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -242,7 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_lh7a404_driver = {
.probe = ohci_hcd_lh7a404_drv_probe,
.remove = ohci_hcd_lh7a404_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_lh7a404_drv_suspend, */
/*.resume = ohci_hcd_lh7a404_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index d976614eebd3..2f20d3dc895b 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -1,24 +1,24 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
- *
+ *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* This file is licenced under the GPL.
*/
/*-------------------------------------------------------------------------*/
/*
- * There's basically three types of memory:
+ * OHCI deals with three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use dma_pool or dma_alloc_coherent
* - driver buffers, read/written by HC ... the hcd glue or the
* device driver provides us with dma addresses
*
- * There's also PCI "register" data, which is memory mapped.
- * No memory seen by this driver is pagable.
+ * There's also "register" data, which is memory mapped.
+ * No memory seen by this driver (or any HCD) may be paged out.
*/
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 9c02177de50a..27be1f936885 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
.reset = ohci_omap_init,
.start = ohci_omap_start,
.stop = ohci_omap_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -533,7 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev)
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_drv_probe,
.remove = ohci_hcd_omap_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
.resume = ohci_omap_resume,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 874418552789..596e0b41e606 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -3,17 +3,17 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* [ Initialisation is based on Linus' ]
* [ uhci code and gregs ohci fragments ]
* [ (C) Copyright 1999 Linus Torvalds ]
* [ (C) Copyright 1999 Gregory P. Smith]
- *
+ *
* PCI Bus Glue
*
* This file is licenced under the GPL.
*/
-
+
#ifndef CONFIG_PCI
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
#endif
@@ -83,7 +83,7 @@ ohci_pci_start (struct usb_hcd *hcd)
pci_dev_put(b);
}
- /* Check for Compaq's ZFMicro chipset, which needs short
+ /* Check for Compaq's ZFMicro chipset, which needs short
* delays before control or bulk queues get re-activated
* in finish_unlinks()
*/
@@ -238,8 +238,8 @@ static struct pci_driver ohci_pci_driver = {
.shutdown = usb_hcd_pci_shutdown,
};
-
-static int __init ohci_hcd_pci_init (void)
+
+static int __init ohci_hcd_pci_init (void)
{
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
if (usb_disabled())
@@ -253,8 +253,8 @@ module_init (ohci_hcd_pci_init);
/*-------------------------------------------------------------------------*/
-static void __exit ohci_hcd_pci_cleanup (void)
-{
+static void __exit ohci_hcd_pci_cleanup (void)
+{
pci_unregister_driver (&ohci_pci_driver);
}
module_exit (ohci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 2dbb77414905..3a8cbfb69054 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -4,7 +4,7 @@
* driver for Philips PNX4008 USB Host
*
* Authors: Dmitry Chigirev <source@mvista.com>
- * Vitaly Wool <vitalywool@gmail.com>
+ * Vitaly Wool <vitalywool@gmail.com>
*
* register initialization is based on code examples provided by Philips
* Copyright (c) 2005 Koninklijke Philips Electronics N.V.
@@ -29,7 +29,7 @@
#include <asm/arch/irqs.h>
#include <asm/arch/gpio.h>
-#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
+#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
/* USB_CTRL bit defines */
#define USB_SLAVE_HCLK_EN (1 << 24)
@@ -134,7 +134,7 @@ static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct i2c_client *c;
- c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL);
+ c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
new file mode 100644
index 000000000000..6922b91b1704
--- /dev/null
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -0,0 +1,258 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2005 Embedded Alley Solutions, Inc.
+ *
+ * Bus Glue for PNX8550
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ * Based on fragments of previous driver by Russell King et al.
+ *
+ * Modified for LH7A404 from ohci-sa1111.c
+ * by Durgesh Pattamatta <pattamattad@sharpsec.com>
+ *
+ * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
+ * by Vitaly Wool <vitalywool@gmail.com>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <asm/mach-pnx8550/usb.h>
+#include <asm/mach-pnx8550/int.h>
+#include <asm/mach-pnx8550/pci.h>
+
+#ifndef CONFIG_PNX8550
+#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined."
+#endif
+
+extern int usb_disabled(void);
+
+/*-------------------------------------------------------------------------*/
+
+static void pnx8550_start_hc(struct platform_device *dev)
+{
+ /*
+ * Set register CLK48CTL to enable and 48MHz
+ */
+ outl(0x00000003, PCI_BASE | 0x0004770c);
+
+ /*
+ * Set register CLK12CTL to enable and 48MHz
+ */
+ outl(0x00000003, PCI_BASE | 0x00047710);
+
+ udelay(100);
+}
+
+static void pnx8550_stop_hc(struct platform_device *dev)
+{
+ udelay(10);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+
+/**
+ * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
+ struct platform_device *dev)
+{
+ int retval;
+ struct usb_hcd *hcd;
+
+ if (dev->resource[0].flags != IORESOURCE_MEM ||
+ dev->resource[1].flags != IORESOURCE_IRQ) {
+ dev_err (&dev->dev,"invalid resource type\n");
+ return -ENOMEM;
+ }
+
+ hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = dev->resource[0].start;
+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
+ "failed\n", hcd->rsrc_start, hcd->rsrc_len);
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
+ hcd->rsrc_start, hcd->rsrc_len);
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ pnx8550_start_hc(dev);
+
+ ohci_hcd_init(hcd_to_ohci(hcd));
+
+ retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+ if (retval == 0)
+ return retval;
+
+ pnx8550_stop_hc(dev);
+ iounmap(hcd->regs);
+ err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+ usb_put_hcd(hcd);
+ return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
+ * the HCD's stop() method. It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
+{
+ usb_remove_hcd(hcd);
+ pnx8550_stop_hc(dev);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int __devinit
+ohci_pnx8550_start (struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
+
+ ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
+
+ if ((ret = ohci_init(ohci)) < 0)
+ return ret;
+
+ if ((ret = ohci_run (ohci)) < 0) {
+ err ("can't start %s", hcd->self.bus_name);
+ ohci_stop (hcd);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static const struct hc_driver ohci_pnx8550_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "PNX8550 OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ohci_irq,
+ .flags = HCD_USB11 | HCD_MEMORY,
+
+ /*
+ * basic lifecycle operations
+ */
+ .start = ohci_pnx8550_start,
+ .stop = ohci_stop,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ohci_urb_enqueue,
+ .urb_dequeue = ohci_urb_dequeue,
+ .endpoint_disable = ohci_endpoint_disable,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ohci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ohci_hub_status_data,
+ .hub_control = ohci_hub_control,
+ .hub_irq_enable = ohci_rhsc_enable,
+#ifdef CONFIG_PM
+ .bus_suspend = ohci_bus_suspend,
+ .bus_resume = ohci_bus_resume,
+#endif
+ .start_port_reset = ohci_start_port_reset,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
+ return ret;
+}
+
+static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_hcd_pnx8550_remove(hcd, pdev);
+ return 0;
+}
+
+MODULE_ALIAS("pnx8550-ohci");
+
+static struct platform_driver ohci_hcd_pnx8550_driver = {
+ .driver = {
+ .name = "pnx8550-ohci",
+ },
+ .probe = ohci_hcd_pnx8550_drv_probe,
+ .remove = ohci_hcd_pnx8550_drv_remove,
+};
+
+static int __init ohci_hcd_pnx8550_init (void)
+{
+ pr_debug (DRIVER_INFO " (pnx8550)");
+ pr_debug ("block sizes: ed %d td %d\n",
+ sizeof (struct ed), sizeof (struct td));
+
+ return platform_driver_register(&ohci_hcd_pnx8550_driver);
+}
+
+static void __exit ohci_hcd_pnx8550_cleanup (void)
+{
+ platform_driver_unregister(&ohci_hcd_pnx8550_driver);
+}
+
+module_init (ohci_hcd_pnx8550_init);
+module_exit (ohci_hcd_pnx8550_cleanup);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index d9d1ae236bd5..e1a7eb817313 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -5,7 +5,7 @@
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
* (C) Copyright 2003-2005 MontaVista Software Inc.
- *
+ *
* Bus Glue for PPC On-Chip OHCI driver
* Tested on Freescale MPC5200 and IBM STB04xxx
*
@@ -85,7 +85,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1:
- usb_put_hcd(hcd);
+ usb_put_hcd(hcd);
return retval;
}
@@ -148,7 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.start = ohci_ppc_soc_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -197,7 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_ppc_soc_driver = {
.probe = ohci_hcd_ppc_soc_drv_probe,
.remove = ohci_hcd_ppc_soc_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
/*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
/*.resume = ohci_hcd_ppc_soc_drv_resume,*/
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index e176b04d7aeb..3bbea844a9e3 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -47,7 +47,7 @@ static int pxa27x_ohci_select_pmm( int mode )
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
- break;
+ break;
case PMM_GLOBAL_MODE:
UHCRHDA &= ~(RH_A_NPS & RH_A_PSM);
break;
@@ -60,7 +60,7 @@ static int pxa27x_ohci_select_pmm( int mode )
break;
default:
printk( KERN_ERR
- "Invalid mode %d, set to non-power switch mode.\n",
+ "Invalid mode %d, set to non-power switch mode.\n",
mode );
UHCRHDA |= RH_A_NPS;
@@ -270,7 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.start = ohci_pxa27x_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -359,9 +359,9 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
- .suspend = ohci_hcd_pxa27x_drv_suspend,
+ .suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
#endif
.driver = {
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index fe1fe2f97cb5..830a3fe8615e 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
- *
+ *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* This file is licenced under the GPL.
*/
@@ -89,7 +89,7 @@ __acquires(ohci->lock)
/*-------------------------------------------------------------------------*
* ED handling functions
- *-------------------------------------------------------------------------*/
+ *-------------------------------------------------------------------------*/
/* search for the right schedule branch to use for a periodic ed.
* does some load balancing; returns the branch, or negative errno.
@@ -107,7 +107,6 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
*/
for (i = 0; i < interval ; i++) {
if (branch < 0 || ohci->load [branch] > ohci->load [i]) {
-#if 1 /* CONFIG_USB_BANDWIDTH */
int j;
/* usb 1.1 says 90% of one frame */
@@ -117,8 +116,7 @@ static int balance (struct ohci_hcd *ohci, int interval, int load)
}
if (j < NUM_INTS)
continue;
-#endif
- branch = i;
+ branch = i;
}
}
return branch;
@@ -171,7 +169,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
/* link an ed into one of the HC chains */
static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
-{
+{
int branch;
if (ohci_to_hcd(ohci)->state == HC_STATE_QUIESCING)
@@ -248,7 +246,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
}
ed->branch = branch;
periodic_link (ohci, ed);
- }
+ }
/* the HC may not see the schedule updates yet, but if it does
* then they'll be properly ordered.
@@ -277,7 +275,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
*prev = ed->ed_next;
}
ohci->load [i] -= ed->load;
- }
+ }
ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval;
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
@@ -285,7 +283,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
ed, ed->branch, ed->load, ed->interval);
}
-/* unlink an ed from one of the HC chains.
+/* unlink an ed from one of the HC chains.
* just the link to the ed is unlinked.
* the link from the ed still points to another operational ed or 0
* so the HC can eventually finish the processing of the unlinked ed
@@ -307,7 +305,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
* When finish_unlinks() runs later, after SOF interrupt, it will often
* complete one or more URB unlinks before making that state change.
*/
-static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
+static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
@@ -397,7 +395,7 @@ static struct ed *ed_get (
unsigned int pipe,
int interval
) {
- struct ed *ed;
+ struct ed *ed;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -413,9 +411,9 @@ static struct ed *ed_get (
goto done;
}
- /* dummy td; end of td list for ed */
+ /* dummy td; end of td list for ed */
td = td_alloc (ohci, GFP_ATOMIC);
- if (!td) {
+ if (!td) {
/* out of memory */
ed_free (ohci, ed);
ed = NULL;
@@ -462,7 +460,7 @@ static struct ed *ed_get (
done:
spin_unlock_irqrestore (&ohci->lock, flags);
- return ed;
+ return ed;
}
/*-------------------------------------------------------------------------*/
@@ -474,7 +472,7 @@ done:
* and that ed->state is ED_OPER
*/
static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed)
-{
+{
ed->hwINFO |= cpu_to_hc32 (ohci, ED_DEQUEUE);
ed_deschedule (ohci, ed);
@@ -541,7 +539,7 @@ td_fill (struct ohci_hcd *ohci, u32 info,
td->ed = urb_priv->ed;
td->next_dl_td = NULL;
td->index = index;
- td->urb = urb;
+ td->urb = urb;
td->data_dma = data;
if (!len)
data = 0;
@@ -553,8 +551,8 @@ td_fill (struct ohci_hcd *ohci, u32 info,
(data & 0x0FFF) | 0xE000);
td->ed->last_iso = info & 0xffff;
} else {
- td->hwCBP = cpu_to_hc32 (ohci, data);
- }
+ td->hwCBP = cpu_to_hc32 (ohci, data);
+ }
if (data)
td->hwBE = cpu_to_hc32 (ohci, data + len - 1);
else
@@ -597,7 +595,7 @@ static void td_submit_urb (
* use the device toggle bits for resetting, and rely on the fact
* that resetting toggle is meaningless if the endpoint is active.
*/
- if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
+ if (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
is_out, 1);
urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C);
@@ -721,16 +719,16 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
list_del (&td->td_list);
/* ISO ... drivers see per-TD length/status */
- if (tdINFO & TD_ISO) {
- u16 tdPSW = ohci_hwPSW (ohci, td, 0);
+ if (tdINFO & TD_ISO) {
+ u16 tdPSW = ohci_hwPSW (ohci, td, 0);
int dlen = 0;
/* NOTE: assumes FC in tdINFO == 0, and that
* only the first of 0..MAXPSW psws is used.
*/
- cc = (tdPSW >> 12) & 0xF;
- if (tdINFO & TD_CC) /* hc didn't touch? */
+ cc = (tdPSW >> 12) & 0xF;
+ if (tdINFO & TD_CC) /* hc didn't touch? */
return;
if (usb_pipeout (urb->pipe))
@@ -758,7 +756,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
int type = usb_pipetype (urb->pipe);
u32 tdBE = hc32_to_cpup (ohci, &td->hwBE);
- cc = TD_CC_GET (tdINFO);
+ cc = TD_CC_GET (tdINFO);
/* update packet status if needed (short is normally ok) */
if (cc == TD_DATAUNDERRUN
@@ -787,7 +785,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
urb, td, 1 + td->index, cc,
urb->actual_length,
urb->transfer_buffer_length);
- }
+ }
}
/*-------------------------------------------------------------------------*/
@@ -795,7 +793,7 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
static inline struct td *
ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
{
- struct urb *urb = td->urb;
+ struct urb *urb = td->urb;
struct ed *ed = td->ed;
struct list_head *tmp = td->td_list.next;
__hc32 toggle = ed->hwHeadP & cpu_to_hc32 (ohci, ED_C);
@@ -805,7 +803,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
*/
ed->hwINFO |= cpu_to_hc32 (ohci, ED_SKIP);
wmb ();
- ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
+ ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_H);
/* put any later tds from this urb onto the donelist, after 'td',
* order won't matter here: no errors, and nothing was transferred.
@@ -833,7 +831,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
info &= ~cpu_to_hc32 (ohci, TD_CC);
next->hwINFO = info;
- next->next_dl_td = rev;
+ next->next_dl_td = rev;
rev = next;
ed->hwHeadP = next->hwNextTD | toggle;
@@ -881,8 +879,8 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
/* get TD from hc's singly linked list, and
* prepend to ours. ed->td_list changes later.
*/
- while (td_dma) {
- int cc;
+ while (td_dma) {
+ int cc;
td = dma_to_td (ohci, td_dma);
if (!td) {
@@ -901,10 +899,10 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
&& (td->ed->hwHeadP & cpu_to_hc32 (ohci, ED_H)))
td_rev = ed_halted (ohci, td, cc, td_rev);
- td->next_dl_td = td_rev;
+ td->next_dl_td = td_rev;
td_rev = td;
td_dma = hc32_to_cpup (ohci, &td->hwNextTD);
- }
+ }
return td_rev;
}
@@ -1013,9 +1011,9 @@ rescan_this:
if (modified)
goto rescan_all;
- }
+ }
- /* maybe reenable control and bulk lists */
+ /* maybe reenable control and bulk lists */
if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)
&& ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
&& !ohci->ed_rm_list) {
@@ -1041,20 +1039,20 @@ rescan_this:
&ohci->regs->ed_bulkcurrent);
}
}
-
+
/* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */
if (control) {
ohci->hc_control |= control;
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
- ohci_writel (ohci, ohci->hc_control,
- &ohci->regs->control);
- }
+ ohci_writel (ohci, ohci->hc_control,
+ &ohci->regs->control);
+ }
if (command) {
if (ohci->flags & OHCI_QUIRK_ZFMICRO)
mdelay(1);
- ohci_writel (ohci, command, &ohci->regs->cmdstatus);
- }
+ ohci_writel (ohci, command, &ohci->regs->cmdstatus);
+ }
}
}
@@ -1074,19 +1072,19 @@ dl_done_list (struct ohci_hcd *ohci)
{
struct td *td = dl_reverse_done_list (ohci);
- while (td) {
+ while (td) {
struct td *td_next = td->next_dl_td;
struct urb *urb = td->urb;
urb_priv_t *urb_priv = urb->hcpriv;
struct ed *ed = td->ed;
/* update URB's length and status from TD */
- td_done (ohci, urb, td);
- urb_priv->td_cnt++;
+ td_done (ohci, urb, td);
+ urb_priv->td_cnt++;
/* If all this urb's TDs are done, call complete() */
- if (urb_priv->td_cnt == urb_priv->length)
- finish_urb (ohci, urb);
+ if (urb_priv->td_cnt == urb_priv->length)
+ finish_urb (ohci, urb);
/* clean schedule: unlink EDs that are no longer busy */
if (list_empty (&ed->td_list)) {
@@ -1094,25 +1092,26 @@ dl_done_list (struct ohci_hcd *ohci)
start_ed_unlink (ohci, ed);
/* ... reenabling halted EDs only after fault cleanup */
- } else if ((ed->hwINFO & cpu_to_hc32 (ohci, ED_SKIP | ED_DEQUEUE))
+ } else if ((ed->hwINFO & cpu_to_hc32 (ohci,
+ ED_SKIP | ED_DEQUEUE))
== cpu_to_hc32 (ohci, ED_SKIP)) {
td = list_entry (ed->td_list.next, struct td, td_list);
- if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
+ if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) {
ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP);
/* ... hc may need waking-up */
switch (ed->type) {
case PIPE_CONTROL:
ohci_writel (ohci, OHCI_CLF,
- &ohci->regs->cmdstatus);
+ &ohci->regs->cmdstatus);
break;
case PIPE_BULK:
ohci_writel (ohci, OHCI_BLF,
- &ohci->regs->cmdstatus);
+ &ohci->regs->cmdstatus);
break;
}
}
}
- td = td_next;
- }
+ td = td_next;
+ }
}
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index 59e436424d41..b350d45033e7 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -447,7 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.start = ohci_s3c2410_start,
.stop = ohci_stop,
- .shutdown = ohci_shutdown,
+ .shutdown = ohci_shutdown,
/*
* managing i/o requests and associated device resources
@@ -492,7 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_drv_probe,
.remove = ohci_hcd_s3c2410_drv_remove,
- .shutdown = usb_hcd_platform_shutdown,
+ .shutdown = usb_hcd_platform_shutdown,
/*.suspend = ohci_hcd_s3c2410_drv_suspend, */
/*.resume = ohci_hcd_s3c2410_drv_resume, */
.driver = {
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 71371de32ada..fe0090e33675 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -4,7 +4,7 @@
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
* (C) Copyright 2002 Hewlett-Packard Company
- *
+ *
* SA1111 Bus Glue
*
* Written by Christopher Hoover <ch@hpl.hp.com>
@@ -12,7 +12,7 @@
*
* This file is licenced under the GPL.
*/
-
+
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/assabet.h>
@@ -31,7 +31,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst = 0;
- printk(KERN_DEBUG __FILE__
+ printk(KERN_DEBUG __FILE__
": starting SA-1111 OHCI USB Controller\n");
#ifdef CONFIG_SA1100_BADGE4
@@ -65,7 +65,7 @@ static void sa1111_start_hc(struct sa1111_dev *dev)
static void sa1111_stop_hc(struct sa1111_dev *dev)
{
unsigned int usb_rst;
- printk(KERN_DEBUG __FILE__
+ printk(KERN_DEBUG __FILE__
": stopping SA-1111 OHCI USB Controller\n");
/*
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index a2f42a2f47c6..405257f3e853 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -1,9 +1,9 @@
/*
* OHCI HCD (Host Controller Driver) for USB.
- *
+ *
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- *
+ *
* This file is licenced under the GPL.
*/
@@ -14,7 +14,7 @@
*/
typedef __u32 __bitwise __hc32;
typedef __u16 __bitwise __hc16;
-
+
/*
* OHCI Endpoint Descriptor (ED) ... holds TD queue
* See OHCI spec, section 4.2
@@ -24,7 +24,7 @@ typedef __u16 __bitwise __hc16;
*/
struct ed {
/* first fields are hardware-specified */
- __hc32 hwINFO; /* endpoint config bitmap */
+ __hc32 hwINFO; /* endpoint config bitmap */
/* info bits defined by hcd */
#define ED_DEQUEUE (1 << 27)
/* info bits defined by the hardware */
@@ -52,11 +52,11 @@ struct ed {
* usually: OPER --> UNLINK --> (IDLE | OPER) --> ...
*/
u8 state; /* ED_{IDLE,UNLINK,OPER} */
-#define ED_IDLE 0x00 /* NOT linked to HC */
-#define ED_UNLINK 0x01 /* being unlinked from hc */
+#define ED_IDLE 0x00 /* NOT linked to HC */
+#define ED_UNLINK 0x01 /* being unlinked from hc */
#define ED_OPER 0x02 /* IS linked to hc */
- u8 type; /* PIPE_{BULK,...} */
+ u8 type; /* PIPE_{BULK,...} */
/* periodic scheduling params (for intr and iso) */
u8 branch;
@@ -70,7 +70,7 @@ struct ed {
#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */
-
+
/*
* OHCI Transfer Descriptor (TD) ... one per transfer segment
* See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt)
@@ -107,22 +107,22 @@ struct td {
/* (no hwINFO #defines yet for iso tds) */
- __hc32 hwCBP; /* Current Buffer Pointer (or 0) */
- __hc32 hwNextTD; /* Next TD Pointer */
- __hc32 hwBE; /* Memory Buffer End Pointer */
+ __hc32 hwCBP; /* Current Buffer Pointer (or 0) */
+ __hc32 hwNextTD; /* Next TD Pointer */
+ __hc32 hwBE; /* Memory Buffer End Pointer */
/* PSW is only for ISO. Only 1 PSW entry is used, but on
* big-endian PPC hardware that's the second entry.
*/
#define MAXPSW 2
- __hc16 hwPSW [MAXPSW];
+ __hc16 hwPSW [MAXPSW];
/* rest are purely for the driver's use */
- __u8 index;
- struct ed *ed;
- struct td *td_hash; /* dma-->td hashtable */
- struct td *next_dl_td;
- struct urb *urb;
+ __u8 index;
+ struct ed *ed;
+ struct td *td_hash; /* dma-->td hashtable */
+ struct td *next_dl_td;
+ struct urb *urb;
dma_addr_t td_dma; /* addr of this TD */
dma_addr_t data_dma; /* addr of data it points to */
@@ -152,8 +152,8 @@ struct td {
#define TD_NOTACCESSED 0x0F
-/* map OHCI TD status codes (CC) to errno values */
-static const int cc_to_error [16] = {
+/* map OHCI TD status codes (CC) to errno values */
+static const int cc_to_error [16] = {
/* No Error */ 0,
/* CRC Error */ -EILSEQ,
/* Bit Stuff */ -EPROTO,
@@ -169,7 +169,7 @@ static const int cc_to_error [16] = {
/* BufferOver */ -ECOMM,
/* BuffUnder */ -ENOSR,
/* (for HCD) */ -EALREADY,
- /* (for HCD) */ -EALREADY
+ /* (for HCD) */ -EALREADY
};
@@ -182,7 +182,7 @@ struct ohci_hcca {
#define NUM_INTS 32
__hc32 int_table [NUM_INTS]; /* periodic schedule */
- /*
+ /*
* OHCI defines u16 frame_no, followed by u16 zero pad.
* Since some processors can't do 16 bit bus accesses,
* portable access must be a 32 bits wide.
@@ -262,10 +262,10 @@ struct ohci_regs {
* HcCommandStatus (cmdstatus) register masks
*/
#define OHCI_HCR (1 << 0) /* host controller reset */
-#define OHCI_CLF (1 << 1) /* control list filled */
-#define OHCI_BLF (1 << 2) /* bulk list filled */
-#define OHCI_OCR (1 << 3) /* ownership change request */
-#define OHCI_SOC (3 << 16) /* scheduling overrun count */
+#define OHCI_CLF (1 << 1) /* control list filled */
+#define OHCI_BLF (1 << 2) /* bulk list filled */
+#define OHCI_OCR (1 << 3) /* ownership change request */
+#define OHCI_SOC (3 << 16) /* scheduling overrun count */
/*
* masks used with interrupt registers:
@@ -285,20 +285,20 @@ struct ohci_regs {
/* OHCI ROOT HUB REGISTER MASKS */
-
+
/* roothub.portstatus [i] bits */
-#define RH_PS_CCS 0x00000001 /* current connect status */
-#define RH_PS_PES 0x00000002 /* port enable status*/
-#define RH_PS_PSS 0x00000004 /* port suspend status */
-#define RH_PS_POCI 0x00000008 /* port over current indicator */
-#define RH_PS_PRS 0x00000010 /* port reset status */
-#define RH_PS_PPS 0x00000100 /* port power status */
-#define RH_PS_LSDA 0x00000200 /* low speed device attached */
-#define RH_PS_CSC 0x00010000 /* connect status change */
-#define RH_PS_PESC 0x00020000 /* port enable status change */
-#define RH_PS_PSSC 0x00040000 /* port suspend status change */
-#define RH_PS_OCIC 0x00080000 /* over current indicator change */
-#define RH_PS_PRSC 0x00100000 /* port reset status change */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status*/
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
/* roothub.status bits */
#define RH_HS_LPS 0x00000001 /* local power status */
@@ -333,7 +333,7 @@ typedef struct urb_priv {
} urb_priv_t;
#define TD_HASH_SIZE 64 /* power'o'two */
-// sizeof (struct td) ~= 64 == 2^6 ...
+// sizeof (struct td) ~= 64 == 2^6 ...
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
@@ -364,11 +364,11 @@ struct ohci_hcd {
struct ed *ed_bulktail; /* last in bulk list */
struct ed *ed_controltail; /* last in ctrl list */
- struct ed *periodic [NUM_INTS]; /* shadow int_table */
+ struct ed *periodic [NUM_INTS]; /* shadow int_table */
/*
* OTG controllers and transceivers need software interaction;
- * other external transceivers should be software-transparent
+ * other external transceivers should be software-transparent
*/
struct otg_transceiver *transceiver;
@@ -385,7 +385,7 @@ struct ohci_hcd {
*/
int num_ports;
int load [NUM_INTS];
- u32 hc_control; /* copy of hc control reg */
+ u32 hc_control; /* copy of hc control reg */
unsigned long next_statechange; /* suspend/resume */
u32 fminterval; /* saved register */
unsigned autostop:1; /* rh auto stopping/stopped */
@@ -598,11 +598,11 @@ static inline void disable (struct ohci_hcd *ohci)
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
-#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
#define FIT (1 << 31)
#define LSTHRESH 0x628 /* lowspeed bit threshold */
-static void periodic_reinit (struct ohci_hcd *ohci)
+static inline void periodic_reinit (struct ohci_hcd *ohci)
{
u32 fi = ohci->fminterval & 0x03fff;
u32 fit = ohci_readl(ohci, &ohci->regs->fminterval) & FIT;
@@ -626,11 +626,11 @@ static void periodic_reinit (struct ohci_hcd *ohci)
temp = ohci_readl (hc, &hc->regs->roothub.register); \
temp; })
-static u32 roothub_a (struct ohci_hcd *hc)
+static inline u32 roothub_a (struct ohci_hcd *hc)
{ return read_roothub (hc, a, 0xfc0fe000); }
static inline u32 roothub_b (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.b); }
static inline u32 roothub_status (struct ohci_hcd *hc)
{ return ohci_readl (hc, &hc->regs->roothub.status); }
-static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
+static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i)
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 54f554e0f0ad..ac9f11d19817 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -169,21 +169,14 @@ static int sl811_cs_config(struct pcmcia_device *link)
DBG(0, "sl811_cs_config(0x%p)\n", link);
- tuple.DesiredTuple = CISTPL_CONFIG;
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
- link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
-
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(link, &conf));
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 32c635ecbf31..a7fa0d75567d 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -40,6 +40,7 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/pci_ids.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
@@ -71,7 +72,7 @@ static int distrust_firmware = 1;
module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup");
-DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
/*
* u132_module_lock exists to protect access to global variables
*
@@ -163,7 +164,7 @@ struct u132_endp {
u16 queue_next;
struct urb *urb_list[ENDP_QUEUE_SIZE];
struct list_head urb_more;
- struct work_struct scheduler;
+ struct delayed_work scheduler;
};
struct u132_ring {
unsigned in_use:1;
@@ -171,7 +172,7 @@ struct u132_ring {
u8 number;
struct u132 *u132;
struct u132_endp *curr_endp;
- struct work_struct scheduler;
+ struct delayed_work scheduler;
};
#define OHCI_QUIRK_AMD756 0x01
#define OHCI_QUIRK_SUPERIO 0x02
@@ -198,31 +199,28 @@ struct u132 {
u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
int flags;
unsigned long next_statechange;
- struct work_struct monitor;
+ struct delayed_work monitor;
int num_endpoints;
struct u132_addr addr[MAX_U132_ADDRS];
struct u132_udev udev[MAX_U132_UDEVS];
struct u132_port port[MAX_U132_PORTS];
struct u132_endp *endp[MAX_U132_ENDPS];
};
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
-int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
- u8 width, u32 *data);
-int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
- u8 width, u32 data);
+
/*
-* these can not be inlines because we need the structure offset!!
+* these cannot be inlines because we need the structure offset!!
* Does anyone have a better way?????
*/
+#define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
+ offsetof(struct ohci_regs, member), 0, data);
#define u132_read_pcimem(u132, member, data) \
usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
#define u132_write_pcimem(u132, member, data) \
usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
ohci_regs, member), 0, data);
-#define u132_write_pcimem_byte(u132, member, data) \
- usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
- ohci_regs, member), 0x0e, data);
static inline struct u132 *udev_to_u132(struct u132_udev *udev)
{
u8 udev_number = udev->udev_number;
@@ -314,7 +312,7 @@ static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
if (delta > 0) {
if (queue_delayed_work(workqueue, &ring->scheduler, delta))
return;
- } else if (queue_work(workqueue, &ring->scheduler))
+ } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
return;
kref_put(&u132->kref, u132_hcd_delete);
return;
@@ -393,12 +391,8 @@ static inline void u132_endp_init_kref(struct u132 *u132,
static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(workqueue, &endp->scheduler, delta))
- kref_get(&endp->kref);
- } else if (queue_work(workqueue, &endp->scheduler))
- kref_get(&endp->kref);
- return;
+ if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+ kref_get(&endp->kref);
}
static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
@@ -414,24 +408,14 @@ static inline void u132_monitor_put_kref(struct u132 *u132)
static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(workqueue, &u132->monitor, delta)) {
- kref_get(&u132->kref);
- }
- } else if (queue_work(workqueue, &u132->monitor))
- kref_get(&u132->kref);
- return;
+ if (queue_delayed_work(workqueue, &u132->monitor, delta))
+ kref_get(&u132->kref);
}
static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(workqueue, &u132->monitor, delta))
- return;
- } else if (queue_work(workqueue, &u132->monitor))
- return;
- kref_put(&u132->kref, u132_hcd_delete);
- return;
+ if (!queue_delayed_work(workqueue, &u132->monitor, delta))
+ kref_put(&u132->kref, u132_hcd_delete);
}
static void u132_monitor_cancel_work(struct u132 *u132)
@@ -493,9 +477,9 @@ static int read_roothub_info(struct u132 *u132)
return 0;
}
-static void u132_hcd_monitor_work(void *data)
+static void u132_hcd_monitor_work(struct work_struct *work)
{
- struct u132 *u132 = data;
+ struct u132 *u132 = container_of(work, struct u132, monitor.work);
if (u132->going > 1) {
dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
, u132->going);
@@ -1319,15 +1303,14 @@ static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
}
}
-static void u132_hcd_ring_work_scheduler(void *data);
-static void u132_hcd_endp_work_scheduler(void *data);
/*
* this work function is only executed from the work queue
*
*/
-static void u132_hcd_ring_work_scheduler(void *data)
+static void u132_hcd_ring_work_scheduler(struct work_struct *work)
{
- struct u132_ring *ring = data;
+ struct u132_ring *ring =
+ container_of(work, struct u132_ring, scheduler.work);
struct u132 *u132 = ring->u132;
down(&u132->scheduler_lock);
if (ring->in_use) {
@@ -1386,10 +1369,11 @@ static void u132_hcd_ring_work_scheduler(void *data)
}
}
-static void u132_hcd_endp_work_scheduler(void *data)
+static void u132_hcd_endp_work_scheduler(struct work_struct *work)
{
struct u132_ring *ring;
- struct u132_endp *endp = data;
+ struct u132_endp *endp =
+ container_of(work, struct u132_endp, scheduler.work);
struct u132 *u132 = endp->u132;
down(&u132->scheduler_lock);
ring = endp->ring;
@@ -1592,59 +1576,12 @@ static char *hcfs2string(int state)
return "?";
}
-static int u132_usb_reset(struct u132 *u132)
-{
- int retval;
- retval = u132_read_pcimem(u132, control, &u132->hc_control);
- if (retval)
- return retval;
- u132->hc_control &= OHCI_CTRL_RWC;
- retval = u132_write_pcimem(u132, control, u132->hc_control);
- if (retval)
- return retval;
- return 0;
-}
-
static int u132_init(struct u132 *u132)
{
int retval;
u32 control;
u132_disable(u132);
- u132->next_statechange =
- jiffies; /* SMM owns the HC? not for long! */ {
- u32 control;
- retval = u132_read_pcimem(u132, control, &control);
- if (retval)
- return retval;
- if (control & OHCI_CTRL_IR) {
- u32 temp = 50;
- retval = u132_write_pcimem(u132, intrenable,
- OHCI_INTR_OC);
- if (retval)
- return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus,
- OHCI_OCR);
- if (retval)
- return retval;
- check:{
- retval = u132_read_pcimem(u132, control,
- &control);
- if (retval)
- return retval;
- }
- if (control & OHCI_CTRL_IR) {
- msleep(10);
- if (--temp == 0) {
- dev_err(&u132->platform_dev->dev, "USB "
- "HC takeover failed!(BIOS/SMM b"
- "ug) control=%08X\n", control);
- return -EBUSY;
- }
- goto check;
- }
- u132_usb_reset(u132);
- }
- }
+ u132->next_statechange = jiffies;
retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
if (retval)
return retval;
@@ -1743,7 +1680,7 @@ static int u132_run(struct u132 *u132)
retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
if (retval)
return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
+ retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
if (retval)
return retval;
extra:{
@@ -1800,7 +1737,7 @@ static int u132_run(struct u132 *u132)
retval = u132_write_pcimem(u132, control, u132->hc_control);
if (retval)
return retval;
- retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
+ retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
if (retval)
return retval;
retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
@@ -1857,8 +1794,8 @@ static void u132_hcd_stop(struct usb_hcd *hcd)
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 1) {
- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
- , u132->going);
+ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
+ "een removed %d\n", u132, hcd, u132->going);
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
@@ -1947,7 +1884,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
if (!endp) {
return -ENOMEM;
}
- INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
spin_lock_init(&endp->queue_lock.slock);
INIT_LIST_HEAD(&endp->urb_more);
ring = endp->ring = &u132->ring[0];
@@ -2036,7 +1973,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
if (!endp) {
return -ENOMEM;
}
- INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
spin_lock_init(&endp->queue_lock.slock);
INIT_LIST_HEAD(&endp->urb_more);
endp->dequeueing = 0;
@@ -2121,7 +2058,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
if (!endp) {
return -ENOMEM;
}
- INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+ INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
spin_lock_init(&endp->queue_lock.slock);
INIT_LIST_HEAD(&endp->urb_more);
ring = endp->ring = &u132->ring[0];
@@ -2563,8 +2500,9 @@ static void u132_endpoint_disable(struct usb_hcd *hcd,
{
struct u132 *u132 = hcd_to_u132(hcd);
if (u132->going > 2) {
- dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
- , u132->going);
+ dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
+ ") has been removed %d\n", u132, hcd, hep,
+ u132->going);
} else {
struct u132_endp *endp = hep->hcpriv;
if (endp)
@@ -2808,7 +2746,6 @@ static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
} else if (u132->going > 0) {
dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
"ed\n", hcd);
- dump_stack();
return -ESHUTDOWN;
} else {
int i, changed = 0, length = 1;
@@ -3045,19 +2982,22 @@ static struct hc_driver u132_hc_driver = {
* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
* is held for writing, thus this module must not call usb_remove_hcd()
* synchronously - but instead should immediately stop activity to the
-* device and ansynchronously call usb_remove_hcd()
+* device and asynchronously call usb_remove_hcd()
*/
static int __devexit u132_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
if (hcd) {
struct u132 *u132 = hcd_to_u132(hcd);
- dump_stack();
if (u132->going++ > 1) {
+ dev_err(&u132->platform_dev->dev, "already being remove"
+ "d\n");
return -ENODEV;
} else {
int rings = MAX_U132_RINGS;
int endps = MAX_U132_ENDPS;
+ dev_err(&u132->platform_dev->dev, "removing device u132"
+ ".%d\n", u132->sequence_num);
msleep(100);
down(&u132->sw_lock);
u132_monitor_cancel_work(u132);
@@ -3100,10 +3040,10 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
ring->number = rings + 1;
ring->length = 0;
ring->curr_endp = NULL;
- INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler,
- (void *)ring);
+ INIT_DELAYED_WORK(&ring->scheduler,
+ u132_hcd_ring_work_scheduler);
} down(&u132->sw_lock);
- INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132);
+ INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
while (ports-- > 0) {
struct u132_port *port = &u132->port[ports];
port->u132 = u132;
@@ -3139,10 +3079,24 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
static int __devinit u132_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
+ int retval;
+ u32 control;
+ u32 rh_a = -1;
+ u32 num_ports;
msleep(100);
if (u132_exiting > 0) {
return -ENODEV;
- } /* refuse to confuse usbcore */
+ }
+ retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(pdev, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
+ if (retval)
+ return retval;
+ num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
if (pdev->dev.dma_mask) {
return -EINVAL;
}
@@ -3241,7 +3195,7 @@ static int u132_resume(struct platform_device *pdev)
#define u132_resume NULL
#endif
/*
-* this driver is loaded explicitely by ftdi_u132
+* this driver is loaded explicitly by ftdi_u132
*
* the platform_driver struct is static because it is per type of module
*/
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 226bf3de8edd..e0d4c2358b39 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -60,6 +60,11 @@ Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+/* for flakey hardware, ignore overcurrent indicators */
+static int ignore_oc;
+module_param(ignore_oc, bool, S_IRUGO);
+MODULE_PARM_DESC(ignore_oc, "ignore hardware overcurrent indications");
+
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URBs except for stalls
@@ -81,7 +86,7 @@ MODULE_PARM_DESC(debug, "Debug level");
static char *errbuf;
#define ERRBUF_LEN (32 * 1024)
-static kmem_cache_t *uhci_up_cachep; /* urb_priv */
+static struct kmem_cache *uhci_up_cachep; /* urb_priv */
static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
static void wakeup_rh(struct uhci_hcd *uhci);
@@ -169,6 +174,11 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
{
int port;
+ /* If we have to ignore overcurrent events then almost by definition
+ * we can't depend on resume-detect interrupts. */
+ if (ignore_oc)
+ return 1;
+
switch (to_pci_dev(uhci_dev(uhci))->vendor) {
default:
break;
@@ -199,24 +209,16 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
static int remote_wakeup_is_broken(struct uhci_hcd *uhci)
{
- static struct dmi_system_id broken_wakeup_table[] = {
- {
- .ident = "Asus A7V8X",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"),
- DMI_MATCH(DMI_BOARD_NAME, "A7V8X"),
- DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"),
- }
- },
- { }
- };
int port;
+ char *sys_info;
+ static char bad_Asus_board[] = "A7V8X";
/* One of Asus's motherboards has a bug which causes it to
* wake up immediately from suspend-to-RAM if any of the ports
* are connected. In such cases we will not set EGSM.
*/
- if (dmi_check_system(broken_wakeup_table)) {
+ sys_info = dmi_get_system_info(DMI_BOARD_NAME);
+ if (sys_info && !strcmp(sys_info, bad_Asus_board)) {
for (port = 0; port < uhci->rh_numports; ++port) {
if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
USBPORTSC_CCS)
@@ -255,7 +257,9 @@ __acquires(uhci->lock)
int_enable = USBINTR_RESUME;
if (remote_wakeup_is_broken(uhci))
egsm_enable = 0;
- if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable)
+ if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable ||
+ !device_may_wakeup(
+ &uhci_to_hcd(uhci)->self.root_hub->dev))
uhci->working_RD = int_enable = 0;
outw(int_enable, uhci->io_addr + USBINTR);
@@ -921,7 +925,8 @@ static int __init uhci_hcd_init(void)
{
int retval = -ENOMEM;
- printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n");
+ printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n",
+ ignore_oc ? ", overcurrent ignored" : "");
if (usb_disabled())
return -ENODEV;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index f8347f1a10b6..bacc25c53ba3 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -52,10 +52,20 @@ static int any_ports_active(struct uhci_hcd *uhci)
static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
{
int port;
+ int mask = RWC_BITS;
+
+ /* Some boards (both VIA and Intel apparently) report bogus
+ * overcurrent indications, causing massive log spam unless
+ * we completely ignore them. This doesn't seem to be a problem
+ * with the chipset so much as with the way it is connected on
+ * the motherboard; if the overcurrent input is left to float
+ * then it may constantly register false positives. */
+ if (ignore_oc)
+ mask &= ~USBPORTSC_OCC;
*buf = 0;
for (port = 0; port < uhci->rh_numports; ++port) {
- if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
+ if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & mask) ||
test_bit(port, &uhci->port_c_suspend))
*buf |= (1 << (port + 1));
}
@@ -263,7 +273,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
wPortChange |= USB_PORT_STAT_C_CONNECTION;
if (status & USBPORTSC_PEC)
wPortChange |= USB_PORT_STAT_C_ENABLE;
- if (status & USBPORTSC_OCC)
+ if ((status & USBPORTSC_OCC) && !ignore_oc)
wPortChange |= USB_PORT_STAT_C_OVERCURRENT;
if (test_bit(port, &uhci->port_c_suspend)) {
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 06115f22a4fa..30b88459ac7d 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -498,7 +498,7 @@ static inline struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci,
{
struct urb_priv *urbp;
- urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+ urbp = kmem_cache_alloc(uhci_up_cachep, GFP_ATOMIC);
if (!urbp)
return NULL;
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 3038ed0700d3..8ccddf74534a 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
if (!new_desc->context.scsi_status)
- goto out_kfree2;
+ goto out_free_urb;
new_desc->usb_dev = dev;
new_desc->usb_intf = intf;
@@ -822,18 +822,20 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->host = scsi_host_alloc(&mts_scsi_host_template,
sizeof(new_desc));
if (!new_desc->host)
- goto out_free_urb;
+ goto out_kfree2;
new_desc->host->hostdata[0] = (unsigned long)new_desc;
if (scsi_add_host(new_desc->host, NULL)) {
err_retval = -EIO;
- goto out_free_urb;
+ goto out_host_put;
}
scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc);
return 0;
+ out_host_put:
+ scsi_host_put(new_desc->host);
out_kfree2:
kfree(new_desc->context.scsi_status);
out_free_urb:
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig
index 20db36448ab3..258a5d09d3dc 100644
--- a/drivers/usb/input/Kconfig
+++ b/drivers/usb/input/Kconfig
@@ -6,14 +6,14 @@ comment "USB Input Devices"
config USB_HID
tristate "USB Human Interface Device (full HID) support"
+ default y
depends on USB
+ select HID
---help---
- Say Y here if you want full HID support to connect keyboards,
+ Say Y here if you want full HID support to connect USB keyboards,
mice, joysticks, graphic tablets, or any other HID based devices
- to your computer via USB. You also need to select HID Input layer
- support (below) if you want to use keyboards, mice, joysticks and
- the like ... as well as Uninterruptible Power Supply (UPS) and
- monitor control devices.
+ to your computer via USB, as well as Uninterruptible Power Supply
+ (UPS) and monitor control devices.
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
@@ -27,20 +27,10 @@ config USB_HID
comment "Input core support is needed for USB HID input layer or HIDBP support"
depends on USB_HID && INPUT=n
-config USB_HIDINPUT
- bool "HID input layer support"
- default y
- depends on INPUT && USB_HID
- help
- Say Y here if you want to use a USB keyboard, mouse or joystick,
- or any other HID input device.
-
- If unsure, say Y.
-
config USB_HIDINPUT_POWERBOOK
bool "Enable support for iBook/PowerBook special keys"
default n
- depends on USB_HIDINPUT
+ depends on USB_HID
help
Say Y here if you want support for the special keys (Fn, Numlock) on
Apple iBooks and PowerBooks.
@@ -49,7 +39,7 @@ config USB_HIDINPUT_POWERBOOK
config HID_FF
bool "Force feedback support (EXPERIMENTAL)"
- depends on USB_HIDINPUT && EXPERIMENTAL
+ depends on USB_HID && EXPERIMENTAL
help
Say Y here is you want force feedback support for a few HID devices.
See below for a list of supported devices.
@@ -221,6 +211,7 @@ config USB_TOUCHSCREEN
- ITM
- some other eTurboTouch
- Gunze AHL61
+ - DMC TSC-10/25
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -258,6 +249,11 @@ config USB_TOUCHSCREEN_GUNZE
bool "Gunze AHL61 device support" if EMBEDDED
depends on USB_TOUCHSCREEN
+config USB_TOUCHSCREEN_DMC_TSC10
+ default y
+ bool "DMC TSC-10/25 device support" if EMBEDDED
+ depends on USB_TOUCHSCREEN
+
config USB_YEALINK
tristate "Yealink usb-p1k voip phone"
depends on USB && INPUT && EXPERIMENTAL
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile
index d946d5213b30..1a24b5bfa05f 100644
--- a/drivers/usb/input/Makefile
+++ b/drivers/usb/input/Makefile
@@ -11,9 +11,6 @@ usbhid-objs := hid-core.o
ifeq ($(CONFIG_USB_HIDDEV),y)
usbhid-objs += hiddev.o
endif
-ifeq ($(CONFIG_USB_HIDINPUT),y)
- usbhid-objs += hid-input.o
-endif
ifeq ($(CONFIG_HID_PID),y)
usbhid-objs += hid-pidff.o
endif
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index 0096373b5f98..909138e5aa04 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -152,7 +152,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
if (!acecad || !input_dev)
goto fail1;
- acecad->data = usb_buffer_alloc(dev, 8, SLAB_KERNEL, &acecad->data_dma);
+ acecad->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &acecad->data_dma);
if (!acecad->data)
goto fail1;
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index bf428184608f..9f52429ce654 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -1988,7 +1988,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto fail1;
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
- SLAB_ATOMIC, &aiptek->data_dma);
+ GFP_ATOMIC, &aiptek->data_dma);
if (!aiptek->data)
goto fail1;
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index 4c213513484d..c77291d3d063 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -38,14 +38,29 @@
#define APPLE_VENDOR_ID 0x05AC
/* These names come from Info.plist in AppleUSBTrackpad.kext */
-#define GEYSER_ANSI_PRODUCT_ID 0x0214
-#define GEYSER_ISO_PRODUCT_ID 0x0215
-#define GEYSER_JIS_PRODUCT_ID 0x0216
+#define FOUNTAIN_ANSI_PRODUCT_ID 0x020E
+#define FOUNTAIN_ISO_PRODUCT_ID 0x020F
+
+#define FOUNTAIN_TP_ONLY_PRODUCT_ID 0x030A
+
+#define GEYSER1_TP_ONLY_PRODUCT_ID 0x030B
+
+#define GEYSER_ANSI_PRODUCT_ID 0x0214
+#define GEYSER_ISO_PRODUCT_ID 0x0215
+#define GEYSER_JIS_PRODUCT_ID 0x0216
/* MacBook devices */
-#define GEYSER3_ANSI_PRODUCT_ID 0x0217
-#define GEYSER3_ISO_PRODUCT_ID 0x0218
-#define GEYSER3_JIS_PRODUCT_ID 0x0219
+#define GEYSER3_ANSI_PRODUCT_ID 0x0217
+#define GEYSER3_ISO_PRODUCT_ID 0x0218
+#define GEYSER3_JIS_PRODUCT_ID 0x0219
+
+/*
+ * Geyser IV: same as Geyser III according to Info.plist in AppleUSBTrackpad.kext
+ * -> same IOClass (AppleUSBGrIIITrackpad), same acceleration tables
+ */
+#define GEYSER4_ANSI_PRODUCT_ID 0x021A
+#define GEYSER4_ISO_PRODUCT_ID 0x021B
+#define GEYSER4_JIS_PRODUCT_ID 0x021C
#define ATP_DEVICE(prod) \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
@@ -58,20 +73,26 @@
/* table of devices that work with this driver */
static struct usb_device_id atp_table [] = {
- { ATP_DEVICE(0x020E) },
- { ATP_DEVICE(0x020F) },
- { ATP_DEVICE(0x030A) },
- { ATP_DEVICE(0x030B) },
+ { ATP_DEVICE(FOUNTAIN_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(FOUNTAIN_TP_ONLY_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER1_TP_ONLY_PRODUCT_ID) },
/* PowerBooks Oct 2005 */
{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+ /* Core Duo MacBook & MacBook Pro */
{ ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
{ ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+ /* Core2 Duo MacBook & MacBook Pro */
+ { ATP_DEVICE(GEYSER4_ANSI_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_ISO_PRODUCT_ID) },
+ { ATP_DEVICE(GEYSER4_JIS_PRODUCT_ID) },
+
/* Terminating entry */
{ }
};
@@ -108,7 +129,7 @@ MODULE_DEVICE_TABLE (usb, atp_table);
*/
#define ATP_THRESHOLD 5
-/* MacBook Pro (Geyser 3) initialization constants */
+/* MacBook Pro (Geyser 3 & 4) initialization constants */
#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
@@ -154,6 +175,13 @@ MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
MODULE_LICENSE("GPL");
+/*
+ * Make the threshold a module parameter
+ */
+static int threshold = ATP_THRESHOLD;
+module_param(threshold, int, 0644);
+MODULE_PARM_DESC(threshold, "Discards any change in data from a sensor (trackpad has hundreds of these sensors) less than this value");
+
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output");
@@ -174,7 +202,10 @@ static inline int atp_is_geyser_3(struct atp *dev)
return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
(productId == GEYSER3_ISO_PRODUCT_ID) ||
- (productId == GEYSER3_JIS_PRODUCT_ID);
+ (productId == GEYSER3_JIS_PRODUCT_ID) ||
+ (productId == GEYSER4_ANSI_PRODUCT_ID) ||
+ (productId == GEYSER4_ISO_PRODUCT_ID) ||
+ (productId == GEYSER4_JIS_PRODUCT_ID);
}
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
@@ -183,16 +214,48 @@ static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
int i;
/* values to calculate mean */
int pcum = 0, psum = 0;
+ int is_increasing = 0;
*fingers = 0;
for (i = 0; i < nb_sensors; i++) {
- if (xy_sensors[i] < ATP_THRESHOLD)
+ if (xy_sensors[i] < threshold) {
+ if (is_increasing)
+ is_increasing = 0;
+
continue;
- if ((i - 1 < 0) || (xy_sensors[i - 1] < ATP_THRESHOLD))
+ }
+
+ /*
+ * Makes the finger detection more versatile. For example,
+ * two fingers with no gap will be detected. Also, my
+ * tests show it less likely to have intermittent loss
+ * of multiple finger readings while moving around (scrolling).
+ *
+ * Changes the multiple finger detection to counting humps on
+ * sensors (transitions from nonincreasing to increasing)
+ * instead of counting transitions from low sensors (no
+ * finger reading) to high sensors (finger above
+ * sensor)
+ *
+ * - Jason Parekh <jasonparekh@gmail.com>
+ */
+ if (i < 1 || (!is_increasing && xy_sensors[i - 1] < xy_sensors[i])) {
(*fingers)++;
- pcum += xy_sensors[i] * i;
- psum += xy_sensors[i];
+ is_increasing = 1;
+ } else if (i > 0 && xy_sensors[i - 1] >= xy_sensors[i]) {
+ is_increasing = 0;
+ }
+
+ /*
+ * Subtracts threshold so a high sensor that just passes the threshold
+ * won't skew the calculated absolute coordinate. Fixes an issue
+ * where slowly moving the mouse would occassionaly jump a number of
+ * pixels (let me restate--slowly moving the mouse makes this issue
+ * most apparent).
+ */
+ pcum += (xy_sensors[i] - threshold) * i;
+ psum += (xy_sensors[i] - threshold);
}
if (psum > 0) {
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 787b847d38cc..b724e36f7b92 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -592,7 +592,7 @@ static void ati_remote_irq_in(struct urb *urb)
__FUNCTION__, urb->status);
}
- retval = usb_submit_urb(urb, SLAB_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n",
__FUNCTION__, retval);
@@ -604,12 +604,12 @@ static void ati_remote_irq_in(struct urb *urb)
static int ati_remote_alloc_buffers(struct usb_device *udev,
struct ati_remote *ati_remote)
{
- ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
if (!ati_remote->inbuf)
return -1;
- ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
+ ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
if (!ati_remote->outbuf)
return -1;
@@ -630,11 +630,8 @@ static int ati_remote_alloc_buffers(struct usb_device *udev,
*/
static void ati_remote_free_buffers(struct ati_remote *ati_remote)
{
- if (ati_remote->irq_urb)
- usb_free_urb(ati_remote->irq_urb);
-
- if (ati_remote->out_urb)
- usb_free_urb(ati_remote->out_urb);
+ usb_free_urb(ati_remote->irq_urb);
+ usb_free_urb(ati_remote->out_urb);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
ati_remote->inbuf, ati_remote->inbuf_dma);
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index f982a2b4a7f9..83f1f79db7c7 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
int i;
for (i = 0; i < 2; i++) {
- if (ar2->urb[i])
- usb_free_urb(ar2->urb[i]);
+ usb_free_urb(ar2->urb[i]);
if (ar2->buf[i])
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 6d08a3bcc952..89fa6885709b 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -4,6 +4,7 @@
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
+ * Copyright (c) 2006 Jiri Kosina
*/
/*
@@ -32,8 +33,9 @@
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
#include <linux/hiddev.h>
+#include "usbhid.h"
/*
* Version Information
@@ -54,886 +56,10 @@ static unsigned int hid_mousepoll_interval;
module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
-/*
- * Register a new report for a device.
- */
-
-static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
-{
- struct hid_report_enum *report_enum = device->report_enum + type;
- struct hid_report *report;
-
- if (report_enum->report_id_hash[id])
- return report_enum->report_id_hash[id];
-
- if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL)))
- return NULL;
-
- if (id != 0)
- report_enum->numbered = 1;
-
- report->id = id;
- report->type = type;
- report->size = 0;
- report->device = device;
- report_enum->report_id_hash[id] = report;
-
- list_add_tail(&report->list, &report_enum->report_list);
-
- return report;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
-{
- struct hid_field *field;
-
- if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
- return NULL;
- }
-
- if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
- + values * sizeof(unsigned), GFP_KERNEL))) return NULL;
-
- field->index = report->maxfield++;
- report->field[field->index] = field;
- field->usage = (struct hid_usage *)(field + 1);
- field->value = (unsigned *)(field->usage + usages);
- field->report = report;
-
- return field;
-}
-
-/*
- * Open a collection. The type/usage is pushed on the stack.
- */
-
-static int open_collection(struct hid_parser *parser, unsigned type)
-{
- struct hid_collection *collection;
- unsigned usage;
-
- usage = parser->local.usage[0];
-
- if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
- return -1;
- }
-
- if (parser->device->maxcollection == parser->device->collection_size) {
- collection = kmalloc(sizeof(struct hid_collection) *
- parser->device->collection_size * 2, GFP_KERNEL);
- if (collection == NULL) {
- dbg("failed to reallocate collection array");
- return -1;
- }
- memcpy(collection, parser->device->collection,
- sizeof(struct hid_collection) *
- parser->device->collection_size);
- memset(collection + parser->device->collection_size, 0,
- sizeof(struct hid_collection) *
- parser->device->collection_size);
- kfree(parser->device->collection);
- parser->device->collection = collection;
- parser->device->collection_size *= 2;
- }
-
- parser->collection_stack[parser->collection_stack_ptr++] =
- parser->device->maxcollection;
-
- collection = parser->device->collection +
- parser->device->maxcollection++;
- collection->type = type;
- collection->usage = usage;
- collection->level = parser->collection_stack_ptr - 1;
-
- if (type == HID_COLLECTION_APPLICATION)
- parser->device->maxapplication++;
-
- return 0;
-}
-
-/*
- * Close a collection.
- */
-
-static int close_collection(struct hid_parser *parser)
-{
- if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
- return -1;
- }
- parser->collection_stack_ptr--;
- return 0;
-}
-
-/*
- * Climb up the stack, search for the specified collection type
- * and return the usage.
- */
-
-static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
-{
- int n;
- for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
- if (parser->device->collection[parser->collection_stack[n]].type == type)
- return parser->device->collection[parser->collection_stack[n]].usage;
- return 0; /* we know nothing about this usage type */
-}
-
-/*
- * Add a usage to the temporary parser table.
- */
-
-static int hid_add_usage(struct hid_parser *parser, unsigned usage)
-{
- if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
- return -1;
- }
- parser->local.usage[parser->local.usage_index] = usage;
- parser->local.collection_index[parser->local.usage_index] =
- parser->collection_stack_ptr ?
- parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
- parser->local.usage_index++;
- return 0;
-}
-
-/*
- * Register a new field for this report.
- */
-
-static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags)
-{
- struct hid_report *report;
- struct hid_field *field;
- int usages;
- unsigned offset;
- int i;
-
- if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
- return -1;
- }
-
- if (parser->global.logical_maximum < parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
- return -1;
- }
-
- offset = report->size;
- report->size += parser->global.report_size * parser->global.report_count;
-
- if (!parser->local.usage_index) /* Ignore padding fields */
- return 0;
-
- usages = max_t(int, parser->local.usage_index, parser->global.report_count);
-
- if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
- return 0;
-
- field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
- field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
- field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
-
- for (i = 0; i < usages; i++) {
- int j = i;
- /* Duplicate the last usage we parsed if we have excess values */
- if (i >= parser->local.usage_index)
- j = parser->local.usage_index - 1;
- field->usage[i].hid = parser->local.usage[j];
- field->usage[i].collection_index =
- parser->local.collection_index[j];
- }
-
- field->maxusage = usages;
- field->flags = flags;
- field->report_offset = offset;
- field->report_type = report_type;
- field->report_size = parser->global.report_size;
- field->report_count = parser->global.report_count;
- field->logical_minimum = parser->global.logical_minimum;
- field->logical_maximum = parser->global.logical_maximum;
- field->physical_minimum = parser->global.physical_minimum;
- field->physical_maximum = parser->global.physical_maximum;
- field->unit_exponent = parser->global.unit_exponent;
- field->unit = parser->global.unit;
-
- return 0;
-}
-
-/*
- * Read data value from item.
- */
-
-static u32 item_udata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.u8;
- case 2: return item->data.u16;
- case 4: return item->data.u32;
- }
- return 0;
-}
-
-static s32 item_sdata(struct hid_item *item)
-{
- switch (item->size) {
- case 1: return item->data.s8;
- case 2: return item->data.s16;
- case 4: return item->data.s32;
- }
- return 0;
-}
-
-/*
- * Process a global item.
- */
-
-static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
-{
- switch (item->tag) {
-
- case HID_GLOBAL_ITEM_TAG_PUSH:
-
- if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
- return -1;
- }
-
- memcpy(parser->global_stack + parser->global_stack_ptr++,
- &parser->global, sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_POP:
-
- if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
- return -1;
- }
-
- memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
- sizeof(struct hid_global));
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
- parser->global.usage_page = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
- parser->global.logical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
- if (parser->global.logical_minimum < 0)
- parser->global.logical_maximum = item_sdata(item);
- else
- parser->global.logical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
- parser->global.physical_minimum = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
- if (parser->global.physical_minimum < 0)
- parser->global.physical_maximum = item_sdata(item);
- else
- parser->global.physical_maximum = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
- parser->global.unit_exponent = item_sdata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_UNIT:
- parser->global.unit = item_udata(item);
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
- if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
- if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
- return -1;
- }
- return 0;
-
- case HID_GLOBAL_ITEM_TAG_REPORT_ID:
- if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
- return -1;
- }
- return 0;
-
- default:
- dbg("unknown global tag 0x%x", item->tag);
- return -1;
- }
-}
-
-/*
- * Process a local item.
- */
-
-static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- unsigned n;
-
- if (item->size == 0) {
- dbg("item data expected for local item");
- return -1;
- }
-
- data = item_udata(item);
-
- switch (item->tag) {
-
- case HID_LOCAL_ITEM_TAG_DELIMITER:
-
- if (data) {
- /*
- * We treat items before the first delimiter
- * as global to all usage sets (branch 0).
- * In the moment we process only these global
- * items and the first delimiter set.
- */
- if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
- return -1;
- }
- parser->local.delimiter_depth++;
- parser->local.delimiter_branch++;
- } else {
- if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
- return -1;
- }
- parser->local.delimiter_depth--;
- }
- return 1;
-
- case HID_LOCAL_ITEM_TAG_USAGE:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- return hid_add_usage(parser, data);
-
- case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- parser->local.usage_minimum = data;
- return 0;
-
- case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
-
- if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
- return 0;
- }
-
- if (item->size <= 2)
- data = (parser->global.usage_page << 16) + data;
-
- for (n = parser->local.usage_minimum; n <= data; n++)
- if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
- return -1;
- }
- return 0;
-
- default:
-
- dbg("unknown local item tag 0x%x", item->tag);
- return 0;
- }
- return 0;
-}
-
-/*
- * Process a main item.
- */
-
-static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
-{
- __u32 data;
- int ret;
-
- data = item_udata(item);
-
- switch (item->tag) {
- case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
- ret = open_collection(parser, data & 0xff);
- break;
- case HID_MAIN_ITEM_TAG_END_COLLECTION:
- ret = close_collection(parser);
- break;
- case HID_MAIN_ITEM_TAG_INPUT:
- ret = hid_add_field(parser, HID_INPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_OUTPUT:
- ret = hid_add_field(parser, HID_OUTPUT_REPORT, data);
- break;
- case HID_MAIN_ITEM_TAG_FEATURE:
- ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
- break;
- default:
- dbg("unknown main item tag 0x%x", item->tag);
- ret = 0;
- }
-
- memset(&parser->local, 0, sizeof(parser->local)); /* Reset the local parser environment */
-
- return ret;
-}
-
-/*
- * Process a reserved item.
- */
-
-static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
-{
- dbg("reserved item type, tag 0x%x", item->tag);
- return 0;
-}
-
-/*
- * Free a report and all registered fields. The field->usage and
- * field->value table's are allocated behind the field, so we need
- * only to free(field) itself.
- */
-
-static void hid_free_report(struct hid_report *report)
-{
- unsigned n;
-
- for (n = 0; n < report->maxfield; n++)
- kfree(report->field[n]);
- kfree(report);
-}
-
-/*
- * Free a device structure, all reports, and all fields.
- */
-
-static void hid_free_device(struct hid_device *device)
-{
- unsigned i,j;
-
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- struct hid_report_enum *report_enum = device->report_enum + i;
-
- for (j = 0; j < 256; j++) {
- struct hid_report *report = report_enum->report_id_hash[j];
- if (report)
- hid_free_report(report);
- }
- }
-
- kfree(device->rdesc);
- kfree(device);
-}
-
-/*
- * Fetch a report description item from the data stream. We support long
- * items, though they are not used yet.
- */
-
-static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
-{
- u8 b;
-
- if ((end - start) <= 0)
- return NULL;
-
- b = *start++;
-
- item->type = (b >> 2) & 3;
- item->tag = (b >> 4) & 15;
-
- if (item->tag == HID_ITEM_TAG_LONG) {
-
- item->format = HID_ITEM_FORMAT_LONG;
-
- if ((end - start) < 2)
- return NULL;
-
- item->size = *start++;
- item->tag = *start++;
-
- if ((end - start) < item->size)
- return NULL;
-
- item->data.longdata = start;
- start += item->size;
- return start;
- }
-
- item->format = HID_ITEM_FORMAT_SHORT;
- item->size = b & 3;
-
- switch (item->size) {
-
- case 0:
- return start;
-
- case 1:
- if ((end - start) < 1)
- return NULL;
- item->data.u8 = *start++;
- return start;
-
- case 2:
- if ((end - start) < 2)
- return NULL;
- item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
- start = (__u8 *)((__le16 *)start + 1);
- return start;
-
- case 3:
- item->size++;
- if ((end - start) < 4)
- return NULL;
- item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
- start = (__u8 *)((__le32 *)start + 1);
- return start;
- }
-
- return NULL;
-}
-
-/*
- * Parse a report description into a hid_device structure. Reports are
- * enumerated, fields are attached to these reports.
- */
-
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
-{
- struct hid_device *device;
- struct hid_parser *parser;
- struct hid_item item;
- __u8 *end;
- unsigned i;
- static int (*dispatch_type[])(struct hid_parser *parser,
- struct hid_item *item) = {
- hid_parser_main,
- hid_parser_global,
- hid_parser_local,
- hid_parser_reserved
- };
-
- if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
- return NULL;
-
- if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
- HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
- kfree(device);
- return NULL;
- }
- device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
-
- for (i = 0; i < HID_REPORT_TYPES; i++)
- INIT_LIST_HEAD(&device->report_enum[i].report_list);
-
- if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
- kfree(device->collection);
- kfree(device);
- return NULL;
- }
- memcpy(device->rdesc, start, size);
- device->rsize = size;
-
- if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
- kfree(device->rdesc);
- kfree(device->collection);
- kfree(device);
- return NULL;
- }
- parser->device = device;
-
- end = start + size;
- while ((start = fetch_item(start, end, &item)) != NULL) {
-
- if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
- item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
-
- if (start == end) {
- if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
- }
- kfree(parser);
- return device;
- }
- }
-
- dbg("item fetching failed at offset %d\n", (int)(end - start));
- kfree(device->collection);
- hid_free_device(device);
- kfree(parser);
- return NULL;
-}
-
-/*
- * Convert a signed n-bit integer to signed 32-bit integer. Common
- * cases are done through the compiler, the screwed things has to be
- * done by hand.
- */
-
-static s32 snto32(__u32 value, unsigned n)
-{
- switch (n) {
- case 8: return ((__s8)value);
- case 16: return ((__s16)value);
- case 32: return ((__s32)value);
- }
- return value & (1 << (n - 1)) ? value | (-1 << n) : value;
-}
-
-/*
- * Convert a signed 32-bit integer to a signed n-bit integer.
- */
-
-static u32 s32ton(__s32 value, unsigned n)
-{
- s32 a = value >> (n - 1);
- if (a && a != -1)
- return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
- return value & ((1 << n) - 1);
-}
-
-/*
- * Extract/implement a data field from/to a little endian report (bit array).
- *
- * Code sort-of follows HID spec:
- * http://www.usb.org/developers/devclass_docs/HID1_11.pdf
- *
- * While the USB HID spec allows unlimited length bit fields in "report
- * descriptors", most devices never use more than 16 bits.
- * One model of UPS is claimed to report "LINEV" as a 32-bit field.
- * Search linux-kernel and linux-usb-devel archives for "hid-core extract".
- */
-
-static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
-{
- u64 x;
-
- WARN_ON(n > 32);
-
- report += offset >> 3; /* adjust byte index */
- offset &= 7; /* now only need bit offset into one byte */
- x = get_unaligned((u64 *) report);
- x = le64_to_cpu(x);
- x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
- return (u32) x;
-}
-
-/*
- * "implement" : set bits in a little endian bit stream.
- * Same concepts as "extract" (see comments above).
- * The data mangled in the bit stream remains in little endian
- * order the whole time. It make more sense to talk about
- * endianness of register values by considering a register
- * a "cached" copy of the little endiad bit stream.
- */
-static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
-{
- u64 x;
- u64 m = (1ULL << n) - 1;
-
- WARN_ON(n > 32);
-
- WARN_ON(value > m);
- value &= m;
-
- report += offset >> 3;
- offset &= 7;
-
- x = get_unaligned((u64 *)report);
- x &= cpu_to_le64(~(m << offset));
- x |= cpu_to_le64(((u64) value) << offset);
- put_unaligned(x, (u64 *) report);
-}
-
-/*
- * Search an array for a value.
- */
-
-static __inline__ int search(__s32 *array, __s32 value, unsigned n)
-{
- while (n--) {
- if (*array++ == value)
- return 0;
- }
- return -1;
-}
-
-static void hid_process_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value, int interrupt)
-{
- hid_dump_input(usage, value);
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_hid_event(hid, field, usage, value);
- if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
- hiddev_hid_event(hid, field, usage, value);
-}
-
-/*
- * Analyse a received field, and fetch the data from it. The field
- * content is stored for next report processing (we do differential
- * reporting to the layer).
- */
-
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
-{
- unsigned n;
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- __s32 min = field->logical_minimum;
- __s32 max = field->logical_maximum;
- __s32 *value;
-
- if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
- return;
-
- for (n = 0; n < count; n++) {
-
- value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) :
- extract(data, offset + n * size, size);
-
- if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */
- && value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
- goto exit;
- }
-
- for (n = 0; n < count; n++) {
-
- if (HID_MAIN_ITEM_VARIABLE & field->flags) {
- hid_process_event(hid, field, &field->usage[n], value[n], interrupt);
- continue;
- }
-
- if (field->value[n] >= min && field->value[n] <= max
- && field->usage[field->value[n] - min].hid
- && search(value, field->value[n], count))
- hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
-
- if (value[n] >= min && value[n] <= max
- && field->usage[value[n] - min].hid
- && search(field->value, value[n], count))
- hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
- }
-
- memcpy(field->value, value, count * sizeof(__s32));
-exit:
- kfree(value);
-}
-
-static int hid_input_report(int type, struct urb *urb, int interrupt)
-{
- struct hid_device *hid = urb->context;
- struct hid_report_enum *report_enum = hid->report_enum + type;
- u8 *data = urb->transfer_buffer;
- int len = urb->actual_length;
- struct hid_report *report;
- int n, size;
-
- if (!len) {
- dbg("empty report");
- return -1;
- }
-
-#ifdef DEBUG_DATA
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un");
-#endif
-
- n = 0; /* Normally report number is 0 */
- if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
- n = *data++;
- len--;
- }
-
-#ifdef DEBUG_DATA
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, len);
- for (i = 0; i < len; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
-
- if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
- return -1;
- }
-
- size = ((report->size - 1) >> 3) + 1;
-
- if (len < size) {
- dbg("report %d is too short, (%d < %d)", report->id, len, size);
- memset(data + len, 0, size - len);
- }
-
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- hiddev_report_event(hid, report);
-
- for (n = 0; n < report->maxfield; n++)
- hid_input_field(hid, report->field[n], data, interrupt);
-
- if (hid->claimed & HID_CLAIMED_INPUT)
- hidinput_report_event(hid, report);
-
- return 0;
-}
+static int usbhid_pb_fnmode = 1;
+module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
+MODULE_PARM_DESC(pb_fnmode,
+ "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
/*
* Input submission and I/O error handler.
@@ -946,15 +72,16 @@ static int hid_start_in(struct hid_device *hid)
{
unsigned long flags;
int rc = 0;
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irqsave(&hid->inlock, flags);
- if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
- !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
- rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
+ spin_lock_irqsave(&usbhid->inlock, flags);
+ if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+ !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+ rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
if (rc != 0)
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
}
- spin_unlock_irqrestore(&hid->inlock, flags);
+ spin_unlock_irqrestore(&usbhid->inlock, flags);
return rc;
}
@@ -962,37 +89,49 @@ static int hid_start_in(struct hid_device *hid)
static void hid_retry_timeout(unsigned long _hid)
{
struct hid_device *hid = (struct hid_device *) _hid;
+ struct usbhid_device *usbhid = hid->driver_data;
- dev_dbg(&hid->intf->dev, "retrying intr urb\n");
+ dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
if (hid_start_in(hid))
hid_io_error(hid);
}
-/* Workqueue routine to reset the device */
-static void hid_reset(void *_hid)
+/* Workqueue routine to reset the device or clear a halt */
+static void hid_reset(struct work_struct *work)
{
- struct hid_device *hid = (struct hid_device *) _hid;
- int rc_lock, rc;
-
- dev_dbg(&hid->intf->dev, "resetting device\n");
- rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
- if (rc_lock >= 0) {
- rc = usb_reset_composite_device(hid->dev, hid->intf);
- if (rc_lock)
- usb_unlock_device(hid->dev);
+ struct usbhid_device *usbhid =
+ container_of(work, struct usbhid_device, reset_work);
+ struct hid_device *hid = usbhid->hid;
+ int rc_lock, rc = 0;
+
+ if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+ dev_dbg(&usbhid->intf->dev, "clear halt\n");
+ rc = usb_clear_halt(to_usb_device(hid->dev), usbhid->urbin->pipe);
+ clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ hid_start_in(hid);
+ }
+
+ else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ dev_dbg(&usbhid->intf->dev, "resetting device\n");
+ rc = rc_lock = usb_lock_device_for_reset(to_usb_device(hid->dev), usbhid->intf);
+ if (rc_lock >= 0) {
+ rc = usb_reset_composite_device(to_usb_device(hid->dev), usbhid->intf);
+ if (rc_lock)
+ usb_unlock_device(to_usb_device(hid->dev));
+ }
+ clear_bit(HID_RESET_PENDING, &usbhid->iofl);
}
- clear_bit(HID_RESET_PENDING, &hid->iofl);
switch (rc) {
case 0:
- if (!test_bit(HID_IN_RUNNING, &hid->iofl))
+ if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
hid_io_error(hid);
break;
default:
err("can't reset device, %s-%s/input%d, status %d",
- hid->dev->bus->bus_name,
- hid->dev->devpath,
- hid->ifnum, rc);
+ to_usb_device(hid->dev)->bus->bus_name,
+ to_usb_device(hid->dev)->devpath,
+ usbhid->ifnum, rc);
/* FALLTHROUGH */
case -EHOSTUNREACH:
case -ENODEV:
@@ -1005,34 +144,34 @@ static void hid_reset(void *_hid)
static void hid_io_error(struct hid_device *hid)
{
unsigned long flags;
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irqsave(&hid->inlock, flags);
+ spin_lock_irqsave(&usbhid->inlock, flags);
/* Stop when disconnected */
- if (usb_get_intfdata(hid->intf) == NULL)
+ if (usb_get_intfdata(usbhid->intf) == NULL)
goto done;
/* When an error occurs, retry at increasing intervals */
- if (hid->retry_delay == 0) {
- hid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
- hid->stop_retry = jiffies + msecs_to_jiffies(1000);
- } else if (hid->retry_delay < 100)
- hid->retry_delay *= 2;
+ if (usbhid->retry_delay == 0) {
+ usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */
+ usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
+ } else if (usbhid->retry_delay < 100)
+ usbhid->retry_delay *= 2;
- if (time_after(jiffies, hid->stop_retry)) {
+ if (time_after(jiffies, usbhid->stop_retry)) {
/* Retries failed, so do a port reset */
- if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
- if (schedule_work(&hid->reset_work))
- goto done;
- clear_bit(HID_RESET_PENDING, &hid->iofl);
+ if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+ schedule_work(&usbhid->reset_work);
+ goto done;
}
}
- mod_timer(&hid->io_retry,
- jiffies + msecs_to_jiffies(hid->retry_delay));
+ mod_timer(&usbhid->io_retry,
+ jiffies + msecs_to_jiffies(usbhid->retry_delay));
done:
- spin_unlock_irqrestore(&hid->inlock, flags);
+ spin_unlock_irqrestore(&usbhid->inlock, flags);
}
/*
@@ -1042,104 +181,51 @@ done:
static void hid_irq_in(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
int status;
switch (urb->status) {
case 0: /* success */
- hid->retry_delay = 0;
- hid_input_report(HID_INPUT_REPORT, urb, 1);
+ usbhid->retry_delay = 0;
+ hid_input_report(urb->context, HID_INPUT_REPORT,
+ urb->transfer_buffer,
+ urb->actual_length, 1);
break;
+ case -EPIPE: /* stall */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ schedule_work(&usbhid->reset_work);
+ return;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN: /* unplug */
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
return;
case -EILSEQ: /* protocol error or unplug */
case -EPROTO: /* protocol error or unplug */
case -ETIME: /* protocol error or unplug */
case -ETIMEDOUT: /* Should never happen, but... */
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
hid_io_error(hid);
return;
default: /* error */
warn("input irq status %d received", urb->status);
}
- status = usb_submit_urb(urb, SLAB_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- clear_bit(HID_IN_RUNNING, &hid->iofl);
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
if (status != -EPERM) {
err("can't resubmit intr, %s-%s/input%d, status %d",
- hid->dev->bus->bus_name,
- hid->dev->devpath,
- hid->ifnum, status);
+ to_usb_device(hid->dev)->bus->bus_name,
+ to_usb_device(hid->dev)->devpath,
+ usbhid->ifnum, status);
hid_io_error(hid);
}
}
}
/*
- * Output the field into the report.
- */
-
-static void hid_output_field(struct hid_field *field, __u8 *data)
-{
- unsigned count = field->report_count;
- unsigned offset = field->report_offset;
- unsigned size = field->report_size;
- unsigned n;
-
- for (n = 0; n < count; n++) {
- if (field->logical_minimum < 0) /* signed values */
- implement(data, offset + n * size, size, s32ton(field->value[n], size));
- else /* unsigned values */
- implement(data, offset + n * size, size, field->value[n]);
- }
-}
-
-/*
- * Create a report.
- */
-
-static void hid_output_report(struct hid_report *report, __u8 *data)
-{
- unsigned n;
-
- if (report->id > 0)
- *data++ = report->id;
-
- for (n = 0; n < report->maxfield; n++)
- hid_output_field(report->field[n], data);
-}
-
-/*
- * Set a field value. The report this field belongs to has to be
- * created and transferred to the device, to set this value in the
- * device.
- */
-
-int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
-{
- unsigned size = field->report_size;
-
- hid_dump_input(field->usage + offset, value);
-
- if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
- hid_dump_field(field, 8);
- return -1;
- }
- if (field->logical_minimum < 0) {
- if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
- return -1;
- }
- }
- field->value[offset] = value;
- return 0;
-}
-
-/*
* Find a report field with a specified HID usage.
*/
#if 0
@@ -1159,16 +245,17 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u
static int hid_submit_out(struct hid_device *hid)
{
struct hid_report *report;
+ struct usbhid_device *usbhid = hid->driver_data;
- report = hid->out[hid->outtail];
+ report = usbhid->out[usbhid->outtail];
- hid_output_report(report, hid->outbuf);
- hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
- hid->urbout->dev = hid->dev;
+ hid_output_report(report, usbhid->outbuf);
+ usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+ usbhid->urbout->dev = to_usb_device(hid->dev);
dbg("submitting out urb");
- if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
+ if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
err("usb_submit_urb(out) failed");
return -1;
}
@@ -1181,42 +268,43 @@ static int hid_submit_ctrl(struct hid_device *hid)
struct hid_report *report;
unsigned char dir;
int len;
+ struct usbhid_device *usbhid = hid->driver_data;
- report = hid->ctrl[hid->ctrltail].report;
- dir = hid->ctrl[hid->ctrltail].dir;
+ report = usbhid->ctrl[usbhid->ctrltail].report;
+ dir = usbhid->ctrl[usbhid->ctrltail].dir;
len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
if (dir == USB_DIR_OUT) {
- hid_output_report(report, hid->ctrlbuf);
- hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0);
- hid->urbctrl->transfer_buffer_length = len;
+ hid_output_report(report, usbhid->ctrlbuf);
+ usbhid->urbctrl->pipe = usb_sndctrlpipe(to_usb_device(hid->dev), 0);
+ usbhid->urbctrl->transfer_buffer_length = len;
} else {
int maxpacket, padlen;
- hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0);
- maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0);
+ usbhid->urbctrl->pipe = usb_rcvctrlpipe(to_usb_device(hid->dev), 0);
+ maxpacket = usb_maxpacket(to_usb_device(hid->dev), usbhid->urbctrl->pipe, 0);
if (maxpacket > 0) {
padlen = (len + maxpacket - 1) / maxpacket;
padlen *= maxpacket;
- if (padlen > hid->bufsize)
- padlen = hid->bufsize;
+ if (padlen > usbhid->bufsize)
+ padlen = usbhid->bufsize;
} else
padlen = 0;
- hid->urbctrl->transfer_buffer_length = padlen;
+ usbhid->urbctrl->transfer_buffer_length = padlen;
}
- hid->urbctrl->dev = hid->dev;
+ usbhid->urbctrl->dev = to_usb_device(hid->dev);
- hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
- hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
- hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
- hid->cr->wIndex = cpu_to_le16(hid->ifnum);
- hid->cr->wLength = cpu_to_le16(len);
+ usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+ usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
+ usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
+ usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
+ usbhid->cr->wLength = cpu_to_le16(len);
dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
- hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
- hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+ usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+ usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
- if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
+ if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
err("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -1231,6 +319,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
static void hid_irq_out(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags;
int unplug = 0;
@@ -1248,24 +337,24 @@ static void hid_irq_out(struct urb *urb)
warn("output irq status %d received", urb->status);
}
- spin_lock_irqsave(&hid->outlock, flags);
+ spin_lock_irqsave(&usbhid->outlock, flags);
if (unplug)
- hid->outtail = hid->outhead;
+ usbhid->outtail = usbhid->outhead;
else
- hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+ usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
- if (hid->outhead != hid->outtail) {
+ if (usbhid->outhead != usbhid->outtail) {
if (hid_submit_out(hid)) {
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
wake_up(&hid->wait);
}
- spin_unlock_irqrestore(&hid->outlock, flags);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
return;
}
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
- spin_unlock_irqrestore(&hid->outlock, flags);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
wake_up(&hid->wait);
}
@@ -1276,15 +365,17 @@ static void hid_irq_out(struct urb *urb)
static void hid_ctrl(struct urb *urb)
{
struct hid_device *hid = urb->context;
+ struct usbhid_device *usbhid = hid->driver_data;
unsigned long flags;
int unplug = 0;
- spin_lock_irqsave(&hid->ctrllock, flags);
+ spin_lock_irqsave(&usbhid->ctrllock, flags);
switch (urb->status) {
case 0: /* success */
- if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
- hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0);
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+ hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
+ urb->transfer_buffer, urb->actual_length, 0);
break;
case -ESHUTDOWN: /* unplug */
unplug = 1;
@@ -1299,76 +390,102 @@ static void hid_ctrl(struct urb *urb)
}
if (unplug)
- hid->ctrltail = hid->ctrlhead;
+ usbhid->ctrltail = usbhid->ctrlhead;
else
- hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+ usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
- if (hid->ctrlhead != hid->ctrltail) {
+ if (usbhid->ctrlhead != usbhid->ctrltail) {
if (hid_submit_ctrl(hid)) {
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
wake_up(&hid->wait);
}
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
return;
}
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
wake_up(&hid->wait);
}
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
{
int head;
unsigned long flags;
+ struct usbhid_device *usbhid = hid->driver_data;
if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
return;
- if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
+ if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
- spin_lock_irqsave(&hid->outlock, flags);
+ spin_lock_irqsave(&usbhid->outlock, flags);
- if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
- spin_unlock_irqrestore(&hid->outlock, flags);
+ if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
warn("output queue full");
return;
}
- hid->out[hid->outhead] = report;
- hid->outhead = head;
+ usbhid->out[usbhid->outhead] = report;
+ usbhid->outhead = head;
- if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
+ if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
if (hid_submit_out(hid))
- clear_bit(HID_OUT_RUNNING, &hid->iofl);
+ clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
- spin_unlock_irqrestore(&hid->outlock, flags);
+ spin_unlock_irqrestore(&usbhid->outlock, flags);
return;
}
- spin_lock_irqsave(&hid->ctrllock, flags);
+ spin_lock_irqsave(&usbhid->ctrllock, flags);
- if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
warn("control queue full");
return;
}
- hid->ctrl[hid->ctrlhead].report = report;
- hid->ctrl[hid->ctrlhead].dir = dir;
- hid->ctrlhead = head;
+ usbhid->ctrl[usbhid->ctrlhead].report = report;
+ usbhid->ctrl[usbhid->ctrlhead].dir = dir;
+ usbhid->ctrlhead = head;
- if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
+ if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
if (hid_submit_ctrl(hid))
- clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+ clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+
+ spin_unlock_irqrestore(&usbhid->ctrllock, flags);
+}
+
+static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_field *field;
+ int offset;
+
+ if (type == EV_FF)
+ return input_ff_event(dev, type, code, value);
+
+ if (type != EV_LED)
+ return -1;
+
+ if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
+ warn("event field not found");
+ return -1;
+ }
+
+ hid_set_field(field, offset, value);
+ usbhid_submit_report(hid, field->report, USB_DIR_OUT);
- spin_unlock_irqrestore(&hid->ctrllock, flags);
+ return 0;
}
-int hid_wait_io(struct hid_device *hid)
+int usbhid_wait_io(struct hid_device *hid)
{
- if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
- !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+ !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
dbg("timeout waiting for ctrl or out queue to clear");
return -1;
@@ -1400,7 +517,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
return result;
}
-int hid_open(struct hid_device *hid)
+int usbhid_open(struct hid_device *hid)
{
++hid->open;
if (hid_start_in(hid))
@@ -1408,10 +525,24 @@ int hid_open(struct hid_device *hid)
return 0;
}
-void hid_close(struct hid_device *hid)
+void usbhid_close(struct hid_device *hid)
{
+ struct usbhid_device *usbhid = hid->driver_data;
+
if (!--hid->open)
- usb_kill_urb(hid->urbin);
+ usb_kill_urb(usbhid->urbin);
+}
+
+static int hidinput_open(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ return usbhid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+ struct hid_device *hid = dev->private;
+ usbhid_close(hid);
}
#define USB_VENDOR_ID_PANJIT 0x134c
@@ -1423,26 +554,27 @@ void hid_close(struct hid_device *hid)
* Initialize all reports
*/
-void hid_init_reports(struct hid_device *hid)
+void usbhid_init_reports(struct hid_device *hid)
{
struct hid_report *report;
+ struct usbhid_device *usbhid = hid->driver_data;
int err, ret;
list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
- hid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
- hid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
err = 0;
- ret = hid_wait_io(hid);
+ ret = usbhid_wait_io(hid);
while (ret) {
err |= ret;
- if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
- usb_kill_urb(hid->urbctrl);
- if (test_bit(HID_OUT_RUNNING, &hid->iofl))
- usb_kill_urb(hid->urbout);
- ret = hid_wait_io(hid);
+ if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+ usb_kill_urb(usbhid->urbctrl);
+ if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+ usb_kill_urb(usbhid->urbout);
+ ret = usbhid_wait_io(hid);
}
if (err)
@@ -1627,6 +759,19 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
@@ -1643,6 +788,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_AIRCABLE 0x16CA
#define USB_DEVICE_ID_AIRCABLE1 0x1502
+#define USB_VENDOR_ID_LOGITECH 0x046d
+#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101
+
/*
* Alphabetically sorted blacklist by quirk type.
*/
@@ -1794,17 +942,19 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
- { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
- { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
- { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+ { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@@ -1812,7 +962,9 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+
{ 0, 0 }
};
@@ -1835,13 +987,15 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *
static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->inbuf_dma)))
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
return -1;
- if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->outbuf_dma)))
+ if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
return -1;
- if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), SLAB_ATOMIC, &hid->cr_dma)))
+ if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
return -1;
- if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, SLAB_ATOMIC, &hid->ctrlbuf_dma)))
+ if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
return -1;
return 0;
@@ -1849,14 +1003,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
- if (hid->inbuf)
- usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
- if (hid->outbuf)
- usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
- if (hid->cr)
- usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
- if (hid->ctrlbuf)
- usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
+ struct usbhid_device *usbhid = hid->driver_data;
+
+ if (usbhid->inbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+ if (usbhid->outbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+ if (usbhid->cr)
+ usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+ if (usbhid->ctrlbuf)
+ usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
/*
@@ -1882,6 +1038,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
unsigned quirks = 0, rsize = 0;
char *rdesc;
int n, len, insize = 0;
+ struct usbhid_device *usbhid;
/* Ignore all Wacom devices */
if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
@@ -1951,13 +1108,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
kfree(rdesc);
hid->quirks = quirks;
- hid->bufsize = HID_MIN_BUFFER_SIZE;
- hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
- hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
- hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+ if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
+ goto fail;
+
+ hid->driver_data = usbhid;
+ usbhid->hid = hid;
+
+ usbhid->bufsize = HID_MIN_BUFFER_SIZE;
+ hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
+ hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
+ hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);
- if (hid->bufsize > HID_MAX_BUFFER_SIZE)
- hid->bufsize = HID_MAX_BUFFER_SIZE;
+ if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
+ usbhid->bufsize = HID_MAX_BUFFER_SIZE;
hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
@@ -1985,48 +1148,48 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
interval = hid_mousepoll_interval;
- if (endpoint->bEndpointAddress & USB_DIR_IN) {
- if (hid->urbin)
+ if (usb_endpoint_dir_in(endpoint)) {
+ if (usbhid->urbin)
continue;
- if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
+ if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
+ usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
hid_irq_in, hid, interval);
- hid->urbin->transfer_dma = hid->inbuf_dma;
- hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
+ usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
} else {
- if (hid->urbout)
+ if (usbhid->urbout)
continue;
- if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
+ if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
goto fail;
pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
- usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
+ usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
hid_irq_out, hid, interval);
- hid->urbout->transfer_dma = hid->outbuf_dma;
- hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
+ usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
}
- if (!hid->urbin) {
+ if (!usbhid->urbin) {
err("couldn't find an input interrupt endpoint");
goto fail;
}
init_waitqueue_head(&hid->wait);
- INIT_WORK(&hid->reset_work, hid_reset, hid);
- setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
+ INIT_WORK(&usbhid->reset_work, hid_reset);
+ setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
- spin_lock_init(&hid->inlock);
- spin_lock_init(&hid->outlock);
- spin_lock_init(&hid->ctrllock);
+ spin_lock_init(&usbhid->inlock);
+ spin_lock_init(&usbhid->outlock);
+ spin_lock_init(&usbhid->ctrllock);
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
- hid->dev = dev;
- hid->intf = intf;
- hid->ifnum = interface->desc.bInterfaceNumber;
+ hid->dev = &dev->dev;
+ usbhid->intf = intf;
+ usbhid->ifnum = interface->desc.bInterfaceNumber;
hid->name[0] = 0;
@@ -2044,6 +1207,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
+ hid->bus = BUS_USB;
+ hid->vendor = dev->descriptor.idVendor;
+ hid->product = dev->descriptor.idProduct;
+
usb_make_path(dev, hid->phys, sizeof(hid->phys));
strlcat(hid->phys, "/input", sizeof(hid->phys));
len = strlen(hid->phys);
@@ -2054,26 +1221,32 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
hid->uniq[0] = 0;
- hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
- if (!hid->urbctrl)
+ usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+ if (!usbhid->urbctrl)
goto fail;
- usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
- hid->ctrlbuf, 1, hid_ctrl, hid);
- hid->urbctrl->setup_dma = hid->cr_dma;
- hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
- hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
+ usbhid->ctrlbuf, 1, hid_ctrl, hid);
+ usbhid->urbctrl->setup_dma = usbhid->cr_dma;
+ usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
+ usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+ hid->hidinput_input_event = usb_hidinput_input_event;
+ hid->hidinput_open = hidinput_open;
+ hid->hidinput_close = hidinput_close;
+#ifdef CONFIG_USB_HIDDEV
+ hid->hiddev_hid_event = hiddev_hid_event;
+ hid->hiddev_report_event = hiddev_report_event;
+#endif
+#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+ hid->pb_fnmode = usbhid_pb_fnmode;
+#endif
return hid;
fail:
-
- if (hid->urbin)
- usb_free_urb(hid->urbin);
- if (hid->urbout)
- usb_free_urb(hid->urbout);
- if (hid->urbctrl)
- usb_free_urb(hid->urbctrl);
+ usb_free_urb(usbhid->urbin);
+ usb_free_urb(usbhid->urbout);
+ usb_free_urb(usbhid->urbctrl);
hid_free_buffers(dev, hid);
hid_free_device(hid);
@@ -2083,18 +1256,21 @@ fail:
static void hid_disconnect(struct usb_interface *intf)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid;
if (!hid)
return;
- spin_lock_irq(&hid->inlock); /* Sync with error handler */
+ usbhid = hid->driver_data;
+
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
usb_set_intfdata(intf, NULL);
- spin_unlock_irq(&hid->inlock);
- usb_kill_urb(hid->urbin);
- usb_kill_urb(hid->urbout);
- usb_kill_urb(hid->urbctrl);
+ spin_unlock_irq(&usbhid->inlock);
+ usb_kill_urb(usbhid->urbin);
+ usb_kill_urb(usbhid->urbout);
+ usb_kill_urb(usbhid->urbctrl);
- del_timer_sync(&hid->io_retry);
+ del_timer_sync(&usbhid->io_retry);
flush_scheduled_work();
if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2102,12 +1278,11 @@ static void hid_disconnect(struct usb_interface *intf)
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_disconnect(hid);
- usb_free_urb(hid->urbin);
- usb_free_urb(hid->urbctrl);
- if (hid->urbout)
- usb_free_urb(hid->urbout);
+ usb_free_urb(usbhid->urbin);
+ usb_free_urb(usbhid->urbctrl);
+ usb_free_urb(usbhid->urbout);
- hid_free_buffers(hid->dev, hid);
+ hid_free_buffers(to_usb_device(hid->dev), hid);
hid_free_device(hid);
}
@@ -2124,7 +1299,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (!(hid = usb_hid_configure(intf)))
return -ENODEV;
- hid_init_reports(hid);
+ usbhid_init_reports(hid);
hid_dump_device(hid);
if (!hidinput_connect(hid))
@@ -2140,6 +1315,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV;
}
+ /* This only gets called when we are a single-input (most of the
+ * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
+ * only useful in this case, and not for multi-input quirks. */
+ if ((hid->claimed & HID_CLAIMED_INPUT) &&
+ !(hid->quirks & HID_QUIRK_MULTI_INPUT))
+ hid_ff_init(hid);
+
printk(KERN_INFO);
if (hid->claimed & HID_CLAIMED_INPUT)
@@ -2170,12 +1352,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
static int hid_suspend(struct usb_interface *intf, pm_message_t message)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid = hid->driver_data;
- spin_lock_irq(&hid->inlock); /* Sync with error handler */
- set_bit(HID_SUSPENDED, &hid->iofl);
- spin_unlock_irq(&hid->inlock);
- del_timer(&hid->io_retry);
- usb_kill_urb(hid->urbin);
+ spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
+ set_bit(HID_SUSPENDED, &usbhid->iofl);
+ spin_unlock_irq(&usbhid->inlock);
+ del_timer(&usbhid->io_retry);
+ usb_kill_urb(usbhid->urbin);
dev_dbg(&intf->dev, "suspend\n");
return 0;
}
@@ -2183,10 +1366,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
static int hid_resume(struct usb_interface *intf)
{
struct hid_device *hid = usb_get_intfdata (intf);
+ struct usbhid_device *usbhid = hid->driver_data;
int status;
- clear_bit(HID_SUSPENDED, &hid->iofl);
- hid->retry_delay = 0;
+ clear_bit(HID_SUSPENDED, &usbhid->iofl);
+ usbhid->retry_delay = 0;
status = hid_start_in(hid);
dev_dbg(&intf->dev, "resume status %d\n", status);
return status;
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
deleted file mode 100644
index f04d6d75c098..000000000000
--- a/drivers/usb/input/hid-debug.h
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
- *
- * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
- * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
- *
- * Some debug stuff for the HID parser.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/input.h>
-
-struct hid_usage_entry {
- unsigned page;
- unsigned usage;
- char *description;
-};
-
-static const struct hid_usage_entry hid_usage_table[] = {
- { 0, 0, "Undefined" },
- { 1, 0, "GenericDesktop" },
- {0, 0x01, "Pointer"},
- {0, 0x02, "Mouse"},
- {0, 0x04, "Joystick"},
- {0, 0x05, "GamePad"},
- {0, 0x06, "Keyboard"},
- {0, 0x07, "Keypad"},
- {0, 0x08, "MultiAxis"},
- {0, 0x30, "X"},
- {0, 0x31, "Y"},
- {0, 0x32, "Z"},
- {0, 0x33, "Rx"},
- {0, 0x34, "Ry"},
- {0, 0x35, "Rz"},
- {0, 0x36, "Slider"},
- {0, 0x37, "Dial"},
- {0, 0x38, "Wheel"},
- {0, 0x39, "HatSwitch"},
- {0, 0x3a, "CountedBuffer"},
- {0, 0x3b, "ByteCount"},
- {0, 0x3c, "MotionWakeup"},
- {0, 0x3d, "Start"},
- {0, 0x3e, "Select"},
- {0, 0x40, "Vx"},
- {0, 0x41, "Vy"},
- {0, 0x42, "Vz"},
- {0, 0x43, "Vbrx"},
- {0, 0x44, "Vbry"},
- {0, 0x45, "Vbrz"},
- {0, 0x46, "Vno"},
- {0, 0x80, "SystemControl"},
- {0, 0x81, "SystemPowerDown"},
- {0, 0x82, "SystemSleep"},
- {0, 0x83, "SystemWakeUp"},
- {0, 0x84, "SystemContextMenu"},
- {0, 0x85, "SystemMainMenu"},
- {0, 0x86, "SystemAppMenu"},
- {0, 0x87, "SystemMenuHelp"},
- {0, 0x88, "SystemMenuExit"},
- {0, 0x89, "SystemMenuSelect"},
- {0, 0x8a, "SystemMenuRight"},
- {0, 0x8b, "SystemMenuLeft"},
- {0, 0x8c, "SystemMenuUp"},
- {0, 0x8d, "SystemMenuDown"},
- {0, 0x90, "D-PadUp"},
- {0, 0x91, "D-PadDown"},
- {0, 0x92, "D-PadRight"},
- {0, 0x93, "D-PadLeft"},
- { 2, 0, "Simulation" },
- {0, 0xb0, "Aileron"},
- {0, 0xb1, "AileronTrim"},
- {0, 0xb2, "Anti-Torque"},
- {0, 0xb3, "Autopilot"},
- {0, 0xb4, "Chaff"},
- {0, 0xb5, "Collective"},
- {0, 0xb6, "DiveBrake"},
- {0, 0xb7, "ElectronicCountermeasures"},
- {0, 0xb8, "Elevator"},
- {0, 0xb9, "ElevatorTrim"},
- {0, 0xba, "Rudder"},
- {0, 0xbb, "Throttle"},
- {0, 0xbc, "FlightCommunications"},
- {0, 0xbd, "FlareRelease"},
- {0, 0xbe, "LandingGear"},
- {0, 0xbf, "ToeBrake"},
- { 7, 0, "Keyboard" },
- { 8, 0, "LED" },
- {0, 0x01, "NumLock"},
- {0, 0x02, "CapsLock"},
- {0, 0x03, "ScrollLock"},
- {0, 0x04, "Compose"},
- {0, 0x05, "Kana"},
- {0, 0x4b, "GenericIndicator"},
- { 9, 0, "Button" },
- { 10, 0, "Ordinal" },
- { 12, 0, "Consumer" },
- {0, 0x238, "HorizontalWheel"},
- { 13, 0, "Digitizers" },
- {0, 0x01, "Digitizer"},
- {0, 0x02, "Pen"},
- {0, 0x03, "LightPen"},
- {0, 0x04, "TouchScreen"},
- {0, 0x05, "TouchPad"},
- {0, 0x20, "Stylus"},
- {0, 0x21, "Puck"},
- {0, 0x22, "Finger"},
- {0, 0x30, "TipPressure"},
- {0, 0x31, "BarrelPressure"},
- {0, 0x32, "InRange"},
- {0, 0x33, "Touch"},
- {0, 0x34, "UnTouch"},
- {0, 0x35, "Tap"},
- {0, 0x39, "TabletFunctionKey"},
- {0, 0x3a, "ProgramChangeKey"},
- {0, 0x3c, "Invert"},
- {0, 0x42, "TipSwitch"},
- {0, 0x43, "SecondaryTipSwitch"},
- {0, 0x44, "BarrelSwitch"},
- {0, 0x45, "Eraser"},
- {0, 0x46, "TabletPick"},
- { 15, 0, "PhysicalInterfaceDevice" },
- {0, 0x00, "Undefined"},
- {0, 0x01, "Physical_Interface_Device"},
- {0, 0x20, "Normal"},
- {0, 0x21, "Set_Effect_Report"},
- {0, 0x22, "Effect_Block_Index"},
- {0, 0x23, "Parameter_Block_Offset"},
- {0, 0x24, "ROM_Flag"},
- {0, 0x25, "Effect_Type"},
- {0, 0x26, "ET_Constant_Force"},
- {0, 0x27, "ET_Ramp"},
- {0, 0x28, "ET_Custom_Force_Data"},
- {0, 0x30, "ET_Square"},
- {0, 0x31, "ET_Sine"},
- {0, 0x32, "ET_Triangle"},
- {0, 0x33, "ET_Sawtooth_Up"},
- {0, 0x34, "ET_Sawtooth_Down"},
- {0, 0x40, "ET_Spring"},
- {0, 0x41, "ET_Damper"},
- {0, 0x42, "ET_Inertia"},
- {0, 0x43, "ET_Friction"},
- {0, 0x50, "Duration"},
- {0, 0x51, "Sample_Period"},
- {0, 0x52, "Gain"},
- {0, 0x53, "Trigger_Button"},
- {0, 0x54, "Trigger_Repeat_Interval"},
- {0, 0x55, "Axes_Enable"},
- {0, 0x56, "Direction_Enable"},
- {0, 0x57, "Direction"},
- {0, 0x58, "Type_Specific_Block_Offset"},
- {0, 0x59, "Block_Type"},
- {0, 0x5A, "Set_Envelope_Report"},
- {0, 0x5B, "Attack_Level"},
- {0, 0x5C, "Attack_Time"},
- {0, 0x5D, "Fade_Level"},
- {0, 0x5E, "Fade_Time"},
- {0, 0x5F, "Set_Condition_Report"},
- {0, 0x60, "CP_Offset"},
- {0, 0x61, "Positive_Coefficient"},
- {0, 0x62, "Negative_Coefficient"},
- {0, 0x63, "Positive_Saturation"},
- {0, 0x64, "Negative_Saturation"},
- {0, 0x65, "Dead_Band"},
- {0, 0x66, "Download_Force_Sample"},
- {0, 0x67, "Isoch_Custom_Force_Enable"},
- {0, 0x68, "Custom_Force_Data_Report"},
- {0, 0x69, "Custom_Force_Data"},
- {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
- {0, 0x6B, "Set_Custom_Force_Report"},
- {0, 0x6C, "Custom_Force_Data_Offset"},
- {0, 0x6D, "Sample_Count"},
- {0, 0x6E, "Set_Periodic_Report"},
- {0, 0x6F, "Offset"},
- {0, 0x70, "Magnitude"},
- {0, 0x71, "Phase"},
- {0, 0x72, "Period"},
- {0, 0x73, "Set_Constant_Force_Report"},
- {0, 0x74, "Set_Ramp_Force_Report"},
- {0, 0x75, "Ramp_Start"},
- {0, 0x76, "Ramp_End"},
- {0, 0x77, "Effect_Operation_Report"},
- {0, 0x78, "Effect_Operation"},
- {0, 0x79, "Op_Effect_Start"},
- {0, 0x7A, "Op_Effect_Start_Solo"},
- {0, 0x7B, "Op_Effect_Stop"},
- {0, 0x7C, "Loop_Count"},
- {0, 0x7D, "Device_Gain_Report"},
- {0, 0x7E, "Device_Gain"},
- {0, 0x7F, "PID_Pool_Report"},
- {0, 0x80, "RAM_Pool_Size"},
- {0, 0x81, "ROM_Pool_Size"},
- {0, 0x82, "ROM_Effect_Block_Count"},
- {0, 0x83, "Simultaneous_Effects_Max"},
- {0, 0x84, "Pool_Alignment"},
- {0, 0x85, "PID_Pool_Move_Report"},
- {0, 0x86, "Move_Source"},
- {0, 0x87, "Move_Destination"},
- {0, 0x88, "Move_Length"},
- {0, 0x89, "PID_Block_Load_Report"},
- {0, 0x8B, "Block_Load_Status"},
- {0, 0x8C, "Block_Load_Success"},
- {0, 0x8D, "Block_Load_Full"},
- {0, 0x8E, "Block_Load_Error"},
- {0, 0x8F, "Block_Handle"},
- {0, 0x90, "PID_Block_Free_Report"},
- {0, 0x91, "Type_Specific_Block_Handle"},
- {0, 0x92, "PID_State_Report"},
- {0, 0x94, "Effect_Playing"},
- {0, 0x95, "PID_Device_Control_Report"},
- {0, 0x96, "PID_Device_Control"},
- {0, 0x97, "DC_Enable_Actuators"},
- {0, 0x98, "DC_Disable_Actuators"},
- {0, 0x99, "DC_Stop_All_Effects"},
- {0, 0x9A, "DC_Device_Reset"},
- {0, 0x9B, "DC_Device_Pause"},
- {0, 0x9C, "DC_Device_Continue"},
- {0, 0x9F, "Device_Paused"},
- {0, 0xA0, "Actuators_Enabled"},
- {0, 0xA4, "Safety_Switch"},
- {0, 0xA5, "Actuator_Override_Switch"},
- {0, 0xA6, "Actuator_Power"},
- {0, 0xA7, "Start_Delay"},
- {0, 0xA8, "Parameter_Block_Size"},
- {0, 0xA9, "Device_Managed_Pool"},
- {0, 0xAA, "Shared_Parameter_Blocks"},
- {0, 0xAB, "Create_New_Effect_Report"},
- {0, 0xAC, "RAM_Pool_Available"},
- { 0x84, 0, "Power Device" },
- { 0x84, 0x02, "PresentStatus" },
- { 0x84, 0x03, "ChangeStatus" },
- { 0x84, 0x04, "UPS" },
- { 0x84, 0x05, "PowerSupply" },
- { 0x84, 0x10, "BatterySystem" },
- { 0x84, 0x11, "BatterySystemID" },
- { 0x84, 0x12, "Battery" },
- { 0x84, 0x13, "BatteryID" },
- { 0x84, 0x14, "Charger" },
- { 0x84, 0x15, "ChargerID" },
- { 0x84, 0x16, "PowerConverter" },
- { 0x84, 0x17, "PowerConverterID" },
- { 0x84, 0x18, "OutletSystem" },
- { 0x84, 0x19, "OutletSystemID" },
- { 0x84, 0x1a, "Input" },
- { 0x84, 0x1b, "InputID" },
- { 0x84, 0x1c, "Output" },
- { 0x84, 0x1d, "OutputID" },
- { 0x84, 0x1e, "Flow" },
- { 0x84, 0x1f, "FlowID" },
- { 0x84, 0x20, "Outlet" },
- { 0x84, 0x21, "OutletID" },
- { 0x84, 0x22, "Gang" },
- { 0x84, 0x24, "PowerSummary" },
- { 0x84, 0x25, "PowerSummaryID" },
- { 0x84, 0x30, "Voltage" },
- { 0x84, 0x31, "Current" },
- { 0x84, 0x32, "Frequency" },
- { 0x84, 0x33, "ApparentPower" },
- { 0x84, 0x35, "PercentLoad" },
- { 0x84, 0x40, "ConfigVoltage" },
- { 0x84, 0x41, "ConfigCurrent" },
- { 0x84, 0x43, "ConfigApparentPower" },
- { 0x84, 0x53, "LowVoltageTransfer" },
- { 0x84, 0x54, "HighVoltageTransfer" },
- { 0x84, 0x56, "DelayBeforeStartup" },
- { 0x84, 0x57, "DelayBeforeShutdown" },
- { 0x84, 0x58, "Test" },
- { 0x84, 0x5a, "AudibleAlarmControl" },
- { 0x84, 0x60, "Present" },
- { 0x84, 0x61, "Good" },
- { 0x84, 0x62, "InternalFailure" },
- { 0x84, 0x65, "Overload" },
- { 0x84, 0x66, "OverCharged" },
- { 0x84, 0x67, "OverTemperature" },
- { 0x84, 0x68, "ShutdownRequested" },
- { 0x84, 0x69, "ShutdownImminent" },
- { 0x84, 0x6b, "SwitchOn/Off" },
- { 0x84, 0x6c, "Switchable" },
- { 0x84, 0x6d, "Used" },
- { 0x84, 0x6e, "Boost" },
- { 0x84, 0x73, "CommunicationLost" },
- { 0x84, 0xfd, "iManufacturer" },
- { 0x84, 0xfe, "iProduct" },
- { 0x84, 0xff, "iSerialNumber" },
- { 0x85, 0, "Battery System" },
- { 0x85, 0x01, "SMBBatteryMode" },
- { 0x85, 0x02, "SMBBatteryStatus" },
- { 0x85, 0x03, "SMBAlarmWarning" },
- { 0x85, 0x04, "SMBChargerMode" },
- { 0x85, 0x05, "SMBChargerStatus" },
- { 0x85, 0x06, "SMBChargerSpecInfo" },
- { 0x85, 0x07, "SMBSelectorState" },
- { 0x85, 0x08, "SMBSelectorPresets" },
- { 0x85, 0x09, "SMBSelectorInfo" },
- { 0x85, 0x29, "RemainingCapacityLimit" },
- { 0x85, 0x2c, "CapacityMode" },
- { 0x85, 0x42, "BelowRemainingCapacityLimit" },
- { 0x85, 0x44, "Charging" },
- { 0x85, 0x45, "Discharging" },
- { 0x85, 0x4b, "NeedReplacement" },
- { 0x85, 0x66, "RemainingCapacity" },
- { 0x85, 0x68, "RunTimeToEmpty" },
- { 0x85, 0x6a, "AverageTimeToFull" },
- { 0x85, 0x83, "DesignCapacity" },
- { 0x85, 0x85, "ManufacturerDate" },
- { 0x85, 0x89, "iDeviceChemistry" },
- { 0x85, 0x8b, "Rechargable" },
- { 0x85, 0x8f, "iOEMInformation" },
- { 0x85, 0x8d, "CapacityGranularity1" },
- { 0x85, 0xd0, "ACPresent" },
- /* pages 0xff00 to 0xffff are vendor-specific */
- { 0xffff, 0, "Vendor-specific-FF" },
- { 0, 0, NULL }
-};
-
-static void resolv_usage_page(unsigned page) {
- const struct hid_usage_entry *p;
-
- for (p = hid_usage_table; p->description; p++)
- if (p->page == page) {
- printk("%s", p->description);
- return;
- }
- printk("%04x", page);
-}
-
-static void resolv_usage(unsigned usage) {
- const struct hid_usage_entry *p;
-
- resolv_usage_page(usage >> 16);
- printk(".");
- for (p = hid_usage_table; p->description; p++)
- if (p->page == (usage >> 16)) {
- for(++p; p->description && p->usage != 0; p++)
- if (p->usage == (usage & 0xffff)) {
- printk("%s", p->description);
- return;
- }
- break;
- }
- printk("%04x", usage & 0xffff);
-}
-
-__inline__ static void tab(int n) {
- while (n--) printk(" ");
-}
-
-static void hid_dump_field(struct hid_field *field, int n) {
- int j;
-
- if (field->physical) {
- tab(n);
- printk("Physical(");
- resolv_usage(field->physical); printk(")\n");
- }
- if (field->logical) {
- tab(n);
- printk("Logical(");
- resolv_usage(field->logical); printk(")\n");
- }
- tab(n); printk("Usage(%d)\n", field->maxusage);
- for (j = 0; j < field->maxusage; j++) {
- tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
- }
- if (field->logical_minimum != field->logical_maximum) {
- tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
- tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
- }
- if (field->physical_minimum != field->physical_maximum) {
- tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
- tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
- }
- if (field->unit_exponent) {
- tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
- }
- if (field->unit) {
- char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
- char *units[5][8] = {
- { "None", "None", "None", "None", "None", "None", "None", "None" },
- { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
- { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" },
- { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
- { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
- };
-
- int i;
- int sys;
- __u32 data = field->unit;
-
- /* First nibble tells us which system we're in. */
- sys = data & 0xf;
- data >>= 4;
-
- if(sys > 4) {
- tab(n); printk("Unit(Invalid)\n");
- }
- else {
- int earlier_unit = 0;
-
- tab(n); printk("Unit(%s : ", systems[sys]);
-
- for (i=1 ; i<sizeof(__u32)*2 ; i++) {
- char nibble = data & 0xf;
- data >>= 4;
- if (nibble != 0) {
- if(earlier_unit++ > 0)
- printk("*");
- printk("%s", units[sys][i]);
- if(nibble != 1) {
- /* This is a _signed_ nibble(!) */
-
- int val = nibble & 0x7;
- if(nibble & 0x08)
- val = -((0x7 & ~val) +1);
- printk("^%d", val);
- }
- }
- }
- printk(")\n");
- }
- }
- tab(n); printk("Report Size(%u)\n", field->report_size);
- tab(n); printk("Report Count(%u)\n", field->report_count);
- tab(n); printk("Report Offset(%u)\n", field->report_offset);
-
- tab(n); printk("Flags( ");
- j = field->flags;
- printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
- printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
- printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
- printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
- printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
- printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
- printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
- printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
- printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
- printk(")\n");
-}
-
-static void __attribute__((unused)) hid_dump_device(struct hid_device *device) {
- struct hid_report_enum *report_enum;
- struct hid_report *report;
- struct list_head *list;
- unsigned i,k;
- static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
-
- for (i = 0; i < HID_REPORT_TYPES; i++) {
- report_enum = device->report_enum + i;
- list = report_enum->report_list.next;
- while (list != &report_enum->report_list) {
- report = (struct hid_report *) list;
- tab(2);
- printk("%s", table[i]);
- if (report->id)
- printk("(%d)", report->id);
- printk("[%s]", table[report->type]);
- printk("\n");
- for (k = 0; k < report->maxfield; k++) {
- tab(4);
- printk("Field(%d)\n", k);
- hid_dump_field(report->field[k], 6);
- }
- list = list->next;
- }
- }
-}
-
-static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) {
- printk("hid-debug: input ");
- resolv_usage(usage->hid);
- printk(" = %d\n", value);
-}
-
-
-static char *events[EV_MAX + 1] = {
- [EV_SYN] = "Sync", [EV_KEY] = "Key",
- [EV_REL] = "Relative", [EV_ABS] = "Absolute",
- [EV_MSC] = "Misc", [EV_LED] = "LED",
- [EV_SND] = "Sound", [EV_REP] = "Repeat",
- [EV_FF] = "ForceFeedback", [EV_PWR] = "Power",
- [EV_FF_STATUS] = "ForceFeedbackStatus",
-};
-
-static char *syncs[2] = {
- [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
-};
-static char *keys[KEY_MAX + 1] = {
- [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
- [KEY_1] = "1", [KEY_2] = "2",
- [KEY_3] = "3", [KEY_4] = "4",
- [KEY_5] = "5", [KEY_6] = "6",
- [KEY_7] = "7", [KEY_8] = "8",
- [KEY_9] = "9", [KEY_0] = "0",
- [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal",
- [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab",
- [KEY_Q] = "Q", [KEY_W] = "W",
- [KEY_E] = "E", [KEY_R] = "R",
- [KEY_T] = "T", [KEY_Y] = "Y",
- [KEY_U] = "U", [KEY_I] = "I",
- [KEY_O] = "O", [KEY_P] = "P",
- [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace",
- [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl",
- [KEY_A] = "A", [KEY_S] = "S",
- [KEY_D] = "D", [KEY_F] = "F",
- [KEY_G] = "G", [KEY_H] = "H",
- [KEY_J] = "J", [KEY_K] = "K",
- [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon",
- [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave",
- [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash",
- [KEY_Z] = "Z", [KEY_X] = "X",
- [KEY_C] = "C", [KEY_V] = "V",
- [KEY_B] = "B", [KEY_N] = "N",
- [KEY_M] = "M", [KEY_COMMA] = "Comma",
- [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash",
- [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk",
- [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space",
- [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1",
- [KEY_F2] = "F2", [KEY_F3] = "F3",
- [KEY_F4] = "F4", [KEY_F5] = "F5",
- [KEY_F6] = "F6", [KEY_F7] = "F7",
- [KEY_F8] = "F8", [KEY_F9] = "F9",
- [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock",
- [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7",
- [KEY_KP8] = "KP8", [KEY_KP9] = "KP9",
- [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4",
- [KEY_KP5] = "KP5", [KEY_KP6] = "KP6",
- [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1",
- [KEY_KP2] = "KP2", [KEY_KP3] = "KP3",
- [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot",
- [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
- [KEY_F11] = "F11", [KEY_F12] = "F12",
- [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana",
- [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan",
- [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
- [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter",
- [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash",
- [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt",
- [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home",
- [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp",
- [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right",
- [KEY_END] = "End", [KEY_DOWN] = "Down",
- [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert",
- [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro",
- [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown",
- [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power",
- [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus",
- [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma",
- [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja",
- [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta",
- [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose",
- [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again",
- [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo",
- [KEY_FRONT] = "Front", [KEY_COPY] = "Copy",
- [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste",
- [KEY_FIND] = "Find", [KEY_CUT] = "Cut",
- [KEY_HELP] = "Help", [KEY_MENU] = "Menu",
- [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup",
- [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp",
- [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile",
- [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer",
- [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2",
- [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS",
- [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction",
- [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail",
- [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer",
- [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward",
- [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD",
- [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong",
- [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong",
- [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record",
- [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone",
- [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config",
- [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh",
- [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move",
- [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp",
- [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
- [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
- [KEY_REDO] = "Redo", [KEY_F13] = "F13",
- [KEY_F14] = "F14", [KEY_F15] = "F15",
- [KEY_F16] = "F16", [KEY_F17] = "F17",
- [KEY_F18] = "F18", [KEY_F19] = "F19",
- [KEY_F20] = "F20", [KEY_F21] = "F21",
- [KEY_F22] = "F22", [KEY_F23] = "F23",
- [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD",
- [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
- [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
- [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
- [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost",
- [KEY_PRINT] = "Print", [KEY_HP] = "HP",
- [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound",
- [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email",
- [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search",
- [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance",
- [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop",
- [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel",
- [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
- [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown",
- [BTN_0] = "Btn0", [BTN_1] = "Btn1",
- [BTN_2] = "Btn2", [BTN_3] = "Btn3",
- [BTN_4] = "Btn4", [BTN_5] = "Btn5",
- [BTN_6] = "Btn6", [BTN_7] = "Btn7",
- [BTN_8] = "Btn8", [BTN_9] = "Btn9",
- [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn",
- [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn",
- [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn",
- [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn",
- [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn",
- [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn",
- [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn",
- [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2",
- [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4",
- [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6",
- [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA",
- [BTN_B] = "BtnB", [BTN_C] = "BtnC",
- [BTN_X] = "BtnX", [BTN_Y] = "BtnY",
- [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL",
- [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2",
- [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect",
- [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode",
- [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR",
- [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber",
- [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil",
- [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger",
- [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens",
- [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus",
- [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
- [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
- [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok",
- [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto",
- [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2",
- [KEY_OPTION] = "Option", [KEY_INFO] = "Info",
- [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor",
- [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program",
- [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites",
- [KEY_EPG] = "EPG", [KEY_PVR] = "PVR",
- [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language",
- [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle",
- [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom",
- [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard",
- [KEY_SCREEN] = "Screen", [KEY_PC] = "PC",
- [KEY_TV] = "TV", [KEY_TV2] = "TV2",
- [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2",
- [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2",
- [KEY_CD] = "CD", [KEY_TAPE] = "Tape",
- [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner",
- [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text",
- [KEY_DVD] = "DVD", [KEY_AUX] = "Aux",
- [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio",
- [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory",
- [KEY_LIST] = "List", [KEY_MEMO] = "Memo",
- [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red",
- [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow",
- [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp",
- [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First",
- [KEY_LAST] = "Last", [KEY_AB] = "AB",
- [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart",
- [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle",
- [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous",
- [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN",
- [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL",
- [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine",
- [KEY_DEL_LINE] = "DeleteLine",
- [KEY_SEND] = "Send", [KEY_REPLY] = "Reply",
- [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save",
- [KEY_DOCUMENTS] = "Documents",
- [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC",
- [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2",
- [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D",
- [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F",
- [KEY_FN_S] = "Fn+S",
- [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2",
- [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4",
- [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6",
- [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8",
- [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10",
- [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12",
- [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
- [KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
- [KEY_KBDILLUMUP] = "KbdIlluminationUp",
- [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
-};
-
-static char *relatives[REL_MAX + 1] = {
- [REL_X] = "X", [REL_Y] = "Y",
- [REL_Z] = "Z", [REL_HWHEEL] = "HWheel",
- [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel",
- [REL_MISC] = "Misc",
-};
-
-static char *absolutes[ABS_MAX + 1] = {
- [ABS_X] = "X", [ABS_Y] = "Y",
- [ABS_Z] = "Z", [ABS_RX] = "Rx",
- [ABS_RY] = "Ry", [ABS_RZ] = "Rz",
- [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder",
- [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas",
- [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X",
- [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X",
- [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X",
- [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
- [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
- [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
- [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
- [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
-};
-
-static char *misc[MSC_MAX + 1] = {
- [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled",
- [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData"
-};
-
-static char *leds[LED_MAX + 1] = {
- [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock",
- [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose",
- [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep",
- [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute",
- [LED_MISC] = "Misc",
-};
-
-static char *repeats[REP_MAX + 1] = {
- [REP_DELAY] = "Delay", [REP_PERIOD] = "Period"
-};
-
-static char *sounds[SND_MAX + 1] = {
- [SND_CLICK] = "Click", [SND_BELL] = "Bell",
- [SND_TONE] = "Tone"
-};
-
-static char **names[EV_MAX + 1] = {
- [EV_SYN] = syncs, [EV_KEY] = keys,
- [EV_REL] = relatives, [EV_ABS] = absolutes,
- [EV_MSC] = misc, [EV_LED] = leds,
- [EV_SND] = sounds, [EV_REP] = repeats,
-};
-
-static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) {
-
- printk("%s.%s", events[type] ? events[type] : "?",
- names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
-}
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index a8fc46c721c5..f8f660ee3fac 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -32,7 +32,7 @@
#undef DEBUG
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
/*
* This table contains pointers to initializers. To add support for new
@@ -70,8 +70,8 @@ static struct hid_ff_initializer inits[] = {
int hid_ff_init(struct hid_device* hid)
{
struct hid_ff_initializer *init;
- int vendor = le16_to_cpu(hid->dev->descriptor.idVendor);
- int product = le16_to_cpu(hid->dev->descriptor.idProduct);
+ int vendor = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idVendor);
+ int product = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idProduct);
for (init = inits; init->idVendor; init++)
if (init->idVendor == vendor && init->idProduct == product)
@@ -79,3 +79,5 @@ int hid_ff_init(struct hid_device* hid)
return init->init(hid);
}
+EXPORT_SYMBOL_GPL(hid_ff_init);
+
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
deleted file mode 100644
index 68e7ebb978a9..000000000000
--- a/drivers/usb/input/hid-input.c
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
- *
- * Copyright (c) 2000-2001 Vojtech Pavlik
- *
- * USB HID to Linux Input mapping
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/usb/input.h>
-
-#undef DEBUG
-
-#include "hid.h"
-
-#define unk KEY_UNKNOWN
-
-static const unsigned char hid_keyboard[256] = {
- 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
- 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
- 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
- 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
- 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
- 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
- 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
- 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
- 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
- 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
- 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
- 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
-};
-
-static const struct {
- __s32 x;
- __s32 y;
-} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
-
-#define map_abs(c) do { usage->code = c; usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX; } while (0)
-#define map_rel(c) do { usage->code = c; usage->type = EV_REL; bit = input->relbit; max = REL_MAX; } while (0)
-#define map_key(c) do { usage->code = c; usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX; } while (0)
-#define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)
-
-#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
-
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-
-struct hidinput_key_translation {
- u16 from;
- u16 to;
- u8 flags;
-};
-
-#define POWERBOOK_FLAG_FKEY 0x01
-
-static struct hidinput_key_translation powerbook_fn_keys[] = {
- { KEY_BACKSPACE, KEY_DELETE },
- { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
- { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
- { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
- { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
- { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
- { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
- { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
- { KEY_UP, KEY_PAGEUP },
- { KEY_DOWN, KEY_PAGEDOWN },
- { KEY_LEFT, KEY_HOME },
- { KEY_RIGHT, KEY_END },
- { }
-};
-
-static struct hidinput_key_translation powerbook_numlock_keys[] = {
- { KEY_J, KEY_KP1 },
- { KEY_K, KEY_KP2 },
- { KEY_L, KEY_KP3 },
- { KEY_U, KEY_KP4 },
- { KEY_I, KEY_KP5 },
- { KEY_O, KEY_KP6 },
- { KEY_7, KEY_KP7 },
- { KEY_8, KEY_KP8 },
- { KEY_9, KEY_KP9 },
- { KEY_M, KEY_KP0 },
- { KEY_DOT, KEY_KPDOT },
- { KEY_SLASH, KEY_KPPLUS },
- { KEY_SEMICOLON, KEY_KPMINUS },
- { KEY_P, KEY_KPASTERISK },
- { KEY_MINUS, KEY_KPEQUAL },
- { KEY_0, KEY_KPSLASH },
- { KEY_F6, KEY_NUMLOCK },
- { KEY_KPENTER, KEY_KPENTER },
- { KEY_BACKSPACE, KEY_BACKSPACE },
- { }
-};
-
-static struct hidinput_key_translation powerbook_iso_keyboard[] = {
- { KEY_GRAVE, KEY_102ND },
- { KEY_102ND, KEY_GRAVE },
- { }
-};
-
-static int usbhid_pb_fnmode = 1;
-module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
- "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-
-static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
-{
- struct hidinput_key_translation *trans;
-
- /* Look for the translation */
- for (trans = table; trans->from; trans++)
- if (trans->from == from)
- return trans;
-
- return NULL;
-}
-
-static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
-{
- struct hidinput_key_translation *trans;
-
- if (usage->code == KEY_FN) {
- if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
- else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
-
- input_event(input, usage->type, usage->code, value);
-
- return 1;
- }
-
- if (usbhid_pb_fnmode) {
- int do_translate;
-
- trans = find_translation(powerbook_fn_keys, usage->code);
- if (trans) {
- if (test_bit(usage->code, hid->pb_pressed_fn))
- do_translate = 1;
- else if (trans->flags & POWERBOOK_FLAG_FKEY)
- do_translate =
- (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
- (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
- else
- do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
-
- if (do_translate) {
- if (value)
- set_bit(usage->code, hid->pb_pressed_fn);
- else
- clear_bit(usage->code, hid->pb_pressed_fn);
-
- input_event(input, usage->type, trans->to, value);
-
- return 1;
- }
- }
-
- if (test_bit(usage->code, hid->pb_pressed_numlock) ||
- test_bit(LED_NUML, input->led)) {
- trans = find_translation(powerbook_numlock_keys, usage->code);
-
- if (trans) {
- if (value)
- set_bit(usage->code, hid->pb_pressed_numlock);
- else
- clear_bit(usage->code, hid->pb_pressed_numlock);
-
- input_event(input, usage->type, trans->to, value);
- }
-
- return 1;
- }
- }
-
- if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
- trans = find_translation(powerbook_iso_keyboard, usage->code);
- if (trans) {
- input_event(input, usage->type, trans->to, value);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void hidinput_pb_setup(struct input_dev *input)
-{
- struct hidinput_key_translation *trans;
-
- set_bit(KEY_NUMLOCK, input->keybit);
-
- /* Enable all needed keys */
- for (trans = powerbook_fn_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_numlock_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_iso_keyboard; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-}
-#else
-static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
-{
- return 0;
-}
-
-static inline void hidinput_pb_setup(struct input_dev *input)
-{
-}
-#endif
-
-static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
- struct hid_usage *usage)
-{
- struct input_dev *input = hidinput->input;
- struct hid_device *device = input->private;
- int max = 0, code;
- unsigned long *bit = NULL;
-
- field->hidinput = hidinput;
-
-#ifdef DEBUG
- printk(KERN_DEBUG "Mapping: ");
- resolv_usage(usage->hid);
- printk(" ---> ");
-#endif
-
- if (field->flags & HID_MAIN_ITEM_CONSTANT)
- goto ignore;
-
- switch (usage->hid & HID_USAGE_PAGE) {
-
- case HID_UP_UNDEFINED:
- goto ignore;
-
- case HID_UP_KEYBOARD:
-
- set_bit(EV_REP, input->evbit);
-
- if ((usage->hid & HID_USAGE) < 256) {
- if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
- map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
- } else
- map_key(KEY_UNKNOWN);
-
- break;
-
- case HID_UP_BUTTON:
-
- code = ((usage->hid - 1) & 0xf);
-
- switch (field->application) {
- case HID_GD_MOUSE:
- case HID_GD_POINTER: code += 0x110; break;
- case HID_GD_JOYSTICK: code += 0x120; break;
- case HID_GD_GAMEPAD: code += 0x130; break;
- default:
- switch (field->physical) {
- case HID_GD_MOUSE:
- case HID_GD_POINTER: code += 0x110; break;
- case HID_GD_JOYSTICK: code += 0x120; break;
- case HID_GD_GAMEPAD: code += 0x130; break;
- default: code += 0x100;
- }
- }
-
- map_key(code);
- break;
-
-
- case HID_UP_SIMULATION:
-
- switch (usage->hid & 0xffff) {
- case 0xba: map_abs(ABS_RUDDER); break;
- case 0xbb: map_abs(ABS_THROTTLE); break;
- case 0xc4: map_abs(ABS_GAS); break;
- case 0xc5: map_abs(ABS_BRAKE); break;
- case 0xc8: map_abs(ABS_WHEEL); break;
- default: goto ignore;
- }
- break;
-
- case HID_UP_GENDESK:
-
- if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
- switch (usage->hid & 0xf) {
- case 0x1: map_key_clear(KEY_POWER); break;
- case 0x2: map_key_clear(KEY_SLEEP); break;
- case 0x3: map_key_clear(KEY_WAKEUP); break;
- default: goto unknown;
- }
- break;
- }
-
- if ((usage->hid & 0xf0) == 0x90) { /* D-pad */
- switch (usage->hid) {
- case HID_GD_UP: usage->hat_dir = 1; break;
- case HID_GD_DOWN: usage->hat_dir = 5; break;
- case HID_GD_RIGHT: usage->hat_dir = 3; break;
- case HID_GD_LEFT: usage->hat_dir = 7; break;
- default: goto unknown;
- }
- if (field->dpad) {
- map_abs(field->dpad);
- goto ignore;
- }
- map_abs(ABS_HAT0X);
- break;
- }
-
- switch (usage->hid) {
-
- /* These usage IDs map directly to the usage codes. */
- case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
- case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
- case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
- if (field->flags & HID_MAIN_ITEM_RELATIVE)
- map_rel(usage->hid & 0xf);
- else
- map_abs(usage->hid & 0xf);
- break;
-
- case HID_GD_HATSWITCH:
- usage->hat_min = field->logical_minimum;
- usage->hat_max = field->logical_maximum;
- map_abs(ABS_HAT0X);
- break;
-
- case HID_GD_START: map_key_clear(BTN_START); break;
- case HID_GD_SELECT: map_key_clear(BTN_SELECT); break;
-
- default: goto unknown;
- }
-
- break;
-
- case HID_UP_LED:
- if (((usage->hid - 1) & 0xffff) >= LED_MAX)
- goto ignore;
- map_led((usage->hid - 1) & 0xffff);
- break;
-
- case HID_UP_DIGITIZER:
-
- switch (usage->hid & 0xff) {
-
- case 0x30: /* TipPressure */
- if (!test_bit(BTN_TOUCH, input->keybit)) {
- device->quirks |= HID_QUIRK_NOTOUCH;
- set_bit(EV_KEY, input->evbit);
- set_bit(BTN_TOUCH, input->keybit);
- }
-
- map_abs_clear(ABS_PRESSURE);
- break;
-
- case 0x32: /* InRange */
- switch (field->physical & 0xff) {
- case 0x21: map_key(BTN_TOOL_MOUSE); break;
- case 0x22: map_key(BTN_TOOL_FINGER); break;
- default: map_key(BTN_TOOL_PEN); break;
- }
- break;
-
- case 0x3c: /* Invert */
- map_key_clear(BTN_TOOL_RUBBER);
- break;
-
- case 0x33: /* Touch */
- case 0x42: /* TipSwitch */
- case 0x43: /* TipSwitch2 */
- device->quirks &= ~HID_QUIRK_NOTOUCH;
- map_key_clear(BTN_TOUCH);
- break;
-
- case 0x44: /* BarrelSwitch */
- map_key_clear(BTN_STYLUS);
- break;
-
- default: goto unknown;
- }
- break;
-
- case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
-
- switch (usage->hid & HID_USAGE) {
- case 0x000: goto ignore;
- case 0x034: map_key_clear(KEY_SLEEP); break;
- case 0x036: map_key_clear(BTN_MISC); break;
- case 0x045: map_key_clear(KEY_RADIO); break;
- case 0x08a: map_key_clear(KEY_WWW); break;
- case 0x08d: map_key_clear(KEY_PROGRAM); break;
- case 0x095: map_key_clear(KEY_HELP); break;
- case 0x09c: map_key_clear(KEY_CHANNELUP); break;
- case 0x09d: map_key_clear(KEY_CHANNELDOWN); break;
- case 0x0b0: map_key_clear(KEY_PLAY); break;
- case 0x0b1: map_key_clear(KEY_PAUSE); break;
- case 0x0b2: map_key_clear(KEY_RECORD); break;
- case 0x0b3: map_key_clear(KEY_FASTFORWARD); break;
- case 0x0b4: map_key_clear(KEY_REWIND); break;
- case 0x0b5: map_key_clear(KEY_NEXTSONG); break;
- case 0x0b6: map_key_clear(KEY_PREVIOUSSONG); break;
- case 0x0b7: map_key_clear(KEY_STOPCD); break;
- case 0x0b8: map_key_clear(KEY_EJECTCD); break;
- case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
- case 0x0e0: map_abs_clear(ABS_VOLUME); break;
- case 0x0e2: map_key_clear(KEY_MUTE); break;
- case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
- case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
- case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
- case 0x183: map_key_clear(KEY_CONFIG); break;
- case 0x18a: map_key_clear(KEY_MAIL); break;
- case 0x192: map_key_clear(KEY_CALC); break;
- case 0x194: map_key_clear(KEY_FILE); break;
- case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
- case 0x201: map_key_clear(KEY_NEW); break;
- case 0x207: map_key_clear(KEY_SAVE); break;
- case 0x208: map_key_clear(KEY_PRINT); break;
- case 0x209: map_key_clear(KEY_PROPS); break;
- case 0x21a: map_key_clear(KEY_UNDO); break;
- case 0x21b: map_key_clear(KEY_COPY); break;
- case 0x21c: map_key_clear(KEY_CUT); break;
- case 0x21d: map_key_clear(KEY_PASTE); break;
- case 0x221: map_key_clear(KEY_FIND); break;
- case 0x223: map_key_clear(KEY_HOMEPAGE); break;
- case 0x224: map_key_clear(KEY_BACK); break;
- case 0x225: map_key_clear(KEY_FORWARD); break;
- case 0x226: map_key_clear(KEY_STOP); break;
- case 0x227: map_key_clear(KEY_REFRESH); break;
- case 0x22a: map_key_clear(KEY_BOOKMARKS); break;
- case 0x233: map_key_clear(KEY_SCROLLUP); break;
- case 0x234: map_key_clear(KEY_SCROLLDOWN); break;
- case 0x238: map_rel(REL_HWHEEL); break;
- case 0x279: map_key_clear(KEY_REDO); break;
- case 0x289: map_key_clear(KEY_REPLY); break;
- case 0x28b: map_key_clear(KEY_FORWARDMAIL); break;
- case 0x28c: map_key_clear(KEY_SEND); break;
-
- /* Reported on a Cherry Cymotion keyboard */
- case 0x301: map_key_clear(KEY_PROG1); break;
- case 0x302: map_key_clear(KEY_PROG2); break;
- case 0x303: map_key_clear(KEY_PROG3); break;
-
- default: goto ignore;
- }
- break;
-
- case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
-
- set_bit(EV_REP, input->evbit);
- switch (usage->hid & HID_USAGE) {
- case 0x021: map_key_clear(KEY_PRINT); break;
- case 0x070: map_key_clear(KEY_HP); break;
- case 0x071: map_key_clear(KEY_CAMERA); break;
- case 0x072: map_key_clear(KEY_SOUND); break;
- case 0x073: map_key_clear(KEY_QUESTION); break;
- case 0x080: map_key_clear(KEY_EMAIL); break;
- case 0x081: map_key_clear(KEY_CHAT); break;
- case 0x082: map_key_clear(KEY_SEARCH); break;
- case 0x083: map_key_clear(KEY_CONNECT); break;
- case 0x084: map_key_clear(KEY_FINANCE); break;
- case 0x085: map_key_clear(KEY_SPORT); break;
- case 0x086: map_key_clear(KEY_SHOP); break;
- default: goto ignore;
- }
- break;
-
- case HID_UP_MSVENDOR:
- goto ignore;
-
- case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- case 0x003:
- /* The fn key on Apple PowerBooks */
- map_key_clear(KEY_FN);
- hidinput_pb_setup(input);
- break;
-
- default: goto ignore;
- }
- break;
-
- case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
- set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- case 0x004: map_key_clear(KEY_AGAIN); break;
- case 0x00d: map_key_clear(KEY_HOME); break;
- case 0x024: map_key_clear(KEY_SHUFFLE); break;
- case 0x025: map_key_clear(KEY_TV); break;
- case 0x026: map_key_clear(KEY_MENU); break;
- case 0x031: map_key_clear(KEY_AUDIO); break;
- case 0x032: map_key_clear(KEY_TEXT); break;
- case 0x033: map_key_clear(KEY_LAST); break;
- case 0x047: map_key_clear(KEY_MP3); break;
- case 0x048: map_key_clear(KEY_DVD); break;
- case 0x049: map_key_clear(KEY_MEDIA); break;
- case 0x04a: map_key_clear(KEY_VIDEO); break;
- case 0x04b: map_key_clear(KEY_ANGLE); break;
- case 0x04c: map_key_clear(KEY_LANGUAGE); break;
- case 0x04d: map_key_clear(KEY_SUBTITLE); break;
- case 0x051: map_key_clear(KEY_RED); break;
- case 0x052: map_key_clear(KEY_CLOSE); break;
- default: goto ignore;
- }
- break;
-
- case HID_UP_PID:
-
- switch(usage->hid & HID_USAGE) {
- case 0xa4: map_key_clear(BTN_DEAD); break;
- default: goto ignore;
- }
- break;
-
- default:
- unknown:
- if (field->report_size == 1) {
- if (field->report->type == HID_OUTPUT_REPORT) {
- map_led(LED_MISC);
- break;
- }
- map_key(BTN_MISC);
- break;
- }
- if (field->flags & HID_MAIN_ITEM_RELATIVE) {
- map_rel(REL_MISC);
- break;
- }
- map_abs(ABS_MISC);
- break;
- }
-
- if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
- if (usage->hid == HID_GD_Z)
- map_rel(REL_HWHEEL);
- else if (usage->code == BTN_1)
- map_key(BTN_2);
- else if (usage->code == BTN_2)
- map_key(BTN_1);
- }
-
- if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
- (usage->type == EV_REL) && (usage->code == REL_WHEEL))
- set_bit(REL_HWHEEL, bit);
-
- if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
- || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
- goto ignore;
-
- set_bit(usage->type, input->evbit);
-
- while (usage->code <= max && test_and_set_bit(usage->code, bit))
- usage->code = find_next_zero_bit(bit, max + 1, usage->code);
-
- if (usage->code > max)
- goto ignore;
-
-
- if (usage->type == EV_ABS) {
-
- int a = field->logical_minimum;
- int b = field->logical_maximum;
-
- if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) {
- a = field->logical_minimum = 0;
- b = field->logical_maximum = 255;
- }
-
- if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK)
- input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
- else input_set_abs_params(input, usage->code, a, b, 0, 0);
-
- }
-
- if (usage->type == EV_ABS &&
- (usage->hat_min < usage->hat_max || usage->hat_dir)) {
- int i;
- for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
- input_set_abs_params(input, i, -1, 1, 0, 0);
- set_bit(i, input->absbit);
- }
- if (usage->hat_dir && !field->dpad)
- field->dpad = usage->code;
- }
-
-#ifdef DEBUG
- resolv_event(usage->type, usage->code);
- printk("\n");
-#endif
- return;
-
-ignore:
-#ifdef DEBUG
- printk("IGNORED\n");
-#endif
- return;
-}
-
-void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
-{
- struct input_dev *input;
- int *quirks = &hid->quirks;
-
- if (!field->hidinput)
- return;
-
- input = field->hidinput->input;
-
- if (!usage->type)
- return;
-
- if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
- || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
- if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
- return;
- }
-
- if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
- input_event(input, usage->type, usage->code, -value);
- return;
- }
-
- if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
- input_event(input, usage->type, REL_HWHEEL, value);
- return;
- }
-
- if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
- return;
-
- if (usage->hat_min < usage->hat_max || usage->hat_dir) {
- int hat_dir = usage->hat_dir;
- if (!hat_dir)
- hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
- if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
- input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x);
- input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
- *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
- if (value) {
- input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
- return;
- }
- input_event(input, usage->type, usage->code, 0);
- input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
- return;
- }
-
- if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
- int a = field->logical_minimum;
- int b = field->logical_maximum;
- input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
- }
-
- if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
- dbg("Maximum Effects - %d",value);
- return;
- }
-
- if (usage->hid == (HID_UP_PID | 0x7fUL)) {
- dbg("PID Pool Report\n");
- return;
- }
-
- if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
- return;
-
- input_event(input, usage->type, usage->code, value);
-
- if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
- input_event(input, usage->type, usage->code, 0);
-}
-
-void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
-{
- struct hid_input *hidinput;
-
- list_for_each_entry(hidinput, &hid->inputs, list)
- input_sync(hidinput->input);
-}
-
-static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
- struct hid_report *report;
- int i, j;
-
- list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
- for (i = 0; i < report->maxfield; i++) {
- *field = report->field[i];
- for (j = 0; j < (*field)->maxusage; j++)
- if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
- return j;
- }
- }
- return -1;
-}
-
-static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
-{
- struct hid_device *hid = dev->private;
- struct hid_field *field;
- int offset;
-
- if (type == EV_FF)
- return input_ff_event(dev, type, code, value);
-
- if (type != EV_LED)
- return -1;
-
- if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
- warn("event field not found");
- return -1;
- }
-
- hid_set_field(field, offset, value);
- hid_submit_report(hid, field->report, USB_DIR_OUT);
-
- return 0;
-}
-
-static int hidinput_open(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- return hid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
- struct hid_device *hid = dev->private;
- hid_close(hid);
-}
-
-/*
- * Register the input device; print a message.
- * Configure the input layer interface
- * Read all reports and initialize the absolute field values.
- */
-
-int hidinput_connect(struct hid_device *hid)
-{
- struct usb_device *dev = hid->dev;
- struct hid_report *report;
- struct hid_input *hidinput = NULL;
- struct input_dev *input_dev;
- int i, j, k;
-
- INIT_LIST_HEAD(&hid->inputs);
-
- for (i = 0; i < hid->maxcollection; i++)
- if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
- hid->collection[i].type == HID_COLLECTION_PHYSICAL)
- if (IS_INPUT_APPLICATION(hid->collection[i].usage))
- break;
-
- if (i == hid->maxcollection)
- return -1;
-
- for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
- list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
-
- if (!report->maxfield)
- continue;
-
- if (!hidinput) {
- hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!hidinput || !input_dev) {
- kfree(hidinput);
- input_free_device(input_dev);
- err("Out of memory during hid input probe");
- return -1;
- }
-
- input_dev->private = hid;
- input_dev->event = hidinput_input_event;
- input_dev->open = hidinput_open;
- input_dev->close = hidinput_close;
-
- input_dev->name = hid->name;
- input_dev->phys = hid->phys;
- input_dev->uniq = hid->uniq;
- usb_to_input_id(dev, &input_dev->id);
- input_dev->cdev.dev = &hid->intf->dev;
-
- hidinput->input = input_dev;
- list_add_tail(&hidinput->list, &hid->inputs);
- }
-
- for (i = 0; i < report->maxfield; i++)
- for (j = 0; j < report->field[i]->maxusage; j++)
- hidinput_configure_usage(hidinput, report->field[i],
- report->field[i]->usage + j);
-
- if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
- /* This will leave hidinput NULL, so that it
- * allocates another one if we have more inputs on
- * the same interface. Some devices (e.g. Happ's
- * UGCI) cram a lot of unrelated inputs into the
- * same interface. */
- hidinput->report = report;
- input_register_device(hidinput->input);
- hidinput = NULL;
- }
- }
-
- /* This only gets called when we are a single-input (most of the
- * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
- * only useful in this case, and not for multi-input quirks. */
- if (hidinput) {
- hid_ff_init(hid);
- input_register_device(hidinput->input);
- }
-
- return 0;
-}
-
-void hidinput_disconnect(struct hid_device *hid)
-{
- struct hid_input *hidinput, *next;
-
- list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
- list_del(&hidinput->list);
- input_unregister_device(hidinput->input);
- kfree(hidinput);
- }
-}
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index 93da222b6da8..e47466268565 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -29,7 +29,8 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
struct device_type {
u16 idVendor;
@@ -75,7 +76,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
dbg("(x, y)=(%04x, %04x)", x, y);
- hid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
case FF_RUMBLE:
@@ -90,7 +91,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
dbg("(left, right)=(%04x, %04x)", left, right);
- hid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
}
return 0;
diff --git a/drivers/usb/input/hid-pidff.c b/drivers/usb/input/hid-pidff.c
index 5420c13eb8eb..cbd2d53fefff 100644
--- a/drivers/usb/input/hid-pidff.c
+++ b/drivers/usb/input/hid-pidff.c
@@ -28,7 +28,9 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+
+#include "usbhid.h"
#define PID_EFFECTS_MAX 64
@@ -260,7 +262,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
debug("attack %u => %d", envelope->attack_level,
pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
USB_DIR_OUT);
}
@@ -287,7 +289,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
effect->u.constant.level);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
USB_DIR_OUT);
}
@@ -322,7 +324,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
pidff->effect_direction);
pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT);
}
@@ -354,7 +356,7 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
USB_DIR_OUT);
}
@@ -396,8 +398,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
effect->u.condition[i].left_saturation);
pidff_set(&pidff->set_condition[PID_DEAD_BAND],
effect->u.condition[i].deadband);
- hid_wait_io(pidff->hid);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
+ usbhid_wait_io(pidff->hid);
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
USB_DIR_OUT);
}
}
@@ -438,7 +440,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
effect->u.ramp.start_level);
pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
effect->u.ramp.end_level);
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
USB_DIR_OUT);
}
@@ -463,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
int j;
pidff->create_new_effect_type->value[0] = efnum;
- hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
USB_DIR_OUT);
debug("create_new_effect sent, type: %d", efnum);
pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
pidff->block_load_status->value[0] = 0;
- hid_wait_io(pidff->hid);
+ usbhid_wait_io(pidff->hid);
for (j = 0; j < 60; j++) {
debug("pid_block_load requested");
- hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
USB_DIR_IN);
- hid_wait_io(pidff->hid);
+ usbhid_wait_io(pidff->hid);
if (pidff->block_load_status->value[0] ==
pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
debug("device reported free memory: %d bytes",
@@ -511,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
}
- hid_wait_io(pidff->hid);
- hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+ usbhid_wait_io(pidff->hid);
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
USB_DIR_OUT);
}
@@ -534,7 +536,7 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
{
pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
- hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
USB_DIR_OUT);
}
@@ -714,7 +716,7 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
struct pidff_device *pidff = dev->ff->private;
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
- hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT);
}
@@ -739,7 +741,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
pidff->set_effect[PID_START_DELAY].value[0] = 0;
- hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
USB_DIR_OUT);
}
@@ -1163,19 +1165,19 @@ static void pidff_reset(struct pidff_device *pidff)
pidff->device_control->value[0] = pidff->control_id[PID_RESET];
/* We reset twice as sometimes hid_wait_io isn't waiting long enough */
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
pidff->device_control->value[0] =
pidff->control_id[PID_ENABLE_ACTUATORS];
- hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+ usbhid_wait_io(hid);
/* pool report is sometimes messed up, refetch it */
- hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
+ usbhid_wait_io(hid);
if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0];
@@ -1187,9 +1189,9 @@ static void pidff_reset(struct pidff_device *pidff)
break;
}
debug("pid_pool requested again");
- hid_submit_report(hid, pidff->reports[PID_POOL],
+ usbhid_submit_report(hid, pidff->reports[PID_POOL],
USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_wait_io(hid);
}
}
}
@@ -1275,7 +1277,7 @@ int hid_pidff_init(struct hid_device *hid)
if (test_bit(FF_GAIN, dev->ffbit)) {
pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
- hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+ usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
USB_DIR_OUT);
}
diff --git a/drivers/usb/input/hid-tmff.c b/drivers/usb/input/hid-tmff.c
index 2d5be4c318ac..ab67331620d0 100644
--- a/drivers/usb/input/hid-tmff.c
+++ b/drivers/usb/input/hid-tmff.c
@@ -32,7 +32,8 @@
#undef DEBUG
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
/* Usages for thrustmaster devices I know about */
#define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb)
@@ -70,7 +71,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
tmff->rumble->value[0] = left;
tmff->rumble->value[1] = right;
dbg("(left,right)=(%08x, %08x)", left, right);
- hid_submit_report(hid, tmff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
return 0;
}
diff --git a/drivers/usb/input/hid-zpff.c b/drivers/usb/input/hid-zpff.c
index d2ce3214572c..7bd8238ca212 100644
--- a/drivers/usb/input/hid-zpff.c
+++ b/drivers/usb/input/hid-zpff.c
@@ -27,7 +27,8 @@
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
+#include "usbhid.h"
struct zpff_device {
struct hid_report *report;
@@ -56,7 +57,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
debug("running with 0x%02x 0x%02x", left, right);
- hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
return 0;
}
@@ -101,7 +102,7 @@ int hid_zpff_init(struct hid_device *hid)
zpff->report->field[1]->value[0] = 0x02;
zpff->report->field[2]->value[0] = 0x00;
zpff->report->field[3]->value[0] = 0x00;
- hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+ usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
printk(KERN_INFO "Force feedback for Zeroplus based devices by "
"Anssi Hannula <anssi.hannula@gmail.com>\n");
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
deleted file mode 100644
index 0e76e6dcac37..000000000000
--- a/drivers/usb/input/hid.h
+++ /dev/null
@@ -1,538 +0,0 @@
-#ifndef __HID_H
-#define __HID_H
-
-/*
- * $Id: hid.h,v 1.24 2001/12/27 10:37:41 vojtech Exp $
- *
- * Copyright (c) 1999 Andreas Gal
- * Copyright (c) 2000-2001 Vojtech Pavlik
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-
-/*
- * USB HID (Human Interface Device) interface class code
- */
-
-#define USB_INTERFACE_CLASS_HID 3
-
-/*
- * USB HID interface subclass and protocol codes
- */
-
-#define USB_INTERFACE_SUBCLASS_BOOT 1
-#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
-#define USB_INTERFACE_PROTOCOL_MOUSE 2
-
-/*
- * HID class requests
- */
-
-#define HID_REQ_GET_REPORT 0x01
-#define HID_REQ_GET_IDLE 0x02
-#define HID_REQ_GET_PROTOCOL 0x03
-#define HID_REQ_SET_REPORT 0x09
-#define HID_REQ_SET_IDLE 0x0A
-#define HID_REQ_SET_PROTOCOL 0x0B
-
-/*
- * HID class descriptor types
- */
-
-#define HID_DT_HID (USB_TYPE_CLASS | 0x01)
-#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
-#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
-
-/*
- * We parse each description item into this structure. Short items data
- * values are expanded to 32-bit signed int, long items contain a pointer
- * into the data area.
- */
-
-struct hid_item {
- unsigned format;
- __u8 size;
- __u8 type;
- __u8 tag;
- union {
- __u8 u8;
- __s8 s8;
- __u16 u16;
- __s16 s16;
- __u32 u32;
- __s32 s32;
- __u8 *longdata;
- } data;
-};
-
-/*
- * HID report item format
- */
-
-#define HID_ITEM_FORMAT_SHORT 0
-#define HID_ITEM_FORMAT_LONG 1
-
-/*
- * Special tag indicating long items
- */
-
-#define HID_ITEM_TAG_LONG 15
-
-/*
- * HID report descriptor item type (prefix bit 2,3)
- */
-
-#define HID_ITEM_TYPE_MAIN 0
-#define HID_ITEM_TYPE_GLOBAL 1
-#define HID_ITEM_TYPE_LOCAL 2
-#define HID_ITEM_TYPE_RESERVED 3
-
-/*
- * HID report descriptor main item tags
- */
-
-#define HID_MAIN_ITEM_TAG_INPUT 8
-#define HID_MAIN_ITEM_TAG_OUTPUT 9
-#define HID_MAIN_ITEM_TAG_FEATURE 11
-#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10
-#define HID_MAIN_ITEM_TAG_END_COLLECTION 12
-
-/*
- * HID report descriptor main item contents
- */
-
-#define HID_MAIN_ITEM_CONSTANT 0x001
-#define HID_MAIN_ITEM_VARIABLE 0x002
-#define HID_MAIN_ITEM_RELATIVE 0x004
-#define HID_MAIN_ITEM_WRAP 0x008
-#define HID_MAIN_ITEM_NONLINEAR 0x010
-#define HID_MAIN_ITEM_NO_PREFERRED 0x020
-#define HID_MAIN_ITEM_NULL_STATE 0x040
-#define HID_MAIN_ITEM_VOLATILE 0x080
-#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100
-
-/*
- * HID report descriptor collection item types
- */
-
-#define HID_COLLECTION_PHYSICAL 0
-#define HID_COLLECTION_APPLICATION 1
-#define HID_COLLECTION_LOGICAL 2
-
-/*
- * HID report descriptor global item tags
- */
-
-#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1
-#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3
-#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4
-#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5
-#define HID_GLOBAL_ITEM_TAG_UNIT 6
-#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7
-#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8
-#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9
-#define HID_GLOBAL_ITEM_TAG_PUSH 10
-#define HID_GLOBAL_ITEM_TAG_POP 11
-
-/*
- * HID report descriptor local item tags
- */
-
-#define HID_LOCAL_ITEM_TAG_USAGE 0
-#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1
-#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4
-#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5
-#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7
-#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8
-#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9
-#define HID_LOCAL_ITEM_TAG_DELIMITER 10
-
-/*
- * HID usage tables
- */
-
-#define HID_USAGE_PAGE 0xffff0000
-
-#define HID_UP_UNDEFINED 0x00000000
-#define HID_UP_GENDESK 0x00010000
-#define HID_UP_SIMULATION 0x00020000
-#define HID_UP_KEYBOARD 0x00070000
-#define HID_UP_LED 0x00080000
-#define HID_UP_BUTTON 0x00090000
-#define HID_UP_ORDINAL 0x000a0000
-#define HID_UP_CONSUMER 0x000c0000
-#define HID_UP_DIGITIZER 0x000d0000
-#define HID_UP_PID 0x000f0000
-#define HID_UP_HPVENDOR 0xff7f0000
-#define HID_UP_MSVENDOR 0xff000000
-#define HID_UP_CUSTOM 0x00ff0000
-#define HID_UP_LOGIVENDOR 0xffbc0000
-
-#define HID_USAGE 0x0000ffff
-
-#define HID_GD_POINTER 0x00010001
-#define HID_GD_MOUSE 0x00010002
-#define HID_GD_JOYSTICK 0x00010004
-#define HID_GD_GAMEPAD 0x00010005
-#define HID_GD_KEYBOARD 0x00010006
-#define HID_GD_KEYPAD 0x00010007
-#define HID_GD_MULTIAXIS 0x00010008
-#define HID_GD_X 0x00010030
-#define HID_GD_Y 0x00010031
-#define HID_GD_Z 0x00010032
-#define HID_GD_RX 0x00010033
-#define HID_GD_RY 0x00010034
-#define HID_GD_RZ 0x00010035
-#define HID_GD_SLIDER 0x00010036
-#define HID_GD_DIAL 0x00010037
-#define HID_GD_WHEEL 0x00010038
-#define HID_GD_HATSWITCH 0x00010039
-#define HID_GD_BUFFER 0x0001003a
-#define HID_GD_BYTECOUNT 0x0001003b
-#define HID_GD_MOTION 0x0001003c
-#define HID_GD_START 0x0001003d
-#define HID_GD_SELECT 0x0001003e
-#define HID_GD_VX 0x00010040
-#define HID_GD_VY 0x00010041
-#define HID_GD_VZ 0x00010042
-#define HID_GD_VBRX 0x00010043
-#define HID_GD_VBRY 0x00010044
-#define HID_GD_VBRZ 0x00010045
-#define HID_GD_VNO 0x00010046
-#define HID_GD_FEATURE 0x00010047
-#define HID_GD_UP 0x00010090
-#define HID_GD_DOWN 0x00010091
-#define HID_GD_RIGHT 0x00010092
-#define HID_GD_LEFT 0x00010093
-
-/*
- * HID report types --- Ouch! HID spec says 1 2 3!
- */
-
-#define HID_INPUT_REPORT 0
-#define HID_OUTPUT_REPORT 1
-#define HID_FEATURE_REPORT 2
-
-/*
- * HID device quirks.
- */
-
-#define HID_QUIRK_INVERT 0x00000001
-#define HID_QUIRK_NOTOUCH 0x00000002
-#define HID_QUIRK_IGNORE 0x00000004
-#define HID_QUIRK_NOGET 0x00000008
-#define HID_QUIRK_HIDDEV 0x00000010
-#define HID_QUIRK_BADPAD 0x00000020
-#define HID_QUIRK_MULTI_INPUT 0x00000040
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
-#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
-#define HID_QUIRK_MIGHTYMOUSE 0x00000400
-#define HID_QUIRK_CYMOTION 0x00000800
-#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
-#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
-#define HID_QUIRK_INVERT_HWHEEL 0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
-
-/*
- * This is the global environment of the parser. This information is
- * persistent for main-items. The global environment can be saved and
- * restored with PUSH/POP statements.
- */
-
-struct hid_global {
- unsigned usage_page;
- __s32 logical_minimum;
- __s32 logical_maximum;
- __s32 physical_minimum;
- __s32 physical_maximum;
- __s32 unit_exponent;
- unsigned unit;
- unsigned report_id;
- unsigned report_size;
- unsigned report_count;
-};
-
-/*
- * This is the local environment. It is persistent up the next main-item.
- */
-
-#define HID_MAX_DESCRIPTOR_SIZE 4096
-#define HID_MAX_USAGES 1024
-#define HID_DEFAULT_NUM_COLLECTIONS 16
-
-struct hid_local {
- unsigned usage[HID_MAX_USAGES]; /* usage array */
- unsigned collection_index[HID_MAX_USAGES]; /* collection index array */
- unsigned usage_index;
- unsigned usage_minimum;
- unsigned delimiter_depth;
- unsigned delimiter_branch;
-};
-
-/*
- * This is the collection stack. We climb up the stack to determine
- * application and function of each field.
- */
-
-struct hid_collection {
- unsigned type;
- unsigned usage;
- unsigned level;
-};
-
-struct hid_usage {
- unsigned hid; /* hid usage code */
- unsigned collection_index; /* index into collection array */
- /* hidinput data */
- __u16 code; /* input driver code */
- __u8 type; /* input driver type */
- __s8 hat_min; /* hat switch fun */
- __s8 hat_max; /* ditto */
- __s8 hat_dir; /* ditto */
-};
-
-struct hid_input;
-
-struct hid_field {
- unsigned physical; /* physical usage for this field */
- unsigned logical; /* logical usage for this field */
- unsigned application; /* application usage for this field */
- struct hid_usage *usage; /* usage table for this function */
- unsigned maxusage; /* maximum usage index */
- unsigned flags; /* main-item flags (i.e. volatile,array,constant) */
- unsigned report_offset; /* bit offset in the report */
- unsigned report_size; /* size of this field in the report */
- unsigned report_count; /* number of this field in the report */
- unsigned report_type; /* (input,output,feature) */
- __s32 *value; /* last known value(s) */
- __s32 logical_minimum;
- __s32 logical_maximum;
- __s32 physical_minimum;
- __s32 physical_maximum;
- __s32 unit_exponent;
- unsigned unit;
- struct hid_report *report; /* associated report */
- unsigned index; /* index into report->field[] */
- /* hidinput data */
- struct hid_input *hidinput; /* associated input structure */
- __u16 dpad; /* dpad input code */
-};
-
-#define HID_MAX_FIELDS 64
-
-struct hid_report {
- struct list_head list;
- unsigned id; /* id of this report */
- unsigned type; /* report type */
- struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
- unsigned maxfield; /* maximum valid field index */
- unsigned size; /* size of the report (bits) */
- struct hid_device *device; /* associated device */
-};
-
-struct hid_report_enum {
- unsigned numbered;
- struct list_head report_list;
- struct hid_report *report_id_hash[256];
-};
-
-#define HID_REPORT_TYPES 3
-
-#define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */
-#define HID_MAX_BUFFER_SIZE 4096 /* 4kb */
-#define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */
-#define HID_OUTPUT_FIFO_SIZE 64
-
-struct hid_control_fifo {
- unsigned char dir;
- struct hid_report *report;
-};
-
-#define HID_CLAIMED_INPUT 1
-#define HID_CLAIMED_HIDDEV 2
-
-#define HID_CTRL_RUNNING 1
-#define HID_OUT_RUNNING 2
-#define HID_IN_RUNNING 3
-#define HID_RESET_PENDING 4
-#define HID_SUSPENDED 5
-
-struct hid_input {
- struct list_head list;
- struct hid_report *report;
- struct input_dev *input;
-};
-
-struct hid_device { /* device report descriptor */
- __u8 *rdesc;
- unsigned rsize;
- struct hid_collection *collection; /* List of HID collections */
- unsigned collection_size; /* Number of allocated hid_collections */
- unsigned maxcollection; /* Number of parsed collections */
- unsigned maxapplication; /* Number of applications */
- unsigned version; /* HID version */
- unsigned country; /* HID country */
- struct hid_report_enum report_enum[HID_REPORT_TYPES];
-
- struct usb_device *dev; /* USB device */
- struct usb_interface *intf; /* USB interface */
- int ifnum; /* USB interface number */
-
- unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
- struct timer_list io_retry; /* Retry timer */
- unsigned long stop_retry; /* Time to give up, in jiffies */
- unsigned int retry_delay; /* Delay length in ms */
- struct work_struct reset_work; /* Task context for resets */
-
- unsigned int bufsize; /* URB buffer size */
-
- struct urb *urbin; /* Input URB */
- char *inbuf; /* Input buffer */
- dma_addr_t inbuf_dma; /* Input buffer dma */
- spinlock_t inlock; /* Input fifo spinlock */
-
- struct urb *urbctrl; /* Control URB */
- struct usb_ctrlrequest *cr; /* Control request struct */
- dma_addr_t cr_dma; /* Control request struct dma */
- struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
- unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
- char *ctrlbuf; /* Control buffer */
- dma_addr_t ctrlbuf_dma; /* Control buffer dma */
- spinlock_t ctrllock; /* Control fifo spinlock */
-
- struct urb *urbout; /* Output URB */
- struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
- unsigned char outhead, outtail; /* Output pipe fifo head & tail */
- char *outbuf; /* Output buffer */
- dma_addr_t outbuf_dma; /* Output buffer dma */
- spinlock_t outlock; /* Output fifo spinlock */
-
- unsigned claimed; /* Claimed by hidinput, hiddev? */
- unsigned quirks; /* Various quirks the device can pull on us */
-
- struct list_head inputs; /* The list of inputs */
- void *hiddev; /* The hiddev structure */
- int minor; /* Hiddev minor number */
-
- wait_queue_head_t wait; /* For sleeping */
-
- int open; /* is the device open by anyone? */
- char name[128]; /* Device name */
- char phys[64]; /* Device physical location */
- char uniq[64]; /* Device unique identifier (serial #) */
-
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
- unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
- unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
-#endif
-};
-
-#define HID_GLOBAL_STACK_SIZE 4
-#define HID_COLLECTION_STACK_SIZE 4
-
-struct hid_parser {
- struct hid_global global;
- struct hid_global global_stack[HID_GLOBAL_STACK_SIZE];
- unsigned global_stack_ptr;
- struct hid_local local;
- unsigned collection_stack[HID_COLLECTION_STACK_SIZE];
- unsigned collection_stack_ptr;
- struct hid_device *device;
-};
-
-struct hid_class_descriptor {
- __u8 bDescriptorType;
- __u16 wDescriptorLength;
-} __attribute__ ((packed));
-
-struct hid_descriptor {
- __u8 bLength;
- __u8 bDescriptorType;
- __u16 bcdHID;
- __u8 bCountryCode;
- __u8 bNumDescriptors;
-
- struct hid_class_descriptor desc[1];
-} __attribute__ ((packed));
-
-#ifdef DEBUG
-#include "hid-debug.h"
-#else
-#define hid_dump_input(a,b) do { } while (0)
-#define hid_dump_device(c) do { } while (0)
-#define hid_dump_field(a,b) do { } while (0)
-#define resolv_usage(a) do { } while (0)
-#define resolv_event(a,b) do { } while (0)
-#endif
-
-#endif
-
-#ifdef CONFIG_USB_HIDINPUT
-/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
-/* We ignore a few input applications that are not widely used */
-#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
-extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
-extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
-extern int hidinput_connect(struct hid_device *);
-extern void hidinput_disconnect(struct hid_device *);
-#else
-#define IS_INPUT_APPLICATION(a) (0)
-static inline void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { }
-static inline void hidinput_report_event(struct hid_device *hid, struct hid_report *report) { }
-static inline int hidinput_connect(struct hid_device *hid) { return -ENODEV; }
-static inline void hidinput_disconnect(struct hid_device *hid) { }
-#endif
-
-int hid_open(struct hid_device *);
-void hid_close(struct hid_device *);
-int hid_set_field(struct hid_field *, unsigned, __s32);
-void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
-void hid_init_reports(struct hid_device *hid);
-int hid_wait_io(struct hid_device* hid);
-
-
-#ifdef CONFIG_HID_FF
-int hid_ff_init(struct hid_device *hid);
-
-int hid_lgff_init(struct hid_device *hid);
-int hid_tmff_init(struct hid_device *hid);
-int hid_zpff_init(struct hid_device *hid);
-#ifdef CONFIG_HID_PID
-int hid_pidff_init(struct hid_device *hid);
-#else
-static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
-#endif
-
-#else
-static inline int hid_ff_init(struct hid_device *hid) { return -1; }
-#endif
-
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 7dc14d0cacc1..114d6c9f64b1 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -32,8 +32,9 @@
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include "hid.h"
+#include <linux/hid.h>
#include <linux/hiddev.h>
+#include "usbhid.h"
#ifdef CONFIG_USB_DYNAMIC_MINORS
#define HIDDEV_MINOR_BASE 0
@@ -196,7 +197,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
hiddev_send_event(hid, &uref);
}
-
+EXPORT_SYMBOL_GPL(hiddev_hid_event);
void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
{
@@ -213,6 +214,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report)
hiddev_send_event(hid, &uref);
}
+
/*
* fasync file op
*/
@@ -239,7 +241,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
if (!--list->hiddev->open) {
if (list->hiddev->exist)
- hid_close(list->hiddev->hid);
+ usbhid_close(list->hiddev->hid);
else
kfree(list->hiddev);
}
@@ -270,7 +272,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
if (!list->hiddev->open++)
if (list->hiddev->exist)
- hid_open(hiddev_table[i]->hid);
+ usbhid_open(hiddev_table[i]->hid);
return 0;
}
@@ -382,7 +384,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct hiddev_list *list = file->private_data;
struct hiddev *hiddev = list->hiddev;
struct hid_device *hid = hiddev->hid;
- struct usb_device *dev = hid->dev;
+ struct usb_device *dev = to_usb_device(hid->dev);
struct hiddev_collection_info cinfo;
struct hiddev_report_info rinfo;
struct hiddev_field_info finfo;
@@ -391,6 +393,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
struct hiddev_devinfo dinfo;
struct hid_report *report;
struct hid_field *field;
+ struct usbhid_device *usbhid = hid->driver_data;
void __user *user_arg = (void __user *)arg;
int i;
@@ -420,7 +423,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.bustype = BUS_USB;
dinfo.busnum = dev->bus->busnum;
dinfo.devnum = dev->devnum;
- dinfo.ifnum = hid->ifnum;
+ dinfo.ifnum = usbhid->ifnum;
dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
@@ -479,7 +482,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
}
case HIDIOCINITREPORT:
- hid_init_reports(hid);
+ usbhid_init_reports(hid);
return 0;
@@ -493,8 +496,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_submit_report(hid, report, USB_DIR_IN);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, report, USB_DIR_IN);
+ usbhid_wait_io(hid);
return 0;
@@ -508,8 +511,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
- hid_submit_report(hid, report, USB_DIR_OUT);
- hid_wait_io(hid);
+ usbhid_submit_report(hid, report, USB_DIR_OUT);
+ usbhid_wait_io(hid);
return 0;
@@ -745,6 +748,7 @@ static struct usb_class_driver hiddev_class = {
int hiddev_connect(struct hid_device *hid)
{
struct hiddev *hiddev;
+ struct usbhid_device *usbhid = hid->driver_data;
int i;
int retval;
@@ -760,7 +764,7 @@ int hiddev_connect(struct hid_device *hid)
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
- retval = usb_register_dev(hid->intf, &hiddev_class);
+ retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
err("Not able to get a minor for this device.");
kfree(hiddev);
@@ -772,10 +776,10 @@ int hiddev_connect(struct hid_device *hid)
hiddev->hid = hid;
hiddev->exist = 1;
- hid->minor = hid->intf->minor;
+ hid->minor = usbhid->intf->minor;
hid->hiddev = hiddev;
- hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+ hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
return 0;
}
@@ -788,14 +792,15 @@ static struct usb_class_driver hiddev_class;
void hiddev_disconnect(struct hid_device *hid)
{
struct hiddev *hiddev = hid->hiddev;
+ struct usbhid_device *usbhid = hid->driver_data;
hiddev->exist = 0;
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
- usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+ usb_deregister_dev(usbhid->intf, &hiddev_class);
if (hiddev->open) {
- hid_close(hiddev->hid);
+ usbhid_close(hiddev->hid);
wake_up_interruptible(&hiddev->wait);
} else {
kfree(hiddev);
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 50aa8108a50b..98bd323369c7 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -456,7 +456,7 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
remote->in_endpoint = endpoint;
remote->toggle = -1; /* Set to -1 so we will always not match the toggle from the first remote message. */
- remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, SLAB_ATOMIC, &remote->in_dma);
+ remote->in_buffer = usb_buffer_alloc(udev, RECV_SIZE, GFP_ATOMIC, &remote->in_dma);
if (!remote->in_buffer) {
retval = -ENOMEM;
goto fail1;
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 79a85d46cb13..92c4e07da4c8 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -164,7 +164,7 @@ static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *m
dbg("%s - called", __FUNCTION__);
mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE,
- SLAB_ATOMIC, &mtouch->data_dma);
+ GFP_ATOMIC, &mtouch->data_dma);
if (!mtouch->data)
return -1;
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index 0bf91778c40d..fea97e5437f8 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -277,12 +277,12 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig
static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_device *pm)
{
pm->data = usb_buffer_alloc(udev, POWERMATE_PAYLOAD_SIZE_MAX,
- SLAB_ATOMIC, &pm->data_dma);
+ GFP_ATOMIC, &pm->data_dma);
if (!pm->data)
return -1;
pm->configcr = usb_buffer_alloc(udev, sizeof(*(pm->configcr)),
- SLAB_ATOMIC, &pm->configcr_dma);
+ GFP_ATOMIC, &pm->configcr_dma);
if (!pm->configcr)
return -1;
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 05c0d1ca39ab..2a314b065922 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -248,7 +248,7 @@ static int touchkit_alloc_buffers(struct usb_device *udev,
struct touchkit_usb *touchkit)
{
touchkit->data = usb_buffer_alloc(udev, TOUCHKIT_REPORT_DATA_SIZE,
- SLAB_ATOMIC, &touchkit->data_dma);
+ GFP_ATOMIC, &touchkit->data_dma);
if (!touchkit->data)
return -1;
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
new file mode 100644
index 000000000000..830107e5251f
--- /dev/null
+++ b/drivers/usb/input/usbhid.h
@@ -0,0 +1,84 @@
+#ifndef __USBHID_H
+#define __USBHID_H
+
+/*
+ * Copyright (c) 1999 Andreas Gal
+ * Copyright (c) 2000-2001 Vojtech Pavlik
+ * Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+
+/* API provided by hid-core.c for USB HID drivers */
+int usbhid_wait_io(struct hid_device* hid);
+void usbhid_close(struct hid_device *hid);
+int usbhid_open(struct hid_device *hid);
+void usbhid_init_reports(struct hid_device *hid);
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+
+/*
+ * USB-specific HID struct, to be pointed to
+ * from struct hid_device->driver_data
+ */
+
+struct usbhid_device {
+ struct hid_device *hid; /* pointer to corresponding HID dev */
+
+ struct usb_interface *intf; /* USB interface */
+ int ifnum; /* USB interface number */
+
+ unsigned int bufsize; /* URB buffer size */
+
+ struct urb *urbin; /* Input URB */
+ char *inbuf; /* Input buffer */
+ dma_addr_t inbuf_dma; /* Input buffer dma */
+ spinlock_t inlock; /* Input fifo spinlock */
+
+ struct urb *urbctrl; /* Control URB */
+ struct usb_ctrlrequest *cr; /* Control request struct */
+ dma_addr_t cr_dma; /* Control request struct dma */
+ struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
+ unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
+ char *ctrlbuf; /* Control buffer */
+ dma_addr_t ctrlbuf_dma; /* Control buffer dma */
+ spinlock_t ctrllock; /* Control fifo spinlock */
+
+ struct urb *urbout; /* Output URB */
+ struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */
+ unsigned char outhead, outtail; /* Output pipe fifo head & tail */
+ char *outbuf; /* Output buffer */
+ dma_addr_t outbuf_dma; /* Output buffer dma */
+ spinlock_t outlock; /* Output fifo spinlock */
+
+ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ struct timer_list io_retry; /* Retry timer */
+ unsigned long stop_retry; /* Time to give up, in jiffies */
+ unsigned int retry_delay; /* Delay length in ms */
+ struct work_struct reset_work; /* Task context for resets */
+
+};
+
+#endif
+
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index c73285cf8558..8505824848f6 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -122,7 +122,7 @@ static void usb_kbd_irq(struct urb *urb)
memcpy(kbd->old, kbd->new, 8);
resubmit:
- i = usb_submit_urb (urb, SLAB_ATOMIC);
+ i = usb_submit_urb (urb, GFP_ATOMIC);
if (i)
err ("can't resubmit intr, %s-%s/input0, status %d",
kbd->usbdev->bus->bus_name,
@@ -196,11 +196,11 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
return -1;
if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL)))
return -1;
- if (!(kbd->new = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbd->new_dma)))
+ if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma)))
return -1;
- if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), SLAB_ATOMIC, &kbd->cr_dma)))
+ if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma)))
return -1;
- if (!(kbd->leds = usb_buffer_alloc(dev, 1, SLAB_ATOMIC, &kbd->leds_dma)))
+ if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma)))
return -1;
return 0;
@@ -208,10 +208,8 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
- if (kbd->irq)
- usb_free_urb(kbd->irq);
- if (kbd->led)
- usb_free_urb(kbd->led);
+ usb_free_urb(kbd->irq);
+ usb_free_urb(kbd->led);
if (kbd->new)
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
if (kbd->cr)
@@ -236,9 +234,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index cbbbea332ed7..64a33e420cfb 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -86,7 +86,7 @@ static void usb_mouse_irq(struct urb *urb)
input_sync(dev);
resubmit:
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s/input0, status %d",
mouse->usbdev->bus->bus_name,
@@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
@@ -139,7 +137,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!mouse || !input_dev)
goto fail1;
- mouse->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &mouse->data_dma);
+ mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
if (!mouse->data)
goto fail1;
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index 933ceddf3dee..7f3c57da9bc0 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -8,6 +8,7 @@
* - PanJit TouchSet
* - eTurboTouch
* - Gunze AHL61
+ * - DMC TSC-10/25
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -30,6 +31,8 @@
* - ITM parts are from itmtouch.c
* - 3M parts are from mtouchusb.c
* - PanJit parts are from an unmerged driver by Lanslott Gish
+ * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
+ * driver from Marius Vollmer
*
*****************************************************************************/
@@ -44,7 +47,7 @@
#include <linux/usb/input.h>
-#define DRIVER_VERSION "v0.4"
+#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver"
@@ -103,6 +106,7 @@ enum {
DEVTYPE_ITM,
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
+ DEVTYPE_DMC_TSC10,
};
static struct usb_device_id usbtouch_devices[] = {
@@ -139,6 +143,10 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
+#endif
+
{}
};
@@ -313,6 +321,80 @@ static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *
#endif
/*****************************************************************************
+ * DMC TSC-10/25 Part
+ *
+ * Documentation about the controller and it's protocol can be found at
+ * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
+ * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+
+/* supported data rates. currently using 130 */
+#define TSC10_RATE_POINT 0x50
+#define TSC10_RATE_30 0x40
+#define TSC10_RATE_50 0x41
+#define TSC10_RATE_80 0x42
+#define TSC10_RATE_100 0x43
+#define TSC10_RATE_130 0x44
+#define TSC10_RATE_150 0x45
+
+/* commands */
+#define TSC10_CMD_RESET 0x55
+#define TSC10_CMD_RATE 0x05
+#define TSC10_CMD_DATA1 0x01
+
+static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
+{
+ struct usb_device *dev = usbtouch->udev;
+ int ret;
+ unsigned char buf[2];
+
+ /* reset */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RESET,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* set coordinate output rate */
+ buf[0] = buf[1] = 0xFF;
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_RATE,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+ if (buf[0] != 0x06 || buf[1] != 0x00)
+ return -ENODEV;
+
+ /* start sending data */
+ ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+ TSC10_CMD_DATA1,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+
+static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+ *x = ((pkt[2] & 0x03) << 8) | pkt[1];
+ *y = ((pkt[4] & 0x03) << 8) | pkt[3];
+ *touch = pkt[0] & 0x01;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
@@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = gunze_read_data,
},
#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+ [DEVTYPE_DMC_TSC10] = {
+ .min_xc = 0x0,
+ .max_xc = 0x03ff,
+ .min_yc = 0x0,
+ .max_yc = 0x03ff,
+ .rept_size = 5,
+ .init = dmc_tsc10_init,
+ .read_data = dmc_tsc10_read_data,
+ },
+#endif
};
@@ -586,7 +680,7 @@ static int usbtouch_probe(struct usb_interface *intf,
type->process_pkt = usbtouch_process_pkt;
usbtouch->data = usb_buffer_alloc(udev, type->rept_size,
- SLAB_KERNEL, &usbtouch->data_dma);
+ GFP_KERNEL, &usbtouch->data_dma);
if (!usbtouch->data)
goto out_free;
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
index 1cf08f02c50e..d85abfc5ab58 100644
--- a/drivers/usb/input/wacom.h
+++ b/drivers/usb/input/wacom.h
@@ -110,7 +110,6 @@ struct wacom_combo {
};
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
-extern void wacom_sys_irq(struct urb *urb);
extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
index 3498b893b53b..12b42746ded8 100644
--- a/drivers/usb/input/wacom_sys.c
+++ b/drivers/usb/input/wacom_sys.c
@@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
return wcombo->wacom->dev;
}
-void wacom_sys_irq(struct urb *urb)
+static void wacom_sys_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
struct wacom_combo wcombo;
@@ -159,13 +159,13 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3);
- input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
}
void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
- input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
}
void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
index 92726fe89379..4142e36730fc 100644
--- a/drivers/usb/input/wacom_wac.c
+++ b/drivers/usb/input/wacom_wac.c
@@ -209,13 +209,15 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
}
- }
-
- if (data[1] & 0x10)
wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+ }
else
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
- wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
+
+ if (data[1] & 0x10) /* only report prox-in when in area */
+ wacom_report_key(wcombo, wacom->tool[0], 1);
+ if (!(data[1] & 0x90)) /* report prox-out when physically out */
+ wacom_report_key(wcombo, wacom->tool[0], 0);
wacom_input_sync(wcombo);
/* send pad data */
@@ -405,7 +407,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
return 0;
- if (wacom->features->type >= INTUOS3) {
+ if (wacom->features->type >= INTUOS3S) {
wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
@@ -423,7 +425,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
if (data[1] & 0x02) {
/* Rotation packet */
- if (wacom->features->type >= INTUOS3) {
+ if (wacom->features->type >= INTUOS3S) {
/* I3 marker pen rotation reported as wheel
* due to valuator limitation
*/
@@ -547,11 +549,11 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE },
{ "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 },
{ "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 },
- { "Wacom Volito", 8, 5104, 3712, 511, 0, GRAPHIRE },
- { "Wacom PenStation2", 8, 3250, 2320, 255, 0, GRAPHIRE },
- { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 0, GRAPHIRE },
- { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 0, GRAPHIRE },
- { "Wacom PenPartner2", 8, 3250, 2320, 255, 0, GRAPHIRE },
+ { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE },
+ { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE },
+ { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
+ { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
+ { "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS },
@@ -580,7 +582,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L },
{ "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 },
- { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 15, INTUOS3S },
+ { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S },
{ "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS },
{ }
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index df97e5c803f9..e4bc76ebc835 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -325,7 +325,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
goto fail1;
xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN,
- SLAB_ATOMIC, &xpad->idata_dma);
+ GFP_ATOMIC, &xpad->idata_dma);
if (!xpad->idata)
goto fail1;
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 905bf6398257..caff8e6d7448 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -EIO;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
- return -EIO;
+ if (!usb_endpoint_is_int_in(endpoint))
+ return -ENODEV;
yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
if (!yld)
@@ -876,17 +874,17 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* allocate usb buffers */
yld->irq_data = usb_buffer_alloc(udev, USB_PKT_LEN,
- SLAB_ATOMIC, &yld->irq_dma);
+ GFP_ATOMIC, &yld->irq_dma);
if (yld->irq_data == NULL)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_data = usb_buffer_alloc(udev, USB_PKT_LEN,
- SLAB_ATOMIC, &yld->ctl_dma);
+ GFP_ATOMIC, &yld->ctl_dma);
if (!yld->ctl_data)
return usb_cleanup(yld, -ENOMEM);
yld->ctl_req = usb_buffer_alloc(udev, sizeof(*(yld->ctl_req)),
- SLAB_ATOMIC, &yld->ctl_req_dma);
+ GFP_ATOMIC, &yld->ctl_req_dma);
if (yld->ctl_req == NULL)
return usb_cleanup(yld, -ENOMEM);
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 11dc59540cda..2cba07d31971 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,6 +4,7 @@
#
obj-$(CONFIG_USB_ADUTUX) += adutux.o
+obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 6b23a1def9fe..a7932a72d298 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -76,7 +76,7 @@ struct appledisplay {
char *urbdata; /* interrupt URB data buffer */
char *msgdata; /* control message data buffer */
- struct work_struct work;
+ struct delayed_work work;
int button_pressed;
spinlock_t lock;
};
@@ -117,7 +117,7 @@ static void appledisplay_complete(struct urb *urb)
case ACD_BTN_BRIGHT_UP:
case ACD_BTN_BRIGHT_DOWN:
pdata->button_pressed = 1;
- queue_work(wq, &pdata->work);
+ queue_delayed_work(wq, &pdata->work, 0);
break;
case ACD_BTN_NONE:
default:
@@ -184,9 +184,10 @@ static struct backlight_properties appledisplay_bl_data = {
.max_brightness = 0xFF
};
-static void appledisplay_work(void *private)
+static void appledisplay_work(struct work_struct *work)
{
- struct appledisplay *pdata = private;
+ struct appledisplay *pdata =
+ container_of(work, struct appledisplay, work.work);
int retval;
up(&pdata->bd->sem);
@@ -216,10 +217,7 @@ static int appledisplay_probe(struct usb_interface *iface,
iface_desc = iface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
- if (!int_in_endpointAddr &&
- (endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_INT)) {
+ if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
/* we found an interrupt in endpoint */
int_in_endpointAddr = endpoint->bEndpointAddress;
break;
@@ -241,7 +239,7 @@ static int appledisplay_probe(struct usb_interface *iface,
pdata->udev = udev;
spin_lock_init(&pdata->lock);
- INIT_WORK(&pdata->work, appledisplay_work, pdata);
+ INIT_DELAYED_WORK(&pdata->work, appledisplay_work);
/* Allocate buffer for control messages */
pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
@@ -283,7 +281,7 @@ static int appledisplay_probe(struct usb_interface *iface,
/* Register backlight device */
snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
atomic_inc_return(&count_displays) - 1);
- pdata->bd = backlight_device_register(bl_name, pdata,
+ pdata->bd = backlight_device_register(bl_name, NULL, NULL,
&appledisplay_bl_data);
if (IS_ERR(pdata->bd)) {
err("appledisplay: Backlight registration failed");
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index e4971d6aaafb..b5332e679c46 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp)
{
kfree(bp->bufp);
kfree(bp->dr);
- if (bp->urbp) {
- usb_free_urb(bp->urbp);
- }
+ usb_free_urb(bp->urbp);
kfree(bp);
}
@@ -768,7 +766,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned
bep->bufp = kmalloc (bufsize, GFP_KERNEL);
if (!bep->bufp)
goto bl_fail;
- bep->dr = (struct usb_ctrlrequest *) kmalloc (sizeof (struct usb_ctrlrequest), GFP_KERNEL);
+ bep->dr = kmalloc(sizeof (struct usb_ctrlrequest), GFP_KERNEL);
if (!bep->dr)
goto bl_fail;
bep->urbp = usb_alloc_urb (0, GFP_KERNEL);
@@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp)
dbg ("auerswald_int_release");
/* stop the int endpoint */
- if (cp->inturbp)
- usb_kill_urb (cp->inturbp);
+ usb_kill_urb (cp->inturbp);
/* deallocate memory */
auerswald_int_free (cp);
@@ -1379,7 +1376,7 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* we have access to the device. Now lets allocate memory */
- ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL);
+ ccp = kzalloc(sizeof(auerchar_t), GFP_KERNEL);
if (ccp == NULL) {
err ("out of memory");
ret = -ENOMEM;
@@ -1387,7 +1384,6 @@ static int auerchar_open (struct inode *inode, struct file *file)
}
/* Initialize device descriptor */
- memset( ccp, 0, sizeof(auerchar_t));
init_MUTEX( &ccp->mutex);
init_MUTEX( &ccp->readmutex);
auerbuf_init (&ccp->bufctl);
@@ -1915,14 +1911,13 @@ static int auerswald_probe (struct usb_interface *intf,
return -ENODEV;
/* allocate memory for our device and initialize it */
- cp = kmalloc (sizeof(auerswald_t), GFP_KERNEL);
+ cp = kzalloc (sizeof(auerswald_t), GFP_KERNEL);
if (cp == NULL) {
err ("out of memory");
goto pfail;
}
/* Initialize device descriptor */
- memset (cp, 0, sizeof(auerswald_t));
init_MUTEX (&cp->mutex);
cp->usbdev = usbdev;
auerchain_init (&cp->controlchain);
@@ -1972,7 +1967,7 @@ static int auerswald_probe (struct usb_interface *intf,
info("device is a %s", cp->dev_desc);
/* get the maximum allowed control transfer length */
- pbuf = (__le16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */
+ pbuf = kmalloc(2, GFP_KERNEL); /* use an allocated buffer because of urb target */
if (!pbuf) {
err( "out of memory");
goto pfail;
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index 1fd9cb85f4ca..5c0a26cbd128 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -53,13 +53,12 @@ static void __exit emi26_exit (void);
static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
- unsigned char *buffer = kmalloc (length, GFP_KERNEL);
+ unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
err("emi26: kmalloc(%d) failed.", length);
return -ENOMEM;
}
- memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index fe351371f274..23153eac0dfa 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -61,13 +61,12 @@ static void __exit emi62_exit (void);
static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{
int result;
- unsigned char *buffer = kmalloc (length, GFP_KERNEL);
+ unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) {
err("emi62: kmalloc(%d) failed.", length);
return -ENOMEM;
}
- memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 9b591b8b9369..41c0161abdb9 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/list.h>
#include <linux/ioctl.h>
+#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kref.h>
@@ -51,6 +52,10 @@ MODULE_AUTHOR("Tony Olech");
MODULE_DESCRIPTION("FTDI ELAN driver");
MODULE_LICENSE("GPL");
#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+static int distrust_firmware = 1;
+module_param(distrust_firmware, bool, 0);
+MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+ "t setup");
extern struct platform_driver u132_platform_driver;
static struct workqueue_struct *status_queue;
static struct workqueue_struct *command_queue;
@@ -66,7 +71,9 @@ static struct list_head ftdi_static_list;
* end of the global variables protected by ftdi_module_lock
*/
#include "usb_u132.h"
-#define TD_DEVNOTRESP 5
+#include <asm/io.h>
+#include "../core/hcd.h"
+#include "../host/ohci.h"
/* Define these values to match your devices*/
#define USB_FTDI_ELAN_VENDOR_ID 0x0403
#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
@@ -156,9 +163,9 @@ struct usb_ftdi {
struct usb_device *udev;
struct usb_interface *interface;
struct usb_class_driver *class;
- struct work_struct status_work;
- struct work_struct command_work;
- struct work_struct respond_work;
+ struct delayed_work status_work;
+ struct delayed_work command_work;
+ struct delayed_work respond_work;
struct u132_platform_data platform_data;
struct resource resources[0];
struct platform_device platform_dev;
@@ -210,23 +217,14 @@ static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
- return;
- } else if (queue_work(status_queue, &ftdi->status_work))
- return;
- kref_put(&ftdi->kref, ftdi_elan_delete);
- return;
+ if (!queue_delayed_work(status_queue, &ftdi->status_work, delta))
+ kref_put(&ftdi->kref, ftdi_elan_delete);
}
static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
- kref_get(&ftdi->kref);
- } else if (queue_work(status_queue, &ftdi->status_work))
- kref_get(&ftdi->kref);
- return;
+ if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+ kref_get(&ftdi->kref);
}
static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
@@ -237,25 +235,14 @@ static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(command_queue, &ftdi->command_work,
- delta))
- return;
- } else if (queue_work(command_queue, &ftdi->command_work))
- return;
- kref_put(&ftdi->kref, ftdi_elan_delete);
- return;
+ if (!queue_delayed_work(command_queue, &ftdi->command_work, delta))
+ kref_put(&ftdi->kref, ftdi_elan_delete);
}
static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(command_queue, &ftdi->command_work,
- delta))
- kref_get(&ftdi->kref);
- } else if (queue_work(command_queue, &ftdi->command_work))
- kref_get(&ftdi->kref);
- return;
+ if (queue_delayed_work(command_queue, &ftdi->command_work, delta))
+ kref_get(&ftdi->kref);
}
static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
@@ -267,25 +254,14 @@ static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(respond_queue, &ftdi->respond_work,
- delta))
- return;
- } else if (queue_work(respond_queue, &ftdi->respond_work))
- return;
- kref_put(&ftdi->kref, ftdi_elan_delete);
- return;
+ if (!queue_delayed_work(respond_queue, &ftdi->respond_work, delta))
+ kref_put(&ftdi->kref, ftdi_elan_delete);
}
static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
{
- if (delta > 0) {
- if (queue_delayed_work(respond_queue, &ftdi->respond_work,
- delta))
- kref_get(&ftdi->kref);
- } else if (queue_work(respond_queue, &ftdi->respond_work))
- kref_get(&ftdi->kref);
- return;
+ if (queue_delayed_work(respond_queue, &ftdi->respond_work, delta))
+ kref_get(&ftdi->kref);
}
static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
@@ -303,7 +279,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
-void ftdi_release_platform_dev(struct device *dev)
+static void ftdi_release_platform_dev(struct device *dev)
{
dev->parent = NULL;
}
@@ -475,9 +451,11 @@ static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
return;
}
-static void ftdi_elan_command_work(void *data)
+static void ftdi_elan_command_work(struct work_struct *work)
{
- struct usb_ftdi *ftdi = data;
+ struct usb_ftdi *ftdi =
+ container_of(work, struct usb_ftdi, command_work.work);
+
if (ftdi->disconnected > 0) {
ftdi_elan_put_kref(ftdi);
return;
@@ -500,9 +478,10 @@ static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
return;
}
-static void ftdi_elan_respond_work(void *data)
+static void ftdi_elan_respond_work(struct work_struct *work)
{
- struct usb_ftdi *ftdi = data;
+ struct usb_ftdi *ftdi =
+ container_of(work, struct usb_ftdi, respond_work.work);
if (ftdi->disconnected > 0) {
ftdi_elan_put_kref(ftdi);
return;
@@ -534,9 +513,10 @@ static void ftdi_elan_respond_work(void *data)
* after the FTDI has been synchronized
*
*/
-static void ftdi_elan_status_work(void *data)
+static void ftdi_elan_status_work(struct work_struct *work)
{
- struct usb_ftdi *ftdi = data;
+ struct usb_ftdi *ftdi =
+ container_of(work, struct usb_ftdi, status_work.work);
int work_delay_in_msec = 0;
if (ftdi->disconnected > 0) {
ftdi_elan_put_kref(ftdi);
@@ -578,7 +558,7 @@ static void ftdi_elan_status_work(void *data)
} else {
dev_err(&ftdi->udev->dev, "initialized failed - trying "
"again in 10 seconds\n");
- work_delay_in_msec = 10 *1000;
+ work_delay_in_msec = 1 *1000;
}
} else if (ftdi->registered == 0) {
work_delay_in_msec = 10;
@@ -1426,14 +1406,6 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
}
}
-int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
-{
- struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
- return ftdi_elan_read_reg(ftdi, data);
-}
-
-
-EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
u8 width, u32 *data)
{
@@ -2323,82 +2295,288 @@ static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
}
}
-static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+
+#define ftdi_read_pcimem(ftdi, member, data) ftdi_elan_read_pcimem(ftdi, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define ftdi_write_pcimem(ftdi, member, data) ftdi_elan_write_pcimem(ftdi, \
+ offsetof(struct ohci_regs, member), 0, data);
+#define OHCI_QUIRK_AMD756 0x01
+#define OHCI_QUIRK_SUPERIO 0x02
+#define OHCI_QUIRK_INITRESET 0x04
+#define OHCI_BIG_ENDIAN 0x08
+#define OHCI_QUIRK_ZFMICRO 0x10
+#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+ OHCI_INTR_WDH)
+static int ftdi_elan_check_controller(struct usb_ftdi *ftdi, int quirk)
+{
+ int devices = 0;
+ int retval;
+ u32 hc_control;
+ int num_ports;
+ u32 control;
+ u32 rh_a = -1;
+ u32 status;
+ u32 fminterval;
+ u32 hc_fminterval;
+ u32 periodicstart;
+ u32 cmdstatus;
+ u32 roothub_a;
+ int mask = OHCI_INTR_INIT;
+ int sleep_time = 0;
+ int reset_timeout = 30; /* ... allow extra time */
+ int temp;
+ retval = ftdi_write_pcimem(ftdi, intrdisable, OHCI_INTR_MIE);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &rh_a);
+ if (retval)
+ return retval;
+ num_ports = rh_a & RH_A_NDP;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &hc_fminterval);
+ if (retval)
+ return retval;
+ hc_fminterval &= 0x3fff;
+ if (hc_fminterval != FI) {
+ }
+ hc_fminterval |= FSMP(hc_fminterval) << 16;
+ retval = ftdi_read_pcimem(ftdi, control, &hc_control);
+ if (retval)
+ return retval;
+ switch (hc_control & OHCI_CTRL_HCFS) {
+ case OHCI_USB_OPER:
+ sleep_time = 0;
+ break;
+ case OHCI_USB_SUSPEND:
+ case OHCI_USB_RESUME:
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_USB_RESUME;
+ sleep_time = 10;
+ break;
+ default:
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_USB_RESET;
+ sleep_time = 50;
+ break;
+ }
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ msleep(sleep_time);
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
+ if (retval)
+ return retval;
+ if (!(roothub_a & RH_A_NPS)) { /* power down each port */
+ for (temp = 0; temp < num_ports; temp++) {
+ retval = ftdi_write_pcimem(ftdi,
+ roothub.portstatus[temp], RH_PS_LSDA);
+ if (retval)
+ return retval;
+ }
+ }
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retry:retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_HCR);
+ if (retval)
+ return retval;
+ extra:{
+ retval = ftdi_read_pcimem(ftdi, cmdstatus, &status);
+ if (retval)
+ return retval;
+ if (0 != (status & OHCI_HCR)) {
+ if (--reset_timeout == 0) {
+ dev_err(&ftdi->udev->dev, "USB HC reset timed o"
+ "ut!\n");
+ return -ENODEV;
+ } else {
+ msleep(5);
+ goto extra;
+ }
+ }
+ }
+ if (quirk & OHCI_QUIRK_INITRESET) {
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ }
+ retval = ftdi_write_pcimem(ftdi, ed_controlhead, 0x00000000);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, ed_bulkhead, 0x11000000);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, hcca, 0x00000000);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, fminterval,
+ ((fminterval & FIT) ^ FIT) | hc_fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, periodicstart,
+ ((9 *hc_fminterval) / 10) & 0x3fff);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, fminterval, &fminterval);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, periodicstart, &periodicstart);
+ if (retval)
+ return retval;
+ if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+ if (!(quirk & OHCI_QUIRK_INITRESET)) {
+ quirk |= OHCI_QUIRK_INITRESET;
+ goto retry;
+ } else
+ dev_err(&ftdi->udev->dev, "init err(%08x %04x)\n",
+ fminterval, periodicstart);
+ } /* start controller operations */
+ hc_control &= OHCI_CTRL_RWC;
+ hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+ retval = ftdi_write_pcimem(ftdi, control, hc_control);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, cmdstatus, OHCI_BLF);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, cmdstatus, &cmdstatus);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_DRWE);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, intrstatus, mask);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, intrdisable,
+ OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+ OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+ OHCI_INTR_SO);
+ if (retval)
+ return retval; /* handle root hub init quirks ... */
+ retval = ftdi_read_pcimem(ftdi, roothub.a, &roothub_a);
+ if (retval)
+ return retval;
+ roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+ if (quirk & OHCI_QUIRK_SUPERIO) {
+ roothub_a |= RH_A_NOCP;
+ roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+ retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
+ if (retval)
+ return retval;
+ } else if ((quirk & OHCI_QUIRK_AMD756) || distrust_firmware) {
+ roothub_a |= RH_A_NPS;
+ retval = ftdi_write_pcimem(ftdi, roothub.a, roothub_a);
+ if (retval)
+ return retval;
+ }
+ retval = ftdi_write_pcimem(ftdi, roothub.status, RH_HS_LPSC);
+ if (retval)
+ return retval;
+ retval = ftdi_write_pcimem(ftdi, roothub.b,
+ (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+ if (retval)
+ return retval;
+ retval = ftdi_read_pcimem(ftdi, control, &control);
+ if (retval)
+ return retval;
+ mdelay((roothub_a >> 23) & 0x1fe);
+ for (temp = 0; temp < num_ports; temp++) {
+ u32 portstatus;
+ retval = ftdi_read_pcimem(ftdi, roothub.portstatus[temp],
+ &portstatus);
+ if (retval)
+ return retval;
+ if (1 & portstatus)
+ devices += 1;
+ }
+ return devices;
+}
+
+static int ftdi_elan_setup_controller(struct usb_ftdi *ftdi, int fn)
{
u32 latence_timer;
- u32 controlreg;
int UxxxStatus;
u32 pcidata;
int reg = 0;
- int foundOHCI = 0;
- u8 fn;
- int activePCIfn = 0;
- u32 pciVID = 0;
- u32 pciPID = 0;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
- if (UxxxStatus)
- return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
- if (UxxxStatus)
- return UxxxStatus;
- msleep(750);
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+ int activePCIfn = fn << 8;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+ reg = 16;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+ 0xFFFFFFFF);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+ 0xF0000000);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- msleep(250);
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+ reg = 12;
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &latence_timer);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ latence_timer &= 0xFFFF00FF;
+ latence_timer |= 0x00001600;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+ latence_timer);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ reg = 4;
+ UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+ 0x06);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
if (UxxxStatus)
return UxxxStatus;
- msleep(1000);
- for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
- activePCIfn = fn << 8;
- ftdi->function = fn + 1;
- UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
- &pcidata);
+ for (reg = 0; reg <= 0x54; reg += 4) {
+ UxxxStatus = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
if (UxxxStatus)
return UxxxStatus;
- pciVID = pcidata & 0xFFFF;
- pciPID = (pcidata >> 16) & 0xFFFF;
- if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
- foundOHCI = 1;
- } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
- }
}
- if (foundOHCI == 0) {
- return -ENXIO;
- }
- ftdi->platform_data.vendor = pciVID;
- ftdi->platform_data.device = pciPID;
+ return 0;
+}
+
+static int ftdi_elan_close_controller(struct usb_ftdi *ftdi, int fn)
+{
+ u32 latence_timer;
+ int UxxxStatus;
+ u32 pcidata;
+ int reg = 0;
+ int activePCIfn = fn << 8;
UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
if (UxxxStatus)
return UxxxStatus;
@@ -2412,7 +2590,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
- 0xF0000000);
+ 0x00000000);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
@@ -2436,7 +2614,7 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
return UxxxStatus;
reg = 4;
UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
- 0x06);
+ 0x00);
if (UxxxStatus)
return UxxxStatus;
UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
@@ -2446,159 +2624,139 @@ static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
return 0;
}
+static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
+{
+ int result;
+ int UxxxStatus;
+ UxxxStatus = ftdi_elan_setup_controller(ftdi, fn);
+ if (UxxxStatus)
+ return UxxxStatus;
+ result = ftdi_elan_check_controller(ftdi, quirk);
+ UxxxStatus = ftdi_elan_close_controller(ftdi, fn);
+ if (UxxxStatus)
+ return UxxxStatus;
+ return result;
+}
+
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+{
+ u32 controlreg;
+ u8 sensebits;
+ int UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(750);
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(250);
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+ if (UxxxStatus)
+ return UxxxStatus;
+ msleep(1000);
+ sensebits = (controlreg >> 16) & 0x000F;
+ if (0x0D == sensebits)
+ return 0;
+ else
+ return - ENXIO;
+}
+
static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
{
+ int UxxxStatus;
u32 pcidata;
- int U132Status;
- int reg;
- int reset_repeat = 0;
- do_reset:reg = 8;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
- if (U132Status)
- return U132Status;
- reset_check:{
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- if (pcidata & 1) {
- msleep(500);
- if (reset_repeat++ > 100) {
- reset_repeat = 0;
- goto do_reset;
- } else
- goto reset_check;
+ int reg = 0;
+ u8 fn;
+ int activePCIfn = 0;
+ int max_devices = 0;
+ int controllers = 0;
+ int unrecognized = 0;
+ ftdi->function = 0;
+ for (fn = 0; (fn < 4); fn++) {
+ u32 pciVID = 0;
+ u32 pciPID = 0;
+ int devices = 0;
+ activePCIfn = fn << 8;
+ UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+ &pcidata);
+ if (UxxxStatus)
+ return UxxxStatus;
+ pciVID = pcidata & 0xFFFF;
+ pciPID = (pcidata >> 16) & 0xFFFF;
+ if ((pciVID == PCI_VENDOR_ID_OPTI) && (pciPID == 0xc861)) {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_NEC) && (pciPID == 0x0035))
+ {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_AL) && (pciPID == 0x5237)) {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if ((pciVID == PCI_VENDOR_ID_ATT) && (pciPID == 0x5802))
+ {
+ devices = ftdi_elan_found_controller(ftdi, fn, 0);
+ controllers += 1;
+ } else if (pciVID == PCI_VENDOR_ID_AMD && pciPID == 0x740c) {
+ devices = ftdi_elan_found_controller(ftdi, fn,
+ OHCI_QUIRK_AMD756);
+ controllers += 1;
+ } else if (pciVID == PCI_VENDOR_ID_COMPAQ && pciPID == 0xa0f8) {
+ devices = ftdi_elan_found_controller(ftdi, fn,
+ OHCI_QUIRK_ZFMICRO);
+ controllers += 1;
+ } else if (0 == pcidata) {
+ } else
+ unrecognized += 1;
+ if (devices > max_devices) {
+ max_devices = devices;
+ ftdi->function = fn + 1;
+ ftdi->platform_data.vendor = pciVID;
+ ftdi->platform_data.device = pciPID;
}
}
- goto dump_regs;
- msleep(500);
- reg = 0x28;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x40;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x34;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 4;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(250);
- reg = 8;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x28;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 8;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x48;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x34;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(100);
- reg = 0x50;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- if (!(pcidata & 1)) {
- msleep(500);
- goto power_check;
- }
- msleep(3000);
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x54;
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
- if (U132Status)
- return U132Status;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- msleep(750);
- reg = 0x54;
- if (0) {
- U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
- if (U132Status)
- return U132Status;
- }
- if (0) {
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- }
- reg = 0x54;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- reg = 0x58;
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
- dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
- U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
- if (U132Status)
- return U132Status;
+ if (ftdi->function > 0) {
+ UxxxStatus = ftdi_elan_setup_controller(ftdi,
+ ftdi->function - 1);
+ if (UxxxStatus)
+ return UxxxStatus;
+ return 0;
+ } else if (controllers > 0) {
+ return -ENXIO;
+ } else if (unrecognized > 0) {
+ return -ENXIO;
+ } else {
+ ftdi->enumerated = 0;
+ return -ENXIO;
}
- return 0;
}
@@ -2633,10 +2791,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (!ftdi->bulk_in_endpointAddr &&
- ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_IN) && ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
- {
+ usb_endpoint_is_bulk_in(endpoint)) {
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
ftdi->bulk_in_size = buffer_size;
ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
@@ -2649,10 +2804,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
}
}
if (!ftdi->bulk_out_endpointAddr &&
- ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- == USB_DIR_OUT) && ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
- {
+ usb_endpoint_is_bulk_out(endpoint)) {
ftdi->bulk_out_endpointAddr =
endpoint->bEndpointAddress;
}
@@ -2691,12 +2843,9 @@ static int ftdi_elan_probe(struct usb_interface *interface,
ftdi->class = NULL;
dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a"
"ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber);
- INIT_WORK(&ftdi->status_work, ftdi_elan_status_work,
- (void *)ftdi);
- INIT_WORK(&ftdi->command_work, ftdi_elan_command_work,
- (void *)ftdi);
- INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work,
- (void *)ftdi);
+ INIT_DELAYED_WORK(&ftdi->status_work, ftdi_elan_status_work);
+ INIT_DELAYED_WORK(&ftdi->command_work, ftdi_elan_command_work);
+ INIT_DELAYED_WORK(&ftdi->respond_work, ftdi_elan_respond_work);
ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
return 0;
} else {
@@ -2732,6 +2881,7 @@ static void ftdi_elan_disconnect(struct usb_interface *interface)
platform_device_unregister(&ftdi->platform_dev);
ftdi->synchronized = 0;
ftdi->enumerated = 0;
+ ftdi->initialized = 0;
ftdi->registered = 0;
}
flush_workqueue(status_queue);
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8e6e195a22ba..c9418535bef8 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex);
static int idmouse_create_image(struct usb_idmouse *dev)
{
- int bytes_read = 0;
- int bulk_read = 0;
- int result = 0;
+ int bytes_read;
+ int bulk_read;
+ int result;
memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1);
- bytes_read += sizeof(HEADER)-1;
+ bytes_read = sizeof(HEADER)-1;
/* reset the device and set a fast blink rate */
result = ftip_command(dev, FTIP_RELEASE, 0, 0);
@@ -208,9 +208,9 @@ static inline void idmouse_delete(struct usb_idmouse *dev)
static int idmouse_open(struct inode *inode, struct file *file)
{
- struct usb_idmouse *dev = NULL;
+ struct usb_idmouse *dev;
struct usb_interface *interface;
- int result = 0;
+ int result;
/* prevent disconnects */
mutex_lock(&disconnect_mutex);
@@ -305,7 +305,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
loff_t * ppos)
{
struct usb_idmouse *dev;
- int result = 0;
+ int result;
dev = (struct usb_idmouse *) file->private_data;
@@ -329,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
- struct usb_idmouse *dev = NULL;
+ struct usb_idmouse *dev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int result;
@@ -350,11 +350,7 @@ static int idmouse_probe(struct usb_interface *interface,
/* set up the endpoint information - use only the first bulk-in endpoint */
endpoint = &iface_desc->endpoint[0].desc;
- if (!dev->bulk_in_endpointAddr
- && (endpoint->bEndpointAddress & USB_DIR_IN)
- && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
-
+ if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
/* we found a bulk in endpoint */
dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = 0x200; /* works _much_ faster */
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 27089497e717..5dce797bddb7 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev)
tower_abort_transfers (dev);
/* free data structures */
- if (dev->interrupt_in_urb != NULL) {
- usb_free_urb (dev->interrupt_in_urb);
- }
- if (dev->interrupt_out_urb != NULL) {
- usb_free_urb (dev->interrupt_out_urb);
- }
+ usb_free_urb(dev->interrupt_in_urb);
+ usb_free_urb(dev->interrupt_out_urb);
kfree (dev->read_buffer);
kfree (dev->interrupt_in_buffer);
kfree (dev->interrupt_out_buffer);
@@ -502,15 +498,11 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0;
mb();
- if (dev->interrupt_in_urb != NULL && dev->udev) {
+ if (dev->udev)
usb_kill_urb (dev->interrupt_in_urb);
- }
- }
- if (dev->interrupt_out_busy) {
- if (dev->interrupt_out_urb != NULL && dev->udev) {
- usb_kill_urb (dev->interrupt_out_urb);
- }
}
+ if (dev->interrupt_out_busy && dev->udev)
+ usb_kill_urb(dev->interrupt_out_urb);
exit:
dbg(2, "%s: leave", __FUNCTION__);
@@ -898,14 +890,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
- if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- dev->interrupt_in_endpoint = endpoint;
- }
-
- if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
- ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
- dev->interrupt_out_endpoint = endpoint;
+ if (usb_endpoint_xfer_int(endpoint)) {
+ if (usb_endpoint_dir_in(endpoint))
+ dev->interrupt_in_endpoint = endpoint;
+ else
+ dev->interrupt_out_endpoint = endpoint;
}
}
if(dev->interrupt_in_endpoint == NULL) {
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index abb4dcd811ac..371bf2b1197d 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -81,8 +81,8 @@ struct interfacekit {
unsigned char *data;
dma_addr_t data_dma;
- struct work_struct do_notify;
- struct work_struct do_resubmit;
+ struct delayed_work do_notify;
+ struct delayed_work do_resubmit;
unsigned long input_events;
unsigned long sensor_events;
};
@@ -374,19 +374,20 @@ static void interfacekit_irq(struct urb *urb)
}
if (kit->input_events || kit->sensor_events)
- schedule_work(&kit->do_notify);
+ schedule_delayed_work(&kit->do_notify, 0);
resubmit:
- status = usb_submit_urb(urb, SLAB_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
err("can't resubmit intr, %s-%s/interfacekit0, status %d",
kit->udev->bus->bus_name,
kit->udev->devpath, status);
}
-static void do_notify(void *data)
+static void do_notify(struct work_struct *work)
{
- struct interfacekit *kit = data;
+ struct interfacekit *kit =
+ container_of(work, struct interfacekit, do_notify.work);
int i;
char sysfs_file[8];
@@ -405,9 +406,11 @@ static void do_notify(void *data)
}
}
-static void do_resubmit(void *data)
+static void do_resubmit(struct work_struct *work)
{
- set_outputs(data);
+ struct interfacekit *kit =
+ container_of(work, struct interfacekit, do_resubmit.work);
+ set_outputs(kit);
}
#define show_set_output(value) \
@@ -551,7 +554,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
* bmAttributes
@@ -565,7 +568,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
kit->dev_no = -1;
kit->ifkit = ifkit;
- kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
+ kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma);
if (!kit->data)
goto out;
@@ -575,8 +578,8 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
kit->udev = usb_get_dev(dev);
kit->intf = intf;
- INIT_WORK(&kit->do_notify, do_notify, kit);
- INIT_WORK(&kit->do_resubmit, do_resubmit, kit);
+ 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);
@@ -650,8 +653,7 @@ out2:
device_remove_file(kit->dev, &dev_output_attrs[i]);
out:
if (kit) {
- if (kit->irq)
- usb_free_urb(kit->irq);
+ usb_free_urb(kit->irq);
if (kit->data)
usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
if (kit->dev)
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
index 5c780cab92e0..5727e1ea2f91 100644
--- a/drivers/usb/misc/phidgetmotorcontrol.c
+++ b/drivers/usb/misc/phidgetmotorcontrol.c
@@ -41,7 +41,7 @@ struct motorcontrol {
unsigned char *data;
dma_addr_t data_dma;
- struct work_struct do_notify;
+ struct delayed_work do_notify;
unsigned long input_events;
unsigned long speed_events;
unsigned long exceed_events;
@@ -148,10 +148,10 @@ static void motorcontrol_irq(struct urb *urb)
set_bit(1, &mc->exceed_events);
if (mc->input_events || mc->exceed_events || mc->speed_events)
- schedule_work(&mc->do_notify);
+ schedule_delayed_work(&mc->do_notify, 0);
resubmit:
- status = usb_submit_urb(urb, SLAB_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status)
dev_err(&mc->intf->dev,
"can't resubmit intr, %s-%s/motorcontrol0, status %d",
@@ -159,9 +159,10 @@ resubmit:
mc->udev->devpath, status);
}
-static void do_notify(void *data)
+static void do_notify(struct work_struct *work)
{
- struct motorcontrol *mc = data;
+ struct motorcontrol *mc =
+ container_of(work, struct motorcontrol, do_notify.work);
int i;
char sysfs_file[8];
@@ -323,7 +324,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV;
endpoint = &interface->endpoint[0].desc;
- if (!(endpoint->bEndpointAddress & 0x80))
+ if (!usb_endpoint_dir_in(endpoint))
return -ENODEV;
/*
@@ -337,7 +338,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
goto out;
mc->dev_no = -1;
- mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
+ mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma);
if (!mc->data)
goto out;
@@ -348,7 +349,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
mc->udev = usb_get_dev(dev);
mc->intf = intf;
mc->acceleration[0] = mc->acceleration[1] = 10;
- INIT_WORK(&mc->do_notify, do_notify, mc);
+ 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);
@@ -392,8 +393,7 @@ out2:
device_remove_file(mc->dev, &dev_attrs[i]);
out:
if (mc) {
- if (mc->irq)
- usb_free_urb(mc->irq);
+ usb_free_urb(mc->irq);
if (mc->data)
usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
if (mc->dev)
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 7163f05c5b27..0d9de2f73930 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -282,6 +282,7 @@ servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
dev->dev = NULL;
goto out;
}
+ dev_set_drvdata(dev->dev, dev);
servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index b99ca9c79821..0398908b15d4 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3168,7 +3168,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case SISUSB_GET_CONFIG:
case SISUSB_COMMAND:
lock_kernel();
- retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+ retval = sisusb_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
unlock_kernel();
return retval;
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index bf26c3c56990..9148694627d5 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -403,7 +403,7 @@ sisusbcon_putc(struct vc_data *c, int ch, int y, int x)
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), 2, &written);
+ (long)SISUSB_HADDR(x, y), 2, &written);
mutex_unlock(&sisusb->lock);
}
@@ -438,7 +438,7 @@ sisusbcon_putcs(struct vc_data *c, const unsigned short *s,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), count * 2, &written);
+ (long)SISUSB_HADDR(x, y), count * 2, &written);
mutex_unlock(&sisusb->lock);
}
@@ -492,7 +492,7 @@ sisusbcon_clear(struct vc_data *c, int y, int x, int height, int width)
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
- (u32)SISUSB_HADDR(x, y), length, &written);
+ (long)SISUSB_HADDR(x, y), length, &written);
mutex_unlock(&sisusb->lock);
}
@@ -564,7 +564,7 @@ sisusbcon_bmove(struct vc_data *c, int sy, int sx,
sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
- (u32)SISUSB_HADDR(dx, dy), length, &written);
+ (long)SISUSB_HADDR(dx, dy), length, &written);
mutex_unlock(&sisusb->lock);
}
@@ -612,7 +612,7 @@ sisusbcon_switch(struct vc_data *c)
length);
sisusb_copy_memory(sisusb, (unsigned char *)c->vc_origin,
- (u32)SISUSB_HADDR(0, 0),
+ (long)SISUSB_HADDR(0, 0),
length, &written);
mutex_unlock(&sisusb->lock);
@@ -939,7 +939,7 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb,
}
sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
- (u32)SISUSB_HADDR(0, t), length, &written);
+ (long)SISUSB_HADDR(0, t), length, &written);
mutex_unlock(&sisusb->lock);
diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c
index 33cd91d11eca..67e2fc20eeeb 100644
--- a/drivers/usb/misc/trancevibrator.c
+++ b/drivers/usb/misc/trancevibrator.c
@@ -120,8 +120,8 @@ static void tv_disconnect(struct usb_interface *interface)
struct trancevibrator *dev;
dev = usb_get_intfdata (interface);
- usb_set_intfdata(interface, NULL);
device_remove_file(&interface->dev, &dev_attr_speed);
+ usb_set_intfdata(interface, NULL);
usb_put_dev(dev->udev);
kfree(dev);
}
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
index 551ba8906d62..dc2e5a31caec 100644
--- a/drivers/usb/misc/usb_u132.h
+++ b/drivers/usb/misc/usb_u132.h
@@ -52,7 +52,7 @@
* the kernel to load the "u132-hcd" module.
*
* The "ftdi-u132" module provides the interface to the inserted
-* PC card and the "u132-hcd" module uses the API to send and recieve
+* PC card and the "u132-hcd" module uses the API to send and receive
* data. The API features call-backs, so that part of the "u132-hcd"
* module code will run in the context of one of the kernel threads
* of the "ftdi-u132" module.
@@ -95,3 +95,7 @@ int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
int halted, int skipped, int actual, int non_null));
int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
void *endp);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+ u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+ u8 width, u32 data);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 7c2cbdf81d20..fb321864a92d 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
default:
continue;
}
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!in)
in = e;
} else {
@@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
}
continue;
try_iso:
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!iso_in)
iso_in = e;
} else {
@@ -213,7 +213,7 @@ static struct urb *simple_alloc_urb (
if (bytes < 0)
return NULL;
- urb = usb_alloc_urb (0, SLAB_KERNEL);
+ urb = usb_alloc_urb (0, GFP_KERNEL);
if (!urb)
return urb;
usb_fill_bulk_urb (urb, udev, pipe, NULL, bytes, simple_callback, NULL);
@@ -223,7 +223,7 @@ static struct urb *simple_alloc_urb (
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
if (usb_pipein (pipe))
urb->transfer_flags |= URB_SHORT_NOT_OK;
- urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL,
+ urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL,
&urb->transfer_dma);
if (!urb->transfer_buffer) {
usb_free_urb (urb);
@@ -315,7 +315,7 @@ static int simple_io (
init_completion (&completion);
if (usb_pipeout (urb->pipe))
simple_fill_buf (urb);
- if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0)
+ if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0)
break;
/* NOTE: no timeouts; can't be broken out of by interrupt */
@@ -374,7 +374,7 @@ alloc_sglist (int nents, int max, int vary)
unsigned i;
unsigned size = max;
- sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL);
+ sg = kmalloc (nents * sizeof *sg, GFP_KERNEL);
if (!sg)
return NULL;
@@ -382,7 +382,7 @@ alloc_sglist (int nents, int max, int vary)
char *buf;
unsigned j;
- buf = kzalloc (size, SLAB_KERNEL);
+ buf = kzalloc (size, GFP_KERNEL);
if (!buf) {
free_sglist (sg, i);
return NULL;
@@ -428,7 +428,7 @@ static int perform_sglist (
(udev->speed == USB_SPEED_HIGH)
? (INTERRUPT_RATE << 3)
: INTERRUPT_RATE,
- sg, nents, 0, SLAB_KERNEL);
+ sg, nents, 0, GFP_KERNEL);
if (retval)
break;
@@ -819,7 +819,7 @@ error:
/* resubmit if we need to, else mark this as done */
if ((status == 0) && (ctx->pending < ctx->count)) {
- if ((status = usb_submit_urb (urb, SLAB_ATOMIC)) != 0) {
+ if ((status = usb_submit_urb (urb, GFP_ATOMIC)) != 0) {
dbg ("can't resubmit ctrl %02x.%02x, err %d",
reqp->bRequestType, reqp->bRequest, status);
urb->dev = NULL;
@@ -855,7 +855,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
* as with bulk/intr sglists, sglen is the queue depth; it also
* controls which subtests run (more tests than sglen) or rerun.
*/
- urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL);
+ urb = kcalloc(param->sglen, sizeof(struct urb *), GFP_KERNEL);
if (!urb)
return -ENOMEM;
for (i = 0; i < param->sglen; i++) {
@@ -981,7 +981,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
if (!u)
goto cleanup;
- reqp = usb_buffer_alloc (udev, sizeof *reqp, SLAB_KERNEL,
+ reqp = usb_buffer_alloc (udev, sizeof *reqp, GFP_KERNEL,
&u->setup_dma);
if (!reqp)
goto cleanup;
@@ -999,7 +999,7 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
context.urb = urb;
spin_lock_irq (&context.lock);
for (i = 0; i < param->sglen; i++) {
- context.status = usb_submit_urb (urb [i], SLAB_ATOMIC);
+ context.status = usb_submit_urb (urb [i], GFP_ATOMIC);
if (context.status != 0) {
dbg ("can't submit urb[%d], status %d",
i, context.status);
@@ -1041,7 +1041,7 @@ static void unlink1_callback (struct urb *urb)
// we "know" -EPIPE (stall) never happens
if (!status)
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status) {
urb->status = status;
complete ((struct completion *) urb->context);
@@ -1067,7 +1067,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
* FIXME want additional tests for when endpoint is STALLing
* due to errors, or is just NAKing requests.
*/
- if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) {
+ if ((retval = usb_submit_urb (urb, GFP_KERNEL)) != 0) {
dev_dbg (&dev->intf->dev, "submit fail %d\n", retval);
return retval;
}
@@ -1251,7 +1251,7 @@ static int ctrl_out (struct usbtest_dev *dev,
if (length < 1 || length > 0xffff || vary >= length)
return -EINVAL;
- buf = kmalloc(length, SLAB_KERNEL);
+ buf = kmalloc(length, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -1403,7 +1403,7 @@ static struct urb *iso_alloc_urb (
maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
packets = (bytes + maxp - 1) / maxp;
- urb = usb_alloc_urb (packets, SLAB_KERNEL);
+ urb = usb_alloc_urb (packets, GFP_KERNEL);
if (!urb)
return urb;
urb->dev = udev;
@@ -1411,7 +1411,7 @@ static struct urb *iso_alloc_urb (
urb->number_of_packets = packets;
urb->transfer_buffer_length = bytes;
- urb->transfer_buffer = usb_buffer_alloc (udev, bytes, SLAB_KERNEL,
+ urb->transfer_buffer = usb_buffer_alloc (udev, bytes, GFP_KERNEL,
&urb->transfer_dma);
if (!urb->transfer_buffer) {
usb_free_urb (urb);
@@ -1481,7 +1481,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
spin_lock_irq (&context.lock);
for (i = 0; i < param->sglen; i++) {
++context.pending;
- status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
+ status = usb_submit_urb (urbs [i], GFP_ATOMIC);
if (status < 0) {
ERROR (dev, "submit iso[%d], error %d\n", i, status);
if (i == 0) {
@@ -1900,7 +1900,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
}
#endif
- dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
info = (struct usbtest_info *) id->driver_info;
@@ -1910,7 +1910,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
dev->intf = intf;
/* cacheline-aligned scratch for i/o */
- if ((dev->buf = kmalloc (TBUF_SIZE, SLAB_KERNEL)) == NULL) {
+ if ((dev->buf = kmalloc (TBUF_SIZE, GFP_KERNEL)) == NULL) {
kfree (dev);
return -ENOMEM;
}
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 7e8a0acd52ee..70250252ae2a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -705,7 +705,7 @@ static int uss720_probe(struct usb_interface *intf,
/*
* Allocate parport interface
*/
- if (!(priv = kcalloc(sizeof(struct parport_uss720_private), 1, GFP_KERNEL))) {
+ if (!(priv = kzalloc(sizeof(struct parport_uss720_private), GFP_KERNEL))) {
usb_put_dev(usbdev);
return -ENOMEM;
}
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 7a2346c53284..05cf2c9a8f84 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -50,7 +50,7 @@ struct mon_event_text {
#define SLAB_NAME_SZ 30
struct mon_reader_text {
- kmem_cache_t *e_slab;
+ struct kmem_cache *e_slab;
int nevents;
struct list_head e_list;
struct mon_reader r; /* In C, parent class can be placed anywhere */
@@ -63,7 +63,7 @@ struct mon_reader_text {
char slab_name[SLAB_NAME_SZ];
};
-static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
+static void mon_text_ctor(void *, struct kmem_cache *, unsigned long);
/*
* mon_text_submit
@@ -147,7 +147,7 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
stamp = mon_get_timestamp();
if (rp->nevents >= EVENT_MAX ||
- (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+ (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
rp->r.m_bus->cnt_text_lost++;
return;
}
@@ -188,7 +188,7 @@ static void mon_text_error(void *data, struct urb *urb, int error)
struct mon_event_text *ep;
if (rp->nevents >= EVENT_MAX ||
- (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+ (ep = kmem_cache_alloc(rp->e_slab, GFP_ATOMIC)) == NULL) {
rp->r.m_bus->cnt_text_lost++;
return;
}
@@ -450,7 +450,7 @@ const struct file_operations mon_fops_text = {
/*
* Slab interface: constructor.
*/
-static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+static void mon_text_ctor(void *mem, struct kmem_cache *slab, unsigned long sflags)
{
/*
* Nothing to initialize. No, really!
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 881841e600de..f538013965b0 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -249,9 +249,9 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req->bRequest = cmd;
- req->wValue = value;
- req->wIndex = index;
- req->wLength = size;
+ req->wValue = cpu_to_le16(value);
+ req->wIndex = cpu_to_le16(index);
+ req->wLength = cpu_to_le16(size);
usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0),
@@ -920,7 +920,7 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
goto out2;
if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
- 0x0000, 0, 0, buf)) < 0) {
+ 1, 0, 0, buf)) < 0) {
dbg("Select PHY #1 failed: %d", ret);
goto out2;
}
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index f740325abac4..4852012735f6 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -345,7 +345,7 @@ static void catc_irq_done(struct urb *urb)
}
}
resubmit:
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s, status %d",
catc->usbdev->bus->bus_name,
@@ -786,14 +786,10 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
- if (catc->ctrl_urb)
- usb_free_urb(catc->ctrl_urb);
- if (catc->tx_urb)
- usb_free_urb(catc->tx_urb);
- if (catc->rx_urb)
- usb_free_urb(catc->rx_urb);
- if (catc->irq_urb)
- usb_free_urb(catc->irq_urb);
+ usb_free_urb(catc->ctrl_urb);
+ usb_free_urb(catc->tx_urb);
+ usb_free_urb(catc->rx_urb);
+ usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return -ENOMEM;
}
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index f6971b88349d..44a91547146e 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -200,8 +200,7 @@ next_desc:
dev->status = &info->control->cur_altsetting->endpoint [0];
desc = &dev->status->desc;
- if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
- || !(desc->bEndpointAddress & USB_DIR_IN)
+ if (!usb_endpoint_is_int_in(desc)
|| (le16_to_cpu(desc->wMaxPacketSize)
< sizeof(struct usb_cdc_notification))
|| !desc->bInterval) {
diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c
index a3242be21959..a6f0f4d934df 100644
--- a/drivers/usb/net/gl620a.c
+++ b/drivers/usb/net/gl620a.c
@@ -79,160 +79,6 @@ struct gl_header {
struct gl_packet packets;
};
-#ifdef GENELINK_ACK
-
-// FIXME: this code is incomplete, not debugged; it doesn't
-// handle interrupts correctly; it should use the generic
-// status IRQ code (which didn't exist back in 2001).
-
-struct gl_priv {
- struct urb *irq_urb;
- char irq_buf [INTERRUPT_BUFSIZE];
-};
-
-static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value)
-{
- int retval;
-
- retval = usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- request,
- USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- value,
- 0, // index
- 0, // data buffer
- 0, // size
- USB_CTRL_SET_TIMEOUT);
- return retval;
-}
-
-static void gl_interrupt_complete(struct urb *urb)
-{
- int status = urb->status;
-
- switch (status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, status);
- return;
- default:
- dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
- }
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
- err("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
-}
-
-static int gl_interrupt_read(struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
- int retval;
-
- // issue usb interrupt read
- if (priv && priv->irq_urb) {
- // submit urb
- if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0)
- dbg("gl_interrupt_read: submit fail - %X...", retval);
- else
- dbg("gl_interrupt_read: submit success...");
- }
-
- return 0;
-}
-
-// check whether another side is connected
-static int genelink_check_connect(struct usbnet *dev)
-{
- int retval;
-
- dbg("genelink_check_connect...");
-
- // detect whether another side is connected
- if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) {
- dbg("%s: genelink_check_connect write fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- // usb interrupt read to ack another side
- if ((retval = gl_interrupt_read(dev)) != 0) {
- dbg("%s: genelink_check_connect read fail - %X",
- dev->net->name, retval);
- return retval;
- }
-
- dbg("%s: genelink_check_connect read success", dev->net->name);
- return 0;
-}
-
-// allocate and initialize the private data for genelink
-static int genelink_init(struct usbnet *dev)
-{
- struct gl_priv *priv;
-
- // allocate the private data structure
- if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) {
- dbg("%s: cannot allocate private data per device",
- dev->net->name);
- return -ENOMEM;
- }
-
- // allocate irq urb
- if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) {
- dbg("%s: cannot allocate private irq urb per device",
- dev->net->name);
- kfree(priv);
- return -ENOMEM;
- }
-
- // fill irq urb
- usb_fill_int_urb(priv->irq_urb, dev->udev,
- usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE),
- priv->irq_buf, INTERRUPT_BUFSIZE,
- gl_interrupt_complete, 0,
- GENELINK_INTERRUPT_INTERVAL);
-
- // set private data pointer
- dev->priv_data = priv;
-
- return 0;
-}
-
-// release the private data
-static int genelink_free(struct usbnet *dev)
-{
- struct gl_priv *priv = dev->priv_data;
-
- if (!priv)
- return 0;
-
-// FIXME: can't cancel here; it's synchronous, and
-// should have happened earlier in any case (interrupt
-// handling needs to be generic)
-
- // cancel irq urb first
- usb_kill_urb(priv->irq_urb);
-
- // free irq urb
- usb_free_urb(priv->irq_urb);
-
- // free the private data structure
- kfree(priv);
-
- return 0;
-}
-
-#endif
-
static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
struct gl_header *header;
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 7c906a43e497..fa78326d0bf0 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -222,7 +222,7 @@ struct kaweth_device
int suspend_lowmem_ctrl;
int linkstate;
int opened;
- struct work_struct lowmem_work;
+ struct delayed_work lowmem_work;
struct usb_device *dev;
struct net_device *net;
@@ -530,9 +530,10 @@ resubmit:
kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC);
}
-static void kaweth_resubmit_tl(void *d)
+static void kaweth_resubmit_tl(struct work_struct *work)
{
- struct kaweth_device *kaweth = (struct kaweth_device *)d;
+ struct kaweth_device *kaweth =
+ container_of(work, struct kaweth_device, lowmem_work.work);
if (IS_BLOCKED(kaweth->status))
return;
@@ -1126,7 +1127,7 @@ err_fw:
/* kaweth is zeroed as part of alloc_netdev */
- INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth);
+ INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl);
SET_MODULE_OWNER(netdev);
diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c
index ce00de8f13a1..493635954513 100644
--- a/drivers/usb/net/net1080.c
+++ b/drivers/usb/net/net1080.c
@@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
#define STATUS_CONN_OTHER (1 << 14)
#define STATUS_SUSPEND_OTHER (1 << 13)
#define STATUS_MAILBOX_OTHER (1 << 12)
-#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03)
+#define STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03)
#define STATUS_CONN_THIS (1 << 6)
#define STATUS_SUSPEND_THIS (1 << 5)
#define STATUS_MAILBOX_THIS (1 << 4)
-#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03)
+#define STATUS_PACKETS_THIS(n) (((n) >> 0) & 0x03)
#define STATUS_UNSPEC_MASK 0x0c8c
#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
@@ -383,7 +383,7 @@ static void nc_ensure_sync(struct usbnet *dev)
int status;
/* Send a flush */
- urb = usb_alloc_urb(0, SLAB_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return;
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 33abbd2176b6..d48c024cff59 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -163,6 +163,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
/* using ATOMIC, we'd never wake up if we slept */
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+ set_current_state(TASK_RUNNING);
if (ret == -ENODEV)
netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus))
@@ -855,7 +856,7 @@ static void intr_callback(struct urb *urb)
pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
}
- status = usb_submit_urb(urb, SLAB_ATOMIC);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
if (status == -ENODEV)
netif_device_detach(pegasus->net);
if (status && netif_msg_timer(pegasus))
@@ -1280,9 +1281,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
static struct workqueue_struct *pegasus_workqueue = NULL;
#define CARRIER_CHECK_DELAY (2 * HZ)
-static void check_carrier(void *data)
+static void check_carrier(struct work_struct *work)
{
- pegasus_t *pegasus = data;
+ pegasus_t *pegasus = container_of(work, pegasus_t, carrier_check.work);
set_carrier(pegasus->net);
if (!(pegasus->flags & PEGASUS_UNPLUG)) {
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
@@ -1318,7 +1319,7 @@ static int pegasus_probe(struct usb_interface *intf,
tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
- INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
+ INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
pegasus->intf = intf;
pegasus->usb = dev;
diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
index 006438069b66..98f6898cae1f 100644
--- a/drivers/usb/net/pegasus.h
+++ b/drivers/usb/net/pegasus.h
@@ -95,7 +95,7 @@ typedef struct pegasus {
int dev_index;
int intr_interval;
struct tasklet_struct rx_tl;
- struct work_struct carrier_check;
+ struct delayed_work carrier_check;
struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
struct sk_buff *rx_pool[RX_SKBS];
struct sk_buff *rx_skb;
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index c2a28d88ef3c..ea5f44de3de2 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -469,7 +469,7 @@ static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf)
struct rndis_halt *halt;
/* try to clear any rndis state/activity (no i/o from stack!) */
- halt = kcalloc(1, sizeof *halt, SLAB_KERNEL);
+ halt = kzalloc(sizeof *halt, GFP_KERNEL);
if (halt) {
halt->msg_type = RNDIS_MSG_HALT;
halt->msg_len = ccpu2(sizeof *halt);
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index 72171f94ded4..e0eecda78ec1 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -124,10 +124,11 @@
#define RX_URB_FAIL 3
/* Define these values to match your device */
-#define VENDOR_ID_REALTEK 0x0bda
+#define VENDOR_ID_REALTEK 0x0bda
#define VENDOR_ID_MELCO 0x0411
-#define VENDOR_ID_MICRONET 0x3980
+#define VENDOR_ID_MICRONET 0x3980
#define VENDOR_ID_LONGSHINE 0x07b8
+#define VENDOR_ID_OQO 0x1557
#define VENDOR_ID_ZYXEL 0x0586
#define PRODUCT_ID_RTL8150 0x8150
@@ -144,6 +145,7 @@ static struct usb_device_id rtl8150_table[] = {
{USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)},
{USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)},
{USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)},
+ {USB_DEVICE(VENDOR_ID_OQO, PRODUCT_ID_RTL8150)},
{USB_DEVICE(VENDOR_ID_ZYXEL, PRODUCT_ID_PRESTIGE)},
{}
};
@@ -587,7 +589,7 @@ static void intr_callback(struct urb *urb)
}
resubmit:
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status == -ENODEV)
netif_device_detach(dev->netdev);
else if (status)
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 760b5327b81b..6e39e9988259 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
e = alt->endpoint + ep;
switch (e->desc.bmAttributes) {
case USB_ENDPOINT_XFER_INT:
- if (!(e->desc.bEndpointAddress & USB_DIR_IN))
+ if (!usb_endpoint_dir_in(&e->desc))
continue;
intr = 1;
/* FALLTHROUGH */
@@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
default:
continue;
}
- if (e->desc.bEndpointAddress & USB_DIR_IN) {
+ if (usb_endpoint_dir_in(&e->desc)) {
if (!intr && !in)
in = e;
else if (intr && !status)
@@ -179,9 +179,9 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
period = max ((int) dev->status->desc.bInterval,
(dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
- buf = kmalloc (maxp, SLAB_KERNEL);
+ buf = kmalloc (maxp, GFP_KERNEL);
if (buf) {
- dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL);
+ dev->interrupt = usb_alloc_urb (0, GFP_KERNEL);
if (!dev->interrupt) {
kfree (buf);
return -ENOMEM;
@@ -782,9 +782,10 @@ static struct ethtool_ops usbnet_ethtool_ops = {
* especially now that control transfers can be queued.
*/
static void
-kevent (void *data)
+kevent (struct work_struct *work)
{
- struct usbnet *dev = data;
+ struct usbnet *dev =
+ container_of(work, struct usbnet, kevent);
int status;
/* usb_clear_halt() needs a thread context */
@@ -1146,7 +1147,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
skb_queue_head_init (&dev->done);
dev->bh.func = usbnet_bh;
dev->bh.data = (unsigned long) dev;
- INIT_WORK (&dev->kevent, kevent, dev);
+ INIT_WORK (&dev->kevent, kevent);
dev->delay.function = usbnet_bh;
dev->delay.data = (unsigned long) dev;
init_timer (&dev->delay);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 2a8dd4cc943d..2f4d303ee36f 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET
To compile this driver as a module, choose M here: the
module will be called omninet.
+config USB_SERIAL_DEBUG
+ tristate "USB Debugging Device"
+ depends on USB_SERIAL
+ help
+ Say Y here if you have a USB debugging device used to recieve
+ debugging data from another machine. The most common of these
+ devices is the NetChip TurboCONNECT device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called usb-debug.
+
config USB_EZUSB
bool
depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index a5047dc599bb..61166ad450e6 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.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
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index 812275509137..86bcf63b6ba5 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -92,6 +92,7 @@ struct aircable_private {
struct circ_buf *rx_buf; /* read buffer */
int rx_flags; /* for throttilng */
struct work_struct rx_work; /* work cue for the receiving line */
+ struct usb_serial_port *port; /* USB port with which associated */
};
/* Private methods */
@@ -251,10 +252,11 @@ static void aircable_send(struct usb_serial_port *port)
schedule_work(&port->work);
}
-static void aircable_read(void *params)
+static void aircable_read(struct work_struct *work)
{
- struct usb_serial_port *port = params;
- struct aircable_private *priv = usb_get_serial_port_data(port);
+ struct aircable_private *priv =
+ container_of(work, struct aircable_private, rx_work);
+ struct usb_serial_port *port = priv->port;
struct tty_struct *tty;
unsigned char *data;
int count;
@@ -270,8 +272,11 @@ static void aircable_read(void *params)
*/
tty = port->tty;
- if (!tty)
+ if (!tty) {
schedule_work(&priv->rx_work);
+ err("%s - No tty available", __FUNCTION__);
+ return ;
+ }
count = min(64, serial_buf_data_avail(priv->rx_buf));
@@ -305,9 +310,7 @@ static int aircable_probe(struct usb_serial *serial,
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc;
- if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
- ((endpoint->bmAttributes & 3) == 0x02)) {
- /* we found our bulk out endpoint */
+ if (usb_endpoint_is_bulk_out(endpoint)) {
dbg("found bulk out on endpoint %d", i);
++num_bulk_out;
}
@@ -348,7 +351,8 @@ static int aircable_attach (struct usb_serial *serial)
}
priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
- INIT_WORK(&priv->rx_work, aircable_read, port);
+ priv->port = port;
+ INIT_WORK(&priv->rx_work, aircable_read);
usb_set_serial_port_data(serial->port[0], priv);
@@ -515,7 +519,7 @@ static void aircable_read_bulk_callback(struct urb *urb)
package_length - shift);
}
}
- aircable_read(port);
+ aircable_read(&priv->rx_work);
}
/* Schedule the next read _if_ we are still open */
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 7f5d546da39a..f2ca76a9cbac 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -19,7 +19,11 @@
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+ { USB_DEVICE(0x1410, 0x1130) }, /* Novatel Wireless S720 CDMA/EV-DO */
+ { USB_DEVICE(0x1410, 0x2110) }, /* Novatel Wireless U720 CDMA/EV-DO */
+ { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
+ { USB_DEVICE(0x413c, 0x8115) }, /* Dell Wireless HSDPA 5500 */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index ca52f12f0e24..5261cd22ee6b 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial)
int i;
for (i = 0; i < serial->num_ports; ++i) {
- priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
+ priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
if (!priv)
goto cleanup;
- memset(priv, 0x00, sizeof (struct ark3116_private));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(serial->port[i], priv);
@@ -157,7 +156,7 @@ cleanup:
}
static void ark3116_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct ark3116_private *priv = usb_get_serial_port_data(port);
@@ -327,7 +326,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
static int ark3116_open(struct usb_serial_port *port, struct file *filp)
{
- struct termios tmp_termios;
+ struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
char *buf;
int result = 0;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 8835bb58ca9b..38b4dae319ee 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -92,7 +92,7 @@ static void belkin_sa_shutdown (struct usb_serial *serial);
static int belkin_sa_open (struct usb_serial_port *port, struct file *filp);
static void belkin_sa_close (struct usb_serial_port *port, struct file *filp);
static void belkin_sa_read_int_callback (struct urb *urb);
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old);
+static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state );
static int belkin_sa_tiocmget (struct usb_serial_port *port, struct file *file);
@@ -333,7 +333,7 @@ exit:
__FUNCTION__, retval);
}
-static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct belkin_sa_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 3a9073dbfe6a..9386e216d681 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -65,7 +65,7 @@ static int usb_console_setup(struct console *co, char *options)
struct usb_serial_port *port;
int retval = 0;
struct tty_struct *tty;
- struct termios *termios;
+ struct ktermios *termios;
dbg ("%s", __FUNCTION__);
@@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) {
/* build up a fake tty structure so that the open call has something
* to look at to get the cflag value */
- tty = kmalloc (sizeof (*tty), GFP_KERNEL);
+ tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty) {
err ("no more memory");
return -ENOMEM;
}
- termios = kmalloc (sizeof (*termios), GFP_KERNEL);
+ termios = kzalloc(sizeof(*termios), GFP_KERNEL);
if (!termios) {
err ("no more memory");
kfree (tty);
return -ENOMEM;
}
- memset (tty, 0x00, sizeof(*tty));
- memset (termios, 0x00, sizeof(*termios));
termios->c_cflag = cflag;
tty->termios = termios;
port->tty = tty;
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index f95d42c0d16a..7ebaffd6ed86 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -41,7 +41,7 @@ static int cp2101_open(struct usb_serial_port*, struct file*);
static void cp2101_cleanup(struct usb_serial_port*);
static void cp2101_close(struct usb_serial_port*, struct file*);
static void cp2101_get_termios(struct usb_serial_port*);
-static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static void cp2101_set_termios(struct usb_serial_port*, struct ktermios*);
static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
unsigned int, unsigned int);
@@ -69,6 +69,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ } /* Terminating Entry */
};
@@ -506,7 +507,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
}
static void cp2101_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
unsigned int cflag, old_cflag=0;
int baud=0, bits;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f2e89a083659..6bc1f404e186 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -143,7 +143,7 @@ struct cypress_private {
wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */
char prev_status, diff_status; /* used for TIOCMIWAIT */
/* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
- struct termios tmp_termios; /* stores the old termios settings */
+ struct ktermios tmp_termios; /* stores the old termios settings */
};
/* write buffer structure */
@@ -165,7 +165,7 @@ static int cypress_write (struct usb_serial_port *port, const unsigned char *b
static void cypress_send (struct usb_serial_port *port);
static int cypress_write_room (struct usb_serial_port *port);
static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void cypress_set_termios (struct usb_serial_port *port, struct termios * old);
+static void cypress_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int cypress_tiocmget (struct usb_serial_port *port, struct file *file);
static int cypress_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static int cypress_chars_in_buffer (struct usb_serial_port *port);
@@ -949,28 +949,13 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
switch (cmd) {
case TIOCGSERIAL:
- if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
+ if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct ktermios))) {
return -EFAULT;
}
return (0);
break;
case TIOCSSERIAL:
- if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
- return -EFAULT;
- }
- /* here we need to call cypress_set_termios to invoke the new settings */
- cypress_set_termios(port, &priv->tmp_termios);
- return (0);
- break;
- /* these are called when setting baud rate from gpsd */
- case TCGETS:
- if (copy_to_user((void __user *)arg, port->tty->termios, sizeof(struct termios))) {
- return -EFAULT;
- }
- return (0);
- break;
- case TCSETS:
- if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct termios))) {
+ if (copy_from_user(port->tty->termios, (void __user *)arg, sizeof(struct ktermios))) {
return -EFAULT;
}
/* here we need to call cypress_set_termios to invoke the new settings */
@@ -1019,7 +1004,7 @@ static int cypress_ioctl (struct usb_serial_port *port, struct file * file, unsi
static void cypress_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct cypress_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
@@ -1493,7 +1478,7 @@ static struct cypress_buf *cypress_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- cb = (struct cypress_buf *)kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct cypress_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
@@ -1684,15 +1669,14 @@ static int __init cypress_init(void)
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
+
failed_usb_register:
- usb_deregister(&cypress_driver);
-failed_ca42v2_register:
usb_serial_deregister(&cypress_ca42v2_device);
-failed_hidcom_register:
+failed_ca42v2_register:
usb_serial_deregister(&cypress_hidcom_device);
-failed_em_register:
+failed_hidcom_register:
usb_serial_deregister(&cypress_earthmate_device);
-
+failed_em_register:
return retval;
}
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index bdb58100fc1d..efd9ce3f931f 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -157,7 +157,7 @@
* to TASK_RUNNING will be lost and write_chan's subsequent call to
* schedule() will never return (unless it catches a signal).
* This race condition occurs because write_bulk_callback() (and thus
-* the wakeup) are called asynchonously from an interrupt, rather than
+* the wakeup) are called asynchronously from an interrupt, rather than
* from the scheduler. We can avoid the race by calling the wakeup
* from the scheduler queue and that's our fix: Now, at the end of
* write_bulk_callback() we queue up a wakeup call on the scheduler
@@ -430,13 +430,14 @@ struct digi_port {
int dp_in_close; /* close in progress */
wait_queue_head_t dp_close_wait; /* wait queue for close */
struct work_struct dp_wakeup_work;
+ struct usb_serial_port *dp_port;
};
/* Local Function Declarations */
static void digi_wakeup_write( struct usb_serial_port *port );
-static void digi_wakeup_write_lock(void *);
+static void digi_wakeup_write_lock(struct work_struct *work);
static int digi_write_oob_command( struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible );
static int digi_write_inb_command( struct usb_serial_port *port,
@@ -448,7 +449,7 @@ static int digi_transmit_idle( struct usb_serial_port *port,
static void digi_rx_throttle (struct usb_serial_port *port);
static void digi_rx_unthrottle (struct usb_serial_port *port);
static void digi_set_termios( struct usb_serial_port *port,
- struct termios *old_termios );
+ struct ktermios *old_termios );
static void digi_break_ctl( struct usb_serial_port *port, int break_state );
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg );
@@ -598,11 +599,12 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
* on writes.
*/
-static void digi_wakeup_write_lock(void *arg)
+static void digi_wakeup_write_lock(struct work_struct *work)
{
- struct usb_serial_port *port = arg;
+ struct digi_port *priv =
+ container_of(work, struct digi_port, dp_wakeup_work);
+ struct usb_serial_port *port = priv->dp_port;
unsigned long flags;
- struct digi_port *priv = usb_get_serial_port_data(port);
spin_lock_irqsave( &priv->dp_port_lock, flags );
@@ -974,7 +976,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
static void digi_set_termios( struct usb_serial_port *port,
- struct termios *old_termios )
+ struct ktermios *old_termios )
{
struct digi_port *priv = usb_get_serial_port_data(port);
@@ -1461,7 +1463,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp )
int ret;
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
- struct termios not_termios;
+ struct ktermios not_termios;
unsigned long flags = 0;
@@ -1679,7 +1681,7 @@ dbg( "digi_startup: TOP" );
for( i=0; i<serial->type->num_ports+1; i++ ) {
/* allocate port private structure */
- priv = (struct digi_port *)kmalloc( sizeof(struct digi_port),
+ priv = kmalloc( sizeof(struct digi_port),
GFP_KERNEL );
if( priv == (struct digi_port *)0 ) {
while( --i >= 0 )
@@ -1702,8 +1704,8 @@ dbg( "digi_startup: TOP" );
init_waitqueue_head( &priv->dp_flush_wait );
priv->dp_in_close = 0;
init_waitqueue_head( &priv->dp_close_wait );
- INIT_WORK(&priv->dp_wakeup_work,
- digi_wakeup_write_lock, serial->port[i]);
+ INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+ priv->dp_port = serial->port[i];
/* initialize write wait queue for this port */
init_waitqueue_head( &serial->port[i]->write_wait );
@@ -1712,7 +1714,7 @@ dbg( "digi_startup: TOP" );
}
/* allocate serial private structure */
- serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
+ serial_priv = kmalloc( sizeof(struct digi_serial),
GFP_KERNEL );
if( serial_priv == (struct digi_serial *)0 ) {
for( i=0; i<serial->type->num_ports+1; i++ )
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 4ce10a831953..92beeb19795f 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -92,7 +92,7 @@ static int empeg_ioctl (struct usb_serial_port *port,
struct file * file,
unsigned int cmd,
unsigned long arg);
-static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void empeg_write_bulk_callback (struct urb *urb);
static void empeg_read_bulk_callback (struct urb *urb);
@@ -442,7 +442,7 @@ static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsign
}
-static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void empeg_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s - port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 5169c2d154ab..97ee718b1da2 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
return -ENODEV;
}
- transfer_buffer = kmalloc (length, GFP_KERNEL);
+ transfer_buffer = kmemdup(data, length, GFP_KERNEL);
if (!transfer_buffer) {
dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
return -ENOMEM;
}
- memcpy (transfer_buffer, data, length);
result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
kfree (transfer_buffer);
return result;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c186b4e73c72..6986e756f7c0 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -452,6 +452,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
{ USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
{ USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
@@ -559,7 +560,8 @@ struct ftdi_private {
char prev_status, diff_status; /* Used for TIOCMIWAIT */
__u8 rx_flags; /* receive state flags (throttling) */
spinlock_t rx_lock; /* spinlock for receive state */
- struct work_struct rx_work;
+ struct delayed_work rx_work;
+ struct usb_serial_port *port;
int rx_processed;
unsigned long rx_bytes;
@@ -593,8 +595,8 @@ static int ftdi_write_room (struct usb_serial_port *port);
static int ftdi_chars_in_buffer (struct usb_serial_port *port);
static void ftdi_write_bulk_callback (struct urb *urb);
static void ftdi_read_bulk_callback (struct urb *urb);
-static void ftdi_process_read (void *param);
-static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old);
+static void ftdi_process_read (struct work_struct *work);
+static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
@@ -1201,7 +1203,8 @@ static int ftdi_sio_attach (struct usb_serial *serial)
port->read_urb->transfer_buffer_length = BUFSZ;
}
- INIT_WORK(&priv->rx_work, ftdi_process_read, port);
+ INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read);
+ priv->port = port;
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
@@ -1388,8 +1391,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
flush_scheduled_work();
/* shutdown our bulk read */
- if (port->read_urb)
- usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->read_urb);
} /* ftdi_close */
@@ -1641,17 +1643,18 @@ static void ftdi_read_bulk_callback (struct urb *urb)
priv->rx_bytes += countread;
spin_unlock_irqrestore(&priv->rx_lock, flags);
- ftdi_process_read(port);
+ ftdi_process_read(&priv->rx_work.work);
} /* ftdi_read_bulk_callback */
-static void ftdi_process_read (void *param)
+static void ftdi_process_read (struct work_struct *work)
{ /* ftdi_process_read */
- struct usb_serial_port *port = (struct usb_serial_port*)param;
+ struct ftdi_private *priv =
+ container_of(work, struct ftdi_private, rx_work.work);
+ struct usb_serial_port *port = priv->port;
struct urb *urb;
struct tty_struct *tty;
- struct ftdi_private *priv;
char error_flag;
unsigned char *data;
@@ -1878,7 +1881,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
* WARNING: set_termios calls this with old_termios in kernel space
*/
-static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ftdi_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{ /* ftdi_termios */
struct usb_device *dev = port->serial->dev;
unsigned int cflag = port->tty->termios->c_cflag;
@@ -2180,7 +2183,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->rx_lock, flags);
if (actually_throttled)
- schedule_work(&priv->rx_work);
+ schedule_delayed_work(&priv->rx_work, 0);
}
static int __init ftdi_init (void)
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index bae117d359af..40dd394de58d 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -312,8 +312,9 @@
/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
/* unit for PIC16's/PIC18's */
-#define FTDI_CCSICDU20_0_PID 0xF9D0
-#define FTDI_CCSICDU40_1_PID 0xF9D1
+#define FTDI_CCSICDU20_0_PID 0xF9D0
+#define FTDI_CCSICDU40_1_PID 0xF9D1
+#define FTDI_CCSMACHX_2_PID 0xF9D2
/* Inside Accesso contactless reader (http://www.insidefr.com) */
#define INSIDE_ACCESSO 0xFAD0
diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c
index 77b977206a8c..31501c9361b9 100644
--- a/drivers/usb/serial/funsoft.c
+++ b/drivers/usb/serial/funsoft.c
@@ -14,6 +14,9 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x1404, 0xcddc) },
@@ -21,6 +24,26 @@ static struct usb_device_id id_table [] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
+static int funsoft_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct termios t;
+
+ dbg("%s - port %d, cmd 0x%04x", __FUNCTION__, port->number, cmd);
+
+ if (cmd == TCSETSF) {
+ if (user_termios_to_kernel_termios(&t, (struct termios __user *)arg))
+ return -EFAULT;
+
+ dbg("%s - iflag:%x oflag:%x cflag:%x lflag:%x", __FUNCTION__,
+ t.c_iflag, t.c_oflag, t.c_cflag, t.c_lflag);
+
+ if (!(t.c_lflag & ICANON))
+ return -EINVAL;
+ }
+ return -ENOIOCTLCMD;
+}
+
static struct usb_driver funsoft_driver = {
.name = "funsoft",
.probe = usb_serial_probe,
@@ -39,6 +62,7 @@ static struct usb_serial_driver funsoft_device = {
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
+ .ioctl = funsoft_ioctl,
};
static int __init funsoft_init(void)
@@ -63,3 +87,6 @@ static void __exit funsoft_exit(void)
module_init(funsoft_init);
module_exit(funsoft_exit);
MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 4543152a9966..6530d391ebed 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
+ garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
if (garmin_data_p == NULL) {
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM;
}
- memset (garmin_data_p, 0, sizeof(struct garmin_data));
init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist);
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 91bd3014ef1e..f623d58370a4 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -229,7 +229,7 @@ static int edge_write_room (struct usb_serial_port *port);
static int edge_chars_in_buffer (struct usb_serial_port *port);
static void edge_throttle (struct usb_serial_port *port);
static void edge_unthrottle (struct usb_serial_port *port);
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
static void edge_break (struct usb_serial_port *port, int break_state);
static int edge_tiocmget (struct usb_serial_port *port, struct file *file);
@@ -257,7 +257,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, __u8 lsrData, __u8
static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u8 param);
static int calc_baud_rate_divisor (int baud_rate, int *divisor);
static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRate);
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios);
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios);
static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 regNum, __u8 regValue);
static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int writeLength);
static void send_more_port_data (struct edgeport_serial *edge_serial, struct edgeport_port *edge_port);
@@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->open = FALSE;
edge_port->openPending = FALSE;
- if (edge_port->write_urb) {
- usb_kill_urb(edge_port->write_urb);
- }
+ usb_kill_urb(edge_port->write_urb);
if (edge_port->write_urb) {
/* if this urb had a transfer buffer already (old transfer) free it */
@@ -1433,7 +1431,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
* SerialSetTermios
* this function is called by the tty driver when it wants to change the termios structure
*****************************************************************************/
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -2414,7 +2412,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
#ifndef CMSPAR
#define CMSPAR 0
#endif
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct tty_struct *tty;
int baud;
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ee0c921e1520..980285c0233a 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -238,7 +238,7 @@ static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned c
static void stop_read(struct edgeport_port *edge_port);
static int restart_read(struct edgeport_port *edge_port);
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void edge_send(struct usb_serial_port *port);
/* circular buffer */
@@ -2361,7 +2361,7 @@ static int restart_read(struct edgeport_port *edge_port)
return status;
}
-static void change_port_settings (struct edgeport_port *edge_port, struct termios *old_termios)
+static void change_port_settings (struct edgeport_port *edge_port, struct ktermios *old_termios)
{
struct ump_uart_config *config;
struct tty_struct *tty;
@@ -2512,7 +2512,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
return;
}
-static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -2811,7 +2811,7 @@ static struct edge_buf *edge_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- eb = (struct edge_buf *)kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
+ eb = kmalloc(sizeof(struct edge_buf), GFP_KERNEL);
if (eb == NULL)
return NULL;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index d72cf8bc7f76..42f757a5b876 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -595,7 +595,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
bytes_in = 0;
bytes_out = 0;
- priv = (struct ipaq_private *)kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct ipaq_private), GFP_KERNEL);
if (priv == NULL) {
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 2a4bb66691ad..d3b9a351cef8 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
dbg("%s", __FUNCTION__);
- buf_flow_init = kmalloc(16, GFP_KERNEL);
+ buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
if (!buf_flow_init)
return -ENOMEM;
- memcpy(buf_flow_init, buf_flow_static, 16);
if (port->tty)
port->tty->low_latency = 1;
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 331bf81556fc..8fdf486e3465 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -107,7 +107,7 @@ static void ir_close (struct usb_serial_port *port, struct file *filep);
static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static void ir_write_bulk_callback (struct urb *urb);
static void ir_read_bulk_callback (struct urb *urb);
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static u8 ir_baud = 0;
static u8 ir_xbof = 0;
@@ -497,7 +497,7 @@ static void ir_read_bulk_callback (struct urb *urb)
return;
}
-static void ir_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned char *transfer_buffer;
unsigned int cflag;
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 53be824eb1bf..9d2fdfd6865f 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -264,7 +264,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
static void keyspan_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int baud_rate, device_port;
struct keyspan_port_private *p_priv;
@@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial)
}
/* Now free them */
- if (s_priv->instat_urb)
- usb_free_urb(s_priv->instat_urb);
- if (s_priv->glocont_urb)
- usb_free_urb(s_priv->glocont_urb);
+ usb_free_urb(s_priv->instat_urb);
+ usb_free_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
- if (p_priv->inack_urb)
- usb_free_urb(p_priv->inack_urb);
- if (p_priv->outcont_urb)
- usb_free_urb(p_priv->outcont_urb);
+ usb_free_urb(p_priv->inack_urb);
+ usb_free_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) {
- if (p_priv->in_urbs[j])
- usb_free_urb(p_priv->in_urbs[j]);
- if (p_priv->out_urbs[j])
- usb_free_urb(p_priv->out_urbs[j]);
+ usb_free_urb(p_priv->in_urbs[j]);
+ usb_free_urb(p_priv->out_urbs[j]);
}
}
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index 7472ed6bf626..6413d73c139c 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -59,7 +59,7 @@ static int keyspan_ioctl (struct usb_serial_port *port,
unsigned int cmd,
unsigned long arg);
static void keyspan_set_termios (struct usb_serial_port *port,
- struct termios *old);
+ struct ktermios *old);
static void keyspan_break_ctl (struct usb_serial_port *port,
int break_state);
static int keyspan_tiocmget (struct usb_serial_port *port,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 909005107ea2..126b9703bbaf 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -120,6 +120,8 @@ struct keyspan_pda_private {
int tx_throttled;
struct work_struct wakeup_work;
struct work_struct unthrottle_work;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
};
@@ -175,9 +177,11 @@ static struct usb_device_id id_table_fake_xircom [] = {
};
#endif
-static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
+static void keyspan_pda_wakeup_write(struct work_struct *work)
{
-
+ struct keyspan_pda_private *priv =
+ container_of(work, struct keyspan_pda_private, wakeup_work);
+ struct usb_serial_port *port = priv->port;
struct tty_struct *tty = port->tty;
/* wake up port processes */
@@ -187,8 +191,11 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
tty_wakeup(tty);
}
-static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
+static void keyspan_pda_request_unthrottle(struct work_struct *work)
{
+ struct keyspan_pda_private *priv =
+ container_of(work, struct keyspan_pda_private, unthrottle_work);
+ struct usb_serial *serial = priv->serial;
int result;
dbg(" request_unthrottle");
@@ -358,7 +365,7 @@ static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state
static void keyspan_pda_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
unsigned int cflag = port->tty->termios->c_cflag;
@@ -765,11 +772,10 @@ static int keyspan_pda_startup (struct usb_serial *serial)
return (1); /* error */
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
- INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write,
- (void *)(serial->port[0]));
- INIT_WORK(&priv->unthrottle_work,
- (void *)keyspan_pda_request_unthrottle,
- (void *)(serial));
+ INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
+ INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
+ priv->serial = serial;
+ priv->port = serial->port[0];
return (0);
}
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 17e205699c2b..5c4b06a99ac0 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -86,11 +86,7 @@ static int klsi_105_write_room (struct usb_serial_port *port);
static void klsi_105_read_bulk_callback (struct urb *urb);
static void klsi_105_set_termios (struct usb_serial_port *port,
- struct termios * old);
-static int klsi_105_ioctl (struct usb_serial_port *port,
- struct file * file,
- unsigned int cmd,
- unsigned long arg);
+ struct ktermios *old);
static void klsi_105_throttle (struct usb_serial_port *port);
static void klsi_105_unthrottle (struct usb_serial_port *port);
/*
@@ -140,7 +136,6 @@ static struct usb_serial_driver kl5kusb105d_device = {
.chars_in_buffer = klsi_105_chars_in_buffer,
.write_room = klsi_105_write_room,
.read_bulk_callback =klsi_105_read_bulk_callback,
- .ioctl = klsi_105_ioctl,
.set_termios = klsi_105_set_termios,
/*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget,
@@ -164,7 +159,7 @@ struct klsi_105_port_settings {
#define URB_TRANSFER_BUFFER_SIZE 64
struct klsi_105_private {
struct klsi_105_port_settings cfg;
- struct termios termios;
+ struct ktermios termios;
unsigned long line_state; /* modem line settings */
/* write pool */
struct urb * write_urb_pool[NUM_URBS];
@@ -688,7 +683,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
static void klsi_105_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
@@ -899,69 +894,6 @@ static int klsi_105_tiocmset (struct usb_serial_port *port, struct file *file,
*/
return retval;
}
-
-static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
- unsigned int cmd, unsigned long arg)
-{
- struct klsi_105_private *priv = usb_get_serial_port_data(port);
- void __user *user_arg = (void __user *)arg;
-
- dbg("%scmd=0x%x", __FUNCTION__, cmd);
-
- /* Based on code from acm.c and others */
- switch (cmd) {
- case TIOCMIWAIT:
- /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
- /* TODO */
- dbg("%s - TIOCMIWAIT not handled", __FUNCTION__);
- return -ENOIOCTLCMD;
- case TIOCGICOUNT:
- /* return count of modemline transitions */
- /* TODO */
- dbg("%s - TIOCGICOUNT not handled", __FUNCTION__);
- return -ENOIOCTLCMD;
- case TCGETS:
- /* return current info to caller */
- dbg("%s - TCGETS data faked/incomplete", __FUNCTION__);
-
- if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios)))
- return -EFAULT;
-
- if (kernel_termios_to_user_termios((struct termios __user *)arg,
- &priv->termios))
- return -EFAULT;
- return 0;
- case TCSETS:
- /* set port termios to the one given by the user */
- dbg("%s - TCSETS not handled", __FUNCTION__);
-
- if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios)))
- return -EFAULT;
-
- if (user_termios_to_kernel_termios(&priv->termios,
- (struct termios __user *)arg))
- return -EFAULT;
- klsi_105_set_termios(port, &priv->termios);
- return 0;
- case TCSETSW: {
- /* set port termios and try to wait for completion of last
- * write operation */
- /* We guess here. If there are not too many write urbs
- * outstanding, we lie. */
- /* what is the right way to wait here? schedule() ? */
- /*
- while (klsi_105_chars_in_buffer(port) > (NUM_URBS / 4 ) * URB_TRANSFER_BUFFER_SIZE)
- schedule();
- */
- return -ENOIOCTLCMD;
- }
- default:
- dbg("%s: arg not supported - 0x%04x", __FUNCTION__,cmd);
- return(-ENOIOCTLCMD);
- break;
- }
- return 0;
-} /* klsi_105_ioctl */
static void klsi_105_throttle (struct usb_serial_port *port)
{
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index ff03331e0bcf..62bea0c923bd 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -136,7 +136,7 @@ struct kobil_private {
int cur_pos; // index of the next char to send in buf
__u16 device_type;
int line_state;
- struct termios internal_termios;
+ struct ktermios internal_termios;
};
@@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial)
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
endpoint = &altsetting->endpoint[i];
- if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
- ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ if (usb_endpoint_is_int_out(&endpoint->desc)) {
dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
}
- if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
- ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+ if (usb_endpoint_is_int_in(&endpoint->desc)) {
dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
}
@@ -271,7 +269,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
}
// allocate memory for write_urb transfer buffer
- port->write_urb->transfer_buffer = (unsigned char *) kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
+ port->write_urb->transfer_buffer = kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
if (! port->write_urb->transfer_buffer) {
kfree(transfer_buffer);
usb_free_urb(port->write_urb);
@@ -355,8 +353,7 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
usb_free_urb( port->write_urb );
port->write_urb = NULL;
}
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
@@ -627,11 +624,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) {
case TCGETS: // 0x5401
- if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) {
+ if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) {
dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
return -EFAULT;
}
- if (kernel_termios_to_user_termios((struct termios __user *)arg,
+ if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
&priv->internal_termios))
return -EFAULT;
return 0;
@@ -641,12 +638,12 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
return -ENOTTY;
}
- if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) {
+ if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) {
dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
return -EFAULT;
}
if (user_termios_to_kernel_termios(&priv->internal_termios,
- (struct termios __user *)arg))
+ (struct ktermios __user *)arg))
return -EFAULT;
settings = kzalloc(50, GFP_KERNEL);
@@ -699,7 +696,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
return 0;
case TCFLSH: // 0x540B
- transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL);
+ transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
if (! transfer_buffer) {
return -ENOBUFS;
}
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index b7582cc496dc..38b1d17e06ef 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -98,7 +98,7 @@ static void mct_u232_close (struct usb_serial_port *port,
struct file *filp);
static void mct_u232_read_int_callback (struct urb *urb);
static void mct_u232_set_termios (struct usb_serial_port *port,
- struct termios * old);
+ struct ktermios * old);
static int mct_u232_ioctl (struct usb_serial_port *port,
struct file * file,
unsigned int cmd,
@@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial)
/* Puh, that's dirty */
port = serial->port[0];
rport = serial->port[1];
- if (port->read_urb) {
- /* No unlinking, it wasn't submitted yet. */
- usb_free_urb(port->read_urb);
- }
+ /* No unlinking, it wasn't submitted yet. */
+ usb_free_urb(port->read_urb);
port->read_urb = rport->interrupt_in_urb;
rport->interrupt_in_urb = NULL;
port->read_urb->context = port;
@@ -558,7 +556,7 @@ exit:
} /* mct_u232_read_int_callback */
static void mct_u232_set_termios (struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 82cd15b894b0..e55f4ed81d7b 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -363,7 +363,7 @@ static int mos7720_open(struct usb_serial_port *port, struct file * filp)
/* Initialising the write urb pool */
for (j = 0; j < NUM_URBS; ++j) {
- urb = usb_alloc_urb(0,SLAB_ATOMIC);
+ urb = usb_alloc_urb(0,GFP_ATOMIC);
mos7720_port->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -1014,7 +1014,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port,
* the specified new settings.
*/
static void change_port_settings(struct moschip_port *mos7720_port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial_port *port;
struct usb_serial *serial;
@@ -1203,7 +1203,7 @@ static void change_port_settings(struct moschip_port *mos7720_port,
* termios structure.
*/
static void mos7720_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int status;
unsigned int cflag;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5b71962d0351..83f661403ba1 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -826,7 +826,7 @@ static int mos7840_open(struct usb_serial_port *port, struct file *filp)
/* Initialising the write urb pool */
for (j = 0; j < NUM_URBS; ++j) {
- urb = usb_alloc_urb(0, SLAB_ATOMIC);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
mos7840_port->write_urb_pool[j] = urb;
if (urb == NULL) {
@@ -1931,7 +1931,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
*****************************************************************************/
static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct tty_struct *tty;
int baud;
@@ -2118,7 +2118,7 @@ static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
*****************************************************************************/
static void mos7840_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
int status;
unsigned int cflag;
@@ -2460,12 +2460,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
tty_ldisc_deref(ld);
return 0;
- case TCGETS:
- if (kernel_termios_to_user_termios
- ((struct termios __user *)argp, tty->termios))
- return -EFAULT;
- return 0;
-
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
return mos7840_get_lsr_info(mos7840_port, argp);
@@ -2596,12 +2590,11 @@ static int mos7840_startup(struct usb_serial *serial)
/* set up port private structures */
for (i = 0; i < serial->num_ports; ++i) {
- mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+ mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) {
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
}
- memset(mos7840_port, 0, sizeof(struct moschip_port));
/* Initialize all port interrupt end point to port 0 int endpoint *
* Our device has only one interrupt end point comman to all port */
@@ -2787,7 +2780,7 @@ static int mos7840_startup(struct usb_serial *serial)
i + 1, status);
}
- mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC);
+ mos7840_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC);
mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
}
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 0610409a6568..054abee81652 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
{
dbg("%s - port %d", __FUNCTION__, port->number);
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
}
static int navman_write(struct usb_serial_port *port,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 130afbbd3fca..5ca04e82ea19 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -59,7 +59,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port);
static int option_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg);
static void option_set_termios(struct usb_serial_port *port,
- struct termios *old);
+ struct ktermios *old);
static void option_break_ctl(struct usb_serial_port *port, int break_state);
static int option_tiocmget(struct usb_serial_port *port, struct file *file);
static int option_tiocmset(struct usb_serial_port *port, struct file *file,
@@ -79,6 +79,7 @@ static int option_send_setup(struct usb_serial_port *port);
#define OPTION_PRODUCT_COBRA 0x6500
#define OPTION_PRODUCT_COBRA2 0x6600
#define HUAWEI_PRODUCT_E600 0x1001
+#define HUAWEI_PRODUCT_E220 0x1003
#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
#define NOVATELWIRELESS_PRODUCT_U740 0x1400
#define ANYDATA_PRODUCT_ID 0x6501
@@ -90,6 +91,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
@@ -103,6 +105,7 @@ static struct usb_device_id option_ids1[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+ { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) },
{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
@@ -230,7 +233,7 @@ static void option_break_ctl(struct usb_serial_port *port, int break_state)
}
static void option_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
@@ -622,6 +625,9 @@ static int option_send_setup(struct usb_serial_port *port)
dbg("%s", __FUNCTION__);
+ if (port->number != 0)
+ return 0;
+
portdata = usb_get_serial_port_data(port);
if (port->tty) {
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index bc800c8787a8..5dc2ac9afa90 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -159,7 +159,7 @@ static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
if (size == 0)
return NULL;
- pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+ pb = kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
if (pb == NULL)
return NULL;
@@ -455,7 +455,7 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
}
static void pl2303_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -687,7 +687,7 @@ static void pl2303_close(struct usb_serial_port *port, struct file *filp)
static int pl2303_open(struct usb_serial_port *port, struct file *filp)
{
- struct termios tmp_termios;
+ struct ktermios tmp_termios;
struct usb_serial *serial = port->serial;
struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *buf;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 4b5097fa48d7..6d8e91e00ecf 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -145,7 +145,7 @@ static void sierra_break_ctl(struct usb_serial_port *port, int break_state)
}
static void sierra_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
dbg("%s", __FUNCTION__);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 07400c0c8a8c..83189005c6fb 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -161,7 +161,7 @@ static void ti_throttle(struct usb_serial_port *port);
static void ti_unthrottle(struct usb_serial_port *port);
static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
static void ti_set_termios(struct usb_serial_port *port,
- struct termios *old_termios);
+ struct ktermios *old_termios);
static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear);
@@ -228,6 +228,7 @@ static int product_5052_count;
/* null entry */
static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
};
static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -239,6 +240,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
static struct usb_device_id ti_id_table_combined[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
@@ -459,13 +461,12 @@ static int ti_startup(struct usb_serial *serial)
/* set up port structures */
for (i = 0; i < serial->num_ports; ++i) {
- tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL);
+ tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
if (tport == NULL) {
dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
status = -ENOMEM;
goto free_tports;
}
- memset(tport, 0, sizeof(struct ti_port));
spin_lock_init(&tport->tp_lock);
tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
@@ -880,7 +881,7 @@ static int ti_ioctl(struct usb_serial_port *port, struct file *file,
static void ti_set_termios(struct usb_serial_port *port,
- struct termios *old_termios)
+ struct ktermios *old_termios)
{
struct ti_port *tport = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -1709,7 +1710,7 @@ static struct circ_buf *ti_buf_alloc(void)
{
struct circ_buf *cb;
- cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+ cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
if (cb == NULL)
return NULL;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 02c1aeb9e1b8..b5541bf991ba 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -28,6 +28,7 @@
/* Vendor and product ids */
#define TI_VENDOR_ID 0x0451
#define TI_3410_PRODUCT_ID 0x3410
+#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 8006e51c34bb..716f6806cc89 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -397,7 +397,7 @@ exit:
return retval;
}
-static void serial_set_termios (struct tty_struct *tty, struct termios * old)
+static void serial_set_termios (struct tty_struct *tty, struct ktermios * old)
{
struct usb_serial_port *port = tty->driver_data;
@@ -533,9 +533,10 @@ void usb_serial_port_softint(struct usb_serial_port *port)
schedule_work(&port->work);
}
-static void usb_serial_port_work(void *private)
+static void usb_serial_port_work(struct work_struct *work)
{
- struct usb_serial_port *port = private;
+ struct usb_serial_port *port =
+ container_of(work, struct usb_serial_port, work);
struct tty_struct *tty;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -799,7 +800,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
- INIT_WORK(&port->work, usb_serial_port_work, port);
+ INIT_WORK(&port->work, usb_serial_port_work);
serial->port[i] = port;
}
@@ -952,32 +953,28 @@ probe_error:
port = serial->port[i];
if (!port)
continue;
- if (port->read_urb)
- usb_free_urb (port->read_urb);
+ usb_free_urb(port->read_urb);
kfree(port->bulk_in_buffer);
}
for (i = 0; i < num_bulk_out; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->write_urb)
- usb_free_urb (port->write_urb);
+ usb_free_urb(port->write_urb);
kfree(port->bulk_out_buffer);
}
for (i = 0; i < num_interrupt_in; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->interrupt_in_urb)
- usb_free_urb (port->interrupt_in_urb);
+ usb_free_urb(port->interrupt_in_urb);
kfree(port->interrupt_in_buffer);
}
for (i = 0; i < num_interrupt_out; ++i) {
port = serial->port[i];
if (!port)
continue;
- if (port->interrupt_out_urb)
- usb_free_urb (port->interrupt_out_urb);
+ usb_free_urb(port->interrupt_out_urb);
kfree(port->interrupt_out_buffer);
}
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
new file mode 100644
index 000000000000..257a5e436873
--- /dev/null
+++ b/drivers/usb/serial/usb_debug.c
@@ -0,0 +1,65 @@
+/*
+ * USB Debug cable driver
+ *
+ * Copyright (C) 2006 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 version
+ * 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0525, 0x127a) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver debug_driver = {
+ .name = "debug",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+static struct usb_serial_driver debug_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "debug",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1,
+};
+
+static int __init debug_init(void)
+{
+ int retval;
+
+ retval = usb_serial_register(&debug_device);
+ if (retval)
+ return retval;
+ retval = usb_register(&debug_driver);
+ if (retval)
+ usb_serial_deregister(&debug_device);
+ return retval;
+}
+
+static void __exit debug_exit(void)
+{
+ usb_deregister(&debug_driver);
+ usb_serial_deregister(&debug_device);
+}
+
+module_init(debug_init);
+module_exit(debug_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index befe2e11a041..b09f06096056 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -46,7 +46,7 @@ static int visor_probe (struct usb_serial *serial, const struct usb_device_id
static int visor_calc_num_ports(struct usb_serial *serial);
static void visor_shutdown (struct usb_serial *serial);
static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios);
+static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void visor_write_bulk_callback (struct urb *urb);
static void visor_read_bulk_callback (struct urb *urb);
static void visor_read_int_callback (struct urb *urb);
@@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* shutdown our urbs */
usb_kill_urb(port->read_urb);
- if (port->interrupt_in_urb)
- usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->interrupt_in_urb);
/* Try to send shutdown message, if the device is gone, this will just fail. */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
@@ -917,7 +916,7 @@ static int visor_ioctl (struct usb_serial_port *port, struct file * file, unsign
/* This function is all nice and good, but we don't change anything based on it :) */
-static void visor_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void visor_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag;
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 4d1cd7aeccd3..5483d8564c1b 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -145,7 +145,7 @@ static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
static int whiteheat_write (struct usb_serial_port *port, const unsigned char *buf, int count);
static int whiteheat_write_room (struct usb_serial_port *port);
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios * old);
static int whiteheat_tiocmget (struct usb_serial_port *port, struct file *file);
static int whiteheat_tiocmset (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear);
static void whiteheat_break_ctl (struct usb_serial_port *port, int break_state);
@@ -227,6 +227,7 @@ struct whiteheat_private {
struct list_head rx_urbs_submitted;
struct list_head rx_urb_q;
struct work_struct rx_work;
+ struct usb_serial_port *port;
struct list_head tx_urbs_free;
struct list_head tx_urbs_submitted;
};
@@ -241,7 +242,7 @@ static void command_port_read_callback(struct urb *urb);
static int start_port_read(struct usb_serial_port *port);
static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, struct list_head *head);
static struct list_head *list_first(struct list_head *head);
-static void rx_data_softint(void *private);
+static void rx_data_softint(struct work_struct *work);
static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize);
static int firm_open(struct usb_serial_port *port);
@@ -415,7 +416,7 @@ static int whiteheat_attach (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
- info = (struct whiteheat_private *)kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
+ info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_private;
@@ -424,7 +425,8 @@ static int whiteheat_attach (struct usb_serial *serial)
spin_lock_init(&info->lock);
info->flags = 0;
info->mcr = 0;
- INIT_WORK(&info->rx_work, rx_data_softint, port);
+ INIT_WORK(&info->rx_work, rx_data_softint);
+ info->port = port;
INIT_LIST_HEAD(&info->rx_urbs_free);
INIT_LIST_HEAD(&info->rx_urbs_submitted);
@@ -485,7 +487,7 @@ static int whiteheat_attach (struct usb_serial *serial)
usb_set_serial_port_data(port, info);
}
- command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
+ command_info = kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
if (command_info == NULL) {
err("%s: Out of memory for port structures\n", serial->type->description);
goto no_command_private;
@@ -595,7 +597,7 @@ static void whiteheat_shutdown (struct usb_serial *serial)
static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
{
int retval = 0;
- struct termios old_term;
+ struct ktermios old_term;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -868,7 +870,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
}
-static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s -port %d", __FUNCTION__, port->number);
@@ -949,7 +951,7 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
spin_unlock_irqrestore(&info->lock, flags);
if (actually_throttled)
- rx_data_softint(port);
+ rx_data_softint(&info->rx_work);
return;
}
@@ -1400,10 +1402,11 @@ static struct list_head *list_first(struct list_head *head)
}
-static void rx_data_softint(void *private)
+static void rx_data_softint(struct work_struct *work)
{
- struct usb_serial_port *port = (struct usb_serial_port *)private;
- struct whiteheat_private *info = usb_get_serial_port_data(port);
+ struct whiteheat_private *info =
+ container_of(work, struct whiteheat_private, rx_work);
+ struct usb_serial_port *port = info->port;
struct tty_struct *tty = port->tty;
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 3baf448e300d..e565d3d2ab29 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -76,7 +76,7 @@ static void usb_onetouch_irq(struct urb *urb)
input_sync(dev);
resubmit:
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s/input0, status %d",
onetouch->udev->bus->bus_name,
@@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss)
return -ENODEV;
endpoint = &interface->endpoint[2].desc;
- if (!(endpoint->bEndpointAddress & USB_DIR_IN))
- return -ENODEV;
- if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- != USB_ENDPOINT_XFER_INT)
+ if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
@@ -157,7 +154,7 @@ int onetouch_connect_input(struct us_data *ss)
goto fail1;
onetouch->data = usb_buffer_alloc(udev, ONETOUCH_PKT_LEN,
- SLAB_ATOMIC, &onetouch->data_dma);
+ GFP_ATOMIC, &onetouch->data_dma);
if (!onetouch->data)
goto fail1;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index fb8bacaae27c..e3528eca29a5 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -646,7 +646,7 @@ sddr09_read_sg_test_only(struct us_data *us) {
return result;
}
- buf = (unsigned char *) kmalloc(bulklen, GFP_NOIO);
+ buf = kmalloc(bulklen, GFP_NOIO);
if (!buf)
return -ENOMEM;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 47644b5b6155..323293a3e61f 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -427,7 +427,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
US_DEBUGP("%s: xfer %u bytes, %d entries\n", __FUNCTION__,
length, num_sg);
result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
- sg, num_sg, length, SLAB_NOIO);
+ sg, num_sg, length, GFP_NOIO);
if (result) {
US_DEBUGP("usb_sg_init returned %d\n", result);
return USB_STOR_XFER_ERROR;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index efb047f431e8..cddef3efba0a 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -153,6 +153,13 @@ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+/* Reported by <honkkis@gmail.com> */
+UNUSUAL_DEV( 0x0421, 0x0433, 0x0100, 0x0100,
+ "Nokia",
+ "E70",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
/* Reported by Jon Hart <Jon.Hart@web.de> */
UNUSUAL_DEV( 0x0421, 0x0434, 0x0100, 0x0100,
"Nokia",
@@ -721,7 +728,7 @@ UNUSUAL_DEV( 0x05ac, 0x1204, 0x0000, 0x9999,
"Apple",
"iPod",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_CAPACITY ),
+ US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
UNUSUAL_DEV( 0x05ac, 0x1205, 0x0000, 0x9999,
"Apple",
@@ -1318,6 +1325,25 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
0 ),
+/* Reported by Jaco Kroon <jaco@kroon.co.za>
+ * The usb-storage module found on the Digitech GNX4 (and supposedly other
+ * devices) misbehaves and causes a bunch of invalid I/O errors.
+ */
+UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
+ "Digitech HMG",
+ "DigiTech Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* This prevents the kernel from detecting the virtual cd-drive with the
+ * Windows drivers. <johann.wilhelm@student.tugraz.at>
+*/
+UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0xffff,
+ "HUAWEI",
+ "E220 USB-UMTS Install",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_DEVICE),
+
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
"Minolta",
@@ -1332,6 +1358,21 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Francesco Foresti <frafore@tiscali.it> */
+UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201,
+ "Super Top",
+ "IDE DEVICE",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Robert Schedel <r.schedel@yahoo.de>
+ * Note: this is a 'super top' device like the above 14cd/6600 device */
+UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
+ "Teac",
+ "HD-35PUK-B",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
/* patch submitted by Davide Perini <perini.davide@dpsoftware.org>
* and Renato Perini <rperini@email.it>
*/
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index b8d6031b0975..70644506651f 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -49,7 +49,7 @@
#include <linux/sched.h>
#include <linux/errno.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us)
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))
ep_in = ep;
else
ep_out = ep;
}
/* Is it an interrupt endpoint? */
- else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_INT) {
+ else if (usb_endpoint_xfer_int(ep)) {
ep_int = ep;
}
}