Commit 6406f3a9 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/linux/linux/BK/bleeding-2.5

into kroah.com:/home/linux/linux/BK/gregkh-2.5
parents 828bb5f4 b6f5eb6a
......@@ -255,6 +255,15 @@ MODULE PARAMETERS:
might be necessary if your camera has a custom lens assembly. This has
no effect with video capture devices.
NAME: ov518_color
TYPE: integer (Boolean)
DEFAULT: 0 (off)
DESC: Enable OV518 color support. This is off by default since it doesn't
work most of the time. If you want to try it, you must also load
ov518_decomp with the "nouv=0" parameter. If you get improper colors or
diagonal lines through the image, restart your video app and try again.
Repeat as necessary.
WORKING FEATURES:
o Color streaming/capture at most widths and heights that are multiples of 8.
o Monochrome (use force_palette=1 to enable)
......
......@@ -94,10 +94,11 @@ HandSpring Visor, Palm USB, and Cli
Compaq iPAQ, HP Jornada and Casio EM500 driver
This driver can be used to connect to Compaq iPAQ, HP Jornada and Casio EM500
PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle. It
has been tested only on the Compaq H3135, but is rumoured to work on
with the H3600 and later models as well as the Jornada 548 and 568.
With minor modifications, it may work for other CE based handhelds too.
PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle.
It's very likely that every device supported by ActiveSync USB works with this
driver. The driver supports the Compaq iPAQ, Jornada 548/568 and the Casio
EM500 out of the box. For others, please use module parameters to specify
the product and vendor id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125
The driver presents a serial interface (usually on /dev/ttyUSB0) over
which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
......@@ -105,36 +106,12 @@ Compaq iPAQ, HP Jornada and Casio EM500 driver
significant advantage of using USB is speed - you can get 73 to 113
kbytes/sec for download/upload to the iPAQ.
The driver works intermittently with the usb-uhci driver but quite
reliably with the uhci driver. However, performance is much better
with usb-uhci. It does not seem to work with ohci at all.
You must setup hotplug to invoke pppd as soon as the iPAQ is connected.
A ppp script like the one below should be kept in the file
/etc/hotplug/usb/ipaq Remember to chmod +x. Make sure there are no
options in /etc/ppp/options or ~/.ppprc which conflict with the ones
given below.
#!/bin/bash
MYIP=linux.box.ip
REMOTEIP=ipaq.ip
MYDNS=my.dns.server
killall -9 pppd
/usr/sbin/pppd /dev/ttyUSB0 \
connect "/usr/sbin/chat -v TIMEOUT 60 CLIENT 'CLIENTSERVER\c'" \
nocrtscts local debug passive $MYIP:$REMOTEIP ms-dns $MYDNS noauth \
proxyarp
You must also download and install asyncd from http://synce.sourceforge.net
This is required to emulate keep-alive packets which are exchanged by
ActiveSync and the iPAQ.
On connecting the cable, you should see the usual "Device Connected",
"User Authenticated" messages flash by on your iPAQ. Once connected,
you can use Win CE programs like ftpView, Pocket Outlook from the iPAQ
and xcerdisp, synce utilities from the Linux side. Remember to enable IP
forwarding.
This driver is only one of a set of components required to utilize
the USB connection. Please visit http://synce.sourceforge.net which
contains the necessary packages and a simple step-by-step howto.
Once connected, you can use Win CE programs like ftpView, Pocket Outlook
from the iPAQ and xcerdisp, synce utilities from the Linux side.
To use Pocket IE, follow the instructions given at
http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
......
......@@ -34,7 +34,7 @@ static inline int dev_hotplug(struct device *dev, const char *action)
{
return 0;
}
static int class_hotplug(struct device *dev, const char *action)
static inline int class_hotplug(struct device *dev, const char *action)
{
return 0;
}
......
......@@ -35,6 +35,8 @@
#define BUFFER_SIZE 1024 /* should be enough memory for the env */
#define NUM_ENVP 32 /* number of env pointers */
static char prefix [] = "devices"; /* /sys/devices/... */
static int do_hotplug (struct device *dev, char *argv1, const char *action,
int (* hotplug) (struct device *, char **, int, char *, int))
{
......@@ -72,7 +74,7 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action,
}
dev_length = get_devpath_length (dev);
dev_length += strlen("root");
dev_length += strlen(prefix);
dev_path = kmalloc (dev_length, GFP_KERNEL);
if (!dev_path) {
kfree (buffer);
......@@ -80,7 +82,7 @@ static int do_hotplug (struct device *dev, char *argv1, const char *action,
return -ENOMEM;
}
memset (dev_path, 0x00, dev_length);
strcpy (dev_path, "root");
strcpy (dev_path, prefix);
fill_devpath (dev, dev_path, dev_length);
argv [0] = hotplug_path;
......
......@@ -38,18 +38,6 @@ config USB_DEVICEFS
Most users want to say Y here.
config USB_LONG_TIMEOUT
bool "Long timeout for slow-responding devices (some MGE Ellipse UPSes)"
depends on USB
help
This option makes the standard time out a bit longer. Basically,
some devices are just slow to respond, so this makes usb more
patient. There should be no harm in selecting this, but it is
needed for some MGE Ellipse UPSes.
If you have an MGE Ellipse UPS, or you see timeouts in HID
transactions, say Y; otherwise say N.
config USB_BANDWIDTH
bool "Enforce USB bandwidth allocation (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
......
......@@ -53,6 +53,7 @@ struct async {
struct dev_state *ps;
struct task_struct *task;
unsigned int signr;
unsigned int intf;
void *userbuffer;
void *userurb;
struct urb *urb;
......@@ -273,14 +274,14 @@ static void async_completed(struct urb *urb)
}
}
static void destroy_all_async(struct dev_state *ps)
static void destroy_async (struct dev_state *ps, struct list_head *list)
{
struct async *as;
unsigned long flags;
spin_lock_irqsave(&ps->lock, flags);
while (!list_empty(&ps->async_pending)) {
as = list_entry(ps->async_pending.next, struct async, asynclist);
while (!list_empty(list)) {
as = list_entry(list->next, struct async, asynclist);
list_del_init(&as->asynclist);
spin_unlock_irqrestore(&ps->lock, flags);
/* usb_unlink_urb calls the completion handler with status == -ENOENT */
......@@ -292,6 +293,30 @@ static void destroy_all_async(struct dev_state *ps)
free_async(as);
}
static void destroy_async_on_interface (struct dev_state *ps, unsigned int intf)
{
struct async *as;
struct list_head *p, hitlist;
unsigned long flags;
INIT_LIST_HEAD(&hitlist);
spin_lock_irqsave(&ps->lock, flags);
for (p = ps->async_pending.next; p != &ps->async_pending; ) {
as = list_entry(p, struct async, asynclist);
p = p->next;
if (as->intf == intf)
list_move_tail(&as->asynclist, &hitlist);
}
spin_unlock_irqrestore(&ps->lock, flags);
destroy_async(ps, &hitlist);
}
extern __inline__ void destroy_all_async(struct dev_state *ps)
{
destroy_async(ps, &ps->async_pending);
}
/*
* interface claims are made only at the request of user level code,
* which can also release them (explicitly or by closing files).
......@@ -751,7 +776,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
struct async *as;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int ret, interval = 0;
int ret, interval = 0, intf = -1;
if (copy_from_user(&uurb, arg, sizeof(uurb)))
return -EFAULT;
......@@ -763,9 +788,9 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
return -EINVAL;
if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
return ret;
if ((ret = checkintf(ps, ret)))
if ((intf = findintfep(ps->dev, uurb.endpoint)) < 0)
return intf;
if ((ret = checkintf(ps, intf)))
return ret;
}
switch(uurb.type) {
......@@ -889,6 +914,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
else
as->userbuffer = NULL;
as->signr = uurb.signr;
as->intf = intf;
as->task = current;
if (!(uurb.endpoint & USB_DIR_IN)) {
if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
......@@ -1035,7 +1061,10 @@ static int proc_releaseinterface(struct dev_state *ps, void *arg)
return -EFAULT;
if ((ret = findintfif(ps->dev, intf)) < 0)
return ret;
return releaseintf(ps, intf);
if ((ret = releaseintf(ps, intf)) < 0)
return ret;
destroy_async_on_interface (ps, intf);
return 0;
}
static int proc_ioctl (struct dev_state *ps, void *arg)
......
......@@ -14,7 +14,8 @@
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use pci_pool or pci_alloc_consistent
* - driver buffers, read/written by HC ... single shot DMA mapped
* - driver buffers, read/written by HC ... the hcd glue or the
* device driver provides us with dma addresses
*
* There's also PCI "register" data, which is memory mapped.
* No memory seen by this driver is pagable.
......@@ -41,95 +42,6 @@ static void ohci_hcd_free (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
/* Recover a TD/ED using its collision chain */
static inline void *
dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma)
{
struct hash_t * scan = entry->head;
while (scan && scan->dma != dma)
scan = scan->next;
return scan ? scan->virt : 0;
}
static inline struct td *
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
{
td_dma &= TD_MASK;
return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]),
td_dma);
}
// FIXME: when updating the hashtables this way, mem_flags is unusable...
/* Add a hash entry for a TD/ED; return true on success */
static inline int
hash_add_ed_td (
struct hash_list_t *entry,
void *virt,
dma_addr_t dma,
int mem_flags
)
{
struct hash_t * scan;
scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags);
if (!scan)
return 0;
if (!entry->tail) {
entry->head = entry->tail = scan;
} else {
entry->tail->next = scan;
entry->tail = scan;
}
scan->virt = virt;
scan->dma = dma;
scan->next = NULL;
return 1;
}
static inline int
hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags)
{
return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]),
td, td->td_dma, mem_flags);
}
static inline void
hash_free_ed_td (struct hash_list_t *entry, void *virt)
{
struct hash_t *scan, *prev;
scan = prev = entry->head;
// Find and unlink hash entry
while (scan && scan->virt != virt) {
prev = scan;
scan = scan->next;
}
if (scan) {
if (scan == entry->head) {
if (entry->head == entry->tail)
entry->head = entry->tail = NULL;
else
entry->head = scan->next;
} else if (scan == entry->tail) {
entry->tail = prev;
prev->next = NULL;
} else
prev->next = scan->next;
kfree(scan);
}
}
static inline void
hash_free_td (struct ohci_hcd *hc, struct td * td)
{
hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td);
}
static int ohci_mem_init (struct ohci_hcd *ohci)
{
ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
......@@ -161,6 +73,21 @@ static void ohci_mem_cleanup (struct ohci_hcd *ohci)
}
}
/*-------------------------------------------------------------------------*/
/* ohci "done list" processing needs this mapping */
static inline struct td *
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
{
struct td *td;
td_dma &= TD_MASK;
td = hc->td_hash [TD_HASH_FUNC(td_dma)];
while (td && td->td_dma != td_dma)
td = td->td_hash;
return td;
}
/* TDs ... */
static struct td *
td_alloc (struct ohci_hcd *hc, int mem_flags)
......@@ -170,12 +97,17 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
if (td) {
int hash;
/* in case hc fetches it, make it look dead */
memset (td, 0, sizeof *td);
td->hwNextTD = cpu_to_le32 (dma);
td->td_dma = dma;
/* hash it for later reverse mapping */
if (!hash_add_td (hc, td, mem_flags)) {
pci_pool_free (hc->td_cache, td, dma);
return NULL;
}
hash = TD_HASH_FUNC (dma);
td->td_hash = hc->td_hash [hash];
hc->td_hash [hash] = td;
}
return td;
}
......@@ -183,10 +115,18 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
static void
td_free (struct ohci_hcd *hc, struct td *td)
{
hash_free_td (hc, td);
struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
while (*prev && *prev != td)
prev = &(*prev)->td_hash;
if (*prev)
*prev = td->td_hash;
else
dev_dbg (*hc->hcd.controller, "bad hash for td %p\n", td);
pci_pool_free (hc->td_cache, td, td->td_dma);
}
/*-------------------------------------------------------------------------*/
/* EDs ... */
static struct ed *
......
......@@ -111,6 +111,7 @@ struct td {
/* rest are purely for the driver's use */
__u8 index;
struct ed *ed;
struct td *td_hash; /* dma-->td hashtable */
struct td *next_dl_td;
struct urb *urb;
......@@ -320,23 +321,9 @@ typedef struct urb_priv {
#define URB_DEL 1
/* Hash struct used for TD/ED hashing */
struct hash_t {
void *virt;
dma_addr_t dma;
struct hash_t *next; // chaining for collision cases
};
/* List of TD/ED hash entries */
struct hash_list_t {
struct hash_t *head;
struct hash_t *tail;
};
#define TD_HASH_SIZE 64 /* power'o'two */
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE)
// sizeof (struct td) ~= 64 == 2^6 ...
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
/*
......@@ -373,7 +360,7 @@ struct ohci_hcd {
*/
struct pci_pool *td_cache;
struct pci_pool *ed_cache;
struct hash_list_t td_hash [TD_HASH_SIZE];
struct td *td_hash [TD_HASH_SIZE];
/*
* driver state
......
......@@ -120,15 +120,26 @@ config USB_PWC
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
---help---
Say Y or M here if you want to use one of these Philips USB webcams:
PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
by this driver and never will be.
This driver has an optional plugin, which is distributed as a binary
module only. It contains code that allow you to use higher
resolutions and framerates but may not be distributed as source.
But even without this plugin you can these cams for most
Say Y or M here if you want to use one of these Philips & OEM
webcams:
* Philips PCA645, PCA646
* Philips PCVC675, PCVC680, PCVC690
* Philips PCVC730, PCVC740, PCVC750
* Askey VC010
* Logitech QuickCam Pro 3000, 4000, 'Zoom' and 'Notebook'
* Samsung MPC-C10, MPC-C30
* Creative Webcam 5
* SOTECT Afina Eye
* Visionite VCS-UC300, VCS-UM100
The PCA635, PCVC665 and PCVC720 are not supported by this driver
and never will be, but the 665 and 720 are supported by other
drivers.
This driver has an optional plugin (called PWCX), which is
distributed as a binary module only. It contains code that allow you
to use higher resolutions and framerates but may not be distributed
as source. But even without this plugin you can these cams for most
applications.
See <file:Documentation/usb/philips.txt> for more information and
......
This diff is collapsed.
......@@ -253,6 +253,9 @@
/* Control transfers use up to 4 bytes */
#define OV511_CBUF_SIZE 4
/* Size of usb_make_path() buffer */
#define OV511_USB_PATH_LEN 64
/* Bridge types */
enum {
BRG_UNKNOWN,
......@@ -450,6 +453,7 @@ struct usb_ov511 {
int customid;
char *desc;
unsigned char iface;
char usb_path[OV511_USB_PATH_LEN];
/* Determined by sensor type */
int maxwidth;
......
......@@ -256,8 +256,10 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
memcpy(buf, pEntry->mode, 3);
ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
if (ret < 0)
if (ret < 0) {
Debug("Failed to send video command... %d\n", ret);
return ret;
}
if (pEntry->compressed && pdev->decompressor != NULL)
pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
......@@ -1103,12 +1105,7 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
buf[0] = on_value;
buf[1] = off_value;
return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
SET_STATUS_CTL,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
LED_FORMATTER,
pdev->vcinterface,
&buf, 2, HZ / 2);
return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
}
int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
......@@ -1122,13 +1119,7 @@ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
return 0;
}
ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
GET_STATUS_CTL,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
LED_FORMATTER,
pdev->vcinterface,
&buf, 2, HZ / 2);
ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
if (ret < 0)
return ret;
*on_value = buf[0] * 100;
......@@ -1279,7 +1270,6 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
if (ret < 0)
return ret;
//Debug("pwc_get_dynamic_noise = %d\n", buf);
return buf;
}
......@@ -1363,12 +1353,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case VIDIOCPWCPROBE:
{
struct pwc_probe probe;
struct pwc_probe *probe = arg;
strcpy(probe.name, pdev->vdev->name);
probe.type = pdev->type;
if (copy_to_user(arg, &probe, sizeof(probe)))
ret = -EFAULT;
strcpy(probe->name, pdev->vdev->name);
probe->type = pdev->type;
break;
}
......
This diff is collapsed.
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
(C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
(C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
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
......
/* Linux driver for Philips webcam
Decompression frontend.
(C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
(C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
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
......@@ -77,7 +77,7 @@ int pwc_decompress(struct pwc_device *pdev)
{
struct pwc_frame_buf *fbuf;
int n, line, col, stride;
void *yuv, *image, *dst;
void *yuv, *image;
u16 *src;
u16 *dsty, *dstu, *dstv;
......@@ -114,19 +114,6 @@ int pwc_decompress(struct pwc_device *pdev)
to get the desired output format/size.
*/
switch (pdev->vpalette) {
case VIDEO_PALETTE_YUV420:
/* Calculate byte offsets per line in image & view */
n = (pdev->image.x * 3) / 2;
col = (pdev->view.x * 3) / 2;
/* Offset into image */
dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2;
for (line = 0; line < pdev->image.y; line++) {
memcpy(dst, yuv, n);
yuv += n;
dst += col;
}
break;
case VIDEO_PALETTE_YUV420P:
/*
* We do some byte shuffling here to go from the
......@@ -163,17 +150,20 @@ int pwc_decompress(struct pwc_device *pdev)
dstu += (stride >> 1);
}
break;
default:
Err("Unsupported palette!");
break;
}
}
else {
/* Compressed; the decompressor routines will write the data
in interlaced or planar format immediately.
in planar format immediately.
*/
if (pdev->decompressor)
pdev->decompressor->decompress(
&pdev->image, &pdev->view, &pdev->offset,
yuv, image,
pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0,
1,
pdev->decompress_data, pdev->vbandlength);
else
return -ENXIO; /* No such device or address: missing decompressor */
......
/* (C) 1999-2001 Nemosoft Unv. (webcam@smcc.demon.nl)
/* (C) 1999-2002 Nemosoft Unv. (webcam@smcc.demon.nl)
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
......
......@@ -60,8 +60,8 @@
/* Version block */
#define PWC_MAJOR 8
#define PWC_MINOR 7
#define PWC_VERSION "8.7"
#define PWC_MINOR 9
#define PWC_VERSION "8.9"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
......@@ -130,7 +130,7 @@ struct pwc_device
int vcinterface; /* video control interface */
int valternate; /* alternate interface needed */
int vframes, vsize; /* frames-per-second & size (see PSZ_*) */
int vpalette; /* YUV, RGB24, RGB32, etc */
int vpalette; /* YUV */
int vframe_count; /* received frames */
int vframes_dumped; /* counter for dumped frames */
int vframes_error; /* frames received in error */
......@@ -140,6 +140,7 @@ struct pwc_device
int vbandlength; /* compressed band length; 0 is uncompressed */
char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */
/* The image acquisition requires 3 to 4 steps:
1. data is gathered in short packets from the USB controller
......
This diff is collapsed.
......@@ -185,7 +185,7 @@ tiglusb_read (struct file *filp, char *buf, size_t count, loff_t * f_pos)
pipe = usb_rcvbulkpipe (s->dev, 1);
result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
&bytes_read, HZ / (timeout / 10));
&bytes_read, HZ * 10 / timeout);
if (result == -ETIMEDOUT) { /* NAK */
ret = result;
if (!bytes_read) {
......@@ -242,7 +242,7 @@ tiglusb_write (struct file *filp, const char *buf, size_t count, loff_t * f_pos)
pipe = usb_sndbulkpipe (s->dev, 2);
result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
&bytes_written, HZ / (timeout / 10));
&bytes_written, HZ * 10 / timeout);
if (result == -ETIMEDOUT) { /* NAK */
warn ("tiglusb_write, NAK received.");
......@@ -453,6 +453,8 @@ tiglusb_setup (char *str)
if (ints[0] > 0) {
timeout = ints[1];
}
if (!timeout)
timeout = TIMAXTIME;
return 1;
}
......@@ -494,6 +496,9 @@ tiglusb_init (void)
info (DRIVER_DESC ", " DRIVER_VERSION);
if (!timeout)
timeout = TIMAXTIME;
return 0;
}
......@@ -516,6 +521,6 @@ MODULE_DESCRIPTION (DRIVER_DESC);
MODULE_LICENSE (DRIVER_LICENSE);
MODULE_PARM (timeout, "i");
MODULE_PARM_DESC (timeout, "Timeout (default=1.5 seconds)");
MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
/* --------------------------------------------------------------------- */
......@@ -400,5 +400,10 @@ config USB_SERIAL_OMNINET
The module will be called omninet.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
config USB_EZUSB
bool
depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
default y
endmenu
......@@ -7,6 +7,7 @@
obj-$(CONFIG_USB_SERIAL) += usbserial.o
usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE) += console.o
usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
......@@ -29,9 +30,9 @@ obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
# Objects that export symbols.
export-objs := usb-serial.o
export-objs := usb-serial.o ezusb.o
usbserial-objs := usb-serial.o $(usbserial-obj-y)
usbserial-objs := usb-serial.o generic.o $(usbserial-obj-y)
include $(TOPDIR)/Rules.make
/*
* EZ-USB specific functions used by some of the USB to Serial drivers.
*
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
#ifdef CONFIG_USB_SERIAL_DEBUG
static int debug = 1;
#else
static int debug;
#endif
#include "usb-serial.h"
/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */
#define CPUCS_REG 0x7F92
int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
{
int result;
unsigned char *transfer_buffer;
/* dbg("ezusb_writememory %x, %d", address, length); */
if (!serial->dev) {
dbg("%s - no physical device present, failing.", __FUNCTION__);
return -ENODEV;
}
transfer_buffer = kmalloc (length, GFP_KERNEL);
if (!transfer_buffer) {
err("%s - kmalloc(%d) failed.", __FUNCTION__, length);
return -ENOMEM;
}
memcpy (transfer_buffer, data, length);
result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ);
kfree (transfer_buffer);
return result;
}
int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
{
int response;
dbg("%s - %d", __FUNCTION__, reset_bit);
response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
err("%s- %d failed", __FUNCTION__, reset_bit);
}
return response;
}
EXPORT_SYMBOL(ezusb_writememory);
EXPORT_SYMBOL(ezusb_set_reset);
/*
* USB Serial Converter Generic functions
*
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/usb.h>
#ifdef CONFIG_USB_SERIAL_DEBUG
static int debug = 1;
#else
static int debug;
#endif
#include "usb-serial.h"
#ifdef CONFIG_USB_SERIAL_GENERIC
static __u16 vendor = 0x05f9;
static __u16 product = 0xffff;
MODULE_PARM(vendor, "h");
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
MODULE_PARM(product, "h");
MODULE_PARM_DESC(product, "User specified USB idProduct");
static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */
/* All of the device info needed for the Generic Serial Converter */
struct usb_serial_device_type usb_serial_generic_device = {
.owner = THIS_MODULE,
.name = "Generic",
.id_table = generic_device_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
.shutdown = usb_serial_generic_shutdown,
};
#endif
int usb_serial_generic_register (int _debug)
{
int retval = 0;
debug = _debug;
#ifdef CONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor = vendor;
generic_device_ids[0].idProduct = product;
generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
/* register our generic driver with ourselves */
retval = usb_serial_register (&usb_serial_generic_device);
#endif
return retval;
}
void usb_serial_generic_deregister (void)
{
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
usb_serial_deregister (&usb_serial_generic_device);
#endif
}
int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result = 0;
if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
dbg("%s - port %d", __FUNCTION__, port->number);
/* 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 (port->tty)
port->tty->low_latency = 1;
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
/* Start reading from the device */
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 :
usb_serial_generic_read_bulk_callback),
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
}
return result;
}
static void generic_cleanup (struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->dev) {
/* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out)
usb_unlink_urb (port->write_urb);
if (serial->num_bulk_in)
usb_unlink_urb (port->read_urb);
}
}
void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
{
dbg("%s - port %d", __FUNCTION__, port->number);
generic_cleanup (port);
}
int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
if (count == 0) {
dbg("%s - write request of 0 bytes", __FUNCTION__);
return (0);
}
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS) {
dbg("%s - already writing", __FUNCTION__);
return (0);
}
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
if (from_user) {
if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
return -EFAULT;
}
else {
memcpy (port->write_urb->transfer_buffer, buf, count);
}
usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
/* set up our urb */
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 :
usb_serial_generic_write_bulk_callback), port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else
result = count;
return result;
}
/* no bulk out, so return 0 bytes written */
return (0);
}
int usb_serial_generic_write_room (struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
int room = 0;
dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->num_bulk_out) {
if (port->write_urb->status != -EINPROGRESS)
room = port->bulk_out_size;
}
dbg("%s - returns %d", __FUNCTION__, room);
return (room);
}
int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
int chars = 0;
dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->num_bulk_out) {
if (port->write_urb->status == -EINPROGRESS)
chars = port->write_urb->transfer_buffer_length;
}
dbg("%s - returns %d", __FUNCTION__, chars);
return (chars);
}
void usb_serial_generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
if (!serial) {
dbg("%s - bad serial pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
return;
}
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
tty = port->tty;
if (tty && urb->actual_length) {
for (i = 0; i < urb->actual_length ; ++i) {
/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
tty_flip_buffer_push(tty);
}
/* this doesn't actually push the data through unless tty->low_latency is set */
tty_insert_flip_char(tty, data[i], 0);
}
tty_flip_buffer_push(tty);
}
/* Continue trying to always read */
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 :
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
}
void usb_serial_generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg("%s - port %d", __FUNCTION__, port->number);
if (!serial) {
dbg("%s - bad serial pointer, exiting", __FUNCTION__);
return;
}
if (urb->status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
return;
}
usb_serial_port_softint((void *)port);
schedule_work(&port->work);
}
void usb_serial_generic_shutdown (struct usb_serial *serial)
{
int i;
dbg("%s", __FUNCTION__);
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
generic_cleanup (&serial->port[i]);
}
}
......@@ -9,6 +9,10 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* (26/11/2002) ganesh
* Added insmod options to specify product and vendor id.
* Use modprobe ipaq vendor=0xfoo product=0xbar
*
* (26/7/2002) ganesh
* Fixed up broken error handling in ipaq_open. Retry the "kickstart"
* packet much harder - this drastically reduces connection failures.
......@@ -63,10 +67,13 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.2"
#define DRIVER_VERSION "v0.4"
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
#define DRIVER_DESC "USB Compaq iPAQ, HP Jornada, Casio EM500 driver"
static int product, vendor;
/* Function prototypes for an ipaq */
static int ipaq_open (struct usb_serial_port *port, struct file *filp);
static void ipaq_close (struct usb_serial_port *port, struct file *filp);
......@@ -85,6 +92,8 @@ static void ipaq_destroy_lists(struct usb_serial_port *port);
static struct usb_device_id ipaq_id_table [] = {
/* The first entry is a placeholder for the insmod-specified device */
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
......@@ -521,9 +530,14 @@ static void ipaq_shutdown(struct usb_serial *serial)
static int __init ipaq_init(void)
{
spin_lock_init(&write_list_lock);
usb_serial_register(&ipaq_device);
usb_register(&ipaq_driver);
info(DRIVER_DESC " " DRIVER_VERSION);
if (vendor) {
ipaq_id_table[0].idVendor = vendor;
ipaq_id_table[0].idProduct = product;
}
usb_register(&ipaq_driver);
return 0;
}
......@@ -546,3 +560,8 @@ MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
MODULE_PARM(vendor, "h");
MODULE_PARM_DESC(vendor, "User specified USB idVendor");
MODULE_PARM(product, "h");
MODULE_PARM_DESC(product, "User specified USB idProduct");
......@@ -346,7 +346,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
if (this_urb->status == -EINPROGRESS) {
if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
break;
if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ)
if (time_before(jiffies, p_priv->tx_start_time[flip] + 10 * HZ))
break;
this_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(this_urb);
......
This diff is collapsed.
......@@ -237,24 +237,8 @@ extern void usb_serial_port_softint(void *private);
extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
extern void usb_serial_disconnect(struct usb_interface *iface);
/* determine if we should include the EzUSB loader functions */
#undef USES_EZUSB_FUNCTIONS
#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE)
#define USES_EZUSB_FUNCTIONS
#endif
#if defined(CONFIG_USB_SERIAL_XIRCOM) || defined(CONFIG_USB_SERIAL_XIRCOM_MODULE)
#define USES_EZUSB_FUNCTIONS
#endif
#if defined(CONFIG_USB_SERIAL_KEYSPAN) || defined(CONFIG_USB_SERIAL_KEYSPAN_MODULE)
#define USES_EZUSB_FUNCTIONS
#endif
#if defined(CONFIG_USB_SERIAL_WHITEHEAT) || defined(CONFIG_USB_SERIAL_WHITEHEAT_MODULE)
#define USES_EZUSB_FUNCTIONS
#endif
#ifdef USES_EZUSB_FUNCTIONS
extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
#endif
/* USB Serial console functions */
#ifdef CONFIG_USB_SERIAL_CONSOLE
......@@ -265,10 +249,20 @@ static inline void usb_serial_console_init (int debug, int minor) { }
static inline void usb_serial_console_exit (void) { }
#endif
/* Functions needed by the usb serial console code */
/* Functions needed by other parts of the usbserial core */
extern struct usb_serial *usb_serial_get_by_minor (unsigned int minor);
extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
extern int usb_serial_generic_write_room (struct usb_serial_port *port);
extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
extern void usb_serial_generic_write_bulk_callback (struct urb *urb);
extern void usb_serial_generic_shutdown (struct usb_serial *serial);
extern int usb_serial_generic_register (int debug);
extern void usb_serial_generic_deregister (void);
extern struct usb_serial_device_type usb_serial_generic_device;
/* Inline functions to check the sanity of a pointer that is passed to us */
static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
......
......@@ -186,6 +186,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
......@@ -209,6 +210,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_M130_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_T_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_TUNGSTEN_Z_ID) },
{ USB_DEVICE(PALM_VENDOR_ID, PALM_ZIRE_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_3_5_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
......
......@@ -28,6 +28,7 @@
#define PALM_M125_ID 0x0040
#define PALM_M130_ID 0x0050
#define PALM_TUNGSTEN_T_ID 0x0060
#define PALM_TUNGSTEN_Z_ID 0x0031
#define PALM_ZIRE_ID 0x0070
#define SONY_VENDOR_ID 0x054C
......
This diff is collapsed.
......@@ -901,14 +901,11 @@ 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
* USB identifies 5 second timeouts, maybe more in a few cases, and a few
* slow devices (like some MGE Ellipse UPSes) actually push that limit.
*/
#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
#define USB_CTRL_GET_TIMEOUT 5
#define USB_CTRL_SET_TIMEOUT 5
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment