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

This commit is contained in:
Linus Torvalds 2006-01-04 16:25:44 -08:00
commit c6c88bbde4
198 changed files with 6561 additions and 2035 deletions

View File

@ -253,6 +253,7 @@
!Edrivers/usb/core/urb.c
!Edrivers/usb/core/message.c
!Edrivers/usb/core/file.c
!Edrivers/usb/core/driver.c
!Edrivers/usb/core/usb.c
!Edrivers/usb/core/hub.c
</chapter>

View File

@ -2640,6 +2640,12 @@ L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB ISP116X DRIVER
P: Olav Kongas
M: ok@artecdesign.ee
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
USB KAWASAKI LSI DRIVER
P: Oliver Neukum
M: oliver@neukum.name
@ -2651,7 +2657,7 @@ USB MASS STORAGE DRIVER
P: Matthew Dharm
M: mdharm-usb@one-eyed-alien.net
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
L: usb-storage@lists.one-eyed-alien.net
S: Maintained
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/

View File

@ -43,6 +43,7 @@
#include <asm/arch/pxafb.h>
#include <asm/arch/mmc.h>
#include <asm/arch/irda.h>
#include <asm/arch/ohci.h>
#include "generic.h"
@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = {
&mst_flash_device[1],
};
static int mainstone_ohci_init(struct device *dev)
{
/* setup Port1 GPIO pin. */
pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
return 0;
}
static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.port_mode = PMM_PERPORT_MODE,
.init = mainstone_ohci_init,
};
static void __init mainstone_init(void)
{
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
@ -424,6 +444,7 @@ static void __init mainstone_init(void)
pxa_set_mci_info(&mainstone_mci_platform_data);
pxa_set_ficp_info(&mainstone_ficp_platform_data);
pxa_set_ohci_info(&mainstone_ohci_platform_data);
}

View File

@ -21,6 +21,7 @@
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/ohci.h>
#include "generic.h"
@ -194,6 +195,11 @@ static struct platform_device ohci_device = {
.resource = pxa27x_ohci_resources,
};
void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
{
ohci_device.dev.platform_data = info;
}
static struct platform_device *devices[] __initdata = {
&ohci_device,
};

View File

@ -358,7 +358,8 @@ config BLK_DEV_UB
This driver supports certain USB attached storage devices
such as flash keys.
Warning: Enabling this cripples the usb-storage driver.
If you enable this driver, it is recommended to avoid conflicts
with usb-storage by enabling USB_LIBUSUAL.
If unsure, say N.

View File

@ -9,7 +9,6 @@
*
* TODO (sorted by decreasing priority)
* -- Kill first_open (Al Viro fixed the block layer now)
* -- Do resets with usb_device_reset (needs a thread context, use khubd)
* -- set readonly flag for CDs, set removable flag for CF readers
* -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
* -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
@ -29,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/timer.h>
@ -106,16 +106,6 @@
* +--------+
*/
/*
* Definitions which have to be scattered once we understand the layout better.
*/
/* Transport (despite PR in the name) */
#define US_PR_BULK 0x50 /* bulk only */
/* Protocol */
#define US_SC_SCSI 0x06 /* Transparent */
/*
* This many LUNs per USB device.
* Every one of them takes a host, see UB_MAX_HOSTS.
@ -125,7 +115,7 @@
/*
*/
#define UB_MINORS_PER_MAJOR 8
#define UB_PARTS_PER_LUN 8
#define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */
@ -245,6 +235,13 @@ struct ub_scsi_cmd {
void *back;
};
struct ub_request {
struct request *rq;
unsigned int current_try;
unsigned int nsg; /* sgv[nsg] */
struct scatterlist sgv[UB_MAX_REQ_SG];
};
/*
*/
struct ub_capacity {
@ -340,6 +337,8 @@ struct ub_lun {
int readonly;
int first_open; /* Kludge. See ub_bd_open. */
struct ub_request urq;
/* Use Ingo's mempool if or when we have more than one command. */
/*
* Currently we never need more than one command for the whole device.
@ -360,6 +359,7 @@ struct ub_dev {
atomic_t poison; /* The USB device is disconnected */
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
int reset; /* Reset is running */
unsigned int tagcnt;
char name[12];
struct usb_device *dev;
@ -387,6 +387,9 @@ struct ub_dev {
struct bulk_cs_wrap work_bcs;
struct usb_ctrlrequest work_cr;
struct work_struct reset_work;
wait_queue_head_t reset_wait;
int sg_stat[6];
struct ub_scsi_trace tr;
};
@ -395,12 +398,14 @@ struct ub_dev {
*/
static void ub_cleanup(struct ub_dev *sc);
static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq);
static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq);
static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate);
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
static void ub_scsi_action(unsigned long _dev);
@ -415,6 +420,8 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
static void ub_reset_enter(struct ub_dev *sc);
static void ub_reset_task(void *arg);
static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret);
@ -422,13 +429,18 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum);
/*
*/
#ifdef CONFIG_USB_LIBUSUAL
#define ub_usb_ids storage_usb_ids
#else
static struct usb_device_id ub_usb_ids[] = {
// { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) }, /* SDDR-31 */
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
{ }
};
MODULE_DEVICE_TABLE(usb, ub_usb_ids);
#endif /* CONFIG_USB_LIBUSUAL */
/*
* Find me a way to identify "next free minor" for add_disk(),
@ -521,6 +533,9 @@ static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
cnt = 0;
spin_lock_irqsave(&sc->lock, flags);
cnt += sprintf(page + cnt,
"poison %d reset %d\n",
atomic_read(&sc->poison), sc->reset);
cnt += sprintf(page + cnt,
"qlen %d qmax %d\n",
sc->cmd_queue.qlen, sc->cmd_queue.qmax);
@ -770,7 +785,8 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
{
struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
int rc;
struct ub_request *urq;
int n_elem;
if (atomic_read(&sc->poison) || lun->changed) {
blkdev_dequeue_request(rq);
@ -778,66 +794,71 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
return 0;
}
if (lun->urq.rq != NULL)
return -1;
if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
blkdev_dequeue_request(rq);
if (blk_pc_request(rq)) {
rc = ub_cmd_build_packet(sc, lun, cmd, rq);
} else {
rc = ub_cmd_build_block(sc, lun, cmd, rq);
}
if (rc != 0) {
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
return 0;
}
cmd->state = UB_CMDST_INIT;
cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
cmd->back = rq;
cmd->tag = sc->tagcnt++;
if (ub_submit_scsi(sc, cmd) != 0) {
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
return 0;
}
return 0;
}
static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq)
{
int ub_dir;
int n_elem;
unsigned int block, nblks;
if (rq_data_dir(rq) == WRITE)
ub_dir = UB_DIR_WRITE;
else
ub_dir = UB_DIR_READ;
cmd->dir = ub_dir;
urq = &lun->urq;
memset(urq, 0, sizeof(struct ub_request));
urq->rq = rq;
/*
* get scatterlist from block layer
*/
n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
if (n_elem <= 0) {
n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
if (n_elem < 0) {
printk(KERN_INFO "%s: failed request map (%d)\n",
sc->name, n_elem); /* P3 */
return -1; /* request with no s/g entries? */
lun->name, n_elem); /* P3 */
goto drop;
}
if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
return -1;
lun->name, n_elem);
goto drop;
}
cmd->nsg = n_elem;
urq->nsg = n_elem;
sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
if (blk_pc_request(rq)) {
ub_cmd_build_packet(sc, lun, cmd, urq);
} else {
ub_cmd_build_block(sc, lun, cmd, urq);
}
cmd->state = UB_CMDST_INIT;
cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
cmd->back = urq;
cmd->tag = sc->tagcnt++;
if (ub_submit_scsi(sc, cmd) != 0)
goto drop;
return 0;
drop:
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
return 0;
}
static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq)
{
struct request *rq = urq->rq;
unsigned int block, nblks;
if (rq_data_dir(rq) == WRITE)
cmd->dir = UB_DIR_WRITE;
else
cmd->dir = UB_DIR_READ;
cmd->nsg = urq->nsg;
memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
/*
* build the command
*
@ -847,7 +868,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
block = rq->sector >> lun->capacity.bshift;
nblks = rq->nr_sectors >> lun->capacity.bshift;
cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
cmd->cdb[2] = block >> 24;
cmd->cdb[3] = block >> 16;
@ -858,14 +879,12 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
cmd->cdb_len = 10;
cmd->len = rq->nr_sectors * 512;
return 0;
}
static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct request *rq)
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq)
{
int n_elem;
struct request *rq = urq->rq;
if (rq->data_len == 0) {
cmd->dir = UB_DIR_NONE;
@ -874,40 +893,26 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
cmd->dir = UB_DIR_WRITE;
else
cmd->dir = UB_DIR_READ;
}
/*
* get scatterlist from block layer
*/
n_elem = blk_rq_map_sg(lun->disk->queue, rq, &cmd->sgv[0]);
if (n_elem < 0) {
printk(KERN_INFO "%s: failed request map (%d)\n",
sc->name, n_elem); /* P3 */
return -1;
}
if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
return -1;
}
cmd->nsg = n_elem;
sc->sg_stat[n_elem < 5 ? n_elem : 5]++;
cmd->nsg = urq->nsg;
memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
cmd->cdb_len = rq->cmd_len;
cmd->len = rq->data_len;
return 0;
}
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct request *rq = cmd->back;
struct ub_lun *lun = cmd->lun;
struct ub_request *urq = cmd->back;
struct request *rq;
int uptodate;
rq = urq->rq;
if (cmd->error == 0) {
uptodate = 1;
@ -928,9 +933,16 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rq->errors = SAM_STAT_CHECK_CONDITION;
else
rq->errors = DID_ERROR << 16;
} else {
if (cmd->error == -EIO) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return;
}
}
}
urq->rq = NULL;
ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
blk_start_queue(lun->disk->queue);
@ -938,13 +950,45 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
static void ub_end_rq(struct request *rq, int uptodate)
{
int rc;
rc = end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
// assert(rc == 0);
end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq);
}
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd)
{
if (atomic_read(&sc->poison))
return -ENXIO;
ub_reset_enter(sc);
if (urq->current_try >= 3)
return -EIO;
urq->current_try++;
/* P3 */ printk("%s: dir %c len/act %d/%d "
"[sense %x %02x %02x] retry %d\n",
sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
cmd->key, cmd->asc, cmd->ascq, urq->current_try);
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
ub_cmd_build_block(sc, lun, cmd, urq);
cmd->state = UB_CMDST_INIT;
cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
cmd->back = urq;
cmd->tag = sc->tagcnt++;
#if 0 /* Wasteful */
return ub_submit_scsi(sc, cmd);
#else
ub_cmdq_add(sc, cmd);
return 0;
#endif
}
/*
* Submit a regular SCSI operation (not an auto-sense).
*
@ -1075,7 +1119,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
struct ub_scsi_cmd *cmd;
int rc;
while ((cmd = ub_cmdq_peek(sc)) != NULL) {
while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) {
if (cmd->state == UB_CMDST_DONE) {
ub_cmdq_pop(sc);
(*cmd->done)(sc, cmd);
@ -1098,11 +1142,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct urb *urb = &sc->work_urb;
struct bulk_cs_wrap *bcs;
int len;
int rc;
if (atomic_read(&sc->poison)) {
/* A little too simplistic, I feel... */
goto Bad_End;
ub_state_done(sc, cmd, -ENODEV);
return;
}
if (cmd->state == UB_CMDST_CLEAR) {
@ -1110,7 +1155,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
/*
* STALL while clearning STALL.
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
@ -1129,11 +1173,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else if (cmd->state == UB_CMDST_CLR2STS) {
if (urb->status == -EPIPE) {
/*
* STALL while clearning STALL.
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
goto Bad_End;
@ -1151,11 +1190,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else if (cmd->state == UB_CMDST_CLRRS) {
if (urb->status == -EPIPE) {
/*
* STALL while clearning STALL.
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
printk(KERN_NOTICE "%s: stall on control pipe\n",
sc->name);
goto Bad_End;
@ -1172,7 +1206,12 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_state_stat_counted(sc, cmd);
} else if (cmd->state == UB_CMDST_CMD) {
if (urb->status == -EPIPE) {
switch (urb->status) {
case 0:
break;
case -EOVERFLOW:
goto Bad_End;
case -EPIPE:
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
@ -1182,17 +1221,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
*/
goto Bad_End;
ub_state_done(sc, cmd, rc);
return;
}
cmd->state = UB_CMDST_CLEAR;
ub_cmdtr_state(sc, cmd);
return;
}
if (urb->status != 0) {
case -ESHUTDOWN: /* unplug */
case -EILSEQ: /* unplug timeout on uhci */
ub_state_done(sc, cmd, -ENODEV);
return;
default:
goto Bad_End;
}
if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
/* XXX Must do reset here to unconfuse the device */
goto Bad_End;
}
@ -1211,11 +1253,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_NOTICE "%s: "
"unable to submit clear (%d)\n",
sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
*/
goto Bad_End;
ub_state_done(sc, cmd, rc);
return;
}
cmd->state = UB_CMDST_CLR2STS;
ub_cmdtr_state(sc, cmd);
@ -1224,14 +1263,50 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if (urb->status == -EOVERFLOW) {
/*
* A babble? Failure, but we must transfer CSW now.
* XXX This is going to end in perpetual babble. Reset.
*/
cmd->error = -EOVERFLOW; /* A cheap trick... */
ub_state_stat(sc, cmd);
return;
}
if (urb->status != 0)
goto Bad_End;
if (cmd->dir == UB_DIR_WRITE) {
/*
* Do not continue writes in case of a failure.
* Doing so would cause sectors to be mixed up,
* which is worse than sectors lost.
*
* We must try to read the CSW, or many devices
* get confused.
*/
len = urb->actual_length;
if (urb->status != 0 ||
len != cmd->sgv[cmd->current_sg].length) {
cmd->act_len += len;
ub_cmdtr_act_len(sc, cmd);
cmd->error = -EIO;
ub_state_stat(sc, cmd);
return;
}
} else {
/*
* If an error occurs on read, we record it, and
* continue to fetch data in order to avoid bubble.
*
* As a small shortcut, we stop if we detect that
* a CSW mixed into data.
*/
if (urb->status != 0)
cmd->error = -EIO;
len = urb->actual_length;
if (urb->status != 0 ||
len != cmd->sgv[cmd->current_sg].length) {
if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN)
goto Bad_End;
}
}
cmd->act_len += urb->actual_length;
ub_cmdtr_act_len(sc, cmd);
@ -1249,11 +1324,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_NOTICE "%s: "
"unable to submit clear (%d)\n",
sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
*/
goto Bad_End;
ub_state_done(sc, cmd, rc);
return;
}
/*
@ -1266,14 +1338,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_cmdtr_state(sc, cmd);
return;
}
if (urb->status == -EOVERFLOW) {
/*
* XXX We are screwed here. Retrying is pointless,
* because the pipelined data will not get in until
* we read with a big enough buffer. We must reset XXX.
*/
goto Bad_End;
}
/* Catch everything, including -EOVERFLOW and other nasties. */
if (urb->status != 0)
goto Bad_End;
@ -1319,15 +1385,15 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return;
}
rc = le32_to_cpu(bcs->Residue);
if (rc != cmd->len - cmd->act_len) {
len = le32_to_cpu(bcs->Residue);
if (len != cmd->len - cmd->act_len) {
/*
* It is all right to transfer less, the caller has
* to check. But it's not all right if the device
* counts disagree with our counts.
*/
/* P3 */ printk("%s: resid %d len %d act %d\n",
sc->name, rc, cmd->len, cmd->act_len);
sc->name, len, cmd->len, cmd->act_len);
goto Bad_End;
}
@ -1338,13 +1404,13 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
ub_state_sense(sc, cmd);
return;
case US_BULK_STAT_PHASE:
/* XXX We must reset the transport here */
/* P3 */ printk("%s: status PHASE\n", sc->name);
goto Bad_End;
default:
printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
sc->name, bcs->Status);
goto Bad_End;
ub_state_done(sc, cmd, -EINVAL);
return;
}
/* Not zeroing error to preserve a babble indicator */
@ -1364,7 +1430,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
printk(KERN_WARNING "%s: "
"wrong command state %d\n",
sc->name, cmd->state);
goto Bad_End;
ub_state_done(sc, cmd, -EINVAL);
return;
}
return;
@ -1611,6 +1678,93 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
ub_scsi_urb_compl(sc, cmd);
}
/*
* Reset management
*/
static void ub_reset_enter(struct ub_dev *sc)
{
if (sc->reset) {
/* This happens often on multi-LUN devices. */
return;
}
sc->reset = 1;
#if 0 /* Not needed because the disconnect waits for us. */
unsigned long flags;
spin_lock_irqsave(&ub_lock, flags);
sc->openc++;
spin_unlock_irqrestore(&ub_lock, flags);
#endif
#if 0 /* We let them stop themselves. */
struct list_head *p;
struct ub_lun *lun;
list_for_each(p, &sc->luns) {
lun = list_entry(p, struct ub_lun, link);
blk_stop_queue(lun->disk->queue);
}
#endif
schedule_work(&sc->reset_work);
}
static void ub_reset_task(void *arg)
{
struct ub_dev *sc = arg;
unsigned long flags;
struct list_head *p;
struct ub_lun *lun;
int lkr, rc;
if (!sc->reset) {
printk(KERN_WARNING "%s: Running reset unrequested\n",
sc->name);
return;
}
if (atomic_read(&sc->poison)) {
printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
sc->name); /* P3 This floods. Remove soon. XXX */
} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
sc->name); /* P3 This floods. Remove soon. XXX */
} else {
if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
printk(KERN_NOTICE
"%s: usb_lock_device_for_reset failed (%d)\n",
sc->name, lkr);
} else {
rc = usb_reset_device(sc->dev);
if (rc < 0) {
printk(KERN_NOTICE "%s: "
"usb_lock_device_for_reset failed (%d)\n",
sc->name, rc);
}
if (lkr)
usb_unlock_device(sc->dev);
}
}
/*
* In theory, no commands can be running while reset is active,
* so nobody can ask for another reset, and so we do not need any
* queues of resets or anything. We do need a spinlock though,
* to interact with block layer.
*/
spin_lock_irqsave(&sc->lock, flags);
sc->reset = 0;
tasklet_schedule(&sc->tasklet);
list_for_each(p, &sc->luns) {
lun = list_entry(p, struct ub_lun, link);
blk_start_queue(lun->disk->queue);
}
wake_up(&sc->reset_wait);
spin_unlock_irqrestore(&sc->lock, flags);
}
/*
* This is called from a process context.
*/
@ -2146,7 +2300,7 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
if (ep_in == NULL || ep_out == NULL) {
printk(KERN_NOTICE "%s: failed endpoint check\n",
sc->name);
return -EIO;
return -ENODEV;
}
/* Calculate and store the pipe values */
@ -2172,6 +2326,9 @@ static int ub_probe(struct usb_interface *intf,
int rc;
int i;
if (usb_usual_check_type(dev_id, USB_US_TYPE_UB))
return -ENXIO;
rc = -ENOMEM;
if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
goto err_core;
@ -2181,6 +2338,8 @@ static int ub_probe(struct usb_interface *intf,
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
INIT_WORK(&sc->reset_work, ub_reset_task, sc);
init_waitqueue_head(&sc->reset_wait);
init_timer(&sc->work_timer);
sc->work_timer.data = (unsigned long) sc;
@ -2201,7 +2360,8 @@ static int ub_probe(struct usb_interface *intf,
/* XXX Verify that we can handle the device (from descriptors) */
ub_get_pipes(sc, sc->dev, intf);
if (ub_get_pipes(sc, sc->dev, intf) != 0)
goto err_dev_desc;
if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
goto err_diag;
@ -2272,6 +2432,7 @@ static int ub_probe(struct usb_interface *intf,
/* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
err_diag:
err_dev_desc:
usb_set_intfdata(intf, NULL);
// usb_put_intf(sc->intf);
usb_put_dev(sc->dev);
@ -2309,14 +2470,14 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum)
ub_revalidate(sc, lun);
rc = -ENOMEM;
if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
goto err_diskalloc;
lun->disk = disk;
sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
disk->major = UB_MAJOR;
disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
disk->first_minor = lun->id * UB_PARTS_PER_LUN;
disk->fops = &ub_bd_fops;
disk->private_data = lun;
disk->driverfs_dev = &sc->intf->dev;
@ -2379,6 +2540,11 @@ static void ub_disconnect(struct usb_interface *intf)
*/
atomic_set(&sc->poison, 1);
/*
* Wait for reset to end, if any.
*/
wait_event(sc->reset_wait, !sc->reset);
/*
* Blow away queued commands.
*
@ -2392,7 +2558,7 @@ static void ub_disconnect(struct usb_interface *intf)
{
struct ub_scsi_cmd *cmd;
int cnt = 0;
while ((cmd = ub_cmdq_pop(sc)) != NULL) {
while ((cmd = ub_cmdq_peek(sc)) != NULL) {
cmd->error = -ENOTCONN;
cmd->state = UB_CMDST_DONE;
ub_cmdtr_state(sc, cmd);
@ -2461,7 +2627,6 @@ static void ub_disconnect(struct usb_interface *intf)
}
static struct usb_driver ub_driver = {
.owner = THIS_MODULE,
.name = "ub",
.probe = ub_probe,
.disconnect = ub_disconnect,
@ -2479,6 +2644,7 @@ static int __init ub_init(void)
if ((rc = usb_register(&ub_driver)) != 0)
goto err_register;
usb_usual_set_present(USB_US_TYPE_UB);
return 0;
err_register:
@ -2494,6 +2660,7 @@ static void __exit ub_exit(void)
devfs_remove(DEVFS_NAME);
unregister_blkdev(UB_MAJOR, DRV_NAME);
usb_usual_clear_present(USB_US_TYPE_UB);
}
module_init(ub_init);

View File

@ -275,7 +275,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
}
static struct usb_driver bcm203x_driver = {
.owner = THIS_MODULE,
.name = "bcm203x",
.probe = bcm203x_probe,
.disconnect = bcm203x_disconnect,

View File

@ -768,7 +768,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
}
static struct usb_driver bfusb_driver = {
.owner = THIS_MODULE,
.name = "bfusb",
.probe = bfusb_probe,
.disconnect = bfusb_disconnect,

View File

@ -619,7 +619,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
}
static struct usb_driver bpa10x_driver = {
.owner = THIS_MODULE,
.name = "bpa10x",
.probe = bpa10x_probe,
.disconnect = bpa10x_disconnect,

View File

@ -1044,7 +1044,6 @@ static void hci_usb_disconnect(struct usb_interface *intf)
}
static struct usb_driver hci_usb_driver = {
.owner = THIS_MODULE,
.name = "hci_usb",
.probe = hci_usb_probe,
.disconnect = hci_usb_disconnect,

View File

@ -151,7 +151,6 @@ static void usb_pcwd_disconnect (struct usb_interface *interface);
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver usb_pcwd_driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
.probe = usb_pcwd_probe,
.disconnect = usb_pcwd_disconnect,

View File

@ -235,7 +235,6 @@ static struct usb_device_id iforce_usb_ids [] = {
MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
struct usb_driver iforce_usb_driver = {
.owner = THIS_MODULE,
.name = "iforce",
.probe = iforce_usb_probe,
.disconnect = iforce_usb_disconnect,

View File

@ -1715,7 +1715,6 @@ hfc_usb_disconnect(struct usb_interface
/* our driver information structure */
/************************************/
static struct usb_driver hfc_drv = {
.owner = THIS_MODULE,
.name = "hfc_usb",
.id_table = hfcusb_idtab,
.probe = hfc_usb_probe,

View File

@ -180,7 +180,6 @@ static struct usb_device_id st5481_ids[] = {
MODULE_DEVICE_TABLE (usb, st5481_ids);
static struct usb_driver st5481_usb_driver = {
.owner = THIS_MODULE,
.name = "st5481_usb",
.probe = probe_st5481,
.disconnect = disconnect_st5481,

View File

@ -544,7 +544,6 @@ static struct usb_device_id flexcop_usb_table [] = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver flexcop_usb_driver = {
.owner = THIS_MODULE,
.name = "b2c2_flexcop_usb",
.probe = flexcop_usb_probe,
.disconnect = flexcop_usb_disconnect,

View File

@ -986,7 +986,6 @@ static const struct usb_device_id cinergyt2_table [] __devinitdata = {
MODULE_DEVICE_TABLE(usb, cinergyt2_table);
static struct usb_driver cinergyt2_driver = {
.owner = THIS_MODULE,
.name = "cinergyT2",
.probe = cinergyt2_probe,
.disconnect = cinergyt2_disconnect,

View File

@ -144,7 +144,6 @@ static struct dvb_usb_properties a800_properties = {
};
static struct usb_driver a800_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_a800",
.probe = a800_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -241,7 +241,6 @@ static struct dvb_usb_properties cxusb_properties = {
};
static struct usb_driver cxusb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -373,7 +373,6 @@ static struct dvb_usb_properties artec_t1_usb2_properties = {
};
static struct usb_driver dibusb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dibusb_mb",
.probe = dibusb_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -82,7 +82,6 @@ static struct dvb_usb_properties dibusb_mc_properties = {
};
static struct usb_driver dibusb_mc_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dibusb_mc",
.probe = dibusb_mc_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -233,7 +233,6 @@ static struct dvb_usb_properties digitv_properties = {
};
static struct usb_driver digitv_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_digitv",
.probe = digitv_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -198,7 +198,6 @@ static struct dvb_usb_properties wt220u_properties = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver dtt200u_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_dtt200u",
.probe = dtt200u_usb_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -202,7 +202,6 @@ static struct dvb_usb_properties nova_t_properties = {
};
static struct usb_driver nova_t_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_nova_t_usb2",
.probe = nova_t_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -128,7 +128,6 @@ static struct dvb_usb_properties umt_properties = {
};
static struct usb_driver umt_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_umt_010",
.probe = umt_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -256,7 +256,6 @@ static struct dvb_usb_properties vp702x_properties = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver vp702x_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb-usb-vp702x",
.probe = vp702x_usb_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -253,7 +253,6 @@ static struct dvb_usb_properties vp7045_properties = {
/* usb specific object needed to register this driver with the usb subsystem */
static struct usb_driver vp7045_usb_driver = {
.owner = THIS_MODULE,
.name = "dvb_usb_vp7045",
.probe = vp7045_usb_probe,
.disconnect = dvb_usb_device_exit,

View File

@ -582,7 +582,6 @@ MODULE_LICENSE("GPL");
static struct usb_driver cpia_driver = {
.owner = THIS_MODULE,
.name = "cpia",
.probe = cpia_probe,
.disconnect = cpia_disconnect,

View File

@ -1884,7 +1884,6 @@ static void em28xx_usb_disconnect(struct usb_interface *interface)
}
static struct usb_driver em28xx_usb_driver = {
.owner = THIS_MODULE,
.name = "em28xx",
.probe = em28xx_usb_probe,
.disconnect = em28xx_usb_disconnect,

View File

@ -1539,7 +1539,6 @@ static void irda_usb_disconnect(struct usb_interface *intf)
* USB device callbacks
*/
static struct usb_driver irda_driver = {
.owner = THIS_MODULE,
.name = "irda-usb",
.probe = irda_usb_probe,
.disconnect = irda_usb_disconnect,

View File

@ -1152,7 +1152,6 @@ static int stir_resume(struct usb_interface *intf)
* USB device callbacks
*/
static struct usb_driver irda_driver = {
.owner = THIS_MODULE,
.name = "stir4200",
.probe = stir_probe,
.disconnect = stir_disconnect,

View File

@ -22,6 +22,7 @@ obj-$(CONFIG_USB_MIDI) += class/
obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB) += storage/
obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/

View File

@ -44,6 +44,19 @@ config USB_CXACRU
To compile this driver as a module, choose M here: the
module will be called cxacru.
config USB_UEAGLEATM
tristate "ADI 930 and eagle USB DSL modem"
depends on USB_ATM
select FW_LOADER
help
Say Y here if you have an ADSL USB modem based on the ADI 930
or eagle chipset. In order to use your modem you will need to
install firmwares and CMV (Command Management Variables); see
<https://gna.org/projects/ueagleatm/> for details.
To compile this driver as a module, choose M here: the
module will be called ueagle-atm.
config USB_XUSBATM
tristate "Other USB DSL modem support"
depends on USB_ATM

View File

@ -4,6 +4,7 @@
obj-$(CONFIG_USB_CXACRU) += cxacru.o
obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o
obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o
obj-$(CONFIG_USB_ATM) += usbatm.o
obj-$(CONFIG_USB_XUSBATM) += xusbatm.o

View File

@ -853,7 +853,6 @@ static int cxacru_usb_probe(struct usb_interface *intf, const struct usb_device_
}
static struct usb_driver cxacru_usb_driver = {
.owner = THIS_MODULE,
.name = cxacru_driver_name,
.probe = cxacru_usb_probe,
.disconnect = usbatm_usb_disconnect,

View File

@ -659,7 +659,6 @@ MODULE_DEVICE_TABLE(usb, speedtch_usb_ids);
static int speedtch_usb_probe(struct usb_interface *, const struct usb_device_id *);
static struct usb_driver speedtch_usb_driver = {
.owner = THIS_MODULE,
.name = speedtch_driver_name,
.probe = speedtch_usb_probe,
.disconnect = usbatm_usb_disconnect,

1820
drivers/usb/atm/ueagle-atm.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -646,14 +646,14 @@ static void usbatm_destroy_instance(struct kref *kref)
kfree(instance);
}
void usbatm_get_instance(struct usbatm_data *instance)
static void usbatm_get_instance(struct usbatm_data *instance)
{
dbg("%s", __func__);
kref_get(&instance->refcount);
}
void usbatm_put_instance(struct usbatm_data *instance)
static void usbatm_put_instance(struct usbatm_data *instance)
{
dbg("%s", __func__);

View File

@ -140,7 +140,6 @@ static int xusbatm_usb_probe(struct usb_interface *intf,
}
static struct usb_driver xusbatm_usb_driver = {
.owner = THIS_MODULE,
.name = xusbatm_driver_name,
.probe = xusbatm_usb_probe,
.disconnect = usbatm_usb_disconnect,

View File

@ -2732,7 +2732,6 @@ static struct usb_device_id usb_audio_ids [] = {
MODULE_DEVICE_TABLE (usb, usb_audio_ids);
static struct usb_driver usb_audio_driver = {
.owner = THIS_MODULE,
.name = "audio",
.probe = usb_audio_probe,
.disconnect = usb_audio_disconnect,

View File

@ -6,6 +6,7 @@
* Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Oliver Neukum <oliver@neukum.name>
* Copyright (c) 2005 David Kubicek <dave@awk.cz>
*
* USB Abstract Control Model driver for USB modems and ISDN adapters
*
@ -29,6 +30,7 @@
* config we want, sysadmin changes bConfigurationValue in sysfs.
* v0.23 - use softirq for rx processing, as needed by tty layer
* v0.24 - change probe method to evaluate CDC union descriptor
* v0.25 - downstream tasks paralelized to maximize throughput
*/
/*
@ -63,14 +65,15 @@
#include <linux/usb_cdc.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <linux/list.h>
#include "cdc-acm.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v0.23"
#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
#define DRIVER_VERSION "v0.25"
#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik, David Kubicek"
#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
static struct usb_driver acm_driver;
@ -284,7 +287,9 @@ exit:
/* data interface returns incoming bytes, or we got unthrottled */
static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
{
struct acm *acm = urb->context;
struct acm_rb *buf;
struct acm_ru *rcv = urb->context;
struct acm *acm = rcv->instance;
dbg("Entering acm_read_bulk with status %d\n", urb->status);
if (!ACM_READY(acm))
@ -293,49 +298,109 @@ static void acm_read_bulk(struct urb *urb, struct pt_regs *regs)
if (urb->status)
dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
/* calling tty_flip_buffer_push() in_irq() isn't allowed */
tasklet_schedule(&acm->bh);
buf = rcv->buffer;
buf->size = urb->actual_length;
spin_lock(&acm->read_lock);
list_add_tail(&rcv->list, &acm->spare_read_urbs);
list_add_tail(&buf->list, &acm->filled_read_bufs);
spin_unlock(&acm->read_lock);
tasklet_schedule(&acm->urb_task);
}
static void acm_rx_tasklet(unsigned long _acm)
{
struct acm *acm = (void *)_acm;
struct urb *urb = acm->readurb;
struct acm_rb *buf;
struct tty_struct *tty = acm->tty;
unsigned char *data = urb->transfer_buffer;
struct acm_ru *rcv;
//unsigned long flags;
int i = 0;
dbg("Entering acm_rx_tasklet");
if (urb->actual_length > 0 && !acm->throttle) {
for (i = 0; i < urb->actual_length && !acm->throttle; i++) {
/* if we insert more than TTY_FLIPBUF_SIZE characters,
* we drop them. */
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
tty_insert_flip_char(tty, data[i], 0);
}
dbg("Handed %d bytes to tty layer", i+1);
tty_flip_buffer_push(tty);
if (!ACM_READY(acm) || acm->throttle)
return;
next_buffer:
spin_lock(&acm->read_lock);
if (list_empty(&acm->filled_read_bufs)) {
spin_unlock(&acm->read_lock);
goto urbs;
}
buf = list_entry(acm->filled_read_bufs.next,
struct acm_rb, list);
list_del(&buf->list);
spin_unlock(&acm->read_lock);
dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d\n", buf, buf->size);
for (i = 0; i < buf->size && !acm->throttle; i++) {
/* if we insert more than TTY_FLIPBUF_SIZE characters,
we drop them. */
if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
tty_insert_flip_char(tty, buf->base[i], 0);
}
tty_flip_buffer_push(tty);
spin_lock(&acm->throttle_lock);
if (acm->throttle) {
dbg("Throtteling noticed");
memmove(data, data + i, urb->actual_length - i);
urb->actual_length -= i;
acm->resubmit_to_unthrottle = 1;
memmove(buf->base, buf->base + i, buf->size - i);
buf->size -= i;
spin_unlock(&acm->throttle_lock);
spin_lock(&acm->read_lock);
list_add(&buf->list, &acm->filled_read_bufs);
spin_unlock(&acm->read_lock);
return;
}
spin_unlock(&acm->throttle_lock);
urb->actual_length = 0;
urb->dev = acm->dev;
spin_lock(&acm->read_lock);
list_add(&buf->list, &acm->spare_read_bufs);
spin_unlock(&acm->read_lock);
goto next_buffer;
i = usb_submit_urb(urb, GFP_ATOMIC);
if (i)
dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
urbs:
while (!list_empty(&acm->spare_read_bufs)) {
spin_lock(&acm->read_lock);
if (list_empty(&acm->spare_read_urbs)) {
spin_unlock(&acm->read_lock);
return;
}
rcv = list_entry(acm->spare_read_urbs.next,
struct acm_ru, list);
list_del(&rcv->list);
spin_unlock(&acm->read_lock);
buf = list_entry(acm->spare_read_bufs.next,
struct acm_rb, list);
list_del(&buf->list);
rcv->buffer = buf;
usb_fill_bulk_urb(rcv->urb, acm->dev,
acm->rx_endpoint,
buf->base,
acm->readsize,
acm_read_bulk, rcv);
rcv->urb->transfer_dma = buf->dma;
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
/* This shouldn't kill the driver as unsuccessful URBs are returned to the
free-urbs-pool and resubmited ASAP */
if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
list_add(&buf->list, &acm->spare_read_bufs);
spin_lock(&acm->read_lock);
list_add(&rcv->list, &acm->spare_read_urbs);
spin_unlock(&acm->read_lock);
return;
}
}
}
/* data interface wrote those outgoing bytes */
@ -369,6 +434,7 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
{
struct acm *acm;
int rv = -EINVAL;
int i;
dbg("Entering acm_tty_open.\n");
down(&open_sem);
@ -382,7 +448,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
tty->driver_data = acm;
acm->tty = tty;
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates data can get lost. */
tty->low_latency = 1;
if (acm->used++) {
goto done;
@ -394,18 +462,20 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto bail_out;
}
acm->readurb->dev = acm->dev;
if (usb_submit_urb(acm->readurb, GFP_KERNEL)) {
dbg("usb_submit_urb(read bulk) failed");
goto bail_out_and_unlink;
}
if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS))
goto full_bailout;
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates data can get lost. */
tty->low_latency = 1;
INIT_LIST_HEAD(&acm->spare_read_urbs);
INIT_LIST_HEAD(&acm->spare_read_bufs);
INIT_LIST_HEAD(&acm->filled_read_bufs);
for (i = 0; i < ACM_NRU; i++) {
list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
}
for (i = 0; i < ACM_NRB; i++) {
list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
}
tasklet_schedule(&acm->urb_task);
done:
err_out:
@ -413,8 +483,6 @@ err_out:
return rv;
full_bailout:
usb_kill_urb(acm->readurb);
bail_out_and_unlink:
usb_kill_urb(acm->ctrlurb);
bail_out:
acm->used--;
@ -424,18 +492,22 @@ bail_out:
static void acm_tty_unregister(struct acm *acm)
{
int i;
tty_unregister_device(acm_tty_driver, acm->minor);
usb_put_intf(acm->control);
acm_table[acm->minor] = NULL;
usb_free_urb(acm->ctrlurb);
usb_free_urb(acm->readurb);
usb_free_urb(acm->writeurb);
for (i = 0; i < ACM_NRU; i++)
usb_free_urb(acm->ru[i].urb);
kfree(acm);
}
static void acm_tty_close(struct tty_struct *tty, struct file *filp)
{
struct acm *acm = tty->driver_data;
int i;
if (!acm || !acm->used)
return;
@ -446,7 +518,8 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
acm_set_control(acm, acm->ctrlout = 0);
usb_kill_urb(acm->ctrlurb);
usb_kill_urb(acm->writeurb);
usb_kill_urb(acm->readurb);
for (i = 0; i < ACM_NRU; i++)
usb_kill_urb(acm->ru[i].urb);
} else
acm_tty_unregister(acm);
}
@ -528,10 +601,7 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
spin_lock_bh(&acm->throttle_lock);
acm->throttle = 0;
spin_unlock_bh(&acm->throttle_lock);
if (acm->resubmit_to_unthrottle) {
acm->resubmit_to_unthrottle = 0;
acm_read_bulk(acm->readurb, NULL);
}
tasklet_schedule(&acm->urb_task);
}
static void acm_tty_break_ctl(struct tty_struct *tty, int state)
@ -588,7 +658,7 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
return -ENOIOCTLCMD;
}
static __u32 acm_tty_speed[] = {
static const __u32 acm_tty_speed[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600,
1200, 1800, 2400, 4800, 9600, 19200, 38400,
57600, 115200, 230400, 460800, 500000, 576000,
@ -596,7 +666,7 @@ static __u32 acm_tty_speed[] = {
2500000, 3000000, 3500000, 4000000
};
static __u8 acm_tty_size[] = {
static const __u8 acm_tty_size[] = {
5, 6, 7, 8
};
@ -694,6 +764,7 @@ static int acm_probe (struct usb_interface *intf,
int call_interface_num = -1;
int data_interface_num;
unsigned long quirks;
int i;
/* handle quirks deadly to normal probing*/
quirks = (unsigned long)id->driver_info;
@ -833,7 +904,7 @@ skip_normal_probe:
}
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
readsize = le16_to_cpu(epread->wMaxPacketSize);
readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
acm->control = control_interface;
acm->data = data_interface;
@ -842,12 +913,14 @@ skip_normal_probe:
acm->ctrl_caps = ac_management_function;
acm->ctrlsize = ctrlsize;
acm->readsize = readsize;
acm->bh.func = acm_rx_tasklet;
acm->bh.data = (unsigned long) acm;
acm->urb_task.func = acm_rx_tasklet;
acm->urb_task.data = (unsigned long) acm;
INIT_WORK(&acm->work, acm_softint, acm);
spin_lock_init(&acm->throttle_lock);
spin_lock_init(&acm->write_lock);
spin_lock_init(&acm->read_lock);
acm->write_ready = 1;
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
@ -856,13 +929,6 @@ skip_normal_probe:
}
acm->ctrl_buffer = buf;
buf = usb_buffer_alloc(usb_dev, readsize, GFP_KERNEL, &acm->read_dma);
if (!buf) {
dev_dbg(&intf->dev, "out of memory (read buffer alloc)\n");
goto alloc_fail3;
}
acm->read_buffer = buf;
if (acm_write_buffers_alloc(acm) < 0) {
dev_dbg(&intf->dev, "out of memory (write buffer alloc)\n");
goto alloc_fail4;
@ -873,10 +939,25 @@ skip_normal_probe:
dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
goto alloc_fail5;
}
acm->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->readurb) {
dev_dbg(&intf->dev, "out of memory (readurb kmalloc)\n");
goto alloc_fail6;
for (i = 0; i < ACM_NRU; i++) {
struct acm_ru *rcv = &(acm->ru[i]);
if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n");
goto alloc_fail7;
}
rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
rcv->instance = acm;
}
for (i = 0; i < ACM_NRB; i++) {
struct acm_rb *buf = &(acm->rb[i]);
// Using usb_buffer_alloc instead of kmalloc as Oliver suggested
if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
goto alloc_fail7;
}
}
acm->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!acm->writeurb) {
@ -889,15 +970,9 @@ skip_normal_probe:
acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
acm->ctrlurb->transfer_dma = acm->ctrl_dma;
usb_fill_bulk_urb(acm->readurb, usb_dev, usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress),
acm->read_buffer, readsize, acm_read_bulk, acm);
acm->readurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
acm->readurb->transfer_dma = acm->read_dma;
usb_fill_bulk_urb(acm->writeurb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
NULL, acm->writesize, acm_write_bulk, acm);
acm->writeurb->transfer_flags |= URB_NO_FSBR | URB_NO_TRANSFER_DMA_MAP;
/* acm->writeurb->transfer_dma = 0; */
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
@ -917,14 +992,14 @@ skip_normal_probe:
return 0;
alloc_fail7:
usb_free_urb(acm->readurb);
alloc_fail6:
for (i = 0; i < ACM_NRB; i++)
usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
for (i = 0; i < ACM_NRU; i++)
usb_free_urb(acm->ru[i].urb);
usb_free_urb(acm->ctrlurb);
alloc_fail5:
acm_write_buffers_free(acm);
alloc_fail4:
usb_buffer_free(usb_dev, readsize, acm->read_buffer, acm->read_dma);
alloc_fail3:
usb_buffer_free(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
alloc_fail2:
kfree(acm);
@ -936,6 +1011,7 @@ static void acm_disconnect(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata (intf);
struct usb_device *usb_dev = interface_to_usbdev(intf);
int i;
if (!acm || !acm->dev) {
dbg("disconnect on nonexisting interface");
@ -946,15 +1022,24 @@ static void acm_disconnect(struct usb_interface *intf)
acm->dev = NULL;
usb_set_intfdata (intf, NULL);
tasklet_disable(&acm->urb_task);
usb_kill_urb(acm->ctrlurb);
usb_kill_urb(acm->readurb);
usb_kill_urb(acm->writeurb);
for (i = 0; i < ACM_NRU; i++)
usb_kill_urb(acm->ru[i].urb);
INIT_LIST_HEAD(&acm->filled_read_bufs);
INIT_LIST_HEAD(&acm->spare_read_bufs);
tasklet_enable(&acm->urb_task);
flush_scheduled_work(); /* wait for acm_softint */
acm_write_buffers_free(acm);
usb_buffer_free(usb_dev, acm->readsize, acm->read_buffer, acm->read_dma);
usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
for (i = 0; i < ACM_NRB; i++)
usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
usb_driver_release_interface(&acm_driver, acm->data);
@ -1003,7 +1088,6 @@ static struct usb_device_id acm_ids[] = {
MODULE_DEVICE_TABLE (usb, acm_ids);
static struct usb_driver acm_driver = {
.owner = THIS_MODULE,
.name = "cdc_acm",
.probe = acm_probe,
.disconnect = acm_disconnect,

View File

@ -59,6 +59,9 @@
* when processing onlcr, so we only need 2 buffers.
*/
#define ACM_NWB 2
#define ACM_NRU 16
#define ACM_NRB 16
struct acm_wb {
unsigned char *buf;
dma_addr_t dmah;
@ -66,22 +69,43 @@ struct acm_wb {
int use;
};
struct acm_rb {
struct list_head list;
int size;
unsigned char *base;
dma_addr_t dma;
};
struct acm_ru {
struct list_head list;
struct acm_rb *buffer;
struct urb *urb;
struct acm *instance;
};
struct acm {
struct usb_device *dev; /* the corresponding usb device */
struct usb_interface *control; /* control interface */
struct usb_interface *data; /* data interface */
struct tty_struct *tty; /* the corresponding tty */
struct urb *ctrlurb, *readurb, *writeurb; /* urbs */
u8 *ctrl_buffer, *read_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma, read_dma; /* dma handles of buffers */
struct urb *ctrlurb, *writeurb; /* urbs */
u8 *ctrl_buffer; /* buffers of urbs */
dma_addr_t ctrl_dma; /* dma handles of buffers */
struct acm_wb wb[ACM_NWB];
struct acm_ru ru[ACM_NRU];
struct acm_rb rb[ACM_NRB];
int rx_endpoint;
spinlock_t read_lock;
struct list_head spare_read_urbs;
struct list_head spare_read_bufs;
struct list_head filled_read_bufs;
int write_current; /* current write buffer */
int write_used; /* number of non-empty write buffers */
int write_ready; /* write urb is not running */
spinlock_t write_lock;
struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
struct tasklet_struct bh; /* rx processing */
struct tasklet_struct urb_task; /* rx processing */
spinlock_t throttle_lock; /* synchronize throtteling and read callback */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
@ -91,7 +115,6 @@ struct acm {
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
unsigned char resubmit_to_unthrottle; /* throtteling has disabled the read urb */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
};

View File

@ -2027,7 +2027,6 @@ static struct usb_device_id id_table[] = {
};
static struct usb_driver usb_midi_driver = {
.owner = THIS_MODULE,
.name = "midi",
.probe = usb_midi_probe,
.disconnect = usb_midi_disconnect,

View File

@ -199,7 +199,7 @@ struct quirk_printer_struct {
#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */
#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */
static struct quirk_printer_struct quirk_printers[] = {
static const struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */
{ 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
@ -301,7 +301,7 @@ static void usblp_bulk_write(struct urb *urb, struct pt_regs *regs)
* Get and print printer errors.
*/
static char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
static const char *usblp_messages[] = { "ok", "out of paper", "off-line", "on fire" };
static int usblp_check_status(struct usblp *usblp, int err)
{
@ -438,7 +438,7 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
| (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
}
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
int length, err, i;
@ -838,7 +838,8 @@ static struct file_operations usblp_fops = {
.read = usblp_read,
.write = usblp_write,
.poll = usblp_poll,
.ioctl = usblp_ioctl,
.unlocked_ioctl = usblp_ioctl,
.compat_ioctl = usblp_ioctl,
.open = usblp_open,
.release = usblp_release,
};
@ -849,6 +850,20 @@ static struct usb_class_driver usblp_class = {
.minor_base = USBLP_MINOR_BASE,
};
static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usblp *usblp = usb_get_intfdata (intf);
if (usblp->device_id_string[0] == 0 &&
usblp->device_id_string[1] == 0)
return 0;
return sprintf(buf, "%s", usblp->device_id_string+2);
}
static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL);
static int usblp_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@ -933,20 +948,12 @@ static int usblp_probe(struct usb_interface *intf,
/* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp);
device_create_file(&intf->dev, &dev_attr_ieee1284_id);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
info("usblp%d: USB %sdirectional printer dev %d "
"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
usblp->current_protocol,
le16_to_cpu(usblp->dev->descriptor.idVendor),
le16_to_cpu(usblp->dev->descriptor.idProduct));
usb_set_intfdata (intf, usblp);
usblp->present = 1;
@ -957,11 +964,20 @@ static int usblp_probe(struct usb_interface *intf,
goto abort_intfdata;
}
usblp->minor = intf->minor;
info("usblp%d: USB %sdirectional printer dev %d "
"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
usblp->current_protocol,
le16_to_cpu(usblp->dev->descriptor.idVendor),
le16_to_cpu(usblp->dev->descriptor.idProduct));
return 0;
abort_intfdata:
usb_set_intfdata (intf, NULL);
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
abort:
if (usblp) {
if (usblp->writebuf)
@ -1156,6 +1172,8 @@ static void usblp_disconnect(struct usb_interface *intf)
BUG ();
}
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
down (&usblp_sem);
down (&usblp->sem);
usblp->present = 0;
@ -1186,7 +1204,6 @@ static struct usb_device_id usblp_ids [] = {
MODULE_DEVICE_TABLE (usb, usblp_ids);
static struct usb_driver usblp_driver = {
.owner = THIS_MODULE,
.name = "usblp",
.probe = usblp_probe,
.disconnect = usblp_disconnect,

View File

@ -2,7 +2,7 @@
# Makefile for USB Core files and filesystem
#
usbcore-objs := usb.o hub.o hcd.o urb.o message.o \
usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o devio.o notify.o
ifeq ($(CONFIG_PCI),y)

View File

@ -55,6 +55,9 @@ int hcd_buffer_create (struct usb_hcd *hcd)
char name [16];
int i, size;
if (!hcd->self.controller->dma_mask)
return 0;
for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (!(size = pool_max [i]))
continue;

View File

@ -67,45 +67,45 @@
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
static char *format_topo =
static const char *format_topo =
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
static char *format_string_manufacturer =
static const char *format_string_manufacturer =
/* S: Manufacturer=xxxx */
"S: Manufacturer=%.100s\n";
static char *format_string_product =
static const char *format_string_product =
/* S: Product=xxxx */
"S: Product=%.100s\n";
#ifdef ALLOW_SERIAL_NUMBER
static char *format_string_serialnumber =
static const char *format_string_serialnumber =
/* S: SerialNumber=xxxx */
"S: SerialNumber=%.100s\n";
#endif
static char *format_bandwidth =
static const char *format_bandwidth =
/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
"B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
static char *format_device1 =
static const char *format_device1 =
/* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
"D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
static char *format_device2 =
static const char *format_device2 =
/* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
"P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
static char *format_config =
static const char *format_config =
/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
"C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
static char *format_iface =
static const char *format_iface =
/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
"I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
static char *format_endpt =
static const char *format_endpt =
/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
"E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
struct usb_device *childdev = usbdev->children[chix];
if (childdev) {
down(&childdev->serialize);
usb_lock_device(childdev);
ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
bus, level + 1, chix, ++cnt);
up(&childdev->serialize);
usb_unlock_device(childdev);
if (ret == -EFAULT)
return total_written;
total_written += ret;

View File

@ -402,7 +402,6 @@ static void driver_disconnect(struct usb_interface *intf)
}
struct usb_driver usbfs_driver = {
.owner = THIS_MODULE,
.name = "usbfs",
.probe = driver_probe,
.disconnect = driver_disconnect,
@ -1350,9 +1349,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
usb_unlock_device(ps->dev);
usb_lock_all_devices();
bus_rescan_devices(intf->dev.bus);
usb_unlock_all_devices();
usb_lock_device(ps->dev);
break;

472
drivers/usb/core/driver.c Normal file
View File

@ -0,0 +1,472 @@
/*
* drivers/usb/driver.c - most of the driver model stuff for usb
*
* (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
*
* based on drivers/usb/usb.c which had the following copyrights:
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999 (new USB architecture)
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2004
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002-2003
*
* NOTE! This is not actually a driver at all, rather this is
* just a collection of helper routines that implement the
* generic USB things that the real drivers can use..
*
*/
#include <linux/config.h>
#include <linux/device.h>
#include <linux/usb.h>
#include "hcd.h"
#include "usb.h"
static int usb_match_one_id(struct usb_interface *interface,
const struct usb_device_id *id);
struct usb_dynid {
struct list_head node;
struct usb_device_id id;
};
static int generic_probe(struct device *dev)
{
return 0;
}
static int generic_remove(struct device *dev)
{
struct usb_device *udev = to_usb_device(dev);
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->state == USB_STATE_CONFIGURED)
usb_set_configuration(udev, 0);
/* in case the call failed or the device was suspended */
if (udev->state >= USB_STATE_CONFIGURED)
usb_disable_device(udev, 0);
return 0;
}
struct device_driver usb_generic_driver = {
.owner = THIS_MODULE,
.name = "usb",
.bus = &usb_bus_type,
.probe = generic_probe,
.remove = generic_remove,
};
/* Fun hack to determine if the struct device is a
* usb device or a usb interface. */
int usb_generic_driver_data;
#ifdef CONFIG_HOTPLUG
/*
* Adds a new dynamic USBdevice ID to this driver,
* and cause the driver to probe for all devices again.
*/
static ssize_t store_new_id(struct device_driver *driver,
const char *buf, size_t count)
{
struct usb_driver *usb_drv = to_usb_driver(driver);
struct usb_dynid *dynid;
u32 idVendor = 0;
u32 idProduct = 0;
int fields = 0;
fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
if (fields < 2)
return -EINVAL;
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid)
return -ENOMEM;
INIT_LIST_HEAD(&dynid->node);
dynid->id.idVendor = idVendor;
dynid->id.idProduct = idProduct;
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
spin_lock(&usb_drv->dynids.lock);
list_add_tail(&usb_drv->dynids.list, &dynid->node);
spin_unlock(&usb_drv->dynids.lock);
if (get_driver(driver)) {
driver_attach(driver);
put_driver(driver);
}
return count;
}
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
static int usb_create_newid_file(struct usb_driver *usb_drv)
{
int error = 0;
if (usb_drv->no_dynamic_id)
goto exit;
if (usb_drv->probe != NULL)
error = sysfs_create_file(&usb_drv->driver.kobj,
&driver_attr_new_id.attr);
exit:
return error;
}
static void usb_remove_newid_file(struct usb_driver *usb_drv)
{
if (usb_drv->no_dynamic_id)
return;
if (usb_drv->probe != NULL)
sysfs_remove_file(&usb_drv->driver.kobj,
&driver_attr_new_id.attr);
}
static void usb_free_dynids(struct usb_driver *usb_drv)
{
struct usb_dynid *dynid, *n;
spin_lock(&usb_drv->dynids.lock);
list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
spin_unlock(&usb_drv->dynids.lock);
}
#else
static inline int usb_create_newid_file(struct usb_driver *usb_drv)
{
return 0;
}
static void usb_remove_newid_file(struct usb_driver *usb_drv)
{
}
static inline void usb_free_dynids(struct usb_driver *usb_drv)
{
}
#endif
static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
struct usb_driver *drv)
{
struct usb_dynid *dynid;
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (usb_match_one_id(intf, &dynid->id)) {
spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
spin_unlock(&drv->dynids.lock);
return NULL;
}
/* called from driver core with usb_bus_type.subsys writelock */
static int usb_probe_interface(struct device *dev)
{
struct usb_interface * intf = to_usb_interface(dev);
struct usb_driver * driver = to_usb_driver(dev->driver);
const struct usb_device_id *id;
int error = -ENODEV;
dev_dbg(dev, "%s\n", __FUNCTION__);
if (!driver->probe)
return error;
/* FIXME we'd much prefer to just resume it ... */
if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
id = usb_match_id(intf, driver->id_table);
if (!id)
id = usb_match_dynamic_id(intf, driver);
if (id) {
dev_dbg(dev, "%s - got id\n", __FUNCTION__);
/* Interface "power state" doesn't correspond to any hardware
* state whatsoever. We use it to record when it's bound to
* a driver that may start I/0: it's not frozen/quiesced.
*/
mark_active(intf);
intf->condition = USB_INTERFACE_BINDING;
error = driver->probe(intf, id);
if (error) {
mark_quiesced(intf);
intf->condition = USB_INTERFACE_UNBOUND;
} else
intf->condition = USB_INTERFACE_BOUND;
}
return error;
}
/* called from driver core with usb_bus_type.subsys writelock */
static int usb_unbind_interface(struct device *dev)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_driver *driver = to_usb_driver(intf->dev.driver);
intf->condition = USB_INTERFACE_UNBINDING;
/* release all urbs for this interface */
usb_disable_interface(interface_to_usbdev(intf), intf);
if (driver && driver->disconnect)
driver->disconnect(intf);
/* reset other interface state */
usb_set_interface(interface_to_usbdev(intf),
intf->altsetting[0].desc.bInterfaceNumber,
0);
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
mark_quiesced(intf);
return 0;
}
/* returns 0 if no match, 1 if match */
static int usb_match_one_id(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return 0;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
return 0;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
return 0;
return 1;
}
/**
* usb_match_id - find first usb_device_id matching device or interface
* @interface: the interface of interest
* @id: array of usb_device_id structures, terminated by zero entry
*
* usb_match_id searches an array of usb_device_id's and returns
* the first one matching the device or interface, or null.
* This is used when binding (or rebinding) a driver to an interface.
* Most USB device drivers will use this indirectly, through the usb core,
* but some layered driver frameworks use it directly.
* These device tables are exported with MODULE_DEVICE_TABLE, through
* modutils, to support the driver loading functionality of USB hotplugging.
*
* What Matches:
*
* The "match_flags" element in a usb_device_id controls which
* members are used. If the corresponding bit is set, the
* value in the device_id must match its corresponding member
* in the device or interface descriptor, or else the device_id
* does not match.
*
* "driver_info" is normally used only by device drivers,
* but you can create a wildcard "matches anything" usb_device_id
* as a driver's "modules.usbmap" entry if you provide an id with
* only a nonzero "driver_info" field. If you do this, the USB device
* driver's probe() routine should use additional intelligence to
* decide whether to bind to the specified interface.
*
* What Makes Good usb_device_id Tables:
*
* The match algorithm is very simple, so that intelligence in
* driver selection must come from smart driver id records.
* Unless you have good reasons to use another selection policy,
* provide match elements only in related groups, and order match
* specifiers from specific to general. Use the macros provided
* for that purpose if you can.
*
* The most specific match specifiers use device descriptor
* data. These are commonly used with product-specific matches;
* the USB_DEVICE macro lets you provide vendor and product IDs,
* and you can also match against ranges of product revisions.
* These are widely used for devices with application or vendor
* specific bDeviceClass values.
*
* Matches based on device class/subclass/protocol specifications
* are slightly more general; use the USB_DEVICE_INFO macro, or
* its siblings. These are used with single-function devices
* where bDeviceClass doesn't specify that each interface has
* its own class.
*
* Matches based on interface class/subclass/protocol are the
* 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).
*
* Within those groups, remember that not all combinations are
* meaningful. For example, don't give a product version range
* without vendor and product IDs; or specify a protocol without
* its associated class and subclass.
*/
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id)
{
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return NULL;
/* It is important to check that id->driver_info is nonzero,
since an entry that is all zeroes except for a nonzero
id->driver_info is the way to create an entry that
indicates that the driver want to examine every
device and interface. */
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
id->driver_info; id++) {
if (usb_match_one_id(interface, id))
return id;
}
return NULL;
}
EXPORT_SYMBOL_GPL(usb_match_id);
int usb_device_match(struct device *dev, struct device_driver *drv)
{
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* check for generic driver, which we don't match any device with */
if (drv == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
return 0;
}
/**
* usb_register_driver - register a USB driver
* @new_driver: USB operations for the driver
* @owner: module owner of this driver.
*
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/
int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
{
int retval = 0;
if (usb_disabled())
return -ENODEV;
new_driver->driver.name = (char *)new_driver->name;
new_driver->driver.bus = &usb_bus_type;
new_driver->driver.probe = usb_probe_interface;
new_driver->driver.remove = usb_unbind_interface;
new_driver->driver.owner = owner;
spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->driver);
if (!retval) {
pr_info("%s: registered new driver %s\n",
usbcore_name, new_driver->name);
usbfs_update_special();
usb_create_newid_file(new_driver);
} else {
printk(KERN_ERR "%s: error %d registering driver %s\n",
usbcore_name, retval, new_driver->name);
}
return retval;
}
EXPORT_SYMBOL_GPL(usb_register_driver);
/**
* usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister
* Context: must be able to sleep
*
* Unlinks the specified driver from the internal USB driver list.
*
* NOTE: If you called usb_register_dev(), you still need to call
* usb_deregister_dev() to clean up your driver's allocated minor numbers,
* this * call will no longer do it for you.
*/
void usb_deregister(struct usb_driver *driver)
{
pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
usb_remove_newid_file(driver);
usb_free_dynids(driver);
driver_unregister(&driver->driver);
usbfs_update_special();
}
EXPORT_SYMBOL_GPL(usb_deregister);

View File

@ -857,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
return (retval < 0) ? retval : -EMSGSIZE;
}
usb_lock_device (usb_dev);
retval = usb_new_device (usb_dev);
usb_unlock_device (usb_dev);
if (retval) {
usb_dev->bus->root_hub = NULL;
dev_err (parent_dev, "can't register root hub for %s, %d\n",
@ -1827,8 +1825,6 @@ int usb_add_hcd(struct usb_hcd *hcd,
retval = -ENOMEM;
goto err_allocate_root_hub;
}
rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
USB_SPEED_FULL;
/* Although in principle hcd->driver->start() might need to use rhdev,
* none of the current drivers do.
@ -1846,6 +1842,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
hcd->remote_wakeup = hcd->can_wakeup;
rhdev->speed = (hcd->driver->flags & HCD_USB2) ? USB_SPEED_HIGH :
USB_SPEED_FULL;
rhdev->bus_mA = min(500u, hcd->power_budget);
if ((retval = register_root_hub(rhdev, hcd)) != 0)
goto err_register_root_hub;
@ -1891,7 +1890,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
spin_lock_irq (&hcd_root_hub_lock);
hcd->rh_registered = 0;
spin_unlock_irq (&hcd_root_hub_lock);
down(&usb_bus_list_lock);
usb_disconnect(&hcd->self.root_hub);
up(&usb_bus_list_lock);
hcd->poll_rh = 0;
del_timer_sync(&hcd->rh_timer);

View File

@ -380,6 +380,7 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#ifdef CONFIG_PM
extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_root_hub_lost_power (struct usb_device *rhdev);
extern int hcd_bus_suspend (struct usb_bus *bus);
extern int hcd_bus_resume (struct usb_bus *bus);
#else

View File

@ -32,7 +32,7 @@
#include "hub.h"
/* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->serialize, except that ->state can
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
static DEFINE_SPINLOCK(device_state_lock);
@ -515,6 +515,31 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
return ret;
}
/* caller has locked the hub device */
static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
{
struct usb_device *hdev = hub->hdev;
int port1;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
if (hdev->children[port1 - 1]) {
usb_disconnect(&hdev->children[port1 - 1]);
if (disable_ports)
hub_port_disable(hub, port1, 0);
}
}
hub_quiesce(hub);
}
/* caller has locked the hub device */
static void hub_post_reset(struct usb_hub *hub)
{
hub_activate(hub);
hub_power_on(hub);
}
static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
@ -677,26 +702,40 @@ static int hub_configure(struct usb_hub *hub,
* and battery-powered root hubs (may provide just 8 mA).
*/
ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus);
if (ret < 0) {
if (ret < 2) {
message = "can't get hub status";
goto fail;
}
le16_to_cpus(&hubstatus);
if (hdev == hdev->bus->root_hub) {
struct usb_hcd *hcd =
container_of(hdev->bus, struct usb_hcd, self);
hub->power_budget = min(500u, hcd->power_budget) / 2;
if (hdev->bus_mA == 0 || hdev->bus_mA >= 500)
hub->mA_per_port = 500;
else {
hub->mA_per_port = hdev->bus_mA;
hub->limited_power = 1;
}
} else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
hub->descriptor->bHubContrCurrent);
hub->power_budget = (501 - hub->descriptor->bHubContrCurrent)
/ 2;
}
if (hub->power_budget)
dev_dbg(hub_dev, "%dmA bus power budget for children\n",
hub->power_budget * 2);
hub->limited_power = 1;
if (hdev->maxchild > 0) {
int remaining = hdev->bus_mA -
hub->descriptor->bHubContrCurrent;
if (remaining < hdev->maxchild * 100)
dev_warn(hub_dev,
"insufficient power available "
"to use all downstream ports\n");
hub->mA_per_port = 100; /* 7.2.1.1 */
}
} else { /* Self-powered external hub */
/* FIXME: What about battery-powered external hubs that
* provide less current per port? */
hub->mA_per_port = 500;
}
if (hub->mA_per_port < 500)
dev_dbg(hub_dev, "%umA bus power budget for each child\n",
hub->mA_per_port);
ret = hub_hub_status(hub, &hubstatus, &hubchange);
if (ret < 0) {
@ -750,29 +789,10 @@ fail:
static unsigned highspeed_hubs;
/* Called after the hub driver is unbound from a hub with children */
static void hub_remove_children_work(void *__hub)
{
struct usb_hub *hub = __hub;
struct usb_device *hdev = hub->hdev;
int i;
kfree(hub);
usb_lock_device(hdev);
for (i = 0; i < hdev->maxchild; ++i) {
if (hdev->children[i])
usb_disconnect(&hdev->children[i]);
}
usb_unlock_device(hdev);
usb_put_dev(hdev);
}
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev;
int n, port1;
usb_set_intfdata (intf, NULL);
hdev = hub->hdev;
@ -780,7 +800,9 @@ static void hub_disconnect(struct usb_interface *intf)
if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
hub_quiesce(hub);
/* Disconnect all children and quiesce the hub */
hub_pre_reset(hub, 1);
usb_free_urb(hub->urb);
hub->urb = NULL;
@ -800,27 +822,7 @@ static void hub_disconnect(struct usb_interface *intf)
hub->buffer = NULL;
}
/* If there are any children then this is an unbind only, not a
* physical disconnection. The active ports must be disabled
* and later on we must call usb_disconnect(). We can't call
* it now because we may not hold the hub's device lock.
*/
n = 0;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
if (hdev->children[port1 - 1]) {
++n;
hub_port_disable(hub, port1, 1);
}
}
if (n == 0)
kfree(hub);
else {
/* Reuse the hub->leds work_struct for our own purposes */
INIT_WORK(&hub->leds, hub_remove_children_work, hub);
schedule_work(&hub->leds);
usb_get_dev(hdev);
}
kfree(hub);
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@ -917,26 +919,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
}
}
/* caller has locked the hub device */
static void hub_pre_reset(struct usb_hub *hub)
{
struct usb_device *hdev = hub->hdev;
int i;
for (i = 0; i < hdev->maxchild; ++i) {
if (hdev->children[i])
usb_disconnect(&hdev->children[i]);
}
hub_quiesce(hub);
}
/* caller has locked the hub device */
static void hub_post_reset(struct usb_hub *hub)
{
hub_activate(hub);
hub_power_on(hub);
}
/* grab device/port lock, returning index of that port (zero based).
* protects the upstream link used by this device from concurrent
@ -964,24 +946,21 @@ static int locktree(struct usb_device *udev)
t = locktree(hdev);
if (t < 0)
return t;
for (t = 0; t < hdev->maxchild; t++) {
if (hdev->children[t] == udev) {
/* everything is fail-fast once disconnect
* processing starts
*/
if (udev->state == USB_STATE_NOTATTACHED)
break;
/* when everyone grabs locks top->bottom,
* non-overlapping work may be concurrent
*/
down(&udev->serialize);
up(&hdev->serialize);
return t + 1;
}
/* everything is fail-fast once disconnect
* processing starts
*/
if (udev->state == USB_STATE_NOTATTACHED) {
usb_unlock_device(hdev);
return -ENODEV;
}
/* when everyone grabs locks top->bottom,
* non-overlapping work may be concurrent
*/
usb_lock_device(udev);
usb_unlock_device(hdev);
return -ENODEV;
return udev->portnum;
}
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
@ -1039,6 +1018,39 @@ void usb_set_device_state(struct usb_device *udev,
EXPORT_SYMBOL(usb_set_device_state);
#ifdef CONFIG_PM
/**
* usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
* @rhdev: struct usb_device for the root hub
*
* The USB host controller driver calls this function when its root hub
* is resumed and Vbus power has been interrupted or the controller
* has been reset. The routine marks all the children of the root hub
* as NOTATTACHED and marks logical connect-change events on their ports.
*/
void usb_root_hub_lost_power(struct usb_device *rhdev)
{
struct usb_hub *hub;
int port1;
unsigned long flags;
dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
spin_lock_irqsave(&device_state_lock, flags);
hub = hdev_to_hub(rhdev);
for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
if (rhdev->children[port1 - 1]) {
recursively_mark_NOTATTACHED(
rhdev->children[port1 - 1]);
set_bit(port1, hub->change_bits);
}
}
spin_unlock_irqrestore(&device_state_lock, flags);
}
EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
#endif
static void choose_address(struct usb_device *udev)
{
int devnum;
@ -1099,16 +1111,10 @@ void usb_disconnect(struct usb_device **pdev)
* this quiesces everyting except pending urbs.
*/
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
/* lock the bus list on behalf of HCDs unregistering their root hubs */
if (!udev->parent) {
down(&usb_bus_list_lock);
usb_lock_device(udev);
} else
down(&udev->serialize);
dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
usb_lock_device(udev);
/* Free up all the children before we remove this device */
for (i = 0; i < USB_MAXCHILDREN; i++) {
if (udev->children[i])
@ -1136,54 +1142,112 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
spin_unlock_irq(&device_state_lock);
if (!udev->parent) {
usb_unlock_device(udev);
up(&usb_bus_list_lock);
} else
up(&udev->serialize);
usb_unlock_device(udev);
device_unregister(&udev->dev);
}
static inline const char *plural(int n)
{
return (n == 1 ? "" : "s");
}
static int choose_configuration(struct usb_device *udev)
{
int c, i;
int i;
u16 devstatus;
int bus_powered;
int num_configs;
struct usb_host_config *c, *best;
/* NOTE: this should interact with hub power budgeting */
/* If this fails, assume the device is bus-powered */
devstatus = 0;
usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
le16_to_cpus(&devstatus);
bus_powered = ((devstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0);
dev_dbg(&udev->dev, "device is %s-powered\n",
bus_powered ? "bus" : "self");
c = udev->config[0].desc.bConfigurationValue;
if (udev->descriptor.bNumConfigurations != 1) {
for (i = 0; i < udev->descriptor.bNumConfigurations; i++) {
struct usb_interface_descriptor *desc;
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc =
&c->intf_cache[0]->altsetting->desc;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc = &udev->config[i].intf_cache[0]
->altsetting->desc;
if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC)
continue;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS.
* MSFT needs this to be the first config; never use
* it as the default unless Linux has host-side RNDIS.
* A second config would ideally be CDC-Ethernet, but
* may instead be the "vendor specific" CDC subset
* long used by ARM Linux for sa1100 or pxa255.
*/
if (desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff) {
c = udev->config[1].desc.bConfigurationValue;
continue;
}
c = udev->config[i].desc.bConfigurationValue;
/*
* HP's USB bus-powered keyboard has only one configuration
* and it claims to be self-powered; other devices may have
* similar errors in their descriptors. If the next test
* were allowed to execute, such configurations would always
* be rejected and the devices would not work as expected.
*/
#if 0
/* Rule out self-powered configs for a bus-powered device */
if (bus_powered && (c->desc.bmAttributes &
USB_CONFIG_ATT_SELFPOWER))
continue;
#endif
/*
* The next test may not be as effective as it should be.
* Some hubs have errors in their descriptor, claiming
* to be self-powered when they are really bus-powered.
* We will overestimate the amount of current such hubs
* make available for each port.
*
* This is a fairly benign sort of failure. It won't
* cause us to reject configurations that we should have
* accepted.
*/
/* Rule out configs that draw too much bus current */
if (c->desc.bMaxPower * 2 > udev->bus_mA)
continue;
/* If the first config's first interface is COMM/2/0xff
* (MSFT RNDIS), rule it out unless Linux has host-side
* RNDIS support. */
if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff) {
#ifndef CONFIG_USB_NET_RNDIS
continue;
#else
best = c;
#endif
}
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
* than a vendor-specific driver. */
else if (udev->descriptor.bDeviceClass !=
USB_CLASS_VENDOR_SPEC &&
desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC) {
best = c;
break;
}
dev_info(&udev->dev,
"configuration #%d chosen from %d choices\n",
c, udev->descriptor.bNumConfigurations);
/* If all the remaining configs are vendor-specific,
* choose the first one. */
else if (!best)
best = c;
}
return c;
if (best) {
i = best->desc.bConfigurationValue;
dev_info(&udev->dev,
"configuration #%d chosen from %d choice%s\n",
i, num_configs, plural(num_configs));
} else {
i = -1;
dev_warn(&udev->dev,
"no configuration chosen from %d choice%s\n",
num_configs, plural(num_configs));
}
return i;
}
#ifdef DEBUG
@ -1210,8 +1274,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
*
* 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 udev and
* either the parent hub (if udev is a normal device) or else the
* 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.
@ -1221,8 +1285,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver should ever call this; root hub registration
* uses it indirectly.
* Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
{
@ -1269,15 +1332,9 @@ int usb_new_device(struct usb_device *udev)
le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
unsigned port1;
unsigned port1 = udev->portnum;
struct usb_device *root = udev->parent;
for (port1 = 1; port1 <= root->maxchild;
port1++) {
if (root->children[port1-1] == udev)
break;
}
dev_info(&udev->dev,
"Dual-Role OTG device on %sHNP port\n",
(port1 == bus->otg_port)
@ -1331,27 +1388,27 @@ int usb_new_device(struct usb_device *udev)
}
usb_create_sysfs_dev_files (udev);
usb_lock_device(udev);
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
*/
c = choose_configuration(udev);
if (c < 0)
dev_warn(&udev->dev,
"can't choose an initial configuration\n");
else {
if (c >= 0) {
err = usb_set_configuration(udev, c);
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
usb_remove_sysfs_dev_files(udev);
device_del(&udev->dev);
goto fail;
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
usb_unlock_device(udev);
return 0;
fail:
@ -1654,15 +1711,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
int usb_suspend_device(struct usb_device *udev)
{
#ifdef CONFIG_USB_SUSPEND
int port1, status;
port1 = locktree(udev);
if (port1 < 0)
return port1;
status = __usb_suspend_device(udev, port1);
usb_unlock_device(udev);
return status;
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
return __usb_suspend_device(udev, udev->portnum);
#else
/* NOTE: udev->state unchanged, it's not lying ... */
udev->dev.power.power_state = PMSG_SUSPEND;
@ -1694,13 +1745,14 @@ static int finish_device_resume(struct usb_device *udev)
usb_set_device_state(udev, udev->actconfig
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
udev->dev.power.power_state = PMSG_ON;
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
* and device drivers will know about any resume quirks.
*/
status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
if (status < 0)
if (status < 2)
dev_dbg(&udev->dev,
"gone after usb resume? status %d\n",
status);
@ -1709,7 +1761,7 @@ static int finish_device_resume(struct usb_device *udev)
int (*resume)(struct device *);
le16_to_cpus(&devstatus);
if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)
if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
&& udev->parent) {
status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
@ -1729,8 +1781,14 @@ static int finish_device_resume(struct usb_device *udev)
* may have a child resume event to deal with soon
*/
resume = udev->dev.bus->resume;
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++)
(void) resume(&udev->actconfig->interface[i]->dev);
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
struct device *dev =
&udev->actconfig->interface[i]->dev;
down(&dev->sem);
(void) resume(dev);
up(&dev->sem);
}
status = 0;
} else if (udev->devnum <= 0) {
@ -1813,11 +1871,10 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
*/
int usb_resume_device(struct usb_device *udev)
{
int port1, status;
int status;
port1 = locktree(udev);
if (port1 < 0)
return port1;
if (udev->state == USB_STATE_NOTATTACHED)
return -ENODEV;
#ifdef CONFIG_USB_SUSPEND
/* selective resume of one downstream hub-to-device port */
@ -1826,7 +1883,7 @@ int usb_resume_device(struct usb_device *udev)
// NOTE swsusp may bork us, device state being wrong...
// NOTE this fails if parent is also suspended...
status = hub_port_resume(hdev_to_hub(udev->parent),
port1, udev);
udev->portnum, udev);
} else
status = 0;
} else
@ -1836,13 +1893,11 @@ int usb_resume_device(struct usb_device *udev)
dev_dbg(&udev->dev, "can't resume, status %d\n",
status);
usb_unlock_device(udev);
/* rebind drivers that had no suspend() */
if (status == 0) {
usb_lock_all_devices();
usb_unlock_device(udev);
bus_rescan_devices(&usb_bus_type);
usb_unlock_all_devices();
usb_lock_device(udev);
}
return status;
}
@ -1856,14 +1911,14 @@ static int remote_wakeup(struct usb_device *udev)
/* don't repeat RESUME sequence if this device
* was already woken up by some other task
*/
down(&udev->serialize);
usb_lock_device(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "RESUME (wakeup)\n");
/* TRSMRCY = 10 msec */
msleep(10);
status = finish_device_resume(udev);
}
up(&udev->serialize);
usb_unlock_device(udev);
#endif
return status;
}
@ -1964,7 +2019,7 @@ static int hub_resume(struct usb_interface *intf)
if (!udev || status < 0)
continue;
down (&udev->serialize);
usb_lock_device(udev);
if (portstat & USB_PORT_STAT_SUSPEND)
status = hub_port_resume(hub, port1, udev);
else {
@ -1975,7 +2030,7 @@ static int hub_resume(struct usb_interface *intf)
hub_port_logical_disconnect(hub, port1);
}
}
up(&udev->serialize);
usb_unlock_device(udev);
}
}
#endif
@ -2359,39 +2414,36 @@ hub_power_remaining (struct usb_hub *hub)
{
struct usb_device *hdev = hub->hdev;
int remaining;
unsigned i;
int port1;
remaining = hub->power_budget;
if (!remaining) /* self-powered */
if (!hub->limited_power)
return 0;
for (i = 0; i < hdev->maxchild; i++) {
struct usb_device *udev = hdev->children[i];
int delta, ceiling;
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
struct usb_device *udev = hdev->children[port1 - 1];
int delta;
if (!udev)
continue;
/* 100mA per-port ceiling, or 8mA for OTG ports */
if (i != (udev->bus->otg_port - 1) || hdev->parent)
ceiling = 50;
else
ceiling = 4;
/* Unconfigured devices may not use more than 100mA,
* or 8mA for OTG ports */
if (udev->actconfig)
delta = udev->actconfig->desc.bMaxPower;
delta = udev->actconfig->desc.bMaxPower * 2;
else if (port1 != udev->bus->otg_port || hdev->parent)
delta = 100;
else
delta = ceiling;
// dev_dbg(&udev->dev, "budgeted %dmA\n", 2 * delta);
if (delta > ceiling)
dev_warn(&udev->dev, "%dmA over %dmA budget!\n",
2 * (delta - ceiling), 2 * ceiling);
delta = 8;
if (delta > hub->mA_per_port)
dev_warn(&udev->dev, "%dmA is over %umA budget "
"for port %d!\n",
delta, hub->mA_per_port, port1);
remaining -= delta;
}
if (remaining < 0) {
dev_warn(hub->intfdev,
"%dmA over power budget!\n",
-2 * remaining);
dev_warn(hub->intfdev, "%dmA over power budget!\n",
- remaining);
remaining = 0;
}
return remaining;
@ -2486,7 +2538,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
usb_set_device_state(udev, USB_STATE_POWERED);
udev->speed = USB_SPEED_UNKNOWN;
udev->bus_mA = hub->mA_per_port;
/* set the address */
choose_address(udev);
if (udev->devnum <= 0) {
@ -2506,16 +2559,16 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* on the parent.
*/
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB
&& hub->power_budget) {
&& udev->bus_mA <= 100) {
u16 devstat;
status = usb_get_status(udev, USB_RECIP_DEVICE, 0,
&devstat);
if (status < 0) {
if (status < 2) {
dev_dbg(&udev->dev, "get status %d ?\n", status);
goto loop_disable;
}
cpu_to_le16s(&devstat);
le16_to_cpus(&devstat);
if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
dev_err(&udev->dev,
"can't connect bus-powered hub "
@ -2540,7 +2593,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* udev becomes globally accessible, although presumably
* no one will look at it until hdev is unlocked.
*/
down (&udev->serialize);
status = 0;
/* We mustn't add new devices if the parent hub has
@ -2564,15 +2616,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
}
up (&udev->serialize);
if (status)
goto loop_disable;
status = hub_power_remaining(hub);
if (status)
dev_dbg(hub_dev,
"%dmA power budget left\n",
2 * status);
dev_dbg(hub_dev, "%dmA power budget left\n", status);
return;
@ -2648,6 +2697,8 @@ static void hub_events(void)
if (i) {
dpm_runtime_resume(&hdev->dev);
dpm_runtime_resume(&intf->dev);
usb_put_intf(intf);
continue;
}
/* Lock the device, then check to see if we were
@ -2661,7 +2712,7 @@ static void hub_events(void)
/* If the hub has died, clean up after it */
if (hdev->state == USB_STATE_NOTATTACHED) {
hub_pre_reset(hub);
hub_pre_reset(hub, 0);
goto loop;
}
@ -2784,6 +2835,11 @@ static void hub_events(void)
if (hubchange & HUB_CHANGE_LOCAL_POWER) {
dev_dbg (hub_dev, "power change\n");
clear_hub_feature(hdev, C_HUB_LOCAL_POWER);
if (hubstatus & HUB_STATUS_LOCAL_POWER)
/* FIXME: Is this always true? */
hub->limited_power = 0;
else
hub->limited_power = 1;
}
if (hubchange & HUB_CHANGE_OVERCURRENT) {
dev_dbg (hub_dev, "overcurrent change\n");
@ -2832,7 +2888,6 @@ static struct usb_device_id hub_id_table [] = {
MODULE_DEVICE_TABLE (usb, hub_id_table);
static struct usb_driver hub_driver = {
.owner = THIS_MODULE,
.name = "hub",
.probe = hub_probe,
.disconnect = hub_disconnect,
@ -2944,7 +2999,8 @@ int usb_reset_device(struct usb_device *udev)
struct usb_hub *parent_hub;
struct usb_device_descriptor descriptor = udev->descriptor;
struct usb_hub *hub = NULL;
int i, ret = 0, port1 = -1;
int i, ret = 0;
int port1 = udev->portnum;
if (udev->state == USB_STATE_NOTATTACHED ||
udev->state == USB_STATE_SUSPENDED) {
@ -2958,18 +3014,6 @@ int usb_reset_device(struct usb_device *udev)
dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
return -EISDIR;
}
for (i = 0; i < parent_hdev->maxchild; i++)
if (parent_hdev->children[i] == udev) {
port1 = i + 1;
break;
}
if (port1 < 0) {
/* If this ever happens, it's very bad */
dev_err(&udev->dev, "Can't locate device's port!\n");
return -ENOENT;
}
parent_hub = hdev_to_hub(parent_hdev);
/* If we're resetting an active hub, take some special actions */
@ -2977,7 +3021,7 @@ int usb_reset_device(struct usb_device *udev)
udev->actconfig->interface[0]->dev.driver ==
&hub_driver.driver &&
(hub = hdev_to_hub(udev)) != NULL) {
hub_pre_reset(hub);
hub_pre_reset(hub, 0);
}
set_bit(port1, parent_hub->busy_bits);

View File

@ -220,8 +220,9 @@ struct usb_hub {
struct usb_hub_descriptor *descriptor; /* class descriptor */
struct usb_tt tt; /* Transaction Translator */
u8 power_budget; /* in 2mA units; or zero */
unsigned mA_per_port; /* current for each child */
unsigned limited_power:1;
unsigned quiescing:1;
unsigned activating:1;
unsigned resume_root_hub:1;

View File

@ -1387,6 +1387,12 @@ free_interfaces:
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device (dev, 1); // Skip ep0
i = dev->bus_mA - cp->desc.bMaxPower * 2;
if (i < 0)
dev_warn(&dev->dev, "new config #%d exceeds power "
"limit by %dmA\n",
configuration, -i);
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)

View File

@ -32,7 +32,6 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
#include <linux/rwsem.h>
#include <linux/usb.h>
#include <asm/io.h>
@ -47,165 +46,7 @@
const char *usbcore_name = "usbcore";
static int nousb; /* Disable USB when built into kernel image */
/* Not honored on modular build */
static DECLARE_RWSEM(usb_all_devices_rwsem);
static int generic_probe (struct device *dev)
{
return 0;
}
static int generic_remove (struct device *dev)
{
struct usb_device *udev = to_usb_device(dev);
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->state == USB_STATE_CONFIGURED)
usb_set_configuration(udev, 0);
/* in case the call failed or the device was suspended */
if (udev->state >= USB_STATE_CONFIGURED)
usb_disable_device(udev, 0);
return 0;
}
static struct device_driver usb_generic_driver = {
.owner = THIS_MODULE,
.name = "usb",
.bus = &usb_bus_type,
.probe = generic_probe,
.remove = generic_remove,
};
static int usb_generic_driver_data;
/* called from driver core with usb_bus_type.subsys writelock */
static int usb_probe_interface(struct device *dev)
{
struct usb_interface * intf = to_usb_interface(dev);
struct usb_driver * driver = to_usb_driver(dev->driver);
const struct usb_device_id *id;
int error = -ENODEV;
dev_dbg(dev, "%s\n", __FUNCTION__);
if (!driver->probe)
return error;
/* FIXME we'd much prefer to just resume it ... */
if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
id = usb_match_id (intf, driver->id_table);
if (id) {
dev_dbg (dev, "%s - got id\n", __FUNCTION__);
/* Interface "power state" doesn't correspond to any hardware
* state whatsoever. We use it to record when it's bound to
* a driver that may start I/0: it's not frozen/quiesced.
*/
mark_active(intf);
intf->condition = USB_INTERFACE_BINDING;
error = driver->probe (intf, id);
if (error) {
mark_quiesced(intf);
intf->condition = USB_INTERFACE_UNBOUND;
} else
intf->condition = USB_INTERFACE_BOUND;
}
return error;
}
/* called from driver core with usb_bus_type.subsys writelock */
static int usb_unbind_interface(struct device *dev)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_driver *driver = to_usb_driver(intf->dev.driver);
intf->condition = USB_INTERFACE_UNBINDING;
/* release all urbs for this interface */
usb_disable_interface(interface_to_usbdev(intf), intf);
if (driver && driver->disconnect)
driver->disconnect(intf);
/* reset other interface state */
usb_set_interface(interface_to_usbdev(intf),
intf->altsetting[0].desc.bInterfaceNumber,
0);
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;
mark_quiesced(intf);
return 0;
}
/**
* usb_register - register a USB driver
* @new_driver: USB operations for the driver
*
* Registers a USB driver with the USB core. The list of unattached
* interfaces will be rescanned whenever a new driver is added, allowing
* the new driver to attach to any recognized devices.
* Returns a negative error code on failure and 0 on success.
*
* NOTE: if you want your driver to use the USB major number, you must call
* usb_register_dev() to enable that functionality. This function no longer
* takes care of that.
*/
int usb_register(struct usb_driver *new_driver)
{
int retval = 0;
if (nousb)
return -ENODEV;
new_driver->driver.name = (char *)new_driver->name;
new_driver->driver.bus = &usb_bus_type;
new_driver->driver.probe = usb_probe_interface;
new_driver->driver.remove = usb_unbind_interface;
new_driver->driver.owner = new_driver->owner;
usb_lock_all_devices();
retval = driver_register(&new_driver->driver);
usb_unlock_all_devices();
if (!retval) {
pr_info("%s: registered new driver %s\n",
usbcore_name, new_driver->name);
usbfs_update_special();
} else {
printk(KERN_ERR "%s: error %d registering driver %s\n",
usbcore_name, retval, new_driver->name);
}
return retval;
}
/**
* usb_deregister - unregister a USB driver
* @driver: USB operations of the driver to unregister
* Context: must be able to sleep
*
* Unlinks the specified driver from the internal USB driver list.
*
* NOTE: If you called usb_register_dev(), you still need to call
* usb_deregister_dev() to clean up your driver's allocated minor numbers,
* this * call will no longer do it for you.
*/
void usb_deregister(struct usb_driver *driver)
{
pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
usb_lock_all_devices();
driver_unregister (&driver->driver);
usb_unlock_all_devices();
usbfs_update_special();
}
/**
* usb_ifnum_to_if - get the interface object with a given interface number
@ -351,152 +192,23 @@ void usb_driver_release_interface(struct usb_driver *driver,
iface->condition = USB_INTERFACE_UNBOUND;
mark_quiesced(iface);
}
/**
* usb_match_id - find first usb_device_id matching device or interface
* @interface: the interface of interest
* @id: array of usb_device_id structures, terminated by zero entry
*
* usb_match_id searches an array of usb_device_id's and returns
* the first one matching the device or interface, or null.
* This is used when binding (or rebinding) a driver to an interface.
* Most USB device drivers will use this indirectly, through the usb core,
* but some layered driver frameworks use it directly.
* These device tables are exported with MODULE_DEVICE_TABLE, through
* modutils and "modules.usbmap", to support the driver loading
* functionality of USB hotplugging.
*
* What Matches:
*
* The "match_flags" element in a usb_device_id controls which
* members are used. If the corresponding bit is set, the
* value in the device_id must match its corresponding member
* in the device or interface descriptor, or else the device_id
* does not match.
*
* "driver_info" is normally used only by device drivers,
* but you can create a wildcard "matches anything" usb_device_id
* as a driver's "modules.usbmap" entry if you provide an id with
* only a nonzero "driver_info" field. If you do this, the USB device
* driver's probe() routine should use additional intelligence to
* decide whether to bind to the specified interface.
*
* What Makes Good usb_device_id Tables:
*
* The match algorithm is very simple, so that intelligence in
* driver selection must come from smart driver id records.
* Unless you have good reasons to use another selection policy,
* provide match elements only in related groups, and order match
* specifiers from specific to general. Use the macros provided
* for that purpose if you can.
*
* The most specific match specifiers use device descriptor
* data. These are commonly used with product-specific matches;
* the USB_DEVICE macro lets you provide vendor and product IDs,
* and you can also match against ranges of product revisions.
* These are widely used for devices with application or vendor
* specific bDeviceClass values.
*
* Matches based on device class/subclass/protocol specifications
* are slightly more general; use the USB_DEVICE_INFO macro, or
* its siblings. These are used with single-function devices
* where bDeviceClass doesn't specify that each interface has
* its own class.
*
* Matches based on interface class/subclass/protocol are the
* 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).
*
* Within those groups, remember that not all combinations are
* meaningful. For example, don't give a product version range
* without vendor and product IDs; or specify a protocol without
* its associated class and subclass.
*/
const struct usb_device_id *
usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if (id == NULL)
return NULL;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
/* It is important to check that id->driver_info is nonzero,
since an entry that is all zeroes except for a nonzero
id->driver_info is the way to create an entry that
indicates that the driver want to examine every
device and interface. */
for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
id->driver_info; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
continue;
return id;
}
return NULL;
}
struct find_interface_arg {
int minor;
struct usb_interface *interface;
};
static int __find_interface(struct device * dev, void * data)
{
struct usb_interface ** ret = (struct usb_interface **)data;
struct usb_interface * intf = *ret;
int *minor = (int *)data;
struct find_interface_arg *arg = data;
struct usb_interface *intf;
/* can't look at usb devices, only interfaces */
if (dev->driver == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
if (intf->minor != -1 && intf->minor == *minor) {
*ret = intf;
if (intf->minor != -1 && intf->minor == arg->minor) {
arg->interface = intf;
return 1;
}
return 0;
@ -513,35 +225,14 @@ static int __find_interface(struct device * dev, void * data)
*/
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
{
struct usb_interface *intf = (struct usb_interface *)(long)minor;
int ret;
struct find_interface_arg argb;
ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
return ret ? intf : NULL;
argb.minor = minor;
argb.interface = NULL;
driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
return argb.interface;
}
static int usb_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* check for generic driver, which we don't match any device with */
if (drv == &usb_generic_driver)
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id (intf, usb_drv->id_table);
if (id)
return 1;
return 0;
}
#ifdef CONFIG_HOTPLUG
/*
@ -750,12 +441,11 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
/* hub driver sets up TT records */
}
dev->portnum = port1;
dev->bus = bus;
dev->parent = parent;
INIT_LIST_HEAD(&dev->filelist);
init_MUTEX(&dev->serialize);
return dev;
}
@ -828,75 +518,20 @@ void usb_put_intf(struct usb_interface *intf)
/* USB device locking
*
* Although locking USB devices should be straightforward, it is
* complicated by the way the driver-model core works. When a new USB
* driver is registered or unregistered, the core will automatically
* probe or disconnect all matching interfaces on all USB devices while
* holding the USB subsystem writelock. There's no good way for us to
* tell which devices will be used or to lock them beforehand; our only
* option is to effectively lock all the USB devices.
*
* We do that by using a private rw-semaphore, usb_all_devices_rwsem.
* When locking an individual device you must first acquire the rwsem's
* readlock. When a driver is registered or unregistered the writelock
* must be held. These actions are encapsulated in the subroutines
* below, so all a driver needs to do is call usb_lock_device() and
* usb_unlock_device().
* USB devices and interfaces are locked using the semaphore in their
* embedded struct device. The hub driver guarantees that whenever a
* device is connected or disconnected, drivers are called with the
* USB device locked as well as their particular interface.
*
* Complications arise when several devices are to be locked at the same
* time. Only hub-aware drivers that are part of usbcore ever have to
* do this; nobody else needs to worry about it. The problem is that
* usb_lock_device() must not be called to lock a second device since it
* would acquire the rwsem's readlock reentrantly, leading to deadlock if
* another thread was waiting for the writelock. The solution is simple:
*
* When locking more than one device, call usb_lock_device()
* to lock the first one. Lock the others by calling
* down(&udev->serialize) directly.
*
* When unlocking multiple devices, use up(&udev->serialize)
* to unlock all but the last one. Unlock the last one by
* calling usb_unlock_device().
* do this; nobody else needs to worry about it. The rule for locking
* is simple:
*
* When locking both a device and its parent, always lock the
* the parent first.
*/
/**
* usb_lock_device - acquire the lock for a usb device structure
* @udev: device that's being locked
*
* Use this routine when you don't hold any other device locks;
* to acquire nested inner locks call down(&udev->serialize) directly.
* This is necessary for proper interaction with usb_lock_all_devices().
*/
void usb_lock_device(struct usb_device *udev)
{
down_read(&usb_all_devices_rwsem);
down(&udev->serialize);
}
/**
* usb_trylock_device - attempt to acquire the lock for a usb device structure
* @udev: device that's being locked
*
* Don't use this routine if you already hold a device lock;
* use down_trylock(&udev->serialize) instead.
* This is necessary for proper interaction with usb_lock_all_devices().
*
* Returns 1 if successful, 0 if contention.
*/
int usb_trylock_device(struct usb_device *udev)
{
if (!down_read_trylock(&usb_all_devices_rwsem))
return 0;
if (down_trylock(&udev->serialize)) {
up_read(&usb_all_devices_rwsem);
return 0;
}
return 1;
}
/**
* usb_lock_device_for_reset - cautiously acquire the lock for a
* usb device structure
@ -935,7 +570,7 @@ int usb_lock_device_for_reset(struct usb_device *udev,
}
}
while (!usb_trylock_device(udev)) {
while (usb_trylock_device(udev) != 0) {
/* If we can't acquire the lock after waiting one second,
* we're probably deadlocked */
@ -953,39 +588,6 @@ int usb_lock_device_for_reset(struct usb_device *udev,
return 1;
}
/**
* usb_unlock_device - release the lock for a usb device structure
* @udev: device that's being unlocked
*
* Use this routine when releasing the only device lock you hold;
* to release inner nested locks call up(&udev->serialize) directly.
* This is necessary for proper interaction with usb_lock_all_devices().
*/
void usb_unlock_device(struct usb_device *udev)
{
up(&udev->serialize);
up_read(&usb_all_devices_rwsem);
}
/**
* usb_lock_all_devices - acquire the lock for all usb device structures
*
* This is necessary when registering a new driver or probing a bus,
* since the driver-model core may try to use any usb_device.
*/
void usb_lock_all_devices(void)
{
down_write(&usb_all_devices_rwsem);
}
/**
* usb_unlock_all_devices - release the lock for all usb device structures
*/
void usb_unlock_all_devices(void)
{
up_write(&usb_all_devices_rwsem);
}
static struct usb_device *match_device(struct usb_device *dev,
u16 vendor_id, u16 product_id)
@ -1008,10 +610,10 @@ static struct usb_device *match_device(struct usb_device *dev,
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
down(&dev->children[child]->serialize);
usb_lock_device(dev->children[child]);
ret_dev = match_device(dev->children[child],
vendor_id, product_id);
up(&dev->children[child]->serialize);
usb_unlock_device(dev->children[child]);
if (ret_dev)
goto exit;
}
@ -1496,18 +1098,8 @@ struct bus_type usb_bus_type = {
.resume = usb_generic_resume,
};
#ifndef MODULE
static int __init usb_setup_disable(char *str)
{
nousb = 1;
return 1;
}
/* format to disable USB on kernel command line is: nousb */
__setup("nousb", usb_setup_disable);
#endif
__module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
/*
* for external read access to <nousb>
@ -1598,8 +1190,6 @@ module_exit(usb_exit);
* driver modules to use.
*/
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
EXPORT_SYMBOL(usb_disabled);
EXPORT_SYMBOL_GPL(usb_get_intf);
@ -1610,14 +1200,10 @@ EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);
EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
EXPORT_SYMBOL(usb_lock_device);
EXPORT_SYMBOL(usb_trylock_device);
EXPORT_SYMBOL(usb_lock_device_for_reset);
EXPORT_SYMBOL(usb_unlock_device);
EXPORT_SYMBOL(usb_driver_claim_interface);
EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);

View File

@ -16,9 +16,6 @@ extern int usb_get_device_descriptor(struct usb_device *dev,
extern char *usb_cache_string(struct usb_device *udev, int index);
extern int usb_set_configuration(struct usb_device *dev, int configuration);
extern void usb_lock_all_devices(void);
extern void usb_unlock_all_devices(void);
extern void usb_kick_khubd(struct usb_device *dev);
extern void usb_suspend_root_hub(struct usb_device *hdev);
extern void usb_resume_root_hub(struct usb_device *dev);
@ -33,6 +30,9 @@ extern void usb_host_cleanup(void);
extern int usb_suspend_device(struct usb_device *dev);
extern int usb_resume_device(struct usb_device *dev);
extern struct device_driver usb_generic_driver;
extern int usb_generic_driver_data;
extern int usb_device_match(struct device *dev, struct device_driver *drv);
/* Interfaces and their "power state" are owned by usbcore */

View File

@ -138,7 +138,7 @@ static const char *const ep_name [] = {
/* or like sa1100: two fixed function endpoints */
"ep1out-bulk", "ep2in-bulk",
};
#define DUMMY_ENDPOINTS (sizeof(ep_name)/sizeof(char *))
#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
/*-------------------------------------------------------------------------*/
@ -896,7 +896,7 @@ dummy_gadget_release (struct device *dev)
#endif
}
static int dummy_udc_probe (struct platform_device *dev)
static int dummy_udc_probe (struct platform_device *pdev)
{
struct dummy *dum = the_controller;
int rc;
@ -909,7 +909,7 @@ static int dummy_udc_probe (struct platform_device *dev)
dum->gadget.is_otg = (dummy_to_hcd(dum)->self.otg_port != 0);
strcpy (dum->gadget.dev.bus_id, "gadget");
dum->gadget.dev.parent = &dev->dev;
dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register (&dum->gadget.dev);
if (rc < 0)
@ -919,47 +919,47 @@ static int dummy_udc_probe (struct platform_device *dev)
usb_bus_get (&dummy_to_hcd (dum)->self);
#endif
platform_set_drvdata (dev, dum);
platform_set_drvdata (pdev, dum);
device_create_file (&dum->gadget.dev, &dev_attr_function);
return rc;
}
static int dummy_udc_remove (struct platform_device *dev)
static int dummy_udc_remove (struct platform_device *pdev)
{
struct dummy *dum = platform_get_drvdata (dev);
struct dummy *dum = platform_get_drvdata (pdev);
platform_set_drvdata (dev, NULL);
platform_set_drvdata (pdev, NULL);
device_remove_file (&dum->gadget.dev, &dev_attr_function);
device_unregister (&dum->gadget.dev);
return 0;
}
static int dummy_udc_suspend (struct platform_device *dev, pm_message_t state)
static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)
{
struct dummy *dum = platform_get_drvdata(dev);
struct dummy *dum = platform_get_drvdata(pdev);
dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 1;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
dev->dev.power.power_state = state;
pdev->dev.power.power_state = state;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
static int dummy_udc_resume (struct platform_device *dev)
static int dummy_udc_resume (struct platform_device *pdev)
{
struct dummy *dum = platform_get_drvdata(dev);
struct dummy *dum = platform_get_drvdata(pdev);
dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->udc_suspended = 0;
set_link_state (dum);
spin_unlock_irq (&dum->lock);
dev->dev.power.power_state = PMSG_ON;
pdev->dev.power.power_state = PMSG_ON;
usb_hcd_poll_rh_status (dummy_to_hcd (dum));
return 0;
}
@ -1576,7 +1576,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)
dum = hcd_to_dummy (hcd);
spin_lock_irqsave (&dum->lock, flags);
if (hcd->state != HC_STATE_RUNNING)
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
goto done;
if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) {
@ -1623,7 +1623,7 @@ static int dummy_hub_control (
int retval = 0;
unsigned long flags;
if (hcd->state != HC_STATE_RUNNING)
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
return -ETIMEDOUT;
dum = hcd_to_dummy (hcd);
@ -1756,9 +1756,12 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->rh_state = DUMMY_RH_SUSPENDED;
set_link_state (dum);
hcd->state = HC_STATE_SUSPENDED;
spin_unlock_irq (&dum->lock);
return 0;
}
@ -1766,14 +1769,23 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)
static int dummy_bus_resume (struct usb_hcd *hcd)
{
struct dummy *dum = hcd_to_dummy (hcd);
int rc = 0;
dev_dbg (&hcd->self.root_hub->dev, "%s\n", __FUNCTION__);
spin_lock_irq (&dum->lock);
dum->rh_state = DUMMY_RH_RUNNING;
set_link_state (dum);
if (!list_empty(&dum->urbp_list))
mod_timer (&dum->timer, jiffies);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
rc = -ENODEV;
} else {
dum->rh_state = DUMMY_RH_RUNNING;
set_link_state (dum);
if (!list_empty(&dum->urbp_list))
mod_timer (&dum->timer, jiffies);
hcd->state = HC_STATE_RUNNING;
}
spin_unlock_irq (&dum->lock);
return 0;
return rc;
}
/*-------------------------------------------------------------------------*/
@ -1899,14 +1911,14 @@ static const struct hc_driver dummy_hcd = {
.bus_resume = dummy_bus_resume,
};
static int dummy_hcd_probe (struct platform_device *dev)
static int dummy_hcd_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
int retval;
dev_info(&dev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
hcd = usb_create_hcd (&dummy_hcd, &dev->dev, dev->dev.bus_id);
hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, pdev->dev.bus_id);
if (!hcd)
return -ENOMEM;
the_controller = hcd_to_dummy (hcd);
@ -1919,36 +1931,43 @@ static int dummy_hcd_probe (struct platform_device *dev)
return retval;
}
static int dummy_hcd_remove (struct platform_device *dev)
static int dummy_hcd_remove (struct platform_device *pdev)
{
struct usb_hcd *hcd;
hcd = platform_get_drvdata (dev);
hcd = platform_get_drvdata (pdev);
usb_remove_hcd (hcd);
usb_put_hcd (hcd);
the_controller = NULL;
return 0;
}
static int dummy_hcd_suspend (struct platform_device *dev, pm_message_t state)
static int dummy_hcd_suspend (struct platform_device *pdev, pm_message_t state)
{
struct usb_hcd *hcd;
struct dummy *dum;
int rc = 0;
dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
hcd = platform_get_drvdata (dev);
dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
hcd->state = HC_STATE_SUSPENDED;
return 0;
hcd = platform_get_drvdata (pdev);
dum = hcd_to_dummy (hcd);
if (dum->rh_state == DUMMY_RH_RUNNING) {
dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
rc = -EBUSY;
} else
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
return rc;
}
static int dummy_hcd_resume (struct platform_device *dev)
static int dummy_hcd_resume (struct platform_device *pdev)
{
struct usb_hcd *hcd;
dev_dbg (&dev->dev, "%s\n", __FUNCTION__);
hcd = platform_get_drvdata (dev);
hcd->state = HC_STATE_RUNNING;
dev_dbg (&pdev->dev, "%s\n", __FUNCTION__);
hcd = platform_get_drvdata (pdev);
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
usb_hcd_poll_rh_status (hcd);
return 0;
}

View File

@ -224,6 +224,7 @@
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/kthread.h>
#include <linux/limits.h>
#include <linux/list.h>
@ -238,7 +239,6 @@
#include <linux/string.h>
#include <linux/suspend.h>
#include <linux/utsname.h>
#include <linux/wait.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
@ -250,7 +250,7 @@
#define DRIVER_DESC "File-backed Storage Gadget"
#define DRIVER_NAME "g_file_storage"
#define DRIVER_VERSION "20 October 2004"
#define DRIVER_VERSION "28 November 2005"
static const char longname[] = DRIVER_DESC;
static const char shortname[] = DRIVER_NAME;
@ -335,8 +335,8 @@ MODULE_LICENSE("Dual BSD/GPL");
#define MAX_LUNS 8
/* Arggh! There should be a module_param_array_named macro! */
static char *file[MAX_LUNS] = {NULL, };
static int ro[MAX_LUNS] = {0, };
static char *file[MAX_LUNS];
static int ro[MAX_LUNS];
static struct {
int num_filenames;
@ -587,7 +587,7 @@ enum fsg_buffer_state {
struct fsg_buffhd {
void *buf;
dma_addr_t dma;
volatile enum fsg_buffer_state state;
enum fsg_buffer_state state;
struct fsg_buffhd *next;
/* The NetChip 2280 is faster, and handles some protocol faults
@ -596,9 +596,9 @@ struct fsg_buffhd {
unsigned int bulk_out_intended_length;
struct usb_request *inreq;
volatile int inreq_busy;
int inreq_busy;
struct usb_request *outreq;
volatile int outreq_busy;
int outreq_busy;
};
enum fsg_state {
@ -631,13 +631,16 @@ struct fsg_dev {
/* filesem protects: backing files in use */
struct rw_semaphore filesem;
/* reference counting: wait until all LUNs are released */
struct kref ref;
struct usb_ep *ep0; // Handy copy of gadget->ep0
struct usb_request *ep0req; // For control responses
volatile unsigned int ep0_req_tag;
unsigned int ep0_req_tag;
const char *ep0req_name;
struct usb_request *intreq; // For interrupt responses
volatile int intreq_busy;
int intreq_busy;
struct fsg_buffhd *intr_buffhd;
unsigned int bulk_out_maxpacket;
@ -667,7 +670,6 @@ struct fsg_dev {
struct fsg_buffhd *next_buffhd_to_drain;
struct fsg_buffhd buffhds[NUM_BUFFERS];
wait_queue_head_t thread_wqh;
int thread_wakeup_needed;
struct completion thread_notifier;
struct task_struct *thread_task;
@ -694,7 +696,6 @@ struct fsg_dev {
unsigned int nluns;
struct lun *luns;
struct lun *curlun;
struct completion lun_released;
};
typedef void (*fsg_routine_t)(struct fsg_dev *);
@ -1073,11 +1074,13 @@ static int populate_config_buf(struct usb_gadget *gadget,
/* These routines may be called in process context or in_irq */
/* Caller must hold fsg->lock */
static void wakeup_thread(struct fsg_dev *fsg)
{
/* Tell the main thread that something has happened */
fsg->thread_wakeup_needed = 1;
wake_up_all(&fsg->thread_wqh);
if (fsg->thread_task)
wake_up_process(fsg->thread_task);
}
@ -1164,11 +1167,12 @@ static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
smp_wmb();
spin_lock(&fsg->lock);
bh->inreq_busy = 0;
bh->state = BUF_STATE_EMPTY;
spin_unlock(&fsg->lock);
wakeup_thread(fsg);
spin_unlock(&fsg->lock);
}
static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
@ -1185,11 +1189,12 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
smp_wmb();
spin_lock(&fsg->lock);
bh->outreq_busy = 0;
bh->state = BUF_STATE_FULL;
spin_unlock(&fsg->lock);
wakeup_thread(fsg);
spin_unlock(&fsg->lock);
}
@ -1206,11 +1211,12 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
usb_ep_fifo_flush(ep);
/* Hold the lock while we update the request and buffer states */
smp_wmb();
spin_lock(&fsg->lock);
fsg->intreq_busy = 0;
bh->state = BUF_STATE_EMPTY;
spin_unlock(&fsg->lock);
wakeup_thread(fsg);
spin_unlock(&fsg->lock);
}
#else
@ -1261,8 +1267,8 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
fsg->cbbuf_cmnd_size = req->actual;
memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size);
spin_unlock(&fsg->lock);
wakeup_thread(fsg);
spin_unlock(&fsg->lock);
}
#else
@ -1514,8 +1520,8 @@ static int fsg_setup(struct usb_gadget *gadget,
/* Use this for bulk or interrupt transfers, not ep0 */
static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
struct usb_request *req, volatile int *pbusy,
volatile enum fsg_buffer_state *state)
struct usb_request *req, int *pbusy,
enum fsg_buffer_state *state)
{
int rc;
@ -1523,8 +1529,11 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
dump_msg(fsg, "bulk-in", req->buf, req->length);
else if (ep == fsg->intr_in)
dump_msg(fsg, "intr-in", req->buf, req->length);
spin_lock_irq(&fsg->lock);
*pbusy = 1;
*state = BUF_STATE_BUSY;
spin_unlock_irq(&fsg->lock);
rc = usb_ep_queue(ep, req, GFP_KERNEL);
if (rc != 0) {
*pbusy = 0;
@ -1544,14 +1553,23 @@ static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,
static int sleep_thread(struct fsg_dev *fsg)
{
int rc;
int rc = 0;
/* Wait until a signal arrives or we are woken up */
rc = wait_event_interruptible(fsg->thread_wqh,
fsg->thread_wakeup_needed);
for (;;) {
try_to_freeze();
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) {
rc = -EINTR;
break;
}
if (fsg->thread_wakeup_needed)
break;
schedule();
}
__set_current_state(TASK_RUNNING);
fsg->thread_wakeup_needed = 0;
try_to_freeze();
return (rc ? -EINTR : 0);
return rc;
}
@ -1788,6 +1806,7 @@ static int do_write(struct fsg_dev *fsg)
if (bh->state == BUF_STATE_EMPTY && !get_some_more)
break; // We stopped early
if (bh->state == BUF_STATE_FULL) {
smp_rmb();
fsg->next_buffhd_to_drain = bh->next;
bh->state = BUF_STATE_EMPTY;
@ -2356,6 +2375,7 @@ static int throw_away_data(struct fsg_dev *fsg)
/* Throw away the data in a filled buffer */
if (bh->state == BUF_STATE_FULL) {
smp_rmb();
bh->state = BUF_STATE_EMPTY;
fsg->next_buffhd_to_drain = bh->next;
@ -3021,6 +3041,7 @@ static int get_next_command(struct fsg_dev *fsg)
if ((rc = sleep_thread(fsg)) != 0)
return rc;
}
smp_rmb();
rc = received_cbw(fsg, bh);
bh->state = BUF_STATE_EMPTY;
@ -3642,11 +3663,19 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
/*-------------------------------------------------------------------------*/
static void fsg_release(struct kref *ref)
{
struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref);
kfree(fsg->luns);
kfree(fsg);
}
static void lun_release(struct device *dev)
{
struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
complete(&fsg->lun_released);
kref_put(&fsg->ref, fsg_release);
}
static void fsg_unbind(struct usb_gadget *gadget)
@ -3660,14 +3689,12 @@ static void fsg_unbind(struct usb_gadget *gadget)
clear_bit(REGISTERED, &fsg->atomic_bitflags);
/* Unregister the sysfs attribute files and the LUNs */
init_completion(&fsg->lun_released);
for (i = 0; i < fsg->nluns; ++i) {
curlun = &fsg->luns[i];
if (curlun->registered) {
device_remove_file(&curlun->dev, &dev_attr_ro);
device_remove_file(&curlun->dev, &dev_attr_file);
device_unregister(&curlun->dev);
wait_for_completion(&fsg->lun_released);
curlun->registered = 0;
}
}
@ -3846,6 +3873,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
curlun->dev.release = lun_release;
device_create_file(&curlun->dev, &dev_attr_ro);
device_create_file(&curlun->dev, &dev_attr_file);
kref_get(&fsg->ref);
}
if (file[i] && *file[i]) {
@ -4061,7 +4089,7 @@ static int __init fsg_alloc(void)
return -ENOMEM;
spin_lock_init(&fsg->lock);
init_rwsem(&fsg->filesem);
init_waitqueue_head(&fsg->thread_wqh);
kref_init(&fsg->ref);
init_completion(&fsg->thread_notifier);
the_fsg = fsg;
@ -4069,13 +4097,6 @@ static int __init fsg_alloc(void)
}
static void fsg_free(struct fsg_dev *fsg)
{
kfree(fsg->luns);
kfree(fsg);
}
static int __init fsg_init(void)
{
int rc;
@ -4085,7 +4106,7 @@ static int __init fsg_init(void)
return rc;
fsg = the_fsg;
if ((rc = usb_gadget_register_driver(&fsg_driver)) != 0)
fsg_free(fsg);
kref_put(&fsg->ref, fsg_release);
return rc;
}
module_init(fsg_init);
@ -4103,6 +4124,6 @@ static void __exit fsg_cleanup(void)
wait_for_completion(&fsg->thread_notifier);
close_all_backing_files(fsg);
fsg_free(fsg);
kref_put(&fsg->ref, fsg_release);
}
module_exit(fsg_cleanup);

View File

@ -890,10 +890,12 @@ static void gs_close(struct tty_struct *tty, struct file *file)
/* wait for write buffer to drain, or */
/* at most GS_CLOSE_TIMEOUT seconds */
if (gs_buf_data_avail(port->port_write_buf) > 0) {
spin_unlock_irqrestore(&port->port_lock, flags);
wait_cond_interruptible_timeout(port->port_write_wait,
port->port_dev == NULL
|| gs_buf_data_avail(port->port_write_buf) == 0,
&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
spin_lock_irqsave(&port->port_lock, flags);
}
/* free disconnected port on final close */

View File

@ -2,6 +2,10 @@
# Makefile for USB Host Controller Drivers
#
ifeq ($(CONFIG_USB_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
obj-$(CONFIG_PCI) += pci-quirks.o
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o

View File

@ -17,13 +17,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dmapool.h>
@ -624,7 +617,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
/* remote wakeup [4.3.1] */
if ((status & STS_PCD) && hcd->remote_wakeup) {
if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */

View File

@ -59,7 +59,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
t2 |= PORT_SUSPEND;
if (hcd->remote_wakeup)
if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@ -517,7 +517,7 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0
|| (temp & PORT_RESET) != 0)
goto error;
if (hcd->remote_wakeup)
if (device_may_wakeup(&hcd->self.root_hub->dev))
temp |= PORT_WAKE_BITS;
writel (temp | PORT_SUSPEND,
&ehci->regs->port_status [wIndex]);

View File

@ -210,7 +210,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
/* REVISIT: per-port wake capability (PCI 0x62) currently unused */
/* Workaround current PCI init glitch: wakeup bits aren't
* being set from PCI PM capability.
*/
if (!device_can_wakeup(&pdev->dev)) {
u16 port_wake;
pci_read_config_word(pdev, 0x62, &port_wake);
if (port_wake & 0x0001)
device_init_wakeup(&pdev->dev, 1);
}
retval = ehci_pci_reinit(ehci, pdev);
done:
@ -269,7 +278,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned port;
struct usb_device *root = hcd->self.root_hub;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval = -EINVAL;
@ -303,13 +311,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
restart:
ehci_dbg(ehci, "lost power, restarting\n");
for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
port--;
if (!root->children [port])
continue;
usb_set_device_state(root->children[port],
USB_STATE_NOTATTACHED);
}
usb_root_hub_lost_power(hcd->self.root_hub);
/* Else reset, to cope with power loss or flush-to-storage
* style "resume" having let BIOS kick in during reboot.

View File

@ -514,18 +514,18 @@ qh_urb_transaction (
qtd->urb = urb;
qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
/* for zero length DATA stages, STATUS is always IN */
if (len == 0)
token |= (1 /* "in" */ << 8);
}
/*
* data transfer stage: buffer setup
*/
if (likely (len > 0))
buf = urb->transfer_dma;
else
buf = 0;
buf = urb->transfer_dma;
/* for zero length DATA stages, STATUS is always IN */
if (!buf || is_input)
if (is_input)
token |= (1 /* "in" */ << 8);
/* else it's already initted to "out" pid (0 << 8) */
@ -572,7 +572,7 @@ qh_urb_transaction (
* control requests may need a terminating data "status" ack;
* bulk ones may need a terminating short packet (zero length).
*/
if (likely (buf != 0)) {
if (likely (urb->transfer_buffer_length != 0)) {
int one_more = 0;
if (usb_pipecontrol (urb->pipe)) {

View File

@ -55,19 +55,13 @@
/* enqueuing/finishing log of urbs */
//#define URB_TRACE
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/usb_isp116x.h>
#include <linux/platform_device.h>
@ -77,14 +71,10 @@
#include <asm/system.h>
#include <asm/byteorder.h>
#ifndef DEBUG
# define STUB_DEBUG_FILE
#endif
#include "../core/hcd.h"
#include "isp116x.h"
#define DRIVER_VERSION "05 Aug 2005"
#define DRIVER_VERSION "03 Nov 2005"
#define DRIVER_DESC "ISP116x USB Host Controller Driver"
MODULE_DESCRIPTION(DRIVER_DESC);
@ -164,13 +154,11 @@ static void pack_fifo(struct isp116x *isp116x)
struct ptd *ptd;
int buflen = isp116x->atl_last_dir == PTD_DIR_IN
? isp116x->atl_bufshrt : isp116x->atl_buflen;
int ptd_count = 0;
isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
for (ep = isp116x->atl_active; ep; ep = ep->active) {
++ptd_count;
ptd = &ep->ptd;
dump_ptd(ptd);
dump_ptd_out_data(ptd, ep->data);
@ -305,9 +293,8 @@ static void postproc_atl_queue(struct isp116x *isp116x)
udev = urb->dev;
ptd = &ep->ptd;
cc = PTD_GET_CC(ptd);
spin_lock(&urb->lock);
short_not_ok = 1;
spin_lock(&urb->lock);
/* Data underrun is special. For allowed underrun
we clear the error and continue as normal. For
@ -420,7 +407,7 @@ static void postproc_atl_queue(struct isp116x *isp116x)
ep->nextpid = 0;
break;
default:
BUG_ON(1);
BUG();
}
spin_unlock(&urb->lock);
}
@ -628,8 +615,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
u32 intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
if (intstat & HCINT_UE) {
ERR("Unrecoverable error\n");
/* What should we do here? Reset? */
ERR("Unrecoverable error, HC is dead!\n");
/* IRQ's are off, we do no DMA,
perfectly ready to die ... */
hcd->state = HC_STATE_HALT;
ret = IRQ_HANDLED;
goto done;
}
if (intstat & HCINT_RHSC)
/* When root hub or any of its ports is going
@ -640,7 +631,6 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
if (intstat & HCINT_RD) {
DBG("---- remote wakeup\n");
usb_hcd_resume_root_hub(hcd);
ret = IRQ_HANDLED;
}
irqstat &= ~HCuPINT_OPR;
ret = IRQ_HANDLED;
@ -651,6 +641,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs)
}
isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
done:
spin_unlock(&isp116x->lock);
return ret;
}
@ -724,6 +715,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd,
spin_lock_irqsave(&isp116x->lock, flags);
if (!HC_IS_RUNNING(hcd->state)) {
kfree(ep);
ret = -ENODEV;
goto fail;
}
@ -888,7 +880,7 @@ static void isp116x_endpoint_disable(struct usb_hcd *hcd,
struct usb_host_endpoint *hep)
{
int i;
struct isp116x_ep *ep = hep->hcpriv;;
struct isp116x_ep *ep = hep->hcpriv;
if (!ep)
return;
@ -916,8 +908,6 @@ static int isp116x_get_frame(struct usb_hcd *hcd)
return (int)fmnum;
}
/*----------------------------------------------------------------*/
/*
Adapted from ohci-hub.c. Currently we don't support autosuspend.
*/
@ -968,11 +958,10 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
desc->bHubContrCurrent = 0;
desc->bNbrPorts = (u8) (reg & 0x3);
/* Power switching, device type, overcurrent. */
desc->wHubCharacteristics =
(__force __u16) cpu_to_le16((u16) ((reg >> 8) & 0x1f));
desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
/* two bitmaps: ports removable, and legacy PortPwrCtrlMask */
desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
desc->bitmap[0] = 0;
desc->bitmap[1] = ~0;
}
@ -1159,135 +1148,9 @@ static int isp116x_hub_control(struct usb_hcd *hcd,
return ret;
}
#ifdef CONFIG_PM
static int isp116x_bus_suspend(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long flags;
u32 val;
int ret = 0;
spin_lock_irqsave(&isp116x->lock, flags);
val = isp116x_read_reg32(isp116x, HCCONTROL);
switch (val & HCCONTROL_HCFS) {
case HCCONTROL_USB_OPER:
hcd->state = HC_STATE_QUIESCING;
val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
val |= HCCONTROL_USB_SUSPEND;
if (hcd->remote_wakeup)
val |= HCCONTROL_RWE;
/* Wait for usb transfers to finish */
mdelay(2);
isp116x_write_reg32(isp116x, HCCONTROL, val);
hcd->state = HC_STATE_SUSPENDED;
/* Wait for devices to suspend */
mdelay(5);
case HCCONTROL_USB_SUSPEND:
break;
case HCCONTROL_USB_RESUME:
isp116x_write_reg32(isp116x, HCCONTROL,
(val & ~HCCONTROL_HCFS) |
HCCONTROL_USB_RESET);
case HCCONTROL_USB_RESET:
ret = -EBUSY;
break;
default:
ret = -EINVAL;
}
spin_unlock_irqrestore(&isp116x->lock, flags);
return ret;
}
static int isp116x_bus_resume(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
u32 val;
int ret = -EINPROGRESS;
msleep(5);
spin_lock_irq(&isp116x->lock);
val = isp116x_read_reg32(isp116x, HCCONTROL);
switch (val & HCCONTROL_HCFS) {
case HCCONTROL_USB_SUSPEND:
val &= ~HCCONTROL_HCFS;
val |= HCCONTROL_USB_RESUME;
isp116x_write_reg32(isp116x, HCCONTROL, val);
case HCCONTROL_USB_RESUME:
break;
case HCCONTROL_USB_OPER:
/* Without setting power_state here the
SUSPENDED state won't be removed from
sysfs/usbN/power.state as a response to remote
wakeup. Maybe in the future. */
hcd->self.root_hub->dev.power.power_state = PMSG_ON;
ret = 0;
break;
default:
ret = -EBUSY;
}
if (ret != -EINPROGRESS) {
spin_unlock_irq(&isp116x->lock);
return ret;
}
val = isp116x->rhdesca & RH_A_NDP;
while (val--) {
u32 stat =
isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
/* force global, not selective, resume */
if (!(stat & RH_PS_PSS))
continue;
DBG("%s: Resuming port %d\n", __func__, val);
isp116x_write_reg32(isp116x, RH_PS_POCI, val
? HCRHPORT2 : HCRHPORT1);
}
spin_unlock_irq(&isp116x->lock);
hcd->state = HC_STATE_RESUMING;
mdelay(20);
/* Go operational */
spin_lock_irq(&isp116x->lock);
val = isp116x_read_reg32(isp116x, HCCONTROL);
isp116x_write_reg32(isp116x, HCCONTROL,
(val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
spin_unlock_irq(&isp116x->lock);
/* see analogous comment above */
hcd->self.root_hub->dev.power.power_state = PMSG_ON;
hcd->state = HC_STATE_RUNNING;
return 0;
}
#else
#define isp116x_bus_suspend NULL
#define isp116x_bus_resume NULL
#endif
/*-----------------------------------------------------------------*/
#ifdef STUB_DEBUG_FILE
static inline void create_debug_file(struct isp116x *isp116x)
{
}
static inline void remove_debug_file(struct isp116x *isp116x)
{
}
#else
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#ifdef CONFIG_DEBUG_FS
static void dump_irq(struct seq_file *s, char *label, u16 mask)
{
@ -1311,13 +1174,9 @@ static void dump_int(struct seq_file *s, char *label, u32 mask)
mask & HCINT_SF ? " sof" : "", mask & HCINT_SO ? " so" : "");
}
static int proc_isp116x_show(struct seq_file *s, void *unused)
static int isp116x_show_dbg(struct seq_file *s, void *unused)
{
struct isp116x *isp116x = s->private;
struct isp116x_ep *ep;
struct urb *urb;
unsigned i;
char *str;
seq_printf(s, "%s\n%s version %s\n",
isp116x_to_hcd(isp116x)->product_desc, hcd_name,
@ -1333,105 +1192,50 @@ static int proc_isp116x_show(struct seq_file *s, void *unused)
}
spin_lock_irq(&isp116x->lock);
dump_irq(s, "hc_irq_enable", isp116x_read_reg16(isp116x, HCuPINTENB));
dump_irq(s, "hc_irq_status", isp116x_read_reg16(isp116x, HCuPINT));
dump_int(s, "hc_int_enable", isp116x_read_reg32(isp116x, HCINTENB));
dump_int(s, "hc_int_status", isp116x_read_reg32(isp116x, HCINTSTAT));
list_for_each_entry(ep, &isp116x->async, schedule) {
switch (ep->nextpid) {
case USB_PID_IN:
str = "in";
break;
case USB_PID_OUT:
str = "out";
break;
case USB_PID_SETUP:
str = "setup";
break;
case USB_PID_ACK:
str = "status";
break;
default:
str = "?";
break;
};
seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep,
ep->epnum, str, ep->maxpacket);
list_for_each_entry(urb, &ep->hep->urb_list, urb_list) {
seq_printf(s, " urb%p, %d/%d\n", urb,
urb->actual_length,
urb->transfer_buffer_length);
}
}
if (!list_empty(&isp116x->async))
seq_printf(s, "\n");
seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);
for (i = 0; i < PERIODIC_SIZE; i++) {
ep = isp116x->periodic[i];
if (!ep)
continue;
seq_printf(s, "%2d [%3d]:\n", i, isp116x->load[i]);
/* DUMB: prints shared entries multiple times */
do {
seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n",
ep->period, ep,
(ep->udev->speed ==
USB_SPEED_FULL) ? "" : "ls ",
ep->udev->devnum, ep->epnum,
(ep->epnum ==
0) ? "" : ((ep->nextpid ==
USB_PID_IN) ? "in" : "out"),
ep->maxpacket);
ep = ep->next;
} while (ep);
}
isp116x_show_regs_seq(isp116x, s);
spin_unlock_irq(&isp116x->lock);
seq_printf(s, "\n");
return 0;
}
static int proc_isp116x_open(struct inode *inode, struct file *file)
static int isp116x_open_seq(struct inode *inode, struct file *file)
{
return single_open(file, proc_isp116x_show, PDE(inode)->data);
return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
}
static struct file_operations proc_ops = {
.open = proc_isp116x_open,
static struct file_operations isp116x_debug_fops = {
.open = isp116x_open_seq,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* expect just one isp116x per system */
static const char proc_filename[] = "driver/isp116x";
static void create_debug_file(struct isp116x *isp116x)
static int create_debug_file(struct isp116x *isp116x)
{
struct proc_dir_entry *pde;
pde = create_proc_entry(proc_filename, 0, NULL);
if (pde == NULL)
return;
pde->proc_fops = &proc_ops;
pde->data = isp116x;
isp116x->pde = pde;
isp116x->dentry = debugfs_create_file(hcd_name,
S_IRUGO, NULL, isp116x,
&isp116x_debug_fops);
if (!isp116x->dentry)
return -ENOMEM;
return 0;
}
static void remove_debug_file(struct isp116x *isp116x)
{
if (isp116x->pde)
remove_proc_entry(proc_filename, NULL);
debugfs_remove(isp116x->dentry);
}
#endif
#else
#define create_debug_file(d) 0
#define remove_debug_file(d) do{}while(0)
#endif /* CONFIG_DEBUG_FS */
/*-----------------------------------------------------------------*/
@ -1466,7 +1270,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long t;
u16 clkrdy = 0;
int ret = 0, timeout = 15 /* ms */ ;
int ret, timeout = 15 /* ms */ ;
ret = isp116x_sw_reset(isp116x);
if (ret)
@ -1482,7 +1286,7 @@ static int isp116x_reset(struct usb_hcd *hcd)
break;
}
if (!clkrdy) {
ERR("Clock not ready after 20ms\n");
ERR("Clock not ready after %dms\n", timeout);
/* After sw_reset the clock won't report to be ready, if
H_WAKEUP pin is high. */
ERR("Please make sure that the H_WAKEUP pin is pulled low!\n");
@ -1572,7 +1376,8 @@ static int isp116x_start(struct usb_hcd *hcd)
val = 0;
if (board->remote_wakeup_enable) {
hcd->can_wakeup = 1;
if (!device_can_wakeup(hcd->self.controller))
device_init_wakeup(hcd->self.controller, 1);
val |= RH_HS_DRWE;
}
isp116x_write_reg32(isp116x, HCRHSTATUS, val);
@ -1600,12 +1405,126 @@ static int isp116x_start(struct usb_hcd *hcd)
isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
isp116x_show_regs(isp116x);
isp116x_show_regs_log(isp116x);
spin_unlock_irqrestore(&isp116x->lock, flags);
return 0;
}
/*-----------------------------------------------------------------*/
#ifdef CONFIG_PM
static int isp116x_bus_suspend(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
unsigned long flags;
u32 val;
int ret = 0;
spin_lock_irqsave(&isp116x->lock, flags);
val = isp116x_read_reg32(isp116x, HCCONTROL);
switch (val & HCCONTROL_HCFS) {
case HCCONTROL_USB_OPER:
val &= (~HCCONTROL_HCFS & ~HCCONTROL_RWE);
val |= HCCONTROL_USB_SUSPEND;
if (device_may_wakeup(&hcd->self.root_hub->dev))
val |= HCCONTROL_RWE;
/* Wait for usb transfers to finish */
mdelay(2);
isp116x_write_reg32(isp116x, HCCONTROL, val);
/* Wait for devices to suspend */
mdelay(5);
case HCCONTROL_USB_SUSPEND:
break;
case HCCONTROL_USB_RESUME:
isp116x_write_reg32(isp116x, HCCONTROL,
(val & ~HCCONTROL_HCFS) |
HCCONTROL_USB_RESET);
case HCCONTROL_USB_RESET:
ret = -EBUSY;
break;
default:
ret = -EINVAL;
}
spin_unlock_irqrestore(&isp116x->lock, flags);
return ret;
}
static int isp116x_bus_resume(struct usb_hcd *hcd)
{
struct isp116x *isp116x = hcd_to_isp116x(hcd);
u32 val;
msleep(5);
spin_lock_irq(&isp116x->lock);
val = isp116x_read_reg32(isp116x, HCCONTROL);
switch (val & HCCONTROL_HCFS) {
case HCCONTROL_USB_SUSPEND:
val &= ~HCCONTROL_HCFS;
val |= HCCONTROL_USB_RESUME;
isp116x_write_reg32(isp116x, HCCONTROL, val);
case HCCONTROL_USB_RESUME:
break;
case HCCONTROL_USB_OPER:
spin_unlock_irq(&isp116x->lock);
/* Without setting power_state here the
SUSPENDED state won't be removed from
sysfs/usbN/power.state as a response to remote
wakeup. Maybe in the future. */
hcd->self.root_hub->dev.power.power_state = PMSG_ON;
return 0;
default:
/* HCCONTROL_USB_RESET: this may happen, when during
suspension the HC lost power. Reinitialize completely */
spin_unlock_irq(&isp116x->lock);
DBG("Chip has been reset while suspended. Reinit from scratch.\n");
isp116x_reset(hcd);
isp116x_start(hcd);
isp116x_hub_control(hcd, SetPortFeature,
USB_PORT_FEAT_POWER, 1, NULL, 0);
if ((isp116x->rhdesca & RH_A_NDP) == 2)
isp116x_hub_control(hcd, SetPortFeature,
USB_PORT_FEAT_POWER, 2, NULL, 0);
hcd->self.root_hub->dev.power.power_state = PMSG_ON;
return 0;
}
val = isp116x->rhdesca & RH_A_NDP;
while (val--) {
u32 stat =
isp116x_read_reg32(isp116x, val ? HCRHPORT2 : HCRHPORT1);
/* force global, not selective, resume */
if (!(stat & RH_PS_PSS))
continue;
DBG("%s: Resuming port %d\n", __func__, val);
isp116x_write_reg32(isp116x, RH_PS_POCI, val
? HCRHPORT2 : HCRHPORT1);
}
spin_unlock_irq(&isp116x->lock);
hcd->state = HC_STATE_RESUMING;
msleep(20);
/* Go operational */
spin_lock_irq(&isp116x->lock);
val = isp116x_read_reg32(isp116x, HCCONTROL);
isp116x_write_reg32(isp116x, HCCONTROL,
(val & ~HCCONTROL_HCFS) | HCCONTROL_USB_OPER);
spin_unlock_irq(&isp116x->lock);
/* see analogous comment above */
hcd->self.root_hub->dev.power.power_state = PMSG_ON;
hcd->state = HC_STATE_RUNNING;
return 0;
}
#else
#define isp116x_bus_suspend NULL
#define isp116x_bus_resume NULL
#endif
static struct hc_driver isp116x_hc_driver = {
.description = hcd_name,
@ -1735,12 +1654,19 @@ static int __init isp116x_probe(struct platform_device *pdev)
}
ret = usb_add_hcd(hcd, irq, SA_INTERRUPT);
if (ret != 0)
if (ret)
goto err6;
create_debug_file(isp116x);
ret = create_debug_file(isp116x);
if (ret) {
ERR("Couldn't create debugfs entry\n");
goto err7;
}
return 0;
err7:
usb_remove_hcd(hcd);
err6:
usb_put_hcd(hcd);
err5:
@ -1762,13 +1688,9 @@ static int __init isp116x_probe(struct platform_device *pdev)
*/
static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
{
int ret = 0;
VDBG("%s: state %x\n", __func__, state);
VDBG("%s: state %x\n", __func__, state.event);
dev->dev.power.power_state = state;
return ret;
return 0;
}
/*
@ -1776,13 +1698,9 @@ static int isp116x_suspend(struct platform_device *dev, pm_message_t state)
*/
static int isp116x_resume(struct platform_device *dev)
{
int ret = 0;
VDBG("%s: state %x\n", __func__, dev->dev.power.power_state);
VDBG("%s: state %x\n", __func__, dev->power.power_state.event);
dev->dev.power.power_state = PMSG_ON;
return ret;
return 0;
}
#else

View File

@ -259,7 +259,7 @@ struct isp116x {
struct isp116x_platform_data *board;
struct proc_dir_entry *pde;
struct dentry *dentry;
unsigned long stat1, stat2, stat4, stat8, stat16;
/* HC registers */
@ -450,7 +450,7 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
isp116x_write_data32(isp116x, (u32) val);
}
#define isp116x_show_reg(d,r) { \
#define isp116x_show_reg_log(d,r,s) { \
if ((r) < 0x20) { \
DBG("%-12s[%02x]: %08x\n", #r, \
r, isp116x_read_reg32(d, r)); \
@ -459,35 +459,60 @@ static void isp116x_write_reg32(struct isp116x *isp116x, unsigned reg,
r, isp116x_read_reg16(d, r)); \
} \
}
#define isp116x_show_reg_seq(d,r,s) { \
if ((r) < 0x20) { \
seq_printf(s, "%-12s[%02x]: %08x\n", #r, \
r, isp116x_read_reg32(d, r)); \
} else { \
seq_printf(s, "%-12s[%02x]: %04x\n", #r, \
r, isp116x_read_reg16(d, r)); \
} \
}
static inline void isp116x_show_regs(struct isp116x *isp116x)
#define isp116x_show_regs(d,type,s) { \
isp116x_show_reg_##type(d, HCREVISION, s); \
isp116x_show_reg_##type(d, HCCONTROL, s); \
isp116x_show_reg_##type(d, HCCMDSTAT, s); \
isp116x_show_reg_##type(d, HCINTSTAT, s); \
isp116x_show_reg_##type(d, HCINTENB, s); \
isp116x_show_reg_##type(d, HCFMINTVL, s); \
isp116x_show_reg_##type(d, HCFMREM, s); \
isp116x_show_reg_##type(d, HCFMNUM, s); \
isp116x_show_reg_##type(d, HCLSTHRESH, s); \
isp116x_show_reg_##type(d, HCRHDESCA, s); \
isp116x_show_reg_##type(d, HCRHDESCB, s); \
isp116x_show_reg_##type(d, HCRHSTATUS, s); \
isp116x_show_reg_##type(d, HCRHPORT1, s); \
isp116x_show_reg_##type(d, HCRHPORT2, s); \
isp116x_show_reg_##type(d, HCHWCFG, s); \
isp116x_show_reg_##type(d, HCDMACFG, s); \
isp116x_show_reg_##type(d, HCXFERCTR, s); \
isp116x_show_reg_##type(d, HCuPINT, s); \
isp116x_show_reg_##type(d, HCuPINTENB, s); \
isp116x_show_reg_##type(d, HCCHIPID, s); \
isp116x_show_reg_##type(d, HCSCRATCH, s); \
isp116x_show_reg_##type(d, HCITLBUFLEN, s); \
isp116x_show_reg_##type(d, HCATLBUFLEN, s); \
isp116x_show_reg_##type(d, HCBUFSTAT, s); \
isp116x_show_reg_##type(d, HCRDITL0LEN, s); \
isp116x_show_reg_##type(d, HCRDITL1LEN, s); \
}
/*
Dump registers for debugfs.
*/
static inline void isp116x_show_regs_seq(struct isp116x *isp116x,
struct seq_file *s)
{
isp116x_show_reg(isp116x, HCREVISION);
isp116x_show_reg(isp116x, HCCONTROL);
isp116x_show_reg(isp116x, HCCMDSTAT);
isp116x_show_reg(isp116x, HCINTSTAT);
isp116x_show_reg(isp116x, HCINTENB);
isp116x_show_reg(isp116x, HCFMINTVL);
isp116x_show_reg(isp116x, HCFMREM);
isp116x_show_reg(isp116x, HCFMNUM);
isp116x_show_reg(isp116x, HCLSTHRESH);
isp116x_show_reg(isp116x, HCRHDESCA);
isp116x_show_reg(isp116x, HCRHDESCB);
isp116x_show_reg(isp116x, HCRHSTATUS);
isp116x_show_reg(isp116x, HCRHPORT1);
isp116x_show_reg(isp116x, HCRHPORT2);
isp116x_show_reg(isp116x, HCHWCFG);
isp116x_show_reg(isp116x, HCDMACFG);
isp116x_show_reg(isp116x, HCXFERCTR);
isp116x_show_reg(isp116x, HCuPINT);
isp116x_show_reg(isp116x, HCuPINTENB);
isp116x_show_reg(isp116x, HCCHIPID);
isp116x_show_reg(isp116x, HCSCRATCH);
isp116x_show_reg(isp116x, HCITLBUFLEN);
isp116x_show_reg(isp116x, HCATLBUFLEN);
isp116x_show_reg(isp116x, HCBUFSTAT);
isp116x_show_reg(isp116x, HCRDITL0LEN);
isp116x_show_reg(isp116x, HCRDITL1LEN);
isp116x_show_regs(isp116x, seq, s);
}
/*
Dump registers to syslog.
*/
static inline void isp116x_show_regs_log(struct isp116x *isp116x)
{
isp116x_show_regs(isp116x, log, NULL);
}
#if defined(URB_TRACE)

View File

@ -75,13 +75,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
# define DEBUG
#else
# undef DEBUG
#endif
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
@ -802,7 +795,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
int temp;
int i;
struct urb_priv *priv;
struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
/* mark any devices gone, so they do nothing till khubd disconnects.
* recycle any "live" eds/tds (and urbs) right away.
@ -811,11 +803,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/
spin_lock_irq(&ohci->lock);
disable (ohci);
for (i = 0; i < root->maxchild; i++) {
if (root->children [i])
usb_set_device_state (root->children[i],
USB_STATE_NOTATTACHED);
}
usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
if (!list_empty (&ohci->pending))
ohci_dbg(ohci, "abort schedule...\n");
list_for_each_entry (priv, &ohci->pending, pending) {

View File

@ -372,7 +372,7 @@ done:
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
&& usb_trylock_device (hcd->self.root_hub)
&& usb_trylock_device (hcd->self.root_hub) == 0
) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_bus_suspend (hcd);

View File

@ -26,18 +26,12 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#define PMM_NPS_MODE 1
#define PMM_GLOBAL_MODE 2
#define PMM_PERPORT_MODE 3
#include <asm/arch/ohci.h>
#define PXA_UHC_MAX_PORTNUM 3
#define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 )
static int pxa27x_ohci_pmm_state;
/*
PMM_NPS_MODE -- PMM Non-power switching mode
Ports are powered continuously.
@ -50,8 +44,6 @@ static int pxa27x_ohci_pmm_state;
*/
static int pxa27x_ohci_select_pmm( int mode )
{
pxa27x_ohci_pmm_state = mode;
switch ( mode ) {
case PMM_NPS_MODE:
UHCRHDA |= RH_A_NPS;
@ -71,7 +63,6 @@ static int pxa27x_ohci_select_pmm( int mode )
"Invalid mode %d, set to non-power switch mode.\n",
mode );
pxa27x_ohci_pmm_state = PMM_NPS_MODE;
UHCRHDA |= RH_A_NPS;
}
@ -82,8 +73,13 @@ extern int usb_disabled(void);
/*-------------------------------------------------------------------------*/
static void pxa27x_start_hc(struct platform_device *dev)
static int pxa27x_start_hc(struct device *dev)
{
int retval = 0;
struct pxaohci_platform_data *inf;
inf = dev->platform_data;
pxa_set_cken(CKEN10_USBHOST, 1);
UHCHR |= UHCHR_FHR;
@ -94,21 +90,11 @@ static void pxa27x_start_hc(struct platform_device *dev)
while (UHCHR & UHCHR_FSBIR)
cpu_relax();
/* This could be properly abstracted away through the
device data the day more machines are supported and
their differences can be figured out correctly. */
if (machine_is_mainstone()) {
/* setup Port1 GPIO pin. */
pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
if (inf->init)
retval = inf->init(dev);
/* Set the Power Control Polarity Low and Power Sense
Polarity Low to active low. Supply power to USB ports. */
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
pxa27x_ohci_pmm_state = PMM_PERPORT_MODE;
}
if (retval < 0)
return retval;
UHCHR &= ~UHCHR_SSE;
@ -117,10 +103,19 @@ static void pxa27x_start_hc(struct platform_device *dev)
/* Clear any OTG Pin Hold */
if (PSSR & PSSR_OTGPH)
PSSR |= PSSR_OTGPH;
return 0;
}
static void pxa27x_stop_hc(struct platform_device *dev)
static void pxa27x_stop_hc(struct device *dev)
{
struct pxaohci_platform_data *inf;
inf = dev->platform_data;
if (inf->exit)
inf->exit(dev);
UHCHR |= UHCHR_FHR;
udelay(11);
UHCHR &= ~UHCHR_FHR;
@ -147,22 +142,27 @@ static void pxa27x_stop_hc(struct platform_device *dev)
* through the hotplug entry's driver_data.
*
*/
int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
struct platform_device *dev)
int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev)
{
int retval;
struct usb_hcd *hcd;
struct pxaohci_platform_data *inf;
if (dev->resource[1].flags != IORESOURCE_IRQ) {
inf = pdev->dev.platform_data;
if (!inf)
return -ENODEV;
if (pdev->resource[1].flags != IORESOURCE_IRQ) {
pr_debug ("resource[1] is not IORESOURCE_IRQ");
return -ENOMEM;
}
hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = dev->resource[0].start;
hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
hcd->rsrc_start = pdev->resource[0].start;
hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
pr_debug("request_mem_region failed");
@ -177,18 +177,22 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
goto err2;
}
pxa27x_start_hc(dev);
if ((retval = pxa27x_start_hc(&pdev->dev)) < 0) {
pr_debug("pxa27x_start_hc failed");
goto err3;
}
/* Select Power Management Mode */
pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state);
pxa27x_ohci_select_pmm(inf->port_mode);
ohci_hcd_init(hcd_to_ohci(hcd));
retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
if (retval == 0)
return retval;
pxa27x_stop_hc(dev);
pxa27x_stop_hc(&pdev->dev);
err3:
iounmap(hcd->regs);
err2:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
@ -211,10 +215,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
* context, normally "rmmod", "apmd", or something similar.
*
*/
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev)
{
usb_remove_hcd(hcd);
pxa27x_stop_hc(dev);
pxa27x_stop_hc(&pdev->dev);
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
@ -292,15 +296,12 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
static int ohci_hcd_pxa27x_drv_probe(struct platform_device *pdev)
{
int ret;
pr_debug ("In ohci_hcd_pxa27x_drv_probe");
if (usb_disabled())
return -ENODEV;
ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
return ret;
return usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
}
static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
@ -308,31 +309,55 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev)
struct usb_hcd *hcd = platform_get_drvdata(pdev);
usb_hcd_pxa27x_remove(hcd, pdev);
platform_set_drvdata(pdev, NULL);
return 0;
}
static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *dev, pm_message_t state)
#ifdef CONFIG_PM
static int ohci_hcd_pxa27x_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
// struct usb_hcd *hcd = platform_get_drvdata(dev);
printk("%s: not implemented yet\n", __FUNCTION__);
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
pxa27x_stop_hc(&pdev->dev);
hcd->state = HC_STATE_SUSPENDED;
pdev->dev.power.power_state = PMSG_SUSPEND;
return 0;
}
static int ohci_hcd_pxa27x_drv_resume(struct platform_device *dev)
static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
{
// struct usb_hcd *hcd = platform_get_drvdata(dev);
printk("%s: not implemented yet\n", __FUNCTION__);
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
int status;
if (time_before(jiffies, ohci->next_statechange))
msleep(5);
ohci->next_statechange = jiffies;
if ((status = pxa27x_start_hc(&pdev->dev)) < 0)
return status;
pdev->dev.power.power_state = PMSG_ON;
usb_hcd_resume_root_hub(hcd);
return 0;
}
#endif
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_drv_probe,
.remove = ohci_hcd_pxa27x_drv_remove,
#ifdef CONFIG_PM
.suspend = ohci_hcd_pxa27x_drv_suspend,
.resume = ohci_hcd_pxa27x_drv_resume,
#endif
.driver = {
.name = "pxa27x-ohci",
},

View File

@ -9,12 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>

View File

@ -32,13 +32,6 @@
#undef PACKET_TRACE
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
# define DEBUG
#else
# undef DEBUG
#endif
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@ -1581,7 +1574,9 @@ sl811h_start(struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING;
if (sl811->board) {
hcd->can_wakeup = sl811->board->can_wakeup;
if (!device_can_wakeup(hcd->self.controller))
device_init_wakeup(hcd->self.controller,
sl811->board->can_wakeup);
hcd->power_budget = sl811->board->power * 2;
}
@ -1805,9 +1800,10 @@ sl811h_resume(struct platform_device *dev)
* let's assume it'd only be powered to enable remote wakeup.
*/
if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND
|| !hcd->can_wakeup) {
|| !device_can_wakeup(&hcd->self.root_hub->dev)) {
sl811->port1 = 0;
port_power(sl811, 1);
usb_root_hub_lost_power(hcd->self.root_hub);
return 0;
}

View File

@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
/* MACROS */
/*====================================================================*/
#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
#if defined(DEBUG) || defined(PCMCIA_DEBUG)
static int pc_debug = 0;
module_param(pc_debug, int, 0644);
@ -129,7 +129,8 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
resources[2].end = base_addr + 1;
/* The driver core will probe for us. We know sl811-hcd has been
* initialized already because of the link order dependency.
* initialized already because of the link order dependency created
* by referencing "sl811h_driver".
*/
platform_dev.name = sl811h_driver.name;
return platform_device_register(&platform_dev);

View File

@ -2,8 +2,8 @@
* UHCI-specific debugging code. Invaluable when something
* goes wrong, but don't get in my face.
*
* Kernel visible pointers are surrounded in []'s and bus
* visible pointers are surrounded in ()'s
* Kernel visible pointers are surrounded in []s and bus
* visible pointers are surrounded in ()s
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2001 Johannes Erdfelt
@ -19,7 +19,7 @@
static struct dentry *uhci_debugfs_root = NULL;
/* Handle REALLY large printk's so we don't overflow buffers */
/* Handle REALLY large printks so we don't overflow buffers */
static inline void lprintk(char *buf)
{
char *p;
@ -160,7 +160,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
}
if (active && ni > i) {
out += sprintf(out, "%*s[skipped %d active TD's]\n", space, "", ni - i);
out += sprintf(out, "%*s[skipped %d active TDs]\n", space, "", ni - i);
tmp = ntmp;
td = ntd;
i = ni;
@ -173,7 +173,7 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
if (list_empty(&urbp->queue_list) || urbp->queued)
goto out;
out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
out += sprintf(out, "%*sQueued QHs:\n", -space, "--");
head = &urbp->queue_list;
tmp = head->next;
@ -197,7 +197,7 @@ out:
}
#ifdef CONFIG_PROC_FS
static const char *qh_names[] = {
static const char * const qh_names[] = {
"skel_int128_qh", "skel_int64_qh",
"skel_int32_qh", "skel_int16_qh",
"skel_int8_qh", "skel_int4_qh",
@ -464,7 +464,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
} while (tmp != head);
}
out += sprintf(out, "Skeleton QH's\n");
out += sprintf(out, "Skeleton QHs\n");
for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
int shown = 0;

View File

@ -23,11 +23,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
@ -67,10 +62,10 @@ Alan Stern"
/*
* debug = 0, no debugging messages
* debug = 1, dump failed URB's except for stalls
* debug = 2, dump all failed URB's (including stalls)
* debug = 1, dump failed URBs except for stalls
* debug = 2, dump all failed URBs (including stalls)
* show all queues in /debug/uhci/[pci_addr]
* debug = 3, show all TD's in URB's when dumping
* debug = 3, show all TDs in URBs when dumping
*/
#ifdef DEBUG
static int debug = 1;
@ -93,7 +88,7 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
#define FSBR_DELAY msecs_to_jiffies(50)
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
/* depth first traversal. We'll do it in groups of this number of TD's */
/* depth first traversal. We'll do it in groups of this number of TDs */
/* to make sure it doesn't hog all of the bandwidth */
#define DEPTH_INTERVAL 5
@ -478,8 +473,6 @@ static int uhci_start(struct usb_hcd *hcd)
struct dentry *dentry;
hcd->uses_new_polling = 1;
if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
hcd->can_wakeup = 1; /* Assume it supports PME# */
dentry = debugfs_create_file(hcd->self.bus_name,
S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
@ -573,7 +566,7 @@ static int uhci_start(struct usb_hcd *hcd)
uhci->skel_bulk_qh->link = cpu_to_le32(uhci->skel_term_qh->dma_handle) | UHCI_PTR_QH;
/* This dummy TD is to work around a bug in Intel PIIX controllers */
uhci_fill_td(uhci->term_td, 0, (UHCI_NULL_DATA_SIZE << 21) |
uhci_fill_td(uhci->term_td, 0, uhci_explen(0) |
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN, 0);
uhci->term_td->link = cpu_to_le32(uhci->term_td->dma_handle);
@ -735,8 +728,9 @@ static int uhci_resume(struct usb_hcd *hcd)
dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
/* We aren't in D3 state anymore, we do that even if dead as I
* really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0
/* Since we aren't in D3 any more, it's safe to set this flag
* even if the controller was dead. It might not even be dead
* any more, if the firmware or quirks code has reset it.
*/
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
mb();
@ -755,8 +749,12 @@ static int uhci_resume(struct usb_hcd *hcd)
check_and_reset_hc(uhci);
configure_hc(uhci);
if (uhci->rh_state == UHCI_RH_RESET)
if (uhci->rh_state == UHCI_RH_RESET) {
/* The controller had to be reset */
usb_root_hub_lost_power(hcd->self.root_hub);
suspend_rh(uhci, UHCI_RH_SUSPENDED);
}
spin_unlock_irq(&uhci->lock);
@ -882,7 +880,7 @@ static int __init uhci_hcd_init(void)
init_failed:
if (kmem_cache_destroy(uhci_up_cachep))
warn("not all urb_priv's were freed!");
warn("not all urb_privs were freed!");
up_failed:
debugfs_remove(uhci_debugfs_root);
@ -900,7 +898,7 @@ static void __exit uhci_hcd_cleanup(void)
pci_unregister_driver(&uhci_pci_driver);
if (kmem_cache_destroy(uhci_up_cachep))
warn("not all urb_priv's were freed!");
warn("not all urb_privs were freed!");
debugfs_remove(uhci_debugfs_root);
kfree(errbuf);

View File

@ -71,8 +71,6 @@
#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
#define UHCI_PTR_BITS cpu_to_le32(0x000F)
#define UHCI_PTR_TERM cpu_to_le32(0x0001)
#define UHCI_PTR_QH cpu_to_le32(0x0002)
@ -168,9 +166,11 @@ static __le32 inline qh_element(struct uhci_qh *qh) {
#define TD_TOKEN_EXPLEN_MASK 0x7FF /* expected length, encoded as n - 1 */
#define TD_TOKEN_PID_MASK 0xFF
#define uhci_explen(len) ((len) << TD_TOKEN_EXPLEN_SHIFT)
#define uhci_explen(len) ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
TD_TOKEN_EXPLEN_SHIFT)
#define uhci_expected_length(token) ((((token) >> 21) + 1) & TD_TOKEN_EXPLEN_MASK)
#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
1) & TD_TOKEN_EXPLEN_MASK)
#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE_SHIFT) & 1)
#define uhci_endpoint(token) (((token) >> 15) & 0xf)
#define uhci_devaddr(token) (((token) >> TD_TOKEN_DEVADDR_SHIFT) & 0x7f)
@ -223,10 +223,10 @@ static u32 inline td_status(struct uhci_td *td) {
*/
/*
* The UHCI driver places Interrupt, Control and Bulk into QH's both
* to group together TD's for one transfer, and also to faciliate queuing
* of URB's. To make it easy to insert entries into the schedule, we have
* a skeleton of QH's for each predefined Interrupt latency, low-speed
* The UHCI driver places Interrupt, Control and Bulk into QHs both
* to group together TDs for one transfer, and also to facilitate queuing
* of URBs. To make it easy to insert entries into the schedule, we have
* a skeleton of QHs for each predefined Interrupt latency, low-speed
* control, full-speed control and terminating QH (see explanation for
* the terminating QH below).
*
@ -257,8 +257,8 @@ static u32 inline td_status(struct uhci_td *td) {
* reclamation.
*
* Isochronous transfers are stored before the start of the skeleton
* schedule and don't use QH's. While the UHCI spec doesn't forbid the
* use of QH's for Isochronous, it doesn't use them either. And the spec
* schedule and don't use QHs. While the UHCI spec doesn't forbid the
* use of QHs for Isochronous, it doesn't use them either. And the spec
* says that queues never advance on an error completion status, which
* makes them totally unsuitable for Isochronous transfers.
*/
@ -359,7 +359,7 @@ struct uhci_hcd {
struct dma_pool *td_pool;
struct uhci_td *term_td; /* Terminating TD, see UHCI bug */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QHs */
spinlock_t lock;
@ -389,22 +389,22 @@ struct uhci_hcd {
unsigned long resuming_ports;
unsigned long ports_timeout; /* Time to stop signalling */
/* Main list of URB's currently controlled by this HC */
/* Main list of URBs currently controlled by this HC */
struct list_head urb_list;
/* List of QH's that are done, but waiting to be unlinked (race) */
/* List of QHs that are done, but waiting to be unlinked (race) */
struct list_head qh_remove_list;
unsigned int qh_remove_age; /* Age in frames */
/* List of TD's that are done, but waiting to be freed (race) */
/* List of TDs that are done, but waiting to be freed (race) */
struct list_head td_remove_list;
unsigned int td_remove_age; /* Age in frames */
/* List of asynchronously unlinked URB's */
/* List of asynchronously unlinked URBs */
struct list_head urb_remove_list;
unsigned int urb_remove_age; /* Age in frames */
/* List of URB's awaiting completion callback */
/* List of URBs awaiting completion callback */
struct list_head complete_list;
int rh_numports; /* Number of root-hub ports */

View File

@ -80,7 +80,7 @@ static inline void uhci_fill_td(struct uhci_td *td, u32 status,
}
/*
* We insert Isochronous URB's directly into the frame list at the beginning
* We insert Isochronous URBs directly into the frame list at the beginning
*/
static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
{
@ -369,7 +369,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
uhci_fixup_toggle(urb,
uhci_toggle(td_token(lltd)) ^ 1));
/* All qh's in the queue need to link to the next queue */
/* All qhs in the queue need to link to the next queue */
urbp->qh->link = eurbp->qh->link;
wmb(); /* Make sure we flush everything */
@ -502,7 +502,7 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
}
/* Check to see if the remove list is empty. Set the IOC bit */
/* to force an interrupt so we can remove the TD's*/
/* to force an interrupt so we can remove the TDs*/
if (list_empty(&uhci->td_remove_list))
uhci_set_next_interrupt(uhci);
@ -596,7 +596,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(7),
uhci_fill_td(td, status, destination | uhci_explen(8),
urb->setup_dma);
/*
@ -612,7 +612,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
}
/*
* Build the DATA TD's
* Build the DATA TDs
*/
while (len > 0) {
int pktsze = len;
@ -628,7 +628,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
destination ^= TD_TOKEN_TOGGLE;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
uhci_fill_td(td, status, destination | uhci_explen(pktsze),
data);
data += pktsze;
@ -658,7 +658,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status | TD_CTRL_IOC,
destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
destination | uhci_explen(0), 0);
qh = uhci_alloc_qh(uhci);
if (!qh)
@ -744,7 +744,7 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
urb->actual_length = 0;
/* The rest of the TD's (but the last) are data */
/* The rest of the TDs (but the last) are data */
tmp = tmp->next;
while (tmp != head && tmp->next != head) {
unsigned int ctrlstat;
@ -848,7 +848,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
status |= TD_CTRL_SPD;
/*
* Build the DATA TD's
* Build the DATA TDs
*/
do { /* Allow zero length packets */
int pktsze = maxsze;
@ -864,7 +864,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
uhci_fill_td(td, status, destination | uhci_explen(pktsze) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@ -890,7 +890,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
uhci_fill_td(td, status, destination | uhci_explen(0) |
(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
data);
@ -1025,7 +1025,7 @@ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsig
list_for_each_entry(up, &uhci->urb_list, urb_list) {
struct urb *u = up->urb;
/* look for pending URB's with identical pipe handle */
/* look for pending URBs with identical pipe handle */
if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
(u->status == -EINPROGRESS) && (u != urb)) {
if (!last_urb)
@ -1092,7 +1092,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
return -ENOMEM;
uhci_add_td_to_urb(urb, td);
uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length),
urb->transfer_dma + urb->iso_frame_desc[i].offset);
if (i + 1 >= urb->number_of_packets)
@ -1355,7 +1355,7 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
uhci_delete_queued_urb(uhci, urb);
/* The interrupt loop will reclaim the QH's */
/* The interrupt loop will reclaim the QHs */
uhci_remove_qh(uhci, urbp->qh);
urbp->qh = NULL;
}
@ -1413,7 +1413,7 @@ static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
list_for_each_entry(td, head, list) {
/*
* Make sure we don't do the last one (since it'll have the
* TERM bit set) as well as we skip every so many TD's to
* TERM bit set) as well as we skip every so many TDs to
* make sure it doesn't hog the bandwidth
*/
if (td->list.next != head && (count % DEPTH_INTERVAL) ==

View File

@ -962,7 +962,6 @@ MODULE_DEVICE_TABLE (usb, mdc800_table);
*/
static struct usb_driver mdc800_usb_driver =
{
.owner = THIS_MODULE,
.name = "mdc800",
.probe = mdc800_usb_probe,
.disconnect = mdc800_usb_disconnect,

View File

@ -160,7 +160,6 @@ static void mts_usb_disconnect(struct usb_interface *intf);
static struct usb_device_id mts_usb_ids [];
static struct usb_driver mts_usb_driver = {
.owner = THIS_MODULE,
.name = "microtekX6",
.probe = mts_usb_probe,
.disconnect = mts_usb_disconnect,

View File

@ -273,6 +273,20 @@ config USB_ATI_REMOTE
To compile this driver as a module, choose M here: the module will be
called ati_remote.
config USB_ATI_REMOTE2
tristate "ATI / Philips USB RF remote control"
depends on USB && INPUT
---help---
Say Y here if you want to use an ATI or Philips USB RF remote control.
These are RF remotes with USB receivers.
ATI Remote Wonder II comes with some ATI's All-In-Wonder video cards
and is also available as a separate product.
This driver provides mouse pointer, left and right mouse buttons,
and maps all the other remote buttons to keypress events.
To compile this driver as a module, choose M here: the module will be
called ati_remote2.
config USB_KEYSPAN_REMOTE
tristate "Keyspan DMR USB remote control (EXPERIMENTAL)"
depends on USB && INPUT && EXPERIMENTAL

View File

@ -28,6 +28,7 @@ endif
obj-$(CONFIG_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_USB_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_USB_HID) += usbhid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o

View File

@ -261,7 +261,6 @@ static struct usb_device_id usb_acecad_id_table [] = {
MODULE_DEVICE_TABLE(usb, usb_acecad_id_table);
static struct usb_driver usb_acecad_driver = {
.owner = THIS_MODULE,
.name = "usb_acecad",
.probe = usb_acecad_probe,
.disconnect = usb_acecad_disconnect,

View File

@ -338,7 +338,7 @@ struct aiptek {
* the bitmap which comes from the tablet. This hides the
* issue that the F_keys are not sequentially numbered.
*/
static int macroKeyEvents[] = {
static const int macroKeyEvents[] = {
KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11,
KEY_F12, KEY_F13, KEY_F14, KEY_F15, KEY_F16, KEY_F17,
@ -2093,7 +2093,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Programming the tablet macro keys needs to be done with a for loop
* as the keycodes are discontiguous.
*/
for (i = 0; i < sizeof(macroKeyEvents) / sizeof(macroKeyEvents[0]); ++i)
for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
set_bit(macroKeyEvents[i], inputdev->keybit);
/*
@ -2135,7 +2135,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
* not an error :-)
*/
for (i = 0; i < sizeof(speeds) / sizeof(speeds[0]); ++i) {
for (i = 0; i < ARRAY_SIZE(speeds); ++i) {
aiptek->curSetting.programmableDelay = speeds[i];
(void)aiptek_program_tablet(aiptek);
if (aiptek->inputdev->absmax[ABS_X] > 0) {
@ -2190,7 +2190,6 @@ fail1: input_free_device(inputdev);
static void aiptek_disconnect(struct usb_interface *intf);
static struct usb_driver aiptek_driver = {
.owner = THIS_MODULE,
.name = "aiptek",
.probe = aiptek_probe,
.disconnect = aiptek_disconnect,

View File

@ -452,7 +452,6 @@ static int atp_resume(struct usb_interface *iface)
}
static struct usb_driver atp_driver = {
.owner = THIS_MODULE,
.name = "appletouch",
.probe = atp_probe,
.disconnect = atp_disconnect,

View File

@ -96,6 +96,7 @@
#include <linux/usb.h>
#include <linux/usb_input.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
/*
* Module and Version Information, Module Parameters
@ -146,7 +147,7 @@ static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
/* Acceleration curve for directional control pad */
static char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
/* Duplicate event filtering time.
* Sequential, identical KIND_FILTERED inputs with less than
@ -197,7 +198,7 @@ struct ati_remote {
#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/
/* Translation table from hardware messages to input events. */
static struct {
static const struct {
short kind;
unsigned char data1, data2;
int type;
@ -295,7 +296,6 @@ static void ati_remote_disconnect (struct usb_interface *interface);
/* usb specific object to register with the usb subsystem */
static struct usb_driver ati_remote_driver = {
.owner = THIS_MODULE,
.name = "ati_remote",
.probe = ati_remote_probe,
.disconnect = ati_remote_disconnect,
@ -472,7 +472,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
/* Filter duplicate events which happen "too close" together. */
if ((ati_remote->old_data[0] == data[1]) &&
(ati_remote->old_data[1] == data[2]) &&
((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) {
time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) {
ati_remote->repeat_count++;
} else {
ati_remote->repeat_count = 0;
@ -507,16 +507,16 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs)
* pad down, so we increase acceleration, ramping up over two seconds to
* a maximum speed. The acceleration curve is #defined above.
*/
if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) {
if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) {
acc = 1;
ati_remote->acc_jiffies = jiffies;
}
else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0];
else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1];
else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2];
else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3];
else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4];
else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5];
else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0];
else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1];
else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2];
else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3];
else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4];
else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5];
else acc = accel[6];
input_regs(dev, regs);

View File

@ -0,0 +1,477 @@
/*
* ati_remote2 - ATI/Philips USB RF remote driver
*
* Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
*
* 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/usb_input.h>
#define DRIVER_DESC "ATI/Philips USB RF remote driver"
#define DRIVER_VERSION "0.1"
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>");
MODULE_LICENSE("GPL");
static unsigned int mode_mask = 0x1F;
module_param(mode_mask, uint, 0644);
MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
static struct usb_device_id ati_remote2_id_table[] = {
{ USB_DEVICE(0x0471, 0x0602) }, /* ATI Remote Wonder II */
{ }
};
MODULE_DEVICE_TABLE(usb, ati_remote2_id_table);
static struct {
int hw_code;
int key_code;
} ati_remote2_key_table[] = {
{ 0x00, KEY_0 },
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x0c, KEY_POWER },
{ 0x0d, KEY_MUTE },
{ 0x10, KEY_VOLUMEUP },
{ 0x11, KEY_VOLUMEDOWN },
{ 0x20, KEY_CHANNELUP },
{ 0x21, KEY_CHANNELDOWN },
{ 0x28, KEY_FORWARD },
{ 0x29, KEY_REWIND },
{ 0x2c, KEY_PLAY },
{ 0x30, KEY_PAUSE },
{ 0x31, KEY_STOP },
{ 0x37, KEY_RECORD },
{ 0x38, KEY_DVD },
{ 0x39, KEY_TV },
{ 0x54, KEY_MENU },
{ 0x58, KEY_UP },
{ 0x59, KEY_DOWN },
{ 0x5a, KEY_LEFT },
{ 0x5b, KEY_RIGHT },
{ 0x5c, KEY_OK },
{ 0x78, KEY_A },
{ 0x79, KEY_B },
{ 0x7a, KEY_C },
{ 0x7b, KEY_D },
{ 0x7c, KEY_E },
{ 0x7d, KEY_F },
{ 0x82, KEY_ENTER },
{ 0x8e, KEY_VENDOR },
{ 0x96, KEY_COFFEE },
{ 0xa9, BTN_LEFT },
{ 0xaa, BTN_RIGHT },
{ 0xbe, KEY_QUESTION },
{ 0xd5, KEY_FRONT },
{ 0xd0, KEY_EDIT },
{ 0xf9, KEY_INFO },
{ (0x00 << 8) | 0x3f, KEY_PROG1 },
{ (0x01 << 8) | 0x3f, KEY_PROG2 },
{ (0x02 << 8) | 0x3f, KEY_PROG3 },
{ (0x03 << 8) | 0x3f, KEY_PROG4 },
{ (0x04 << 8) | 0x3f, KEY_PC },
{ 0, KEY_RESERVED }
};
struct ati_remote2 {
struct input_dev *idev;
struct usb_device *udev;
struct usb_interface *intf[2];
struct usb_endpoint_descriptor *ep[2];
struct urb *urb[2];
void *buf[2];
dma_addr_t buf_dma[2];
unsigned long jiffies;
int mode;
char name[64];
char phys[64];
};
static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id);
static void ati_remote2_disconnect(struct usb_interface *interface);
static struct usb_driver ati_remote2_driver = {
.name = "ati_remote2",
.probe = ati_remote2_probe,
.disconnect = ati_remote2_disconnect,
.id_table = ati_remote2_id_table,
};
static int ati_remote2_open(struct input_dev *idev)
{
struct ati_remote2 *ar2 = idev->private;
int r;
r = usb_submit_urb(ar2->urb[0], GFP_KERNEL);
if (r) {
dev_err(&ar2->intf[0]->dev,
"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
return r;
}
r = usb_submit_urb(ar2->urb[1], GFP_KERNEL);
if (r) {
usb_kill_urb(ar2->urb[0]);
dev_err(&ar2->intf[1]->dev,
"%s: usb_submit_urb() = %d\n", __FUNCTION__, r);
return r;
}
return 0;
}
static void ati_remote2_close(struct input_dev *idev)
{
struct ati_remote2 *ar2 = idev->private;
usb_kill_urb(ar2->urb[0]);
usb_kill_urb(ar2->urb[1]);
}
static void ati_remote2_input_mouse(struct ati_remote2 *ar2, struct pt_regs *regs)
{
struct input_dev *idev = ar2->idev;
u8 *data = ar2->buf[0];
if (data[0] > 4) {
dev_err(&ar2->intf[0]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
return;
}
if (!((1 << data[0]) & mode_mask))
return;
input_regs(idev, regs);
input_event(idev, EV_REL, REL_X, (s8) data[1]);
input_event(idev, EV_REL, REL_Y, (s8) data[2]);
input_sync(idev);
}
static int ati_remote2_lookup(unsigned int hw_code)
{
int i;
for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
if (ati_remote2_key_table[i].hw_code == hw_code)
return i;
return -1;
}
static void ati_remote2_input_key(struct ati_remote2 *ar2, struct pt_regs *regs)
{
struct input_dev *idev = ar2->idev;
u8 *data = ar2->buf[1];
int hw_code, index;
if (data[0] > 4) {
dev_err(&ar2->intf[1]->dev,
"Unknown mode byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
return;
}
hw_code = data[2];
/*
* Mode keys (AUX1-AUX4, PC) all generate the same code byte.
* Use the mode byte to figure out which one was pressed.
*/
if (hw_code == 0x3f) {
/*
* For some incomprehensible reason the mouse pad generates
* events which look identical to the events from the last
* pressed mode key. Naturally we don't want to generate key
* events for the mouse pad so we filter out any subsequent
* events from the same mode key.
*/
if (ar2->mode == data[0])
return;
if (data[1] == 0)
ar2->mode = data[0];
hw_code |= data[0] << 8;
}
if (!((1 << data[0]) & mode_mask))
return;
index = ati_remote2_lookup(hw_code);
if (index < 0) {
dev_err(&ar2->intf[1]->dev,
"Unknown code byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
return;
}
switch (data[1]) {
case 0: /* release */
break;
case 1: /* press */
ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_DELAY]);
break;
case 2: /* repeat */
/* No repeat for mouse buttons. */
if (ati_remote2_key_table[index].key_code == BTN_LEFT ||
ati_remote2_key_table[index].key_code == BTN_RIGHT)
return;
if (!time_after_eq(jiffies, ar2->jiffies))
return;
ar2->jiffies = jiffies + msecs_to_jiffies(idev->rep[REP_PERIOD]);
break;
default:
dev_err(&ar2->intf[1]->dev,
"Unknown state byte (%02x %02x %02x %02x)\n",
data[3], data[2], data[1], data[0]);
return;
}
input_regs(idev, regs);
input_event(idev, EV_KEY, ati_remote2_key_table[index].key_code, data[1]);
input_sync(idev);
}
static void ati_remote2_complete_mouse(struct urb *urb, struct pt_regs *regs)
{
struct ati_remote2 *ar2 = urb->context;
int r;
switch (urb->status) {
case 0:
ati_remote2_input_mouse(ar2, regs);
break;
case -ENOENT:
case -EILSEQ:
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&ar2->intf[0]->dev,
"%s(): urb status = %d\n", __FUNCTION__, urb->status);
return;
default:
dev_err(&ar2->intf[0]->dev,
"%s(): urb status = %d\n", __FUNCTION__, urb->status);
}
r = usb_submit_urb(urb, GFP_ATOMIC);
if (r)
dev_err(&ar2->intf[0]->dev,
"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
}
static void ati_remote2_complete_key(struct urb *urb, struct pt_regs *regs)
{
struct ati_remote2 *ar2 = urb->context;
int r;
switch (urb->status) {
case 0:
ati_remote2_input_key(ar2, regs);
break;
case -ENOENT:
case -EILSEQ:
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&ar2->intf[1]->dev,
"%s(): urb status = %d\n", __FUNCTION__, urb->status);
return;
default:
dev_err(&ar2->intf[1]->dev,
"%s(): urb status = %d\n", __FUNCTION__, urb->status);
}
r = usb_submit_urb(urb, GFP_ATOMIC);
if (r)
dev_err(&ar2->intf[1]->dev,
"%s(): usb_submit_urb() = %d\n", __FUNCTION__, r);
}
static int ati_remote2_input_init(struct ati_remote2 *ar2)
{
struct input_dev *idev;
int i;
idev = input_allocate_device();
if (!idev)
return -ENOMEM;
ar2->idev = idev;
idev->private = ar2;
idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_REL);
idev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
idev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
for (i = 0; ati_remote2_key_table[i].key_code != KEY_RESERVED; i++)
set_bit(ati_remote2_key_table[i].key_code, idev->keybit);
idev->rep[REP_DELAY] = 250;
idev->rep[REP_PERIOD] = 33;
idev->open = ati_remote2_open;
idev->close = ati_remote2_close;
idev->name = ar2->name;
idev->phys = ar2->phys;
usb_to_input_id(ar2->udev, &idev->id);
idev->cdev.dev = &ar2->udev->dev;
i = input_register_device(idev);
if (i)
input_free_device(idev);
return i;
}
static int ati_remote2_urb_init(struct ati_remote2 *ar2)
{
struct usb_device *udev = ar2->udev;
int i, pipe, maxp;
for (i = 0; i < 2; i++) {
ar2->buf[i] = usb_buffer_alloc(udev, 4, GFP_KERNEL, &ar2->buf_dma[i]);
if (!ar2->buf[i])
return -ENOMEM;
ar2->urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!ar2->urb[i])
return -ENOMEM;
pipe = usb_rcvintpipe(udev, ar2->ep[i]->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
maxp = maxp > 4 ? 4 : maxp;
usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
i ? ati_remote2_complete_key : ati_remote2_complete_mouse,
ar2, ar2->ep[i]->bInterval);
ar2->urb[i]->transfer_dma = ar2->buf_dma[i];
ar2->urb[i]->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
}
return 0;
}
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]);
if (ar2->buf[i])
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
}
}
static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_host_interface *alt = interface->cur_altsetting;
struct ati_remote2 *ar2;
int r;
if (alt->desc.bInterfaceNumber)
return -ENODEV;
ar2 = kzalloc(sizeof (struct ati_remote2), GFP_KERNEL);
if (!ar2)
return -ENOMEM;
ar2->udev = udev;
ar2->intf[0] = interface;
ar2->ep[0] = &alt->endpoint[0].desc;
ar2->intf[1] = usb_ifnum_to_if(udev, 1);
r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2);
if (r)
goto fail1;
alt = ar2->intf[1]->cur_altsetting;
ar2->ep[1] = &alt->endpoint[0].desc;
r = ati_remote2_urb_init(ar2);
if (r)
goto fail2;
usb_make_path(udev, ar2->phys, sizeof(ar2->phys));
strlcat(ar2->phys, "/input0", sizeof(ar2->phys));
strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name));
r = ati_remote2_input_init(ar2);
if (r)
goto fail2;
usb_set_intfdata(interface, ar2);
return 0;
fail2:
ati_remote2_urb_cleanup(ar2);
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
fail1:
kfree(ar2);
return r;
}
static void ati_remote2_disconnect(struct usb_interface *interface)
{
struct ati_remote2 *ar2;
struct usb_host_interface *alt = interface->cur_altsetting;
if (alt->desc.bInterfaceNumber)
return;
ar2 = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
input_unregister_device(ar2->idev);
ati_remote2_urb_cleanup(ar2);
usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
kfree(ar2);
}
static int __init ati_remote2_init(void)
{
int r;
r = usb_register(&ati_remote2_driver);
if (r)
printk(KERN_ERR "ati_remote2: usb_register() = %d\n", r);
else
printk(KERN_INFO "ati_remote2: " DRIVER_DESC " " DRIVER_VERSION "\n");
return r;
}
static void __exit ati_remote2_exit(void)
{
usb_deregister(&ati_remote2_driver);
}
module_init(ati_remote2_init);
module_exit(ati_remote2_exit);

View File

@ -38,7 +38,7 @@ typedef s16 fixp_t;
#define FRAC_MASK ((1<<FRAC_N)-1)
// Not to be used directly. Use fixp_{cos,sin}
static fixp_t cos_table[45] = {
static const fixp_t cos_table[45] = {
0x0100, 0x00FF, 0x00FF, 0x00FE, 0x00FD, 0x00FC, 0x00FA, 0x00F8,
0x00F6, 0x00F3, 0x00F0, 0x00ED, 0x00E9, 0x00E6, 0x00E2, 0x00DD,
0x00D9, 0x00D4, 0x00CF, 0x00C9, 0x00C4, 0x00BE, 0x00B8, 0x00B1,

View File

@ -1454,7 +1454,7 @@ void hid_init_reports(struct hid_device *hid)
* Alphabetically sorted blacklist by quirk type.
*/
static struct hid_blacklist {
static const struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
unsigned quirks;
@ -1930,7 +1930,6 @@ static struct usb_device_id hid_usb_ids [] = {
MODULE_DEVICE_TABLE (usb, hid_usb_ids);
static struct usb_driver hid_driver = {
.owner = THIS_MODULE,
.name = "usbhid",
.probe = hid_probe,
.disconnect = hid_disconnect,

View File

@ -39,7 +39,7 @@
#define unk KEY_UNKNOWN
static unsigned char hid_keyboard[256] = {
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,
@ -58,7 +58,7 @@ static unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
static struct {
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}};

View File

@ -826,7 +826,6 @@ static int hiddev_usbd_probe(struct usb_interface *intf,
static /* const */ struct usb_driver hiddev_driver = {
.owner = THIS_MODULE,
.name = "hiddev",
.probe = hiddev_usbd_probe,
};

View File

@ -250,7 +250,6 @@ static void itmtouch_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, itmtouch_ids);
static struct usb_driver itmtouch_driver = {
.owner = THIS_MODULE,
.name = "itmtouch",
.probe = itmtouch_probe,
.disconnect = itmtouch_disconnect,

View File

@ -197,7 +197,6 @@ static void kbtab_disconnect(struct usb_interface *intf)
}
static struct usb_driver kbtab_driver = {
.owner = THIS_MODULE,
.name = "kbtab",
.probe = kbtab_probe,
.disconnect = kbtab_disconnect,

View File

@ -95,7 +95,7 @@ struct usb_keyspan {
* Currently there are 15 and 17 button models so RESERVED codes
* are blank areas in the mapping.
*/
static int keyspan_key_table[] = {
static const int keyspan_key_table[] = {
KEY_RESERVED, /* 0 is just a place holder. */
KEY_RESERVED,
KEY_STOP,
@ -559,7 +559,6 @@ static void keyspan_disconnect(struct usb_interface *interface)
*/
static struct usb_driver keyspan_driver =
{
.owner = THIS_MODULE,
.name = "keyspan_remote",
.probe = keyspan_probe,
.disconnect = keyspan_disconnect,

View File

@ -310,7 +310,6 @@ static void mtouchusb_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, mtouchusb_devices);
static struct usb_driver mtouchusb_driver = {
.owner = THIS_MODULE,
.name = "mtouchusb",
.probe = mtouchusb_probe,
.disconnect = mtouchusb_disconnect,

View File

@ -441,7 +441,6 @@ static struct usb_device_id powermate_devices [] = {
MODULE_DEVICE_TABLE (usb, powermate_devices);
static struct usb_driver powermate_driver = {
.owner = THIS_MODULE,
.name = "powermate",
.probe = powermate_probe,
.disconnect = powermate_disconnect,

View File

@ -1,7 +1,7 @@
/******************************************************************************
* touchkitusb.c -- Driver for eGalax TouchKit USB Touchscreens
*
* Copyright (C) 2004 by Daniel Ritz
* Copyright (C) 2004-2005 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
*
* This program is free software; you can redistribute it and/or
@ -41,15 +41,13 @@
#define TOUCHKIT_MAX_YC 0x07ff
#define TOUCHKIT_YC_FUZZ 0x0
#define TOUCHKIT_YC_FLAT 0x0
#define TOUCHKIT_REPORT_DATA_SIZE 8
#define TOUCHKIT_REPORT_DATA_SIZE 16
#define TOUCHKIT_DOWN 0x01
#define TOUCHKIT_POINT_TOUCH 0x81
#define TOUCHKIT_POINT_NOTOUCH 0x80
#define TOUCHKIT_GET_TOUCHED(dat) ((((dat)[0]) & TOUCHKIT_DOWN) ? 1 : 0)
#define TOUCHKIT_GET_X(dat) (((dat)[3] << 7) | (dat)[4])
#define TOUCHKIT_GET_Y(dat) (((dat)[1] << 7) | (dat)[2])
#define TOUCHKIT_PKT_TYPE_MASK 0xFE
#define TOUCHKIT_PKT_TYPE_REPT 0x80
#define TOUCHKIT_PKT_TYPE_DIAG 0x0A
#define DRIVER_VERSION "v0.1"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
@ -62,6 +60,8 @@ MODULE_PARM_DESC(swap_xy, "If set X and Y axes are swapped.");
struct touchkit_usb {
unsigned char *data;
dma_addr_t data_dma;
char buffer[TOUCHKIT_REPORT_DATA_SIZE];
int buf_len;
struct urb *irq;
struct usb_device *udev;
struct input_dev *input;
@ -77,11 +77,128 @@ static struct usb_device_id touchkit_devices[] = {
{}
};
/* helpers to read the data */
static inline int touchkit_get_touched(char *data)
{
return (data[0] & TOUCHKIT_DOWN) ? 1 : 0;
}
static inline int touchkit_get_x(char *data)
{
return ((data[3] & 0x0F) << 7) | (data[4] & 0x7F);
}
static inline int touchkit_get_y(char *data)
{
return ((data[1] & 0x0F) << 7) | (data[2] & 0x7F);
}
/* processes one input packet. */
static void touchkit_process_pkt(struct touchkit_usb *touchkit,
struct pt_regs *regs, char *pkt)
{
int x, y;
/* only process report packets */
if ((pkt[0] & TOUCHKIT_PKT_TYPE_MASK) != TOUCHKIT_PKT_TYPE_REPT)
return;
if (swap_xy) {
y = touchkit_get_x(pkt);
x = touchkit_get_y(pkt);
} else {
x = touchkit_get_x(pkt);
y = touchkit_get_y(pkt);
}
input_regs(touchkit->input, regs);
input_report_key(touchkit->input, BTN_TOUCH, touchkit_get_touched(pkt));
input_report_abs(touchkit->input, ABS_X, x);
input_report_abs(touchkit->input, ABS_Y, y);
input_sync(touchkit->input);
}
static int touchkit_get_pkt_len(char *buf)
{
switch (buf[0] & TOUCHKIT_PKT_TYPE_MASK) {
case TOUCHKIT_PKT_TYPE_REPT:
return 5;
case TOUCHKIT_PKT_TYPE_DIAG:
return buf[1] + 2;
}
return 0;
}
static void touchkit_process(struct touchkit_usb *touchkit, int len,
struct pt_regs *regs)
{
char *buffer;
int pkt_len, buf_len, pos;
/* if the buffer contains data, append */
if (unlikely(touchkit->buf_len)) {
int tmp;
/* if only 1 byte in buffer, add another one to get length */
if (touchkit->buf_len == 1)
touchkit->buffer[1] = touchkit->data[0];
pkt_len = touchkit_get_pkt_len(touchkit->buffer);
/* unknown packet: drop everything */
if (!pkt_len)
return;
/* append, process */
tmp = pkt_len - touchkit->buf_len;
memcpy(touchkit->buffer + touchkit->buf_len, touchkit->data, tmp);
touchkit_process_pkt(touchkit, regs, touchkit->buffer);
buffer = touchkit->data + tmp;
buf_len = len - tmp;
} else {
buffer = touchkit->data;
buf_len = len;
}
/* only one byte left in buffer */
if (unlikely(buf_len == 1)) {
touchkit->buffer[0] = buffer[0];
touchkit->buf_len = 1;
return;
}
/* loop over the buffer */
pos = 0;
while (pos < buf_len) {
/* get packet len */
pkt_len = touchkit_get_pkt_len(buffer + pos);
/* unknown packet: drop everything */
if (unlikely(!pkt_len))
return;
/* full packet: process */
if (likely(pkt_len <= buf_len)) {
touchkit_process_pkt(touchkit, regs, buffer + pos);
} else {
/* incomplete packet: save in buffer */
memcpy(touchkit->buffer, buffer + pos, buf_len - pos);
touchkit->buf_len = buf_len - pos;
}
pos += pkt_len;
}
}
static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
{
struct touchkit_usb *touchkit = urb->context;
int retval;
int x, y;
switch (urb->status) {
case 0:
@ -105,20 +222,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
goto exit;
}
if (swap_xy) {
y = TOUCHKIT_GET_X(touchkit->data);
x = TOUCHKIT_GET_Y(touchkit->data);
} else {
x = TOUCHKIT_GET_X(touchkit->data);
y = TOUCHKIT_GET_Y(touchkit->data);
}
input_regs(touchkit->input, regs);
input_report_key(touchkit->input, BTN_TOUCH,
TOUCHKIT_GET_TOUCHED(touchkit->data));
input_report_abs(touchkit->input, ABS_X, x);
input_report_abs(touchkit->input, ABS_Y, y);
input_sync(touchkit->input);
touchkit_process(touchkit, urb->actual_length, regs);
exit:
retval = usb_submit_urb(urb, GFP_ATOMIC);
@ -267,7 +371,6 @@ static void touchkit_disconnect(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, touchkit_devices);
static struct usb_driver touchkit_driver = {
.owner = THIS_MODULE,
.name = "touchkitusb",
.probe = touchkit_probe,
.disconnect = touchkit_disconnect,

View File

@ -345,7 +345,6 @@ static struct usb_device_id usb_kbd_id_table [] = {
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
static struct usb_driver usb_kbd_driver = {
.owner = THIS_MODULE,
.name = "usbkbd",
.probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect,

View File

@ -226,7 +226,6 @@ static struct usb_device_id usb_mouse_id_table [] = {
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
static struct usb_driver usb_mouse_driver = {
.owner = THIS_MODULE,
.name = "usbmouse",
.probe = usb_mouse_probe,
.disconnect = usb_mouse_disconnect,

View File

@ -945,7 +945,6 @@ static void wacom_disconnect(struct usb_interface *intf)
}
static struct usb_driver wacom_driver = {
.owner = THIS_MODULE,
.name = "wacom",
.probe = wacom_probe,
.disconnect = wacom_disconnect,

View File

@ -70,7 +70,7 @@
#define XPAD_PKT_LEN 32
static struct xpad_device {
static const struct xpad_device {
u16 idVendor;
u16 idProduct;
char *name;
@ -81,13 +81,13 @@ static struct xpad_device {
{ 0x0000, 0x0000, "X-Box pad" }
};
static signed short xpad_btn[] = {
static const signed short xpad_btn[] = {
BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, /* "analog" buttons */
BTN_START, BTN_BACK, BTN_THUMBL, BTN_THUMBR, /* start/back/sticks */
-1 /* terminating entry */
};
static signed short xpad_abs[] = {
static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
ABS_Z, ABS_RZ, /* triggers left/right */
@ -316,7 +316,6 @@ static void xpad_disconnect(struct usb_interface *intf)
}
static struct usb_driver xpad_driver = {
.owner = THIS_MODULE,
.name = "xpad",
.probe = xpad_probe,
.disconnect = xpad_disconnect,

View File

@ -987,7 +987,6 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
static struct usb_driver yealink_driver = {
.owner = THIS_MODULE,
.name = "yealink",
.probe = usb_probe,
.disconnect = usb_disconnect,

View File

@ -812,7 +812,6 @@ static struct usb_device_id dabusb_ids [] = {
MODULE_DEVICE_TABLE (usb, dabusb_ids);
static struct usb_driver dabusb_driver = {
.owner = THIS_MODULE,
.name = "dabusb",
.probe = dabusb_probe,
.disconnect = dabusb_disconnect,

Some files were not shown because too many files have changed in this diff Show More