-Revised: 2000-Dec-05.
+Revised: 2001-Dec-06.
This is the documentation of (hopefully) all possible error codes (and
their interpretation) that can be returned from the host controller drivers
and from usbcore.
-NOTE:
-The USB_ST_* codes are deprecated and are only listed for compatibility;
-new software should use only -E* instead!
-
-
**************************************************************************
* Error codes returned by usb_submit_urb *
Non-USB-specific:
-USB_ST_NOERROR
0 URB submission went fine
-ENOMEM no memory for allocation of internal structures
-ENODEV specified USB-device or bus doesn't exist
-USB_ST_REQUEST_ERROR
-ENXIO a control or interrupt URB is already queued to this endpoint; or
a bulk URB is already queued to this endpoint and
USB_QUEUE_BULK wasn't used (UHCI HCDs only)
-USB_ST_URB_INVALID_ERROR
-EINVAL a) Invalid transfer type specified (or not supported)
b) Invalid interrupt interval (0<=n<256)
c) more than one interrupt packet requested
-EFBIG too much ISO frames requested (currently uhci>900)
-USB_ST_STALL
-EPIPE specified pipe-handle is already stalled
-EMSGSIZE endpoint message size is zero, do interface/alternate setting
-USB_ST_BANDWIDTH_ERROR
-ENOSPC The host controller's bandwidth is already consumed and
this request would push it past its allowed limit.
* or in iso_frame_desc[n].status (for ISO) *
**************************************************************************
-USB_ST_NOERROR
0 Transfer completed successfully
-USB_ST_URB_KILLED
-ENOENT URB was canceled by usb_unlink_urb
-USB_ST_URB_PENDING
-EINPROGRESS URB still pending, no results yet
(actually no error until now;-)
-USB_ST_BITSTUFF
-USB_ST_INTERNALERROR
-EPROTO a) bitstuff error
b) unknown USB error
-USB_ST_CRC
-EILSEQ CRC mismatch
-USB_ST_STALL
-EPIPE endpoint stalled
-USB_ST_BUFFEROVERRUN
-ECOMM During an IN transfer, the host controller
received data from an endpoint faster than it
could be written to system memory
-USB_ST_BUFFERUNDERRUN
-ENOSR During an OUT transfer, the host controller
could not retrieve data from system memory fast
enough to keep up with the USB data rate
-USB_ST_DATAOVERRUN
-EOVERFLOW The amount of data returned by the endpoint was
greater than either the max packet size of the
endpoint or the remaining buffer size. "Babble".
-USB_ST_DATAUNDERRUN
-EREMOTEIO The endpoint returned less than max packet size
and that amount did not fill the specified buffer
-USB_ST_NORESPONSE
-USB_ST_TIMEOUT
-ETIMEDOUT transfer timed out, NAK
-USB_ST_REMOVED
-ENODEV device was removed
-USB_ST_SHORT_PACKET
-EREMOTEIO short packet detected
-USB_ST_PARTIAL_ERROR
-EXDEV ISO transfer only partially completed
look at individual frame status for details
-USB_ST_URB_INVALID_ERROR
-EINVAL ISO madness, if this happens: Log off and go home
-ECONNRESET the URB is being unlinked asynchronously
`mknod /dev/usbscanner1 c 180 49`
.
.
- `mknod /dev/usbscanner15 180 63`
+ `mknod /dev/usbscanner15 c 180 63`
If you foresee using only one scanner it is best to:
VERSION = 2
PATCHLEVEL = 5
SUBLEVEL = 1
-EXTRAVERSION =-pre7
+EXTRAVERSION =-pre8
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
# IrDA (infrared) support
#
# CONFIG_IRDA is not set
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-CONFIG_IRDA_FAST_RR=y
-CONFIG_IRDA_DEBUG=y
#
# ISDN subsystem
*/
RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber);
blk_init_queue(RequestQueue, DAC960_RequestFunction);
- blk_queue_headactive(RequestQueue, 0);
RequestQueue->queuedata = Controller;
RequestQueue->max_segments = Controller->DriverScatterGatherLimit;
RequestQueue->max_sectors = Controller->MaxBlocksPerCommand;
rq->flags |= REQ_BARRIER;
rq->waiting = &wait;
- elv_add_request(q, rq);
+ elv_add_request(q, rq, 1);
generic_unplug_device(q);
wait_for_completion(&wait);
q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
q->queuedata = hba[i];
blk_init_queue(q, do_cciss_request);
- blk_queue_headactive(q, 0);
blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
blk_queue_max_segments(q, MAXSGENTRIES);
blk_queue_max_sectors(q, 512);
q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
q->queuedata = hba[i];
blk_init_queue(q, do_ida_request);
- blk_queue_headactive(q, 0);
blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
blk_queue_max_segments(q, SG_MAX);
blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
char buf[64];
int len, n;
- len = sprintf(page, "major minor #blocks start_sect nr_sects "
- "name\n\n");
+ len = sprintf(page, "major minor #blocks name\n\n");
read_lock(&gendisk_lock);
for (gp = gendisk_head; gp; gp = gp->next) {
for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
continue;
len += snprintf(page + len, 63,
- "%4d %4d %10d %10lu %10lu %s\n",
+ "%4d %4d %10d %s\n",
gp->major, n, gp->sizes[n],
- gp->part[n].start_sect,
- gp->part[n].nr_sects,
disk_name(gp, n, buf));
if (len < offset)
offset -= len, len = 0;
static int blk_init_free_list(request_queue_t *q)
{
+ struct request_list *rl;
struct request *rq;
int i;
/*
* Divide requests in half between read and write
*/
+ rl = &q->rq[READ];
for (i = 0; i < queue_nr_requests; i++) {
rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
if (!rq)
goto nomem;
+ /*
+ * half way through, switch to WRITE list
+ */
+ if (i == queue_nr_requests / 2)
+ rl = &q->rq[WRITE];
+
memset(rq, 0, sizeof(struct request));
rq->rq_status = RQ_INACTIVE;
- if (i < queue_nr_requests >> 1) {
- list_add(&rq->queuelist, &q->rq[READ].free);
- q->rq[READ].count++;
- } else {
- list_add(&rq->queuelist, &q->rq[WRITE].free);
- q->rq[WRITE].count++;
- }
+ list_add(&rq->queuelist, &rl->free);
+ rl->count++;
}
init_waitqueue_head(&q->rq[READ].wait);
static struct request *get_request_wait(request_queue_t *q, int rw)
{
DECLARE_WAITQUEUE(wait, current);
+ struct request_list *rl = &q->rq[rw];
struct request *rq;
spin_lock_prefetch(&q->queue_lock);
generic_unplug_device(q);
- add_wait_queue(&q->rq[rw].wait, &wait);
+ add_wait_queue(&rl->wait, &wait);
do {
set_current_state(TASK_UNINTERRUPTIBLE);
- if (q->rq[rw].count < batch_requests)
+ if (rl->count < batch_requests)
schedule();
spin_lock_irq(&q->queue_lock);
rq = get_request(q, rw);
spin_unlock_irq(&q->queue_lock);
} while (rq == NULL);
- remove_wait_queue(&q->rq[rw].wait, &wait);
+ remove_wait_queue(&rl->wait, &wait);
current->state = TASK_RUNNING;
return rq;
}
*/
BUG_ON(!bio->bi_end_io);
- BIO_BUG_ON(bio_offset(bio) > PAGE_SIZE);
BIO_BUG_ON(!bio->bi_size);
BIO_BUG_ON(!bio->bi_io_vec);
extern int stram_device_init (void);
#endif
+inline void blk_recalc_request(struct request *rq, int nsect)
+{
+ rq->hard_sector += nsect;
+ rq->hard_nr_sectors -= nsect;
+ rq->sector = rq->hard_sector;
+ rq->nr_sectors = rq->hard_nr_sectors;
+
+ rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+ rq->hard_cur_sectors = rq->current_nr_sectors;
+
+ /*
+ * if total number of sectors is less than the first segment
+ * size, something has gone terribly wrong
+ */
+ if (rq->nr_sectors < rq->current_nr_sectors) {
+ printk("blk: request botched\n");
+ rq->nr_sectors = rq->current_nr_sectors;
+ }
+
+ rq->buffer = bio_data(rq->bio);
+}
+
/**
* end_that_request_first - end I/O on one buffer.
* @req: the request being processed
int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
{
- struct bio *bio, *nxt;
- int nsect, total_nsect = 0;
+ int nsect, total_nsect;
+ struct bio *bio;
req->errors = 0;
if (!uptodate)
printk("end_request: I/O error, dev %s, sector %lu\n",
kdevname(req->rq_dev), req->sector);
- if ((bio = req->bio) != NULL) {
-next_chunk:
+ total_nsect = 0;
+ while ((bio = req->bio)) {
nsect = bio_iovec(bio)->bv_len >> 9;
+ bio->bi_size -= bio_iovec(bio)->bv_len;
+
+ /*
+ * not a complete bvec done
+ */
+ if (unlikely(nsect > nr_sectors)) {
+ int residual = (nsect - nr_sectors) << 9;
+
+ bio_iovec(bio)->bv_offset += residual;
+ bio_iovec(bio)->bv_len -= residual;
+ blk_recalc_request(req, nr_sectors);
+ return 1;
+ }
+
nr_sectors -= nsect;
total_nsect += nsect;
if (++bio->bi_idx >= bio->bi_vcnt) {
- nxt = bio->bi_next;
- if (!bio_endio(bio, uptodate, total_nsect)) {
- total_nsect = 0;
- req->bio = nxt;
- } else
+ req->bio = bio->bi_next;
+
+ if (unlikely(bio_endio(bio, uptodate, total_nsect)))
BUG();
+
+ total_nsect = 0;
}
- if ((bio = req->bio) != NULL) {
- req->hard_sector += nsect;
- req->hard_nr_sectors -= nsect;
- req->sector = req->hard_sector;
- req->nr_sectors = req->hard_nr_sectors;
-
- req->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
- req->hard_cur_sectors = req->current_nr_sectors;
- if (req->nr_sectors < req->current_nr_sectors) {
- printk("end_request: buffer-list destroyed\n");
- req->nr_sectors = req->current_nr_sectors;
- }
+ if ((bio = req->bio)) {
+ blk_recalc_request(req, nsect);
- req->buffer = bio_data(bio);
/*
* end more in this run, or just return 'not-done'
*/
- if (nr_sectors > 0)
- goto next_chunk;
-
- return 1;
+ if (unlikely(nr_sectors <= 0))
+ return 1;
}
}
+
return 0;
}
EXPORT_SYMBOL(blk_rq_map_sg);
EXPORT_SYMBOL(blk_nohighio);
EXPORT_SYMBOL(blk_dump_rq_flags);
+EXPORT_SYMBOL(submit_bio);
blksize_size[MAJOR_NR] = nbd_blksizes;
blk_size[MAJOR_NR] = nbd_sizes;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
for (i = 0; i < MAX_NBD; i++) {
nbd_dev[i].refcnt = 0;
nbd_dev[i].file = NULL;
static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES];
static int xd_blocksizes[XD_MAXDRIVES << 6];
-static int xd_maxsect[XD_MAXDRIVES << 6];
extern struct block_device_operations xd_fops;
}
/* xd_maxsectors depends on controller - so set after detection */
- for(i=0; i<(XD_MAXDRIVES << 6); i++) xd_maxsect[i] = xd_maxsectors;
- max_sectors[MAJOR_NR] = xd_maxsect;
+ blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), xd_maxsectors);
for (i = 0; i < xd_drives; i++) {
xd_valid[i] = 1;
block = CURRENT->sector;
count = CURRENT->nr_sectors;
- switch (CURRENT->cmd) {
+ switch (rq_data_dir(CURRENT)) {
case READ:
case WRITE:
for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
- code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
+ code = xd_readwrite(rq_data_dir(CURRENT),CURRENT_DEV,CURRENT->buffer,block,count);
break;
default:
printk("do_xd_request: unknown request\n");
(BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn;
(BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn;
#endif
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
request_region(CDo_command,4,major_name);
/*
* just wrap this around cdrom_do_packet_command
*/
-static int cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
{
struct packet_command pc;
ide_startstop_t startstop;
pc.timeout = cgc->timeout;
pc.sense = cgc->sense;
cgc->stat = cdrom_queue_packet_command(drive, &pc);
- cgc->buflen -= pc.buflen;
+ if (!cgc->stat)
+ cgc->buflen -= pc.buflen;
return cgc->stat;
}
byte curlba[3];
byte nslots;
- __u16 short slot_tablelen;
+ __u16 slot_tablelen;
};
test_and_clear_bit(buf_nr, &b_out->busy);
if (urb->status < 0) {
- if (urb->status != USB_ST_URB_KILLED) {
+ if (urb->status != -ENOENT) {
WARN("urb status %d",urb->status);
if (b_out->busy == 0) {
st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
test_and_clear_bit(buf_nr, &d_out->busy);
if (urb->status < 0) {
- if (urb->status != USB_ST_URB_KILLED) {
+ if (urb->status != -ENOENT) {
WARN("urb status %d",urb->status);
if (d_out->busy == 0) {
st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
struct ctrl_msg *ctrl_msg;
if (urb->status < 0) {
- if (urb->status != USB_ST_URB_KILLED) {
+ if (urb->status != -ENOENT) {
WARN("urb status %d",urb->status);
} else {
DBG(1,"urb killed");
int j;
if (urb->status < 0) {
- if (urb->status != USB_ST_URB_KILLED) {
+ if (urb->status != -ENOENT) {
WARN("urb status %d",urb->status);
urb->actual_length = 0;
} else {
int len, count, status;
if (urb->status < 0) {
- if (urb->status != USB_ST_URB_KILLED) {
+ if (urb->status != -ENOENT) {
WARN("urb status %d",urb->status);
} else {
DBG(1,"urb killed");
atomic_set(&i2ob_queues[unit]->queue_depth, 0);
blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request);
- blk_queue_headactive(&i2ob_queues[unit]->req_queue, 0);
i2ob_queues[unit]->req_queue.queuedata = &i2ob_queues[unit];
return 0;
blk_dev[MAJOR_NR].queue = i2ob_get_queue;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request);
- blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
for (i = 0; i < MAX_I2OB << 4; i++) {
i2ob_dev[i].refcnt = 0;
/* Grab the speed URB */
purb = &self->speed_urb;
- if (purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
WARNING(__FUNCTION__ "(), URB still in use!\n");
return;
}
}
/* Check for timeout and other USB nasties */
- if(purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
/* I get a lot of -ECONNABORTED = -103 here - Jean II */
IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
}
/* urb is now available */
- purb->status = USB_ST_NOERROR;
+ purb->status = 0;
/* If it was the speed URB, allow the stack to send more packets */
if(purb == &self->speed_urb) {
}
}
- if (purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
WARNING(__FUNCTION__ "(), URB still in use!\n");
dev_kfree_skb(skb);
return 0;
purb->context = NULL;
/* Check for timeout and other USB nasties */
- if(purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
/* I get a lot of -ECONNABORTED = -103 here - Jean II */
IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
}
/* urb is now available */
- purb->status = USB_ST_NOERROR;
+ purb->status = 0;
/* If the network is closed, stop everything */
if ((!self->netopen) || (!self->present)) {
/* Check speed URB */
purb = &(self->speed_urb);
- if (purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
switch (purb->status) {
- case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */
+ case -EINPROGRESS:
usb_unlink_urb(purb);
/* Note : above will *NOT* call netif_wake_queue()
* in completion handler, we will come back here.
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
default: /* ??? - Play safe */
- purb->status = USB_ST_NOERROR;
+ purb->status = 0;
netif_wake_queue(self->netdev);
done = 1;
break;
/* Check Tx URB */
purb = &(self->tx_urb);
- if (purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
struct sk_buff *skb = purb->context;
IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
#endif /* IU_BUG_KICK_TIMEOUT */
switch (purb->status) {
- case USB_ST_URB_PENDING: /* -EINPROGRESS == -115 */
+ case -EINPROGRESS:
usb_unlink_urb(purb);
/* Note : above will *NOT* call netif_wake_queue()
* in completion handler, because purb->status will
dev_kfree_skb_any(skb);
purb->context = NULL;
}
- purb->status = USB_ST_NOERROR;
+ purb->status = 0;
netif_wake_queue(self->netdev);
done = 1;
break;
purb->transfer_flags = USB_QUEUE_BULK;
/* Note : unlink *must* be synchronous because of the code in
* irda_usb_net_close() -> free the skb - Jean II */
- purb->status = USB_ST_NOERROR;
+ purb->status = 0;
purb->next = NULL; /* Don't auto resubmit URBs */
ret = usb_submit_urb(purb);
}
/* Check the status */
- if(purb->status != USB_ST_NOERROR) {
+ if (purb->status != 0) {
switch (purb->status) {
- case USB_ST_CRC: /* -EILSEQ */
+ case -EILSEQ:
self->stats.rx_errors++;
self->stats.rx_crc_errors++;
break;
ret = usb_set_interface(dev, ifnum, 0);
IRDA_DEBUG(1, "usb-irda: set interface %d result %d\n", ifnum, ret);
switch (ret) {
- case USB_ST_NOERROR: /* 0 */
+ case 0:
break;
- case USB_ST_STALL: /* -EPIPE = -32 */
+ case -EPIPE: /* -EPIPE = -32 */
usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" );
break;
device->request_queue = kmalloc(sizeof(request_queue_t),GFP_KERNEL);
device->request_queue->queuedata = device;
blk_init_queue (device->request_queue, do_dasd_request);
- blk_queue_headactive (device->request_queue, 0);
elevator_init (&(device->request_queue->elevator),ELEVATOR_NOOP);
for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
#elif (XPRAM_VERSION == 24)
q = BLK_DEFAULT_QUEUE (major);
blk_init_queue (q, xpram_request);
- blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);
#endif /* V22/V24 */
read_ahead[major] = xpram_rahead;
blksize_size[tapeblock_major][ti->blk_minor]=2048; // blocks are 2k by default.
hardsect_size[tapeblock_major][ti->blk_minor]=512;
blk_init_queue (&ti->request_queue, tape_request_fn);
- blk_queue_headactive (&ti->request_queue, 0);
#ifdef CONFIG_DEVFS_FS
tapeblock_mkdevfstree(ti);
#endif
blk_size[JSFD_MAJOR] = jsfd_sizes;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
- /* blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); */
for (i = 0; i < JSF_MAX; i++) {
if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */
pc->current_position=pc->buffer;
bcount = IDE_MIN (pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */
- if (drive->using_dma && rq->special)
+ if (drive->using_dma && rq->bio)
dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
SELECT_DRIVE(HWIF(drive), drive);
int i, nhosts, try_again;
struct parport *pb;
- /*
- * unlock to allow the lowlevel parport driver to probe
- * the irqs
- */
- spin_unlock_irq(&io_request_lock);
pb = parport_enumerate();
printk("imm: Version %s\n", IMM_VERSION);
if (!pb) {
printk("imm: parport reports no devices.\n");
- spin_lock_irq(&io_request_lock);
return 0;
}
retry_entry:
"pardevice is owning the port for too longtime!\n",
i);
parport_unregister_device (imm_hosts[i].dev);
- spin_lock_irq(&io_request_lock);
return 0;
}
}
}
if (nhosts == 0) {
if (try_again == 1) {
- spin_lock_irq(&io_request_lock);
return 0;
}
try_again = 1;
goto retry_entry;
} else {
- spin_lock_irq (&io_request_lock);
return 1; /* return number of hosts detected */
}
}
if (cmd->SCp.buffers_residual--) {
cmd->SCp.buffer++;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = cmd->SCp.buffer->address;
+ cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
/*
* Make sure that we transfer even number of bytes
{
imm_struct *tmp = (imm_struct *) data;
Scsi_Cmnd *cmd = tmp->cur_cmd;
+ struct Scsi_Host *host = cmd->host;
unsigned long flags;
if (!cmd) {
if (cmd->SCp.phase > 0)
imm_pb_release(cmd->host->unique_id);
- spin_lock_irqsave(&io_request_lock, flags);
+ spin_lock_irqsave(&host->host_lock, flags);
tmp->cur_cmd = 0;
cmd->scsi_done(cmd);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irqrestore(&host->host_lock, flags);
return;
}
/* if many buffers are available, start filling the first */
cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
cmd->SCp.this_residual = cmd->SCp.buffer->length;
- cmd->SCp.ptr = cmd->SCp.buffer->address;
+ cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
} else {
/* else fill the only available buffer */
cmd->SCp.buffer = NULL;
request_queue_t *q = &SDpnt->request_queue;
blk_init_queue(q, scsi_request_fn);
- blk_queue_headactive(q, 0);
q->queuedata = (void *) SDpnt;
#ifdef DMA_CHUNK_SIZE
blk_queue_max_segments(q, 64);
req = &SCpnt->request;
req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
- complete(req->waiting);
+ if (req->waiting)
+ complete(req->waiting);
}
/*
ASSERT_LOCK(&q->queue_lock, 0);
- rq->flags = REQ_SPECIAL | REQ_NOMERGE | REQ_BARRIER;
+ /*
+ * tell I/O scheduler that this isn't a regular read/write (ie it
+ * must not attempt merges on this) and that it acts as a soft
+ * barrier
+ */
+ rq->flags = REQ_SPECIAL | REQ_BARRIER;
+
rq->special = data;
rq->q = NULL;
rq->bio = rq->biotail = NULL;
* device, or a host that is unable to accept a particular command.
*/
spin_lock_irqsave(&q->queue_lock, flags);
-
- if (at_head)
- list_add(&rq->queuelist, &q->queue_head);
- else
- list_add_tail(&rq->queuelist, &q->queue_head);
-
+ __elv_add_request(q, rq, !at_head, 0);
q->request_fn(q);
spin_unlock_irqrestore(&q->queue_lock, flags);
}
* the bad sector.
*/
SCpnt->request.special = (void *) SCpnt;
-#if 0
- SCpnt->request.flags |= REQ_SPECIAL;
-#endif
- list_add(&SCpnt->request.queuelist, &q->queue_head);
+ __elv_add_request(q, &SCpnt->request, 0, 0);
}
/*
int frequeue)
{
request_queue_t *q = &SCpnt->device->request_queue;
- struct request *req;
+ struct request *req = &SCpnt->request;
ASSERT_LOCK(&q->queue_lock, 0);
- req = &SCpnt->request;
- while (end_that_request_first(req, 1, sectors)) {
- if (!req->bio) {
- printk("scsi_end_request: missing bio\n");
- break;
- }
- }
-
/*
* If there are blocks left over at the end, set up the command
* to queue the remainder of them.
*/
- if (req->bio) {
+ if (end_that_request_first(req, 1, sectors)) {
if (!requeue)
return SCpnt;
if (SHpnt->in_recovery || blk_queue_plugged(q))
return;
- /*
- * if we are at the max queue depth, don't attempt to queue
- * more
- */
- if (SHpnt->host_busy == SDpnt->queue_depth)
- break;
-
/*
* If the device cannot accept another request, then quit.
*/
char nbuff[6];
#endif
+ /*
+ * don't support specials for nwo
+ */
+ if (!(SCpnt->request.flags & REQ_CMD))
+ return 0;
+
devm = SD_PARTITION(SCpnt->request.rq_dev);
dev = DEVICE_NR(SCpnt->request.rq_dev);
ether_dev->flags |= CDC_ETHER_RX_BUSY;
switch ( urb->status ) {
- case USB_ST_NOERROR:
+ case 0:
break;
- case USB_ST_NORESPONSE:
+ case -ETIMEDOUT:
dbg( "no repsonse in BULK IN" );
ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
break;
// return;
//
// switch ( urb->status ) {
-// case USB_ST_NOERROR:
+// case 0:
// break;
-// case USB_ST_URB_KILLED:
+// case -ENOENT:
// return;
// default:
// info("intr status %d", urb->status);
ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
int res;
- // We are finally getting used!
- MOD_INC_USE_COUNT;
-
// Turn on the USB and let the packets flow!!!
if ( (res = enable_net_traffic( ether_dev )) ) {
err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
- MOD_DEC_USE_COUNT;
return -EIO;
}
usb_unlink_urb( ðer_dev->tx_urb );
usb_unlink_urb( ðer_dev->intr_urb );
- // We are not being used now.
- MOD_DEC_USE_COUNT;
-
// That's it. I'm done.
return 0;
}
i++, mclist = mclist->next) {
memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
}
+#if 0
usb_control_msg(ether_dev->usb,
usb_sndctrlpipe(ether_dev->usb, 0),
SET_ETHERNET_MULTICAST_FILTER, /* request */
buff,
(6* net->mc_count), /* size */
HZ); /* timeout */
+#endif
kfree(buff);
}
-
+
+#if 0
CDC_SetEthernetPacketFilter(ether_dev);
-
+#endif
// Tell the kernel to start giving frames to us again.
netif_wake_queue(net);
}
// Now that we have an ethernet device, let's set it up
// (And I don't mean "set [it] up the bomb".)
net->priv = ether_dev;
+ SET_MODULE_OWNER(net);
net->open = CDCEther_open;
net->stop = CDCEther_close;
net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
bool ' USB verbose debug messages' CONFIG_USB_DEBUG
comment 'Miscellaneous USB options'
- bool ' Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
+ bool ' USB device filesystem' CONFIG_USB_DEVICEFS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
else
struct usbin *u = &as->usbin;
unsigned long flags;
unsigned int mask;
- int suret = USB_ST_NOERROR;
+ int suret = 0;
#if 0
printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
if (!usbin_retire_desc(u, urb) &&
u->flags & FLG_RUNNING &&
!usbin_prepare_desc(u, urb) &&
- (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+ (suret = usb_submit_urb(urb)) == 0) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
struct usbin *u = &as->usbin;
unsigned long flags;
unsigned int mask;
- int suret = USB_ST_NOERROR;
+ int suret = 0;
#if 0
printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
if (!usbin_sync_retire_desc(u, urb) &&
u->flags & FLG_RUNNING &&
!usbin_sync_prepare_desc(u, urb) &&
- (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+ (suret = usb_submit_urb(urb)) == 0) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
struct usbout *u = &as->usbout;
unsigned long flags;
unsigned int mask;
- int suret = USB_ST_NOERROR;
+ int suret = 0;
#if 0
printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
if (!usbout_retire_desc(u, urb) &&
u->flags & FLG_RUNNING &&
!usbout_prepare_desc(u, urb) &&
- (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+ (suret = usb_submit_urb(urb)) == 0) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
struct usbout *u = &as->usbout;
unsigned long flags;
unsigned int mask;
- int suret = USB_ST_NOERROR;
+ int suret = 0;
#if 0
printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
if (!usbout_sync_retire_desc(u, urb) &&
u->flags & FLG_RUNNING &&
!usbout_sync_prepare_desc(u, urb) &&
- (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+ (suret = usb_submit_urb(urb)) == 0) {
u->flags |= mask;
} else {
u->flags &= ~(mask | FLG_RUNNING);
struct usb_device *dev = state->s->usbdev;
unsigned char data[1];
#endif
+ unsigned char nr_logical_channels, i;
usb_audio_recurseunit(state, ftr[4]);
+
+ if (ftr[5] == 0 ) {
+ printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]);
+ return;
+ }
+
if (state->nrchannels == 0) {
printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]);
return;
}
if (state->nrchannels > 2)
printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
- if (state->nrchannels == 1 && ftr[0] == 7+ftr[5]) {
- printk(KERN_DEBUG "usbaudio: workaround for Philips camera microphone descriptor enabled\n");
- mchftr = ftr[6];
- chftr = 0;
- } else {
- if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
- printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
- return;
+
+ nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
+
+ if (nr_logical_channels != state->nrchannels) {
+ printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
+
+ if (state->nrchannels == 1 && nr_logical_channels==0) {
+ printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
+ } else if (state->nrchannels == 1 && nr_logical_channels==2) {
+ printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n");
+ state->nrchannels=nr_logical_channels;
+ } else {
+ printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n");
}
- mchftr = ftr[6];
+ }
+
+ /* There is always a master channel */
+ mchftr = ftr[6];
+ /* Binary AND over logical channels if they exist */
+ if (nr_logical_channels) {
chftr = ftr[6+ftr[5]];
- if (state->nrchannels > 1)
- chftr &= ftr[6+2*ftr[5]];
+ for (i = 2; i <= nr_logical_channels; i++)
+ chftr &= ftr[6+i*ftr[5]];
+ } else {
+ chftr = 0;
}
+
/* volume control */
if (chftr & 2) {
ch = getmixchannel(state, getvolchannel(state));
/*
- * bluetooth.c Version 0.12
+ * bluetooth.c Version 0.13
*
* Copyright (c) 2000, 2001 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
*
* USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
*
+ * (2001/11/30) Version 0.13 gkh
+ * - added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
+ * - removed active variable, as open_count will do.
+ *
* (2001/07/09) Version 0.12 gkh
* - removed in_interrupt() call, as it doesn't make sense to do
* that anymore.
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.12"
+#define DRIVER_VERSION "v0.13"
#define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
#define DRIVER_DESC "USB Bluetooth tty driver"
struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char minor; /* the starting minor number for this device */
- char active; /* someone has this device open */
int throttle; /* throttled by tty layer */
+ int open_count;
__u8 control_out_bInterfaceNum;
struct urb * control_urb_pool[NUM_CONTROL_URBS];
unsigned char int_buffer[EVENT_BUFFER_SIZE];
unsigned int bulk_packet_pos;
unsigned char bulk_buffer[ACL_BUFFER_SIZE]; /* 64k preallocated, fix? */
+ struct semaphore lock;
};
return -ENODEV;
}
- if (bluetooth->active) {
- dbg (__FUNCTION__ " - device already open");
- return -EINVAL;
- }
-
- /* set up our structure making the tty driver remember our object, and us it */
- tty->driver_data = bluetooth;
- bluetooth->tty = tty;
+ down (&bluetooth->lock);
+
+ ++bluetooth->open_count;
+ if (bluetooth->open_count == 1) {
+ /* set up our structure making the tty driver remember our object, and us it */
+ tty->driver_data = bluetooth;
+ bluetooth->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 (like with OHCI) data
- * can get lost. */
- bluetooth->tty->low_latency = 1;
+ /* force low_latency on so that our tty_push actually forces the data through,
+ * otherwise it is scheduled, and with high data rates (like with OHCI) data
+ * can get lost. */
+ bluetooth->tty->low_latency = 1;
- bluetooth->active = 1;
-
- /* Reset the packet position counters */
- bluetooth->int_packet_pos = 0;
- bluetooth->bulk_packet_pos = 0;
+ /* Reset the packet position counters */
+ bluetooth->int_packet_pos = 0;
+ bluetooth->bulk_packet_pos = 0;
#ifndef BTBUGGYHARDWARE
- /* Start reading from the device */
- FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
- usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
- bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size,
- bluetooth_read_bulk_callback, bluetooth);
- result = usb_submit_urb(bluetooth->read_urb);
- if (result)
- dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
+ /* Start reading from the device */
+ FILL_BULK_URB (bluetooth->read_urb, bluetooth->dev,
+ usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+ bluetooth->bulk_in_buffer,
+ bluetooth->bulk_in_buffer_size,
+ bluetooth_read_bulk_callback, bluetooth);
+ result = usb_submit_urb(bluetooth->read_urb);
+ if (result)
+ dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
#endif
- FILL_INT_URB(bluetooth->interrupt_in_urb, bluetooth->dev,
- usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
- bluetooth->interrupt_in_buffer, bluetooth->interrupt_in_buffer_size,
- bluetooth_int_callback, bluetooth, bluetooth->interrupt_in_interval);
- result = usb_submit_urb(bluetooth->interrupt_in_urb);
- if (result)
- dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
+ FILL_INT_URB (bluetooth->interrupt_in_urb, bluetooth->dev,
+ usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
+ bluetooth->interrupt_in_buffer,
+ bluetooth->interrupt_in_buffer_size,
+ bluetooth_int_callback, bluetooth,
+ bluetooth->interrupt_in_interval);
+ result = usb_submit_urb(bluetooth->interrupt_in_urb);
+ if (result)
+ dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
+ }
+
+ up(&bluetooth->lock);
return 0;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not opened");
return;
}
- /* shutdown any bulk reads and writes that might be going on */
- for (i = 0; i < NUM_BULK_URBS; ++i)
- usb_unlink_urb (bluetooth->write_urb_pool[i]);
- usb_unlink_urb (bluetooth->read_urb);
- usb_unlink_urb (bluetooth->interrupt_in_urb);
+ down (&bluetooth->lock);
+
+ --bluetooth->open_count;
+ if (bluetooth->open_count <= 0) {
+ bluetooth->open_count = 0;
- bluetooth->active = 0;
+ /* shutdown any bulk reads and writes that might be going on */
+ for (i = 0; i < NUM_BULK_URBS; ++i)
+ usb_unlink_urb (bluetooth->write_urb_pool[i]);
+ usb_unlink_urb (bluetooth->read_urb);
+ usb_unlink_urb (bluetooth->interrupt_in_urb);
+ }
+ up(&bluetooth->lock);
}
dbg(__FUNCTION__ " - %d byte(s)", count);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not opened");
return -EINVAL;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
return -ENODEV;
}
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -EINVAL;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return -ENODEV;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
dbg(__FUNCTION__);
- if (!bluetooth->active) {
+ if (!bluetooth->open_count) {
dbg (__FUNCTION__ " - device not open");
return;
}
}
exit:
- if (!bluetooth || !bluetooth->active)
+ if (!bluetooth || !bluetooth->open_count)
return;
FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev,
bluetooth->minor = minor;
bluetooth->tqueue.routine = bluetooth_softint;
bluetooth->tqueue.data = bluetooth;
+ init_MUTEX(&bluetooth->lock);
/* record the interface number for the control out */
bluetooth->control_out_bInterfaceNum = control_out_endpoint;
int i;
if (bluetooth) {
- if ((bluetooth->active) && (bluetooth->tty))
+ if ((bluetooth->open_count) && (bluetooth->tty))
tty_hangup(bluetooth->tty);
- bluetooth->active = 0;
+ bluetooth->open_count = 0;
if (bluetooth->read_urb) {
usb_unlink_urb (bluetooth->read_urb);
retval = count;
break;
}
- if (retval != USB_ST_TIMEOUT)
+ if (retval != -ETIMEDOUT)
break;
interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
} else if (!result)
break;
- if (result == USB_ST_TIMEOUT) { /* NAK - delay a bit */
+ if (result == -ETIMEDOUT) { /* NAK - delay a bit */
if (!maxretry--) {
if (!bytes_written)
bytes_written = -ETIME;
{USB_CLASS_PHYSICAL, "PID"},
{USB_CLASS_PRINTER, "print"},
{USB_CLASS_MASS_STORAGE, "stor."},
- {USB_CLASS_DATA, "data"},
+ {USB_CLASS_CDC_DATA, "data"},
{USB_CLASS_APP_SPEC, "app."},
{USB_CLASS_VENDOR_SPEC, "vend."},
+ {USB_CLASS_STILL_IMAGE, "still"},
+ {USB_CLASS_CSCID, "scard"},
+ {USB_CLASS_CONTENT_SEC, "c-sec"},
{-1, "unk."} /* leave as last */
};
list_del(&as->asynclist);
INIT_LIST_HEAD(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
- /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */
+ /* usb_unlink_urb calls the completion handler with status == -ENOENT */
usb_unlink_urb(&as->urb);
spin_lock_irqsave(&ps->lock, flags);
}
{
struct dev_state *ps = (struct dev_state *)context;
- ps->ifclaimed = 0;
+ if (ps)
+ ps->ifclaimed = 0;
}
struct usb_driver usbdevfs_driver = {
- name: "usbdevfs",
+ name: "usbfs",
probe: driver_probe,
disconnect: driver_disconnect,
};
u8 data[len];
int read;
- if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
+ if ((read = hid_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read);
return;
}
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
- usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
+ hid_set_idle(hid->dev, hid->ifnum, 0, report->id);
hid_read_report(hid, report);
list = list->next;
}
{ 0, 0 }
};
+static int get_class_descriptor(struct usb_device *dev, int ifnum,
+ unsigned char type, void *buf, int size)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+ (type << 8), ifnum, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+
static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
{
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
(hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
- if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
- usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) {
+ if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
+ usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
dbg("class descriptor not present\n");
return NULL;
}
for (n = 0; n < hdesc->bNumDescriptors; n++)
- if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT)
+ if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
{
__u8 rdesc[rsize];
- if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) {
+ if ((n = get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
dbg("reading report descriptor failed");
return NULL;
}
for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- hid->out[n].dr.request = USB_REQ_SET_REPORT;
+ hid->out[n].dr.request = HID_REQ_SET_REPORT;
hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
}
#if 0
if (interface->bInterfaceSubClass == 1)
- usb_set_protocol(dev, hid->ifnum, 1);
+ hid_set_protocol(dev, hid->ifnum, 1);
#endif
return hid;
c = "Device";
for (i = 0; i < hid->maxapplication; i++)
- if (IS_INPUT_APPLICATION(hid->application[i])) {
+ if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
c = hid_types[hid->application[i] & 0xffff];
break;
}
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
*/
+/*
+ * HID class requests
+ */
+#define HID_REQ_GET_REPORT 0x01
+#define HID_REQ_GET_IDLE 0x02
+#define HID_REQ_GET_PROTOCOL 0x03
+#define HID_REQ_SET_REPORT 0x09
+#define HID_REQ_SET_IDLE 0x0A
+#define HID_REQ_SET_PROTOCOL 0x0B
+
+/*
+ * HID class descriptor types
+ */
+#define HID_DT_HID (USB_TYPE_CLASS | 0x01)
+#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
+#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
+
+/*
+ * Utilities for class control messaging
+ */
+static inline int
+hid_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
+{
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (duration << 8) | report_id, ifnum, NULL, 0,
+ HZ * USB_CTRL_SET_TIMEOUT);
+}
+
+static inline int
+hid_get_protocol(struct usb_device *dev, int ifnum)
+{
+ unsigned char type;
+ int ret;
+
+ if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ HID_REQ_GET_PROTOCOL,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ 0, ifnum, &type, 1,
+ HZ * USB_CTRL_GET_TIMEOUT)) < 0)
+ return ret;
+
+ return type;
+}
+
+static inline int
+hid_set_protocol(struct usb_device *dev, int ifnum, int protocol)
+{
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ HID_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ protocol, ifnum, NULL, 0,
+ HZ * USB_CTRL_SET_TIMEOUT);
+}
+
+static inline int
+hid_get_report(struct usb_device *dev, int ifnum, unsigned char type,
+ unsigned char id, void *buf, int size)
+{
+ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+ HID_REQ_GET_REPORT,
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id, ifnum, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+static inline int
+hid_set_report(struct usb_device *dev, int ifnum, unsigned char type,
+ unsigned char id, void *buf, int size)
+{
+ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+ HID_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ (type << 8) + id, ifnum, buf, size, HZ);
+ // FIXME USB_CTRL_SET_TIMEOUT
+}
+
+
+/*
+ * "Boot Protocol" keyboard/mouse drivers use don't use all of HID;
+ * they're a lot smaller but can't support all the device features.
+ */
+#ifndef _HID_BOOT_PROTOCOL
+
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/list.h>
#else
#define hid_dump_input(a,b) do { } while (0)
#define hid_dump_device(c) do { } while (0)
-#endif
-
-#endif
+#endif /* DEBUG */
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001))
void hid_write_report(struct hid_device *, struct hid_report *);
void hid_read_report(struct hid_device *, struct hid_report *);
void hid_init_reports(struct hid_device *hid);
+
+#endif /* !_HID_BOOT_PROTOCOL */
+
+#endif /* !__HID_H */
+
return NULL;
}
+/*
+ * The usbdevfs name is now depreciated (as of 2.5.1).
+ * It will be removed when the 2.7.x development cycle is started.
+ * You have been warned :)
+ */
static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
+static DECLARE_FSTYPE(usb_fs_type, "usbfs", usbdevfs_read_super, FS_SINGLE);
/* --------------------------------------------------------------------- */
}
if ((ret = usb_register(&usbdevfs_driver)))
return ret;
+ if ((ret = register_filesystem(&usb_fs_type))) {
+ usb_deregister(&usbdevfs_driver);
+ return ret;
+ }
if ((ret = register_filesystem(&usbdevice_fs_type))) {
+ unregister_filesystem(&usb_fs_type);
usb_deregister(&usbdevfs_driver);
return ret;
}
void __exit usbdevfs_cleanup(void)
{
usb_deregister(&usbdevfs_driver);
+ unregister_filesystem(&usb_fs_type);
unregister_filesystem(&usbdevice_fs_type);
#ifdef CONFIG_PROC_FS
if (usbdir)
#endif
}
-#if 0
-module_init(usbdevfs_init);
-module_exit(usbdevfs_cleanup);
-#endif
}
+// FIXME this completion stuff is a modified clone of
+// an OLD version of some stuff in usb.c ...
+struct usb_api_data {
+ wait_queue_head_t wqh;
+ int done;
+};
+
/*-------------------------------------------------------------------*
* completion handler for compatibility wrappers (sync control/bulk) *
*-------------------------------------------------------------------*/
*
* The driver supports only one camera.
*
- * (08/04/2001) gb
+ * Fix: mdc800 used sleep_on and slept with io_lock held.
+ * Converted sleep_on to waitqueues with schedule_timeout and made io_lock
+ * a semaphore from a spinlock.
+ * by Oliver Neukum <520047054719-0001@t-online.de>
+ * (02/12/2001)
+ *
* Identify version on module load.
+ * (08/04/2001) gb
*
* version 0.7.5
* Fixed potential SMP races with Spinlocks.
purb_t irq_urb;
wait_queue_head_t irq_wait;
+ int irq_woken;
char* irq_urb_buffer;
int camera_busy; // is camera busy ?
purb_t write_urb;
char* write_urb_buffer;
wait_queue_head_t write_wait;
+ int written;
purb_t download_urb;
char* download_urb_buffer;
wait_queue_head_t download_wait;
+ int downloaded;
int download_left; // Bytes left to download ?
int out_count; // Bytes in the buffer
int open; // Camera device open ?
- spinlock_t io_lock; // IO -lock
+ struct semaphore io_lock; // IO -lock
char in [8]; // Command Input Buffer
int in_count;
if (wake_up)
{
mdc800->camera_request_ready=0;
+ mdc800->irq_woken=1;
wake_up_interruptible (&mdc800->irq_wait);
}
}
*/
static int mdc800_usb_waitForIRQ (int mode, int msec)
{
+ DECLARE_WAITQUEUE(wait, current);
+
mdc800->camera_request_ready=1+mode;
- interruptible_sleep_on_timeout (&mdc800->irq_wait, msec*HZ/1000);
+ add_wait_queue(&mdc800->irq_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!mdc800->irq_woken)
+ {
+ schedule_timeout (msec*HZ/1000);
+ }
+ remove_wait_queue(&mdc800->irq_wait, &wait);
+ set_current_state(TASK_RUNNING);
+ mdc800->irq_woken = 0;
if (mdc800->camera_request_ready>0)
{
{
mdc800->state=READY;
}
+ mdc800->written = 1;
wake_up_interruptible (&mdc800->write_wait);
}
{
err ("request bytes fails (status:%i)", urb->status);
}
+ mdc800->downloaded = 1;
wake_up_interruptible (&mdc800->download_wait);
}
info ("Found Mustek MDC800 on USB.");
- spin_lock (&mdc800->io_lock);
+ down (&mdc800->io_lock);
mdc800->dev=dev;
mdc800->open=0;
mdc800->state=READY;
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return mdc800;
}
int retval=0;
int errn=0;
- spin_lock (&mdc800->io_lock);
+ down (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
dbg ("Mustek MDC800 device opened.");
error_out:
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return errn;
}
int retval=0;
dbg ("Mustek MDC800 device closed.");
- spin_lock (&mdc800->io_lock);
+ down (&mdc800->io_lock);
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
- spin_unlock(&mdc800->io_lock);
usb_unlink_urb (mdc800->irq_urb);
usb_unlink_urb (mdc800->write_urb);
usb_unlink_urb (mdc800->download_urb);
}
else
{
- spin_unlock (&mdc800->io_lock);
retval=-EIO;
}
-
+ up(&mdc800->io_lock);
return retval;
}
{
int left=len, sts=len; /* single transfer size */
char* ptr=buf;
+ DECLARE_WAITQUEUE(wait, current);
- spin_lock (&mdc800->io_lock);
+ down (&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EBUSY;
}
if (mdc800->state == WORKING)
{
warn ("Illegal State \"working\" reached during read ?!");
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open)
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EBUSY;
}
{
if (signal_pending (current))
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EINTR;
}
if (usb_submit_urb (mdc800->download_urb))
{
err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return len-left;
}
- interruptible_sleep_on_timeout (&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
+ add_wait_queue(&mdc800->download_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!mdc800->downloaded)
+ {
+ schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&mdc800->download_wait, &wait);
+ mdc800->downloaded = 0;
if (mdc800->download_urb->status != 0)
{
err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return len-left;
}
}
else
{
/* No more bytes -> that's an error*/
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
}
}
}
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return len-left;
}
static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
{
int i=0;
+ DECLARE_WAITQUEUE(wait, current);
- spin_lock (&mdc800->io_lock);
+ down (&mdc800->io_lock);
if (mdc800->state != READY)
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open )
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EBUSY;
}
{
if (signal_pending (current))
{
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EINTR;
}
else
{
err ("Command is to long !\n");
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
err ("Camera didn't get ready.\n");
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
if (usb_submit_urb (mdc800->write_urb))
{
err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
- interruptible_sleep_on_timeout (&mdc800->write_wait, TO_WRITE_GET_READY*HZ/1000);
+ add_wait_queue(&mdc800->write_wait, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!mdc800->written)
+ {
+ schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&mdc800->write_wait, &wait);
+ mdc800->written = 0;
if (mdc800->state == WORKING)
{
usb_unlink_urb (mdc800->write_urb);
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
{
err ("call 0x07 before 0x05,0x3e");
mdc800->state=READY;
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
mdc800->pic_len=-1;
if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
{
err ("requesting answer from irq fails");
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
{
err ("Command Timeout.");
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return -EIO;
}
}
}
i++;
}
- spin_unlock (&mdc800->io_lock);
+ up (&mdc800->io_lock);
return i;
}
mdc800->dev=0;
mdc800->open=0;
mdc800->state=NOT_CONNECTED;
- spin_lock_init (&mdc800->io_lock);
+ init_MUTEX (&mdc800->io_lock);
init_waitqueue_head (&mdc800->irq_wait);
init_waitqueue_head (&mdc800->write_wait);
init_waitqueue_head (&mdc800->download_wait);
+ mdc800->irq_woken = 0;
+ mdc800->downloaded = 0;
+ mdc800->written = 0;
+
try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.4.21 (2001/08/27)"
+#define DRIVER_VERSION "v0.4.22 (2001/12/07)"
#define DRIVER_AUTHOR "Petko Manolov <pmanolov@lnxw.com>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
return;
switch ( urb->status ) {
- case USB_ST_NOERROR:
+ case 0:
if ( pegasus->flags & ETH_REGS_CHANGE ) {
pegasus->flags &= ~ETH_REGS_CHANGE;
pegasus->flags |= ETH_REGS_CHANGED;
return;
}
break;
- case USB_ST_URB_PENDING:
+ case -EINPROGRESS:
return;
- case USB_ST_URB_KILLED:
+ case -ENOENT:
break;
default:
warn( __FUNCTION__ " status %d", urb->status);
pegasus->flags |= PEGASUS_RX_BUSY;
switch ( urb->status ) {
- case USB_ST_NOERROR:
+ case 0:
break;
- case USB_ST_NORESPONSE:
+ case -ETIMEDOUT:
dbg( "reset MAC" );
pegasus->flags &= ~PEGASUS_RX_BUSY;
break;
return;
switch ( urb->status ) {
- case USB_ST_NOERROR:
+ case 0:
break;
- case USB_ST_URB_KILLED:
+ case -ENOENT:
return;
default:
info("intr status %d", urb->status);
pegasus_t *pegasus = (pegasus_t *)net->priv;
int res;
- MOD_INC_USE_COUNT;
if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
err("can't enable_net_traffic() - %d", res);
- MOD_DEC_USE_COUNT;
return -EIO;
}
FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
#ifdef PEGASUS_USE_INTR
usb_unlink_urb( &pegasus->intr_urb );
#endif
- MOD_DEC_USE_COUNT;
return 0;
}
pegasus->usb = dev;
pegasus->net = net;
+ SET_MODULE_OWNER(net);
net->priv = pegasus;
net->open = pegasus_open;
net->stop = pegasus_close;
/*
- * Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg)
+ * Copyright (c) 1999,2000 Petko Manolov - Petkan (pmanolov@lnxw.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define VENDOR_DLINK 0x2001
#define VENDOR_ELSA 0x05cc
#define VENDOR_IODATA 0x04bb
+#define VENDOR_KINGSTON 0x0951
#define VENDOR_LANEED 0x056e
#define VENDOR_LINKSYS 0x066b
#define VENDOR_MELCO 0x0411
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
+ DEFAULT_GPIO_RESET)
PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
DEFAULT_GPIO_RESET )
PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
dbg("write stats: result:%d thistime:%lu partial:%u",
result, thistime, partial);
- if (result == USB_ST_TIMEOUT) { /* NAK - so hold for a while */
+ if (result == -ETIMEDOUT) { /* NAK - so hold for a while */
if (!maxretry--) {
errn = -ETIME;
goto error;
if (partial) {
count = this_read = partial;
- } else if (result == USB_ST_TIMEOUT || result == 15) { /* FIXME: 15 ??? */
+ } else if (result == -ETIMEDOUT || result == 15) { /* FIXME: 15 ??? */
if (!maxretry--) {
up(&(rio->lock));
err("read_rio: maxretry timeout");
interruptible_sleep_on_timeout(&rio->wait_q,
NAK_TIMEOUT);
continue;
- } else if (result != USB_ST_DATAUNDERRUN) {
+ } else if (result != -EREMOTEIO) {
up(&(rio->lock));
err("Read Whoops - result:%u partial:%u this_read:%u",
result, partial, this_read);
* - Users are now notified to consult the Documentation/usb/scanner.txt
* for common error messages rather than the maintainer.
*
+ * 0.4.7 11/28/2001
+ * - Fixed typo in Documentation/scanner.txt. Thanks to
+ * Karel <karel.vervaeke@pandora.be> for pointing it out.
+ * - Added ID's for a Memorex 6136u. Thanks to =C1lvaro Gaspar de
+ * Valenzuela" <agaspard@utsi.edu>.
+ * - Added ID's for Agfa e25. Thanks to Heinrich
+ * Rust <Heinrich.Rust@gmx.de>. Also reported to work with
+ * Linux and SANE (?).
+ * - Added Canon FB620U, D646U, and 1220U ID's. Thanks to Paul
+ * Rensing <Paul_Rensing@StanfordAlumni.org>. For more info
+ * on Linux support for these models, contact
+ * salvestrini@users.sourceforge.net.
+ * - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
+ * ColorPage-HR6 V2 ID's in addition to many "Unknown" models
+ * under those vendors. Thanks to
+ * Jaeger, Gerhard" <g.jaeger@earthling.net>. These scanner are
+ * apparently based upon the LM983x IC's.
+ * - Applied Frank's patch that addressed some locking and module
+ * referencing counts. Thanks to both
+ * Frank Zago <fzago@greshamstorage.com> and
+ * Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
+ *
* TODO
* - Performance
* - Select/poll methods
struct scn_usb_data *scn;
unsigned char *data;
scn = urb->context;
- down(&(scn->sem));
+
data = &scn->button;
data += 0; /* Keep gcc from complaining about unused var */
if (urb->status) {
- up(&(scn->sem));
return;
}
dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
- up(&(scn->sem));
+
return;
}
if (!p_scn_table[scn_minor]) {
up(&scn_mutex);
+ MOD_DEC_USE_COUNT;
err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
}
ret = result;
break;
- } else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
+ } else if ((result < 0) && (result != -EREMOTEIO)) {
warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_minor, (int)result);
ret = -EIO;
break;
/* Check to make sure that the last slot isn't already taken */
if (p_scn_table[scn_minor]) {
err("probe_scanner: No more minor devices remaining.");
+ up(&scn_mutex);
return NULL;
}
if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
err("probe_scanner: Out of memory.");
+ up(&scn_mutex);
return NULL;
}
memset (scn, 0, sizeof(struct scn_usb_data));
if (scn->devfs == NULL)
dbg("scanner%d: device node registration failed", scn_minor);
+ p_scn_table[scn_minor] = scn;
+
up(&scn_mutex);
- return p_scn_table[scn_minor] = scn;
+ return scn;
}
static void
{ USB_DEVICE(0x06bd, 0x2061) }, /* Another SnapScan 1212U (?)*/
{ USB_DEVICE(0x06bd, 0x0100) }, /* SnapScan Touch */
{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
+ { USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
+ /* Canon */
+ { USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
+ { USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
+ { USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
/* Colorado -- See Primax/Colorado below */
/* Epson -- See Seiko/Epson below */
/* Genius */
{ USB_DEVICE(0x0458, 0x2001) }, /* ColorPage-Vivid Pro */
+ { USB_DEVICE(0x0458, 0x2007) }, /* ColorPage HR6 V2 */
+ { USB_DEVICE(0x0458, 0x2008) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2009) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2013) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2015) }, /* Unknown */
+ { USB_DEVICE(0x0458, 0x2016) }, /* Unknown */
/* Hewlett Packard */
{ USB_DEVICE(0x03f0, 0x0205) }, /* 3300C */
{ USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */
{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
/* Lifetec */
{ USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */
+ /* Memorex */
+ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */
{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
+ /* Plustek */
+ { USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
+ { USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
+ { USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
+ { USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
/* Primax/Colorado */
{ USB_DEVICE(0x0461, 0x0300) }, /* G2-300 #1 */
{ USB_DEVICE(0x0461, 0x0380) }, /* G2-600 #1 */
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/*Start reading from the device*/
/* TODO: Look at possibility of submitting mulitple URBs to device to
* enhance buffering. Win trace shows 16 initial read URBs.
usb_unlink_urb (port->read_urb);
usb_unlink_urb (port->interrupt_in_urb);
}
- port->active = 0;
+ port->open_count = 0;
}
up (&port->sem);
++port->open_count;
- if (!port->active) {
- port->active = 1;
+ if (port->open_count == 1) {
/* force low_latency on so that our tty_push actually forces
* the data through, otherwise it is scheduled, and with high
* data rates (like with OHCI) data can get lost.
usb_unlink_urb (port->read_urb);
usb_unlink_urb (port->interrupt_in_urb);
}
-
- port->active = 0;
port->open_count = 0;
}
* Peter Berger (pberger@brimson.com)
* Al Borchers (borchers@steinerpoint.com)
*
+* (12/03/2001) gkh
+* switched to using port->open_count instead of private version.
+* Removed port->active
+*
* (04/08/2001) gb
* Identify version on module load.
*
int dp_write_urb_in_use;
unsigned int dp_modem_signals;
wait_queue_head_t dp_modem_change_wait;
- int dp_open_count; /* inc on open, dec on close */
int dp_transmit_idle;
wait_queue_head_t dp_transmit_idle_wait;
int dp_throttled;
/* try to send any buffered data on this port, if it is open */
spin_lock( &priv->dp_port_lock );
priv->dp_write_urb_in_use = 0;
- if( priv->dp_open_count && port->write_urb->status != -EINPROGRESS
+ if( port->open_count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0 ) {
*((unsigned char *)(port->write_urb->transfer_buffer))
unsigned long flags = 0;
-dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, port->active, priv->dp_open_count );
+dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
/* be sure the device is started up */
if( digi_startup_device( port->serial ) != 0 )
}
/* inc module use count before sleeping to wait for closes */
- ++priv->dp_open_count;
+ ++port->open_count;
MOD_INC_USE_COUNT;
/* wait for a close in progress to finish */
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags );
if( signal_pending(current) ) {
- --priv->dp_open_count;
+ --port->open_count;
MOD_DEC_USE_COUNT;
return( -EINTR );
}
/* if port is already open, just return */
/* be sure exactly one open proceeds */
- if( port->active ) {
+ if( port->open_count != 1) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( 0 );
}
- /* first open, mark port as active */
- port->active = 1;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
/* read modem signals automatically whenever they change */
unsigned long flags = 0;
-dbg( "digi_close: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, port->active, priv->dp_open_count );
+dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
/* do cleanup only after final close on this port */
spin_lock_irqsave( &priv->dp_port_lock, flags );
- if( priv->dp_open_count > 1 ) {
- --priv->dp_open_count;
+ if( port->open_count > 1 ) {
+ --port->open_count;
MOD_DEC_USE_COUNT;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return;
- } else if( priv->dp_open_count <= 0 ) {
+ } else if( port->open_count <= 0 ) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return;
}
tty->closing = 0;
spin_lock_irqsave( &priv->dp_port_lock, flags );
- port->active = 0;
priv->dp_write_urb_in_use = 0;
priv->dp_in_close = 0;
- --priv->dp_open_count;
+ --port->open_count;
MOD_DEC_USE_COUNT;
wake_up_interruptible( &priv->dp_close_wait );
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
/* number of regular ports + 1 for the out-of-band port */
for( i=0; i<serial->type->num_ports+1; i++ ) {
- serial->port[i].active = 0;
-
/* allocate port private structure */
priv = serial->port[i].private =
(digi_port_t *)kmalloc( sizeof(digi_port_t),
priv->dp_write_urb_in_use = 0;
priv->dp_modem_signals = 0;
init_waitqueue_head( &priv->dp_modem_change_wait );
- priv->dp_open_count = 0;
priv->dp_transmit_idle = 0;
init_waitqueue_head( &priv->dp_transmit_idle_wait );
priv->dp_throttled = 0;
for( i=0; i<serial->type->num_ports; i++ ) {
priv = serial->port[i].private;
spin_lock_irqsave( &priv->dp_port_lock, flags );
- while( priv->dp_open_count > 0 ) {
+ while( serial->port[i].open_count > 0 ) {
MOD_DEC_USE_COUNT;
- --priv->dp_open_count;
+ --serial->port[i].open_count;
}
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
}
/* do not process callbacks on closed ports */
/* but do continue the read chain */
- if( priv->dp_open_count == 0 )
+ if( port->open_count == 0 )
return( 0 );
/* short/multiple packet check */
if( val & DIGI_READ_INPUT_SIGNALS_CTS ) {
priv->dp_modem_signals |= TIOCM_CTS;
/* port must be open to use tty struct */
- if( priv->dp_open_count
+ if( port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) {
port->tty->hw_stopped = 0;
digi_wakeup_write( port );
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */
- if( priv->dp_open_count
+ if( port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) {
port->tty->hw_stopped = 1;
}
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
+ if (port->open_count == 1) {
/* Force default termio settings */
empeg_set_termios (port, NULL) ;
- port->active = 1;
bytes_in = 0;
bytes_out = 0;
/* shutdown our bulk read */
usb_unlink_urb (port->read_urb);
}
- port->active = 0;
port->open_count = 0;
}
MOD_INC_USE_COUNT;
++port->open_count;
- if (!port->active){
- port->active = 1;
-
+ if (port->open_count == 1){
/* This will push the characters through immediately rather
than queue a task to deliver them */
port->tty->low_latency = 1;
usb_unlink_urb (port->write_urb);
usb_unlink_urb (port->read_urb);
}
- port->active = 0;
port->open_count = 0;
} else {
/* Send a HUP if necessary */
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates (like with OHCI) data
can get lost. */
serial = port->serial;
edge_serial = (struct edgeport_serial *)serial->private;
if (edge_serial == NULL) {
- port->active = 0;
port->open_count = 0;
MOD_DEC_USE_COUNT;
return -ENODEV;
if (response < 0) {
err(__FUNCTION__" - error sending open port command");
edge_port->openPending = FALSE;
- port->active = 0;
port->open_count = 0;
MOD_DEC_USE_COUNT;
return -ENODEV;
/* open timed out */
dbg(__FUNCTION__" - open timedout");
edge_port->openPending = FALSE;
- port->active = 0;
port->open_count = 0;
MOD_DEC_USE_COUNT;
return -ENODEV;
if (edge_port->txfifo.fifo) {
kfree(edge_port->txfifo.fifo);
}
- port->active = 0;
port->open_count = 0;
}
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
if (buffer_size) {
/* override the default buffer sizes */
buffer = kmalloc (buffer_size, GFP_KERNEL);
/* shutdown our bulk read */
usb_unlink_urb (port->read_urb);
}
- port->active = 0;
port->open_count = 0;
}
p_priv = (struct keyspan_port_private *)(port->private);
dbg (__FUNCTION__ " urb %d\n", urb == p_priv->out_urbs[1]);
- if (port->active) {
+ if (port->open_count) {
queue_task(&port->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
}
MOD_INC_USE_COUNT;
down (&port->sem);
+ already_active = port->open_count;
++port->open_count;
- already_active = port->active;
- port->active = 1;
up (&port->sem);
if (already_active)
down (&port->sem);
if (--port->open_count <= 0) {
- if (port->active) {
- if (serial->dev) {
- /* Stop reading/writing urbs */
- stop_urb(p_priv->inack_urb);
- stop_urb(p_priv->outcont_urb);
- for (i = 0; i < 2; i++) {
- stop_urb(p_priv->in_urbs[i]);
- stop_urb(p_priv->out_urbs[i]);
- }
+ if (serial->dev) {
+ /* Stop reading/writing urbs */
+ stop_urb(p_priv->inack_urb);
+ stop_urb(p_priv->outcont_urb);
+ for (i = 0; i < 2; i++) {
+ stop_urb(p_priv->in_urbs[i]);
+ stop_urb(p_priv->out_urbs[i]);
}
}
- port->active = 0;
port->open_count = 0;
port->tty = 0;
}
MOD_INC_USE_COUNT;
++port->open_count;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/* find out how much room is in the Tx ring */
rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
6, /* write_room */
return rc;
error:
--port->open_count;
- port->active = 0;
MOD_DEC_USE_COUNT;
up (&port->sem);
return rc;
usb_unlink_urb (port->write_urb);
usb_unlink_urb (port->interrupt_in_urb);
}
- port->active = 0;
port->open_count = 0;
}
* 10-Nov-2001 Wolfgang Grandegger
* - Fixed an endianess problem with the baudrate selection for PowerPC.
*
+ * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
+ * Added support for the Belkin F5U109 DB9 adaptor
+ *
* 30-May-2001 Greg Kroah-Hartman
* switched from using spinlock to a semaphore, which fixes lots of problems.
*
{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
+ { USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
{ } /* Terminating entry */
};
#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
- if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID) {
+ if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
+ || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
case 300: return 0x01;
case 600: return 0x02; /* this one not tested */
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/* Compensate for a hardware bug: although the Sitecom U232-P25
* device reports a maximum output packet size of 32 bytes,
* it seems to be able to accept only 16 bytes (and that's what
usb_unlink_urb (port->read_urb);
usb_unlink_urb (port->interrupt_in_urb);
}
- port->active = 0;
+ port->open_count = 0;
}
up (&port->sem);
#define MCT_U232_SITECOM_PID 0x0230 /* Sitecom Product Id */
/* DU-H3SP USB BAY hub */
-
#define MCT_U232_DU_H3SP_PID 0x0200 /* D-Link DU-H3SP USB BAY */
+/* Belkin badge the MCT U232-P9 as the F5U109 */
+#define MCT_U232_BELKIN_F5U109_VID 0x050d /* Vendor Id */
+#define MCT_U232_BELKIN_F5U109_PID 0x0109 /* Product Id */
+
/*
* Vendor Request Interface
*/
* bmAttributes = 03 (Interrupt)
* wMaxPacketSize = 0002
* bInterval = 02
+ *
+ *
+ * Hardware details (added by Martin Hamilton, 2001/12/06)
+ * -----------------------------------------------------------------
+ *
+ * This info was gleaned from opening a Belkin F5U109 DB9 USB serial
+ * adaptor, which turns out to simply be a re-badged U232-P9. We
+ * know this because there is a sticky label on the circuit board
+ * which says "U232-P9" ;-)
+ *
+ * The circuit board inside the adaptor contains a Philips PDIUSBD12
+ * USB endpoint chip and a Phillips P87C52UBAA microcontroller with
+ * embedded UART. Exhaustive documentation for these is available at:
+ *
+ * http://www.semiconductors.philips.com/pip/p87c52ubaa
+ * http://www.semiconductors.philips.com/pip/pdiusbd12
+ *
+ * Thanks to Julian Highfield for the pointer to the Philips database.
+ *
*/
#endif /* __LINUX_USB_SERIAL_MCT_U232_H */
MOD_INC_USE_COUNT;
++port->open_count;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
if( !od ) {
err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
- --port->open_count;
- port->active = 0;
+ port->open_count = 0;
up (&port->sem);
MOD_DEC_USE_COUNT;
return -ENOMEM;
usb_unlink_urb (port->read_urb);
}
- port->active = 0;
port->open_count = 0;
od = (struct omninet_data *)port->private;
if (od)
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
#define FISH(a,b,c,d) \
result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \
b, a, c, d, buf, 1, 100); \
"(interrupt_in_urb) failed with reason: %d",
result);
}
-
- port->active = 0;
port->open_count = 0;
}
if (urb->status) {
dbg (__FUNCTION__ " - urb->status = %d", urb->status);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port is closed, exiting.");
return;
}
}
/* Schedule the next read _if_ we are still open */
- if (port->active) {
+ if (port->open_count) {
urb->dev = serial->dev;
result = usb_submit_urb(urb);
if (result)
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (12/03/2001) gkh
+ * removed active from the port structure.
+ * added documentation to the usb_serial_device_type structure
+ *
* (10/10/2001) gkh
* added vendor and product to serial structure. Needed to determine device
* owner when the device is disconnected.
struct usb_serial *serial; /* pointer back to the owner of this port */
struct tty_struct * tty; /* the coresponding tty for this port */
unsigned char number;
- char active; /* someone has this device open */
unsigned char * interrupt_in_buffer;
struct urb * interrupt_in_urb;
#define NUM_DONT_CARE (-1)
-/* This structure defines the individual serial converter. */
+/**
+ * usb_serial_device_type - a structure that defines a usb serial device
+ * @name: pointer to a string that describes this device. This string used
+ * in the syslog messages when a device is inserted or removed.
+ * @id_table: pointer to a list of usb_device_id structures that define all
+ * of the devices this structure can support.
+ * @num_interrupt_in: the number of interrupt in endpoints this device will
+ * have.
+ * @num_bulk_in: the number of bulk in endpoints this device will have.
+ * @num_bulk_out: the number of bulk out endpoints this device will have.
+ * @num_ports: the number of different ports this device will have.
+ * @startup: pointer to the driver's startup function. This will be called
+ * when the driver is inserted into the system. Return 0 to continue
+ * on with the initialization sequence. Anything else will abort it.
+ * @shutdown: pointer to the driver's shutdown function. This will be
+ * called when the device is removed from the system.
+ *
+ * This structure is defines a USB Serial device. It provides all of
+ * the information that the USB serial core code needs. If the function
+ * pointers are defined, then the USB serial core code will call them when
+ * the corresponding tty port functions are called. If they are not
+ * called, the generic serial function will be used instead.
+ */
struct usb_serial_device_type {
char *name;
const struct usb_device_id *id_table;
char num_interrupt_in;
char num_bulk_in;
char num_bulk_out;
- char num_ports; /* number of serial ports this device has */
+ char num_ports;
struct list_head driver_list;
- /* function call to make before accepting driver */
- /* return 0 to continue initialization, anything else to abort */
int (*startup) (struct usb_serial *serial);
-
void (*shutdown) (struct usb_serial *serial);
/* serial function calls */
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not opened");
return;
}
dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not opened");
return -EINVAL;
}
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -EINVAL;
}
return -ENODEV;
}
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -EINVAL;
}
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
}
dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return -ENODEV;
}
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
}
dbg(__FUNCTION__ " - port %d", port->number);
- if (!port->active) {
+ if (!port->open_count) {
dbg (__FUNCTION__ " - port not open");
return;
}
++port->open_count;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates (like with OHCI) data
can get lost. */
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ((serial->type->read_bulk_callback) ?
- serial->type->read_bulk_callback :
- generic_read_bulk_callback),
- port);
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback),
+ port);
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
if (serial->num_bulk_in)
usb_unlink_urb (port->read_urb);
}
-
- port->active = 0;
port->open_count = 0;
}
usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
/* set up our urb */
- FILL_BULK_URB(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, count,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- generic_write_bulk_callback),
- port);
+ usb_fill_bulk_urb (port->write_urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ generic_write_bulk_callback), port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb);
}
/* Continue trying to always read */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- ((serial->type->read_bulk_callback) ?
- serial->type->read_bulk_callback :
- generic_read_bulk_callback),
- port);
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe (serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
err("Couldn't allocate bulk_in_buffer");
goto probe_error;
}
- FILL_BULK_URB(port->read_urb, dev,
- usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
- port->bulk_in_buffer, buffer_size,
- ((serial->type->read_bulk_callback) ?
- serial->type->read_bulk_callback :
- generic_read_bulk_callback),
- port);
+ usb_fill_bulk_urb (port->read_urb, dev,
+ usb_rcvbulkpipe (dev,
+ endpoint->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size,
+ ((serial->type->read_bulk_callback) ?
+ serial->type->read_bulk_callback :
+ generic_read_bulk_callback),
+ port);
}
for (i = 0; i < num_bulk_out; ++i) {
err("Couldn't allocate bulk_out_buffer");
goto probe_error;
}
- FILL_BULK_URB(port->write_urb, dev,
- usb_sndbulkpipe(dev, endpoint->bEndpointAddress),
- port->bulk_out_buffer, buffer_size,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- generic_write_bulk_callback),
- port);
+ usb_fill_bulk_urb (port->write_urb, dev,
+ usb_sndbulkpipe (dev,
+ endpoint->bEndpointAddress),
+ port->bulk_out_buffer, buffer_size,
+ ((serial->type->write_bulk_callback) ?
+ serial->type->write_bulk_callback :
+ generic_write_bulk_callback),
+ port);
}
for (i = 0; i < num_interrupt_in; ++i) {
err("Couldn't allocate interrupt_in_buffer");
goto probe_error;
}
- FILL_INT_URB(port->interrupt_in_urb, dev,
- usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- port->interrupt_in_buffer, buffer_size,
- serial->type->read_int_callback,
- port,
- endpoint->bInterval);
+ usb_fill_int_urb (port->interrupt_in_urb, dev,
+ usb_rcvintpipe (dev,
+ endpoint->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size,
+ serial->type->read_int_callback, port,
+ endpoint->bInterval);
}
/* initialize some parts of the port structures */
serial_shutdown (serial);
for (i = 0; i < serial->num_ports; ++i)
- serial->port[i].active = 0;
+ serial->port[i].open_count = 0;
for (i = 0; i < serial->num_bulk_in; ++i) {
port = &serial->port[i];
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.6"
+#define DRIVER_VERSION "v1.7"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
+ if (port->open_count == 1) {
bytes_in = 0;
bytes_out = 0;
port->tty->low_latency = 1;
/* Start reading from the device */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- visor_read_bulk_callback, port);
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe (serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
/* shutdown our bulk read */
usb_unlink_urb (port->read_urb);
}
- port->active = 0;
port->open_count = 0;
}
up (&port->sem);
usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, urb->transfer_buffer);
/* build up our urb */
- FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
- urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port);
+ usb_fill_bulk_urb (urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer, transfer_size,
+ visor_write_bulk_callback, port);
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
}
/* Continue trying to always read */
- FILL_BULK_URB(port->read_urb, serial->dev,
- usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
- visor_read_bulk_callback, port);
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe (serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg (__FUNCTION__);
/* stop reads and writes on all ports */
- for (i=0; i < serial->num_ports; ++i) {
- while (serial->port[i].open_count > 0) {
- visor_close (&serial->port[i], NULL);
- }
- }
+ for (i=0; i < serial->num_ports; ++i)
+ serial->port[i].open_count = 0;
}
++port->open_count;
MOD_INC_USE_COUNT;
- if (!port->active) {
- port->active = 1;
-
+ if (port->open_count == 1) {
/* set up some stuff for our command port */
command_port = &port->serial->port[COMMAND_PORT];
if (command_port->private == NULL) {
/* shutdown our bulk reads and writes */
usb_unlink_urb (port->write_urb);
usb_unlink_urb (port->read_urb);
- port->active = 0;
+ port->open_count = 0;
}
MOD_DEC_USE_COUNT;
up (&port->sem);
/* implicitly requeued */
urb->actual_length = 0;
- urb->status = USB_ST_URB_PENDING;
+ urb->status = -EINPROGRESS;
if (urb_priv->state != URB_DEL)
td_submit_urb (urb);
break;
urb->complete (urb);
spin_lock_irqsave (&usb_ed_lock, flags);
urb->actual_length = 0;
- urb->status = USB_ST_URB_PENDING;
+ urb->status = -EINPROGRESS;
urb->start_frame = urb_priv->ed->last_iso + 1;
if (urb_priv->state != URB_DEL) {
for (i = 0; i < urb->number_of_packets; i++) {
urb->actual_length = 0;
urb->hcpriv = urb_priv;
- urb->status = USB_ST_URB_PENDING;
+ urb->status = -EINPROGRESS;
/* link the ed into a chain if is not already */
if (ed->state != ED_OPER)
if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
return rh_unlink_urb (urb);
- if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) {
+ if (urb->hcpriv && (urb->status == -EINPROGRESS)) {
if (!ohci->disabled) {
urb_priv_t * urb_priv;
/* wait until all TDs are deleted */
set_current_state(TASK_UNINTERRUPTIBLE);
- while (timeout && (urb->status == USB_ST_URB_PENDING))
+ while (timeout && (urb->status == -EINPROGRESS))
timeout = schedule_timeout (timeout);
set_current_state(TASK_RUNNING);
remove_wait_queue (&unlink_wakeup, &wait);
- if (urb->status == USB_ST_URB_PENDING) {
+ if (urb->status == -EINPROGRESS) {
err ("unlink URB timeout");
return -ETIMEDOUT;
}
static int cc_to_error[16] = {
/* mapping of the OHCI CC status to error codes */
- /* No Error */ USB_ST_NOERROR,
- /* CRC Error */ USB_ST_CRC,
- /* Bit Stuff */ USB_ST_BITSTUFF,
- /* Data Togg */ USB_ST_CRC,
- /* Stall */ USB_ST_STALL,
- /* DevNotResp */ USB_ST_NORESPONSE,
- /* PIDCheck */ USB_ST_BITSTUFF,
- /* UnExpPID */ USB_ST_BITSTUFF,
- /* DataOver */ USB_ST_DATAOVERRUN,
- /* DataUnder */ USB_ST_DATAUNDERRUN,
- /* reservd */ USB_ST_NORESPONSE,
- /* reservd */ USB_ST_NORESPONSE,
- /* BufferOver */ USB_ST_BUFFEROVERRUN,
- /* BuffUnder */ USB_ST_BUFFERUNDERRUN,
- /* Not Access */ USB_ST_NORESPONSE,
- /* Not Access */ USB_ST_NORESPONSE
+ /* No Error */ 0,
+ /* CRC Error */ -EILSEQ,
+ /* Bit Stuff */ -EPROTO,
+ /* Data Togg */ -EILSEQ,
+ /* Stall */ -EPIPE,
+ /* DevNotResp */ -ETIMEDOUT,
+ /* PIDCheck */ -EPROTO,
+ /* UnExpPID */ -EPROTO,
+ /* DataOver */ -EOVERFLOW,
+ /* DataUnder */ -EREMOTEIO,
+ /* reservd */ -ETIMEDOUT,
+ /* reservd */ -ETIMEDOUT,
+ /* BufferOver */ -ECOMM,
+ /* BuffUnder */ -ENOSR,
+ /* Not Access */ -ETIMEDOUT,
+ /* Not Access */ -ETIMEDOUT
};
#include <linux/config.h>
* Goes through all unclaimed USB interfaces, and offers them to all
* registered USB drivers through the 'probe' function.
* This will automatically be called after usb_register is called.
- * It is called by some of the USB subsystems after one of their subdrivers
- * are registered.
+ * It is called by some of the subsystems layered over USB
+ * after one of their subdrivers are registered.
*/
void usb_scan_devices(void)
{
* bustime is from calc_bus_time(), but converted to microseconds.
*
* returns <bustime in us> if successful,
- * or USB_ST_BANDWIDTH_ERROR if bandwidth request fails.
+ * or -ENOSPC if bandwidth request fails.
*
* FIXME:
* This initial implementation does not use Endpoint.bInterval
if (!usb_bandwidth_option) /* don't enforce it */
return (bustime);
- return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : USB_ST_BANDWIDTH_ERROR;
+ return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : -ENOSPC;
}
void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
* any transfer flags.
*
* Successful submissions return 0; otherwise this routine returns a
- * negative error number.
+ * negative error number. If the submission is successful, the complete
+ * fuction of the urb will be called when the USB host driver is
+ * finished with the urb (either a successful transmission, or some
+ * error case.)
*
* Unreserved Bandwidth Transfers:
*
return -ENODEV;
}
/*-------------------------------------------------------------------*
- * COMPLETION HANDLERS *
+ * SYNCHRONOUS CALLS *
*-------------------------------------------------------------------*/
-/*-------------------------------------------------------------------*
- * completion handler for compatibility wrappers (sync control/bulk) *
- *-------------------------------------------------------------------*/
+struct usb_api_data {
+ wait_queue_head_t wqh;
+ int done;
+};
+
static void usb_api_blocking_completion(urb_t *urb)
{
struct usb_api_data *awd = (struct usb_api_data *)urb->context;
wake_up(&awd->wqh);
}
-/*-------------------------------------------------------------------*
- * SYNCHRONOUS CALLS *
- *-------------------------------------------------------------------*/
-
// Starts urb and waits for completion or timeout
static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length)
{
return size;
}
-// usbcore-internal: enumeration/hub only!!
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally on disconnect/destroy path
void usb_destroy_configuration(struct usb_device *dev)
{
int c, i, j, k;
* These are the actual routines to send
* and receive control messages.
*/
-#ifdef CONFIG_USB_LONG_TIMEOUT
-#define GET_TIMEOUT 4
-#else
-#define GET_TIMEOUT 3
-#endif
-#define SET_TIMEOUT 3
-// hub driver only!!! for enumeration
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for usb_new_device()
int usb_set_address(struct usb_device *dev)
{
return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
- 0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);
+ // FIXME USB_CTRL_SET_TIMEOUT
+ 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
}
/**
* Configuration descriptors (USB_DT_CONFIG) are part of the device
* structure, at least for the current configuration.
* In addition to a number of USB-standard descriptors, some
- * devices also use vendor-specific descriptors.
+ * devices also use class-specific or vendor-specific descriptors.
*
* This call is synchronous, and may not be used in an interrupt context.
*
memset(buf,0,size); // Make sure we parse really received data
while (i--) {
+ /* retries if the returned length was 0; flakey device */
if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) > 0 ||
- result == -EPIPE)
- break; /* retry if the returned length was 0; flaky device */
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ (type << 8) + index, 0, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT)) > 0
+ || result == -EPIPE)
+ break;
}
return result;
}
-// FIXME Doesn't use USB_DT_CLASS ... but hid-core.c expects it this way
-int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
- unsigned char type, unsigned char id, void *buf, int size)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
- (type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
-}
-
/**
* usb_get_string - gets a string descriptor
* @dev: the device whose string descriptor is being retrieved
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- (USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT);
+ (USB_DT_STRING << 8) + index, langid, buf, size,
+ HZ * USB_CTRL_GET_TIMEOUT);
}
/**
int usb_get_status(struct usb_device *dev, int type, int target, void *data)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT);
+ USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
+ HZ * USB_CTRL_GET_TIMEOUT);
}
-// FIXME hid-specific !! DOES NOT BELONG HERE
-int usb_get_protocol(struct usb_device *dev, int ifnum)
-{
- unsigned char type;
- int ret;
-
- if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- 0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0)
- return ret;
- return type;
-}
-
-// FIXME hid-specific !! DOES NOT BELONG HERE
-int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
-{
- return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);
-}
-
-// FIXME hid-specific !! DOES NOT BELONG HERE
-int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
-{
- return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT);
-}
-
-// hub-only!!
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for config/altsetting reconfig.
void usb_set_maxpacket(struct usb_device *dev)
{
int i, b;
*/
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
+ HZ * USB_CTRL_SET_TIMEOUT);
/* don't clear if failed */
if (result < 0)
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
- buffer, sizeof(status), HZ * SET_TIMEOUT);
+ // FIXME USB_CTRL_GET_TIMEOUT, yes? why not usb_get_status() ?
+ buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
memcpy(&status, buffer, sizeof(status));
kfree(buffer);
}
if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0)
+ USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+ NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
return ret;
dev->actconfig = cp;
return 0;
}
-// FIXME hid-specific !! DOES NOT BELONG HERE
-int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
-{
- return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
-}
-
-// FIXME hid-specific !! DOES NOT BELONG HERE
-int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
-{
- return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id, ifnum, buf, size, HZ);
-}
-
-// hub driver only !!
+// hub-only!! ... and only in reset path, or usb_new_device()
+// (used by real hubs and virtual root hubs)
int usb_get_configuration(struct usb_device *dev)
{
int result;
EXPORT_SYMBOL(usb_claim_bandwidth);
EXPORT_SYMBOL(usb_release_bandwidth);
-EXPORT_SYMBOL(usb_set_address);
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_class_descriptor);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
-EXPORT_SYMBOL(usb_get_string);
-EXPORT_SYMBOL(usb_string);
-EXPORT_SYMBOL(usb_get_protocol);
-EXPORT_SYMBOL(usb_set_protocol);
-EXPORT_SYMBOL(usb_get_report);
-EXPORT_SYMBOL(usb_set_report);
-EXPORT_SYMBOL(usb_set_idle);
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_set_interface);
-EXPORT_SYMBOL(usb_get_configuration);
-EXPORT_SYMBOL(usb_set_configuration);
-EXPORT_SYMBOL(usb_get_status);
EXPORT_SYMBOL(usb_get_current_frame_number);
+// asynchronous request completion model
EXPORT_SYMBOL(usb_alloc_urb);
EXPORT_SYMBOL(usb_free_urb);
EXPORT_SYMBOL(usb_submit_urb);
EXPORT_SYMBOL(usb_unlink_urb);
+// synchronous request completion model
EXPORT_SYMBOL(usb_control_msg);
EXPORT_SYMBOL(usb_bulk_msg);
+// synchronous control message convenience routines
+EXPORT_SYMBOL(usb_get_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
+EXPORT_SYMBOL(usb_get_status);
+EXPORT_SYMBOL(usb_get_string);
+EXPORT_SYMBOL(usb_string);
+EXPORT_SYMBOL(usb_clear_halt);
+EXPORT_SYMBOL(usb_set_configuration);
+EXPORT_SYMBOL(usb_set_interface);
EXPORT_SYMBOL(usb_devfs_handle);
MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/usb.h>
+#define _HID_BOOT_PROTOCOL
+#include "hid.h"
+
/*
* Version Information
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- usb_set_protocol(dev, interface->bInterfaceNumber, 0);
- usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
+ hid_set_protocol(dev, interface->bInterfaceNumber, 0);
+ hid_set_idle(dev, interface->bInterfaceNumber, 0, 0);
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
memset(kbd, 0, sizeof(struct usb_kbd));
usb_kbd_irq, kbd, endpoint->bInterval);
kbd->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
- kbd->dr.request = USB_REQ_SET_REPORT;
+ kbd->dr.request = HID_REQ_SET_REPORT;
kbd->dr.value = 0x200;
kbd->dr.index = interface->bInterfaceNumber;
kbd->dr.length = 1;
#include <linux/init.h>
#include <linux/usb.h>
+#define _HID_BOOT_PROTOCOL
+#include "hid.h"
+
/*
* Version Information
*/
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
+ hid_set_idle(dev, interface->bInterfaceNumber, 0, 0);
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
memset(mouse, 0, sizeof(struct usb_mouse));
struct skb_data *entry = (struct skb_data *) skb->cb;
struct usbnet *dev = entry->dev;
- if (urb->status == USB_ST_STALL) {
+ if (urb->status == -EPIPE) {
if (dev->ctrl_task.sync == 0) {
dev->ctrl_task.routine = tx_clear_halt;
dev->ctrl_task.data = dev;
USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults
driver_info: (unsigned long) &an2720_info,
},
+
+{
+ USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET
+ driver_info: (unsigned long) &an2720_info,
+},
#endif
#ifdef CONFIG_USB_BELKIN
struct parport *pp = (struct parport *)dev_id;
struct parport_uss720_private *priv = pp->private_data;
- if (usbstatus != USB_ST_NOERROR || len < 4 || !buffer)
+ if (usbstatus != 0 || len < 4 || !buffer)
return 1;
memcpy(priv->reg, buffer, 4);
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
struct biovec_pool {
int bp_size;
kmem_cache_t *bp_cachep;
- wait_queue_head_t bp_wait;
};
static struct biovec_pool bvec_list[BIOVEC_NR_POOLS];
if ((bvl = kmem_cache_alloc(bp->bp_cachep, gfp_mask)))
goto out_gotit;
- /*
- * we need slab reservations for this to be completely
- * deadlock free...
- */
- if (BIO_CAN_WAIT(gfp_mask)) {
- DECLARE_WAITQUEUE(wait, current);
+ if (!BIO_CAN_WAIT(gfp_mask))
+ return NULL;
- add_wait_queue_exclusive(&bp->bp_wait, &wait);
- for (;;) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- bvl = kmem_cache_alloc(bp->bp_cachep, gfp_mask);
- if (bvl)
- goto out_gotit;
+ do {
+ bvl = kmem_cache_alloc(bp->bp_cachep, gfp_mask);
+ if (bvl)
+ break;
- run_task_queue(&tq_disk);
- schedule();
- }
- remove_wait_queue(&bp->bp_wait, &wait);
+ run_task_queue(&tq_disk);
__set_current_state(TASK_RUNNING);
- }
+ current->policy |= SCHED_YIELD;
+ schedule();
+ } while (1);
- if (bvl) {
out_gotit:
- memset(bvl, 0, bp->bp_size);
- }
-
+ memset(bvl, 0, bp->bp_size);
return bvl;
}
/*
* cloned bio doesn't own the veclist
*/
- if (!(bio->bi_flags & (1 << BIO_CLONED))) {
+ if (!(bio->bi_flags & (1 << BIO_CLONED)))
kmem_cache_free(bp->bp_cachep, bio->bi_io_vec);
- wake_up_nr(&bp->bp_wait, 1);
- }
bio_pool_put(bio);
}
}
/**
- * bio_clone - duplicate a bio
- * @bio: bio to clone
- * @gfp_mask: allocation priority
+ * __bio_clone - clone a bio
+ * @bio: destination bio
+ * @bio_src: bio to clone
*
- * Duplicate a &bio. Caller will own the returned bio, but not
+ * Clone a &bio. Caller will own the returned bio, but not
* the actual data it points to. Reference count of returned
* bio will be one.
*/
-struct bio *bio_clone(struct bio *bio, int gfp_mask)
+inline void __bio_clone(struct bio *bio, struct bio *bio_src)
{
- struct bio *b = bio_alloc(gfp_mask, 0);
+ bio->bi_io_vec = bio_src->bi_io_vec;
- if (b) {
- b->bi_io_vec = bio->bi_io_vec;
+ bio->bi_sector = bio_src->bi_sector;
+ bio->bi_dev = bio_src->bi_dev;
+ bio->bi_flags |= 1 << BIO_CLONED;
+ bio->bi_rw = bio_src->bi_rw;
- b->bi_sector = bio->bi_sector;
- b->bi_dev = bio->bi_dev;
- b->bi_flags |= 1 << BIO_CLONED;
- b->bi_rw = bio->bi_rw;
+ /*
+ * notes -- maybe just leave bi_idx alone. bi_max has no used
+ * on a cloned bio
+ */
+ bio->bi_vcnt = bio_src->bi_vcnt;
+ bio->bi_idx = bio_src->bi_idx;
+ bio->bi_size = bio_src->bi_size;
+ bio->bi_max = bio_src->bi_max;
+}
- b->bi_vcnt = bio->bi_vcnt;
- b->bi_idx = bio->bi_idx;
- b->bi_size = bio->bi_size;
- b->bi_max = bio->bi_max;
- }
+/**
+ * bio_clone - clone a bio
+ * @bio: bio to clone
+ * @gfp_mask: allocation priority
+ *
+ * Like __bio_clone, only also allocates the returned bio
+ */
+struct bio *bio_clone(struct bio *bio, int gfp_mask)
+{
+ struct bio *b = bio_alloc(gfp_mask, 0);
+
+ if (b)
+ __bio_clone(b, bio);
return b;
}
panic("biovec: can't init slab pools\n");
bp->bp_size = size;
- init_waitqueue_head(&bp->bp_wait);
}
}
EXPORT_SYMBOL(bio_endio);
EXPORT_SYMBOL(bio_init);
EXPORT_SYMBOL(bio_copy);
+EXPORT_SYMBOL(__bio_clone);
EXPORT_SYMBOL(bio_clone);
#define PAGE_BUG(page) BUG()
-#define BUG_ON(condition) \
- do { \
- if (unlikely((long)(condition)))\
- BUG(); \
- } while (0)
-
-#define BUG_ON(condition) \
- do { \
- if (unlikely((int)(condition))) \
- BUG(); \
- } while (0)
-
/* Pure 2^n version of get_order */
extern __inline__ int get_order(unsigned long size)
{
BUG(); \
} while (0)
-#define BUG_ON(condition) \
- do { \
- if (unlikely((int)(condition))) \
- BUG(); \
- } while (0)
-
/* Pure 2^n version of get_order */
static __inline__ int get_order(unsigned long size)
{
extern int bio_endio(struct bio *, int, int);
+extern inline void __bio_clone(struct bio *, struct bio *);
extern struct bio *bio_clone(struct bio *, int);
extern struct bio *bio_copy(struct bio *, int, int);
return rq;
}
-extern inline void elv_add_request(request_queue_t *q, struct request *rq)
-{
- blk_plug_device(q);
- q->elevator.elevator_add_req_fn(q, rq, q->queue_head.prev);
-}
-
+#define __elv_add_request_core(q, rq, where, plug) \
+ do { \
+ if ((plug)) \
+ blk_plug_device((q)); \
+ (q)->elevator.elevator_add_req_fn((q), (rq), (where)); \
+ } while (0)
+
+#define __elv_add_request(q, rq, back, p) \
+ if ((back)) \
+ __elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+ else \
+ __elv_add_request_core((q), (rq), &(q)->queue_head, 0); \
+
+#define elv_add_request(q, rq, back) __elv_add_request((q), (rq), (back), 1)
+
#if defined(MAJOR_NR) || defined(IDE_DRIVER)
#undef DEVICE_ON
#include <linux/linkage.h>
#include <linux/stddef.h>
#include <linux/types.h>
+#include <linux/compiler.h>
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
#endif
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
+#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
-#define USB_CLASS_DATA 10
+#define USB_CLASS_CDC_DATA 0x0a
+#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
#define USB_DIR_OUT 0
#define USB_DIR_IN 0x80
-/*
- * Descriptor types
- */
-#define USB_DT_DEVICE 0x01
-#define USB_DT_CONFIG 0x02
-#define USB_DT_STRING 0x03
-#define USB_DT_INTERFACE 0x04
-#define USB_DT_ENDPOINT 0x05
-
-#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
-#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
-#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
-#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
-
-/*
- * Descriptor sizes per descriptor type
- */
-#define USB_DT_DEVICE_SIZE 18
-#define USB_DT_CONFIG_SIZE 9
-#define USB_DT_INTERFACE_SIZE 9
-#define USB_DT_ENDPOINT_SIZE 7
-#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
-#define USB_DT_HUB_NONVAR_SIZE 7
-#define USB_DT_HID_SIZE 9
-
/*
* Endpoints
*/
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
-/*
- * HID requests
- */
-#define USB_REQ_GET_REPORT 0x01
-#define USB_REQ_GET_IDLE 0x02
-#define USB_REQ_GET_PROTOCOL 0x03
-#define USB_REQ_SET_REPORT 0x09
-#define USB_REQ_SET_IDLE 0x0A
-#define USB_REQ_SET_PROTOCOL 0x0B
-
#ifdef __KERNEL__
__u16 length;
} devrequest __attribute__ ((packed));
-/*
- * USB-status codes:
- * USB_ST* maps to -E* and should go away in the future
- */
-
-#define USB_ST_NOERROR 0
-#define USB_ST_CRC (-EILSEQ)
-#define USB_ST_BITSTUFF (-EPROTO)
-#define USB_ST_NORESPONSE (-ETIMEDOUT) /* device not responding/handshaking */
-#define USB_ST_DATAOVERRUN (-EOVERFLOW)
-#define USB_ST_DATAUNDERRUN (-EREMOTEIO)
-#define USB_ST_BUFFEROVERRUN (-ECOMM)
-#define USB_ST_BUFFERUNDERRUN (-ENOSR)
-#define USB_ST_INTERNALERROR (-EPROTO) /* unknown error */
-#define USB_ST_SHORT_PACKET (-EREMOTEIO)
-#define USB_ST_PARTIAL_ERROR (-EXDEV) /* ISO transfer only partially completed */
-#define USB_ST_URB_KILLED (-ENOENT) /* URB canceled by user */
-#define USB_ST_URB_PENDING (-EINPROGRESS)
-#define USB_ST_REMOVED (-ENODEV) /* device not existing or removed */
-#define USB_ST_TIMEOUT (-ETIMEDOUT) /* communication timed out, also in urb->status**/
-#define USB_ST_NOTSUPPORTED (-ENOSYS)
-#define USB_ST_BANDWIDTH_ERROR (-ENOSPC) /* too much bandwidth used */
-#define USB_ST_URB_INVALID_ERROR (-EINVAL) /* invalid value/transfer type */
-#define USB_ST_URB_REQUEST_ERROR (-ENXIO) /* invalid endpoint */
-#define USB_ST_STALL (-EPIPE) /* pipe stalled, also in urb->status*/
-
/*
* USB device number allocation bitmap. There's one bitmap
* per USB tree.
unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
};
+struct usb_device;
+
+/*-------------------------------------------------------------------------*/
+
/*
- * This is a USB device descriptor.
- *
- * USB device information
+ * Standard USB Descriptor support.
+ * Devices may also have class-specific or vendor-specific descriptors.
*/
-/* Everything but the endpoint maximums are aribtrary */
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE 0x01
+#define USB_DT_CONFIG 0x02
+#define USB_DT_STRING 0x03
+#define USB_DT_INTERFACE 0x04
+#define USB_DT_ENDPOINT 0x05
+#define USB_DT_DEVICE_QUALIFIER 0x06
+#define USB_DT_OTHER_SPEED_CONFIG 0x07
+#define USB_DT_INTERFACE_POWER 0x08
+
+// FIXME should be internal to hub driver
+#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
+#define USB_DT_HUB_NONVAR_SIZE 7
+
+/*
+ * Descriptor sizes per descriptor type
+ */
+#define USB_DT_DEVICE_SIZE 18
+#define USB_DT_CONFIG_SIZE 9
+#define USB_DT_INTERFACE_SIZE 9
+#define USB_DT_ENDPOINT_SIZE 7
+#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
+
+/* most of these maximums are arbitrary */
#define USB_MAXCONFIG 8
#define USB_ALTSETTINGALLOC 4
#define USB_MAXALTSETTING 128 /* Hard limit */
#define USB_MAXINTERFACES 32
-#define USB_MAXENDPOINTS 32
+#define USB_MAXENDPOINTS 32 /* Hard limit */
/* All standard descriptors have these 2 fields in common */
struct usb_descriptor_header {
__u8 bDescriptorType;
} __attribute__ ((packed));
-/* Device descriptor */
+/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bNumConfigurations;
} __attribute__ ((packed));
-/* Endpoint descriptor */
+/* USB_DT_ENDPOINT: Endpoint descriptor */
struct usb_endpoint_descriptor {
__u8 bLength __attribute__ ((packed));
__u8 bDescriptorType __attribute__ ((packed));
__u8 bRefresh __attribute__ ((packed));
__u8 bSynchAddress __attribute__ ((packed));
+ /* the rest is internal to the Linux implementation */
unsigned char *extra; /* Extra descriptors */
int extralen;
};
-/* Interface descriptor */
+/* USB_DT_INTERFACE: Interface descriptor */
struct usb_interface_descriptor {
__u8 bLength __attribute__ ((packed));
__u8 bDescriptorType __attribute__ ((packed));
__u8 bInterfaceProtocol __attribute__ ((packed));
__u8 iInterface __attribute__ ((packed));
+ /* the rest is internal to the Linux implementation */
struct usb_endpoint_descriptor *endpoint;
unsigned char *extra; /* Extra descriptors */
void *private_data;
};
-/* Configuration descriptor information.. */
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different. Highspeed-capable devices can look
+ * different depending on what speed they're currently running. Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
+ */
struct usb_config_descriptor {
__u8 bLength __attribute__ ((packed));
__u8 bDescriptorType __attribute__ ((packed));
__u8 bmAttributes __attribute__ ((packed));
__u8 MaxPower __attribute__ ((packed));
+ /* the rest is internal to the Linux implementation */
struct usb_interface *interface;
unsigned char *extra; /* Extra descriptors */
int extralen;
};
-/* String descriptor */
+/* USB_DT_STRING: String descriptor */
struct usb_string_descriptor {
__u8 bLength;
__u8 bDescriptorType;
- __u16 wData[1];
+ __u16 wData[1]; /* UTF-16LE encoded */
} __attribute__ ((packed));
-struct usb_device;
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u16 bcdUSB;
+ __u8 bDeviceClass;
+ __u8 bDeviceSubClass;
+ __u8 bDeviceProtocol;
+ __u8 bMaxPacketSize0;
+ __u8 bNumConfigurations;
+ __u8 bRESERVED;
+} __attribute__ ((packed));
+
+/* helpers for driver access to descriptors */
+extern struct usb_interface *
+ usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
+extern struct usb_endpoint_descriptor *
+ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
+
+int __usb_get_extra_descriptor(char *buffer, unsigned size,
+ unsigned char type, void **ptr);
+#define usb_get_extra_descriptor(ifpoint,type,ptr)\
+ __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
+ type,(void**)ptr)
+
+/*-------------------------------------------------------------------------*/
/*
* Device table entry for "new style" table-driven USB drivers.
* Terminate the driver's table with an all-zeroes entry.
* Use the flag values to control which fields are compared.
*/
-#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
-#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
-#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
-#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
-#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
-#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
-#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
-#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
-#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
-#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
-
-#define USB_DEVICE_ID_MATCH_DEVICE (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
-#define USB_DEVICE_ID_MATCH_DEV_RANGE (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
-#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
-#define USB_DEVICE_ID_MATCH_DEV_INFO \
- (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
-#define USB_DEVICE_ID_MATCH_INT_INFO \
- (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
-
-/* Some useful macros */
-#define USB_DEVICE(vend,prod) \
- match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor: (vend), idProduct: (prod)
-#define USB_DEVICE_VER(vend,prod,lo,hi) \
- match_flags: USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, idVendor: (vend), idProduct: (prod), bcdDevice_lo: (lo), bcdDevice_hi: (hi)
-#define USB_DEVICE_INFO(cl,sc,pr) \
- match_flags: USB_DEVICE_ID_MATCH_DEV_INFO, bDeviceClass: (cl), bDeviceSubClass: (sc), bDeviceProtocol: (pr)
-#define USB_INTERFACE_INFO(cl,sc,pr) \
- match_flags: USB_DEVICE_ID_MATCH_INT_INFO, bInterfaceClass: (cl), bInterfaceSubClass: (sc), bInterfaceProtocol: (pr)
/**
* struct usb_device_id - identifies USB devices for probing and hotplugging
* device flags.
*
* In most cases, drivers will create a table of device IDs by using
- * the USB_DEVICE() macros designed for that purpose.
+ * USB_DEVICE(), or similar macros designed for that purpose.
* They will then export it to userspace using MODULE_DEVICE_TABLE(),
* and provide it to the USB core through their usb_driver structure.
*
unsigned long driver_info;
};
+/* Some useful macros to use to create struct usb_device_id */
+#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
+#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
+#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
+#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
+#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
+#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
+#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
+#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
+#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
+#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
+
+#define USB_DEVICE_ID_MATCH_DEVICE (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
+#define USB_DEVICE_ID_MATCH_DEV_RANGE (USB_DEVICE_ID_MATCH_DEV_LO | USB_DEVICE_ID_MATCH_DEV_HI)
+#define USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION (USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_DEV_RANGE)
+#define USB_DEVICE_ID_MATCH_DEV_INFO \
+ (USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+#define USB_DEVICE_ID_MATCH_INT_INFO \
+ (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+
+/**
+ * USB_DEVICE - macro used to describe a specific usb device
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device.
+ */
+#define USB_DEVICE(vend,prod) \
+ match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor: (vend), idProduct: (prod)
+/**
+ * USB_DEVICE_VER - macro used to describe a specific usb device with a version range
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @lo: the bcdDevice_lo value
+ * @hi: the bcdDevice_hi value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device, with a version range.
+ */
+#define USB_DEVICE_VER(vend,prod,lo,hi) \
+ match_flags: USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, idVendor: (vend), idProduct: (prod), bcdDevice_lo: (lo), bcdDevice_hi: (hi)
+
+/**
+ * USB_DEVICE_INFO - macro used to describe a class of usb devices
+ * @cl: bDeviceClass value
+ * @sc: bDeviceSubClass value
+ * @pr: bDeviceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific class of devices.
+ */
+#define USB_DEVICE_INFO(cl,sc,pr) \
+ match_flags: USB_DEVICE_ID_MATCH_DEV_INFO, bDeviceClass: (cl), bDeviceSubClass: (sc), bDeviceProtocol: (pr)
+
+/**
+ * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific class of interfaces.
+ */
+#define USB_INTERFACE_INFO(cl,sc,pr) \
+ match_flags: USB_DEVICE_ID_MATCH_INT_INFO, bInterfaceClass: (cl), bInterfaceSubClass: (sc), bInterfaceProtocol: (pr)
+
+/* -------------------------------------------------------------------------- */
+
/**
* struct usb_driver - identifies USB driver to usbcore
* @name: The driver name should be unique among USB drivers
* expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem.
* @id_table: USB drivers use ID table to support hotplugging.
+ * Export this with MODULE_DEVICE_TABLE(usb,...), or use NULL to
+ * say that probe() should be called for any unclaimed interfce.
*
* USB drivers should provide a name, probe() and disconnect() methods,
* and an id_table. Other driver fields are optional.
/* suspend before the bus suspends;
* disconnect or resume when the bus resumes */
- // void (*suspend)(struct usb_device *dev);
- // void (*resume)(struct usb_device *dev);
+ /* void (*suspend)(struct usb_device *dev); */
+ /* void (*resume)(struct usb_device *dev); */
};
-
-/*----------------------------------------------------------------------------*
- * New USB Structures *
- *----------------------------------------------------------------------------*/
+
+/*
+ * use these in module_init()/module_exit()
+ * and don't forget MODULE_DEVICE_TABLE(usb, ...)
+ */
+extern int usb_register(struct usb_driver *);
+extern void usb_deregister(struct usb_driver *);
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * URB support, for asynchronous request completions
+ */
/*
* urb->transfer_flags:
#define USB_ASYNC_UNLINK 0x0008
#define USB_QUEUE_BULK 0x0010
#define USB_NO_FSBR 0x0020
-#define USB_ZERO_PACKET 0x0040 // Finish bulk OUTs always with zero length packet
-#define USB_TIMEOUT_KILLED 0x1000 // only set by HCD!
+#define USB_ZERO_PACKET 0x0040 /* Finish bulk OUTs with short packet */
+#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt needed */
+ /* ... less overhead for QUEUE_BULK */
+#define USB_TIMEOUT_KILLED 0x1000 /* only set by HCD! */
typedef struct
{
unsigned int offset;
- unsigned int length; // expected length
+ unsigned int length; /* expected length */
unsigned int actual_length;
unsigned int status;
} iso_packet_descriptor_t, *piso_packet_descriptor_t;
struct urb;
+
typedef void (*usb_complete_t)(struct urb *);
/**
* to poll for transfers. After the URB has been submitted, the interval
* and start_frame fields reflect how the transfer was actually scheduled.
* The polling interval may be more frequent than requested.
+ * For example, some controllers have a maximum interval of 32 microseconds,
+ * while others support intervals of up to 1024 microseconds.
*
* Isochronous URBs normally use the USB_ISO_ASAP transfer flag, telling
* the host controller to schedule the transfer as soon as bandwidth
* When completion callback is invoked for non-isochronous URBs, the
* actual_length field tells how many bytes were transferred.
*
- * For interrupt and isochronous URBs, the URB provided to the calllback
+ * For interrupt and isochronous URBs, the URB provided to the callback
* function is still "owned" by the USB core subsystem unless the status
* indicates that the URB has been unlinked. Completion handlers should
* not modify such URBs until they have been unlinked.
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
- * Initializes a control urb with the proper information needed to submit it to
- * a device.
+ * Initializes a control urb with the proper information needed to submit
+ * it to a device. This macro is depreciated, the usb_fill_control_urb()
+ * function should be used instead.
*/
#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
* @COMPLETE: pointer to the usb_complete_t function
* @CONTEXT: what to set the urb context to.
*
- * Initializes a bulk urb with the proper information needed to submit it to
- * a device.
+ * Initializes a bulk urb with the proper information needed to submit it
+ * to a device. This macro is depreciated, the usb_fill_bulk_urb()
+ * function should be used instead.
*/
#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
do {\
* @CONTEXT: what to set the urb context to.
* @INTERVAL: what to set the urb interval to.
*
- * Initializes a interrupt urb with the proper information needed to submit it to
- * a device.
+ * Initializes a interrupt urb with the proper information needed to submit
+ * it to a device. This macro is depreciated, the usb_fill_int_urb()
+ * function should be used instead.
*/
#define FILL_INT_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL) \
do {\
(URB)->start_frame=-1;\
} while (0)
-#define FILL_CONTROL_URB_TO(a,aa,b,c,d,e,f,g,h) \
- do {\
- spin_lock_init(&(a)->lock);\
- (a)->dev=aa;\
- (a)->pipe=b;\
- (a)->setup_packet=c;\
- (a)->transfer_buffer=d;\
- (a)->transfer_buffer_length=e;\
- (a)->complete=f;\
- (a)->context=g;\
- (a)->timeout=h;\
- } while (0)
+/**
+ * usb_fill_control_urb - initializes a control urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @setup_packet: pointer to the setup_packet buffer
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a control urb with the proper information needed to submit
+ * it to a device.
+ */
+static inline void usb_fill_control_urb (struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ unsigned char *setup_packet,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete,
+ void *context)
+{
+ spin_lock_init(&urb->lock);
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->setup_packet = setup_packet;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = buffer_length;
+ urb->complete = complete;
+ urb->context = context;
+}
-#define FILL_BULK_URB_TO(a,aa,b,c,d,e,f,g) \
- do {\
- spin_lock_init(&(a)->lock);\
- (a)->dev=aa;\
- (a)->pipe=b;\
- (a)->transfer_buffer=c;\
- (a)->transfer_buffer_length=d;\
- (a)->complete=e;\
- (a)->context=f;\
- (a)->timeout=g;\
- } while (0)
+/**
+ * usb_fill_bulk_urb - macro to help initialize a bulk urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a bulk urb with the proper information needed to submit it
+ * to a device.
+ */
+static inline void usb_fill_bulk_urb (struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete,
+ void *context)
+
+{
+ spin_lock_init(&urb->lock);
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = buffer_length;
+ urb->complete = complete;
+ urb->context = context;
+}
-purb_t usb_alloc_urb(int iso_packets);
-void usb_free_urb (purb_t purb);
-int usb_submit_urb(purb_t purb);
-int usb_unlink_urb(purb_t purb);
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len, int timeout);
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
+/**
+ * usb_fill_int_urb - macro to help initialize a interrupt urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ * @interval: what to set the urb interval to.
+ *
+ * Initializes a interrupt urb with the proper information needed to submit
+ * it to a device.
+ */
+static inline void usb_fill_int_urb (struct urb *urb,
+ struct usb_device *dev,
+ unsigned int pipe,
+ void *transfer_buffer,
+ int buffer_length,
+ usb_complete_t complete,
+ void *context,
+ int interval)
+{
+ spin_lock_init(&urb->lock);
+ urb->dev = dev;
+ urb->pipe = pipe;
+ urb->transfer_buffer = transfer_buffer;
+ urb->transfer_buffer_length = buffer_length;
+ urb->complete = complete;
+ urb->context = context;
+ urb->interval = interval;
+ urb->start_frame = -1;
+}
+
+extern struct urb *usb_alloc_urb(int iso_packets);
+extern void usb_free_urb(struct urb *purb);
+extern int usb_submit_urb(struct urb *purb);
+extern int usb_unlink_urb(struct urb *purb);
/*-------------------------------------------------------------------*
* SYNCHRONOUS CALL SUPPORT *
*-------------------------------------------------------------------*/
-struct usb_api_data
-{
- wait_queue_head_t wqh;
- int done;
- /* void* stuff; */ /* Possible extension later. */
-};
+extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
+ __u8 request, __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout);
+extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+ void *data, int len, int *actual_length,
+ int timeout);
+
+/* wrappers around usb_control_msg() for the most common standard requests */
+extern int usb_clear_halt(struct usb_device *dev, int pipe);
+extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
+ unsigned char descindex, void *buf, int size);
+extern int usb_get_device_descriptor(struct usb_device *dev);
+extern int usb_get_status(struct usb_device *dev,
+ int type, int target, void *data);
+extern int usb_get_string(struct usb_device *dev,
+ unsigned short langid, unsigned char index, void *buf, int size);
+extern int usb_string(struct usb_device *dev, int index,
+ char *buf, size_t size);
+extern int usb_set_configuration(struct usb_device *dev, int configuration);
+extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+
+/*
+ * timeouts, in seconds, used for sending/receiving control messages
+ * they typically complete within a few frames (msec) after they're issued
+ */
+#ifdef CONFIG_USB_LONG_TIMEOUT
+#define USB_CTRL_GET_TIMEOUT 4
+#else
+#define USB_CTRL_GET_TIMEOUT 3
+#endif
+
+#define USB_CTRL_SET_TIMEOUT 3
/* -------------------------------------------------------------------------- */
+/* Host Controller Driver (HCD) support */
+
struct usb_operations {
int (*allocate)(struct usb_device *);
int (*deallocate)(struct usb_device *);
atomic_t refcnt;
};
+extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
+extern void usb_free_bus(struct usb_bus *);
+extern void usb_register_bus(struct usb_bus *);
+extern void usb_deregister_bus(struct usb_bus *);
+
+extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
+extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
+ int bustime, int isoc);
+extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb,
+ int isoc);
+extern int usb_root_hub_string(int id, int serial,
+ char *type, __u8 *data, int len);
+
+/*
+ * Some USB 1.1 bandwidth allocation constants.
+ */
+#define BW_HOST_DELAY 1000L /* nanoseconds */
+#define BW_HUB_LS_SETUP 333L /* nanoseconds */
+ /* 4 full-speed bit times (est.) */
+
+#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
+#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
+#define FRAME_TIME_USECS 1000L
+#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
+
+#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
+ /* Trying not to use worst-case bit-stuffing
+ of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+ /* bytecount = data payload byte count */
+
+#define NS_TO_US(ns) ((ns + 500L) / 1000L)
+ /* convert & round nanoseconds to microseconds */
+
+
+/* -------------------------------------------------------------------------- */
+
+/* Enumeration is only for the hub driver, or HCD virtual root hubs */
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
+ struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+extern int usb_new_device(struct usb_device *dev);
+extern void usb_connect(struct usb_device *dev);
+extern void usb_disconnect(struct usb_device **);
+
+#ifndef _LINUX_HUB_H
+/* exported to hub driver ONLY to support usb_reset_device () */
+extern int usb_get_configuration(struct usb_device *dev);
+extern void usb_set_maxpacket(struct usb_device *dev);
+extern void usb_destroy_configuration(struct usb_device *dev);
+extern int usb_set_address(struct usb_device *dev);
+#endif /* _LINUX_HUB_H */
+
+/* -------------------------------------------------------------------------- */
+
/* This is arbitrary.
* From USB 2.0 spec Table 11-13, offset 7, a hub can
* have up to 255 ports. The most yet reported is 10.
struct usb_device *children[USB_MAXCHILDREN];
};
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
-extern struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
-
-extern int usb_register(struct usb_driver *);
-extern void usb_deregister(struct usb_driver *);
+/* for when layers above USB add new non-USB drivers */
extern void usb_scan_devices(void);
-/* used these for multi-interface device registration */
-extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
-extern int usb_interface_claimed(struct usb_interface *iface);
-extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
-const struct usb_device_id *usb_match_id(struct usb_device *dev,
- struct usb_interface *interface,
- const struct usb_device_id *id);
+/* mostly for devices emulating SCSI over USB */
+extern int usb_reset_device(struct usb_device *dev);
-extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
-extern void usb_free_bus(struct usb_bus *);
-extern void usb_register_bus(struct usb_bus *);
-extern void usb_deregister_bus(struct usb_bus *);
+/* for drivers using iso endpoints */
+extern int usb_get_current_frame_number (struct usb_device *usb_dev);
-extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
-extern void usb_free_dev(struct usb_device *);
+/* drivers must track when they bind to a device's interfaces */
extern void usb_inc_dev_use(struct usb_device *);
#define usb_dec_dev_use usb_free_dev
-extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
-extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc);
-extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc);
-
-extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
-
-extern int usb_root_hub_string(int id, int serial, char *type, __u8 *data, int len);
-extern void usb_connect(struct usb_device *dev);
-extern void usb_disconnect(struct usb_device **);
-
-extern void usb_destroy_configuration(struct usb_device *dev);
+/* used these for multi-interface device registration */
+extern void usb_driver_claim_interface(struct usb_driver *driver,
+ struct usb_interface *iface, void* priv);
+extern int usb_interface_claimed(struct usb_interface *iface);
+extern void usb_driver_release_interface(struct usb_driver *driver,
+ struct usb_interface *iface);
+const struct usb_device_id *usb_match_id(struct usb_device *dev,
+ struct usb_interface *interface,
+ const struct usb_device_id *id);
-int usb_get_current_frame_number (struct usb_device *usb_dev);
+/* -------------------------------------------------------------------------- */
/*
* Calling this entity a "pipe" is glorifying it. A USB pipe
* of the following information:
* - device number (7 bits)
* - endpoint number (4 bits)
- * - current Data0/1 state (1 bit)
+ * - current Data0/1 state (1 bit) [Historical; now gone]
* - direction (1 bit)
* - speed (1 bit)
* - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.]
* - direction: bit 7 (0 = Host-to-Device [Out], 1 = Device-to-Host [In])
* - device: bits 8-14
* - endpoint: bits 15-18
- * - Data0/1: bit 19
+ * - Data0/1: bit 19 [Historical; now gone. ]
* - speed: bit 26 (0 = Full, 1 = Low Speed)
* - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
*
* like full speed devices.
*/
+// FIXME 2.5 get rid of usb_pipeslow(), just use dev->speed
+
#define PIPE_ISOCHRONOUS 0
#define PIPE_INTERRUPT 1
#define PIPE_CONTROL 2
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
-#define usb_pipedata(pipe) (((pipe) >> 19) & 1)
#define usb_pipeslow(pipe) (((pipe) >> 26) & 1)
#define usb_pipetype(pipe) (((pipe) >> 30) & 3)
#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
-/*
- * Send and receive control messages..
- */
-int usb_new_device(struct usb_device *dev);
-int usb_reset_device(struct usb_device *dev);
-int usb_set_address(struct usb_device *dev);
-int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
- unsigned char descindex, void *buf, int size);
-int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char desctype,
- unsigned char descindex, void *buf, int size);
-int usb_get_device_descriptor(struct usb_device *dev);
-int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr);
-int usb_get_status(struct usb_device *dev, int type, int target, void *data);
-int usb_get_configuration(struct usb_device *dev);
-int usb_get_protocol(struct usb_device *dev, int ifnum);
-int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
-int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
-int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
-int usb_set_configuration(struct usb_device *dev, int configuration);
-int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
- unsigned char id, void *buf, int size);
-int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type,
- unsigned char id, void *buf, int size);
-int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
-int usb_clear_halt(struct usb_device *dev, int pipe);
-void usb_set_maxpacket(struct usb_device *dev);
-
-#define usb_get_extra_descriptor(ifpoint,type,ptr)\
- __usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr)
-
-/*
- * Some USB bandwidth allocation constants.
- */
-#define BW_HOST_DELAY 1000L /* nanoseconds */
-#define BW_HUB_LS_SETUP 333L /* nanoseconds */
- /* 4 full-speed bit times (est.) */
-
-#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
-#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
-#define FRAME_TIME_USECS 1000L
-#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
-
-#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
- /* Trying not to use worst-case bit-stuffing
- of (7/6 * 8 * bytecount) = 9.33 * bytecount */
- /* bytecount = data payload byte count */
-
-#define NS_TO_US(ns) ((ns + 500L) / 1000L)
- /* convert & round nanoseconds to microseconds */
+/* -------------------------------------------------------------------------- */
/*
- * Debugging helpers..
+ * Debugging and troubleshooting/diagnostic helpers.
*/
void usb_show_device_descriptor(struct usb_device_descriptor *);
void usb_show_config_descriptor(struct usb_config_descriptor *);
#else
#define dbg(format, arg...) do {} while (0)
#endif
+
#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
+/* -------------------------------------------------------------------------- */
+
/*
* bus and driver list
+ * exported only for usbdevfs (not visible outside usbcore)
*/
extern struct list_head usb_driver_list;
mount("devfs", ".", "devfs", 0, NULL);
retry:
for (p = fs_names; *p; p += strlen(p)+1) {
- err = mount(name,"/root",p,root_mountflags,root_mount_data);
+ int err;
+ err = sys_mount(name,"/root",p,root_mountflags,root_mount_data);
switch (err) {
case 0:
goto done;
{
struct shmid_kernel *shp;
unsigned long addr;
+ unsigned long size;
struct file * file;
int err;
unsigned long flags;
return -EINVAL;
}
flags = MAP_SHARED | MAP_FIXED;
- } else
+ } else {
+ if ((shmflg & SHM_REMAP))
+ return -EINVAL;
+
flags = MAP_SHARED;
+ }
if (shmflg & SHM_RDONLY) {
prot = PROT_READ;
/*
* We cannot rely on the fs check since SYSV IPC does have an
- * aditional creator id...
+ * additional creator id...
*/
shp = shm_lock(shmid);
if(shp == NULL)
return -EACCES;
}
file = shp->shm_file;
+ size = file->f_dentry->d_inode->i_size;
shp->shm_nattch++;
shm_unlock(shmid);
down_write(¤t->mm->mmap_sem);
- user_addr = (void *) do_mmap (file, addr, file->f_dentry->d_inode->i_size, prot, flags, 0);
+ if (addr && !(shmflg & SHM_REMAP)) {
+ user_addr = ERR_PTR(-EINVAL);
+ if (find_vma_intersection(current->mm, addr, addr + size))
+ goto invalid;
+ /*
+ * If shm segment goes below stack, make sure there is some
+ * space left for the stack to grow (at least 4 pages).
+ */
+ if (addr < current->mm->start_stack &&
+ addr > current->mm->start_stack - size - PAGE_SIZE * 5)
+ goto invalid;
+ }
+
+ user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);
+
+invalid:
up_write(¤t->mm->mmap_sem);
down (&shm_ids.sem);
char *vto, *vfrom;
vto = page_address(to->bv_page) + to->bv_offset;
- vfrom = kmap(from->bv_page);
- memcpy(vto, vfrom + from->bv_offset, to->bv_len);
- kunmap(to->bv_page);
+ vfrom = kmap(from->bv_page) + from->bv_offset;
+ memcpy(vto, vfrom, to->bv_len);
+ kunmap(from->bv_page);
}
}