Commit da050bdb authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/usb-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 9e0ce90e 9b4b2fa2
......@@ -9,28 +9,32 @@
Index
=====
1. Copyright
2. License
3. Overview
4. Module dependencies
5. Module loading
6. Module parameters
7. Optional device control through "sysfs"
8. Supported devices
9. How to add support for new image sensors
10. Notes for V4L2 application developers
11. Contact information
12. Credits
2. Disclaimer
3. License
4. Overview
5. Driver installation
6. Module loading
7. Module parameters
8. Optional device control through "sysfs"
9. Supported devices
10. How to add support for new image sensors
11. Notes for V4L2 application developers
12. Contact information
13. Credits
1. Copyright
============
Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it>
2. Disclaimer
=============
SONiX is a trademark of SONiX Technology Company Limited, inc.
This driver is not sponsored or developed by SONiX.
This software is not sponsored or developed by SONiX.
2. License
3. License
==========
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
......@@ -47,29 +51,52 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3. Overview
4. Overview
===========
This driver attempts to support the video and audio streaming capabilities of
the devices mounting the SONiX SN9C101, SN9C102 and SN9C103 (or SUI-102) PC
Camera Controllers.
- It's worth to note that SONiX has never collaborated with me during the
It's worth to note that SONiX has never collaborated with the author during the
development of this project, despite several requests for enough detailed
specifications of the register tables, compression engine and video data format
of the above chips -
Up to 64 cameras can be handled at the same time. They can be connected and
disconnected from the host many times without turning off the computer, if
your system supports hotplugging.
of the above chips.
The driver relies on the Video4Linux2 and USB core modules. It has been
designed to run properly on SMP systems as well.
The latest version of the SN9C10x driver can be found at the following URL:
http://go.lamarinapunto.com/
4. Module dependencies
http://www.linux-projects.org/
Some of the features of the driver are:
- full compliance with the Video4Linux2 API (see also "Notes for V4L2
application developers" paragraph);
- available mmap or read/poll methods for video streaming through isochronous
data transfers;
- automatic detection of image sensor;
- support for any window resolutions and optional panning within the maximum
pixel area of image sensor;
- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
directions (see "Notes for V4L2 application developers" paragraph);
- two different video formats for uncompressed or compressed data (see also
"Notes for V4L2 application developers" paragraph);
- full support for the capabilities of many of the possible image sensors that
can be connected to the SN9C10x bridges, including, for istance, red, green,
blue and global gain adjustments and exposure (see "Supported devices"
paragraph for details);
- use of default color settings for sunlight conditions;
- dynamic I/O interface for both SN9C10x and image sensor control (see
"Optional device control through 'sysfs'" paragraph);
- dynamic driver control thanks to various module parameters (see "Module
parameters" paragraph);
- up to 64 cameras can be handled at the same time; they can be connected and
disconnected from the host many times without turning off the computer, if
your system supports hotplugging;
- no known bugs.
5. Module dependencies
======================
For it to work properly, the driver needs kernel support for Video4Linux and
USB.
......@@ -101,7 +128,7 @@ And finally:
CONFIG_USB_SN9C102=m
5. Module loading
6. Module loading
=================
To use the driver, it is necessary to load the "sn9c102" module into memory
after every other module required: "videodev", "usbcore" and, depending on
......@@ -109,7 +136,6 @@ the USB host controller you have, "ehci-hcd", "uhci-hcd" or "ohci-hcd".
Loading can be done as shown below:
[root@localhost home]# modprobe usbcore
[root@localhost home]# modprobe sn9c102
At this point the devices should be recognized. You can invoke "dmesg" to
......@@ -118,7 +144,7 @@ analyze kernel messages and verify that the loading process has gone well:
[user@localhost home]$ dmesg
6. Module parameters
7. Module parameters
====================
Module parameters are listed below:
-------------------------------------------------------------------------------
......@@ -144,12 +170,14 @@ Description: Debugging information level, from 0 to 3:
2 = significant informations
3 = more verbose messages
Level 3 is useful for testing only, when only one device
is used.
is used. It also shows some more informations about the
hardware being detected. This parameter can be changed at
runtime thanks to the /sys filesystem.
Default: 2
-------------------------------------------------------------------------------
7. Optional device control through "sysfs"
8. Optional device control through "sysfs"
==========================================
It is possible to read and write both the SN9C10x and the image sensor
registers by using the "sysfs" filesystem interface.
......@@ -191,10 +219,10 @@ Note that the SN9C10x always returns 0 when some of its registers are read.
To avoid race conditions, all the I/O accesses to the files are serialized.
8. Supported devices
9. Supported devices
====================
- I won't mention any of the names of the companies as well as their products
here. They have never collaborated with me, so no advertising -
None of the names of the companies as well as their products will be mentioned
here. They have never collaborated with the author, so no advertising.
From the point of view of a driver, what unambiguously identify a device are
its vendor and product USB identifiers. Below is a list of known identifiers of
......@@ -241,7 +269,7 @@ Vendor ID Product ID
0x0c45 0x60bc
0x0c45 0x60be
The list above does NOT imply that all those devices work with this driver: up
The list above does not imply that all those devices work with this driver: up
until now only the ones that mount the following image sensors are supported;
kernel messages will always tell you whether this is the case:
......@@ -259,16 +287,16 @@ If you think your camera is based on the above hardware and is not actually
listed in the above table, you may try to add the specific USB VendorID and
ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h";
then compile, load the module again and look at the kernel output.
If this works, please send an email to me reporting the kernel messages, so
that I can add a new entry in the list of supported devices.
If this works, please send an email to the author reporting the kernel
messages, so that a new entry in the list of supported devices can be added.
Donations of new models for further testing and support would be much
appreciated. I won't add official support for hardware that I don't actually
have.
appreciated. Non-available hardware won't be supported by the author of this
driver.
9. How to add support for new image sensors
===========================================
10. How to add support for new image sensors
============================================
It should be easy to write code for new sensors by using the small API that I
have created for this purpose, which is present in "sn9c102_sensor.h"
(documentation is included there). As an example, have a look at the code in
......@@ -278,7 +306,7 @@ At the moment, possible unsupported image sensors are: HV7131x series (VGA),
MI03x series (VGA), OV7620 (VGA), OV7630 (VGA), CIS-VF10 (VGA).
10. Notes for V4L2 application developers
11. Notes for V4L2 application developers
=========================================
This driver follows the V4L2 API specifications. In particular, it enforces two
rules:
......@@ -301,8 +329,18 @@ factor can be chosen arbitrarily by the "negotiation" of the "source" and
that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
scaling factor is restored to 1.
This driver supports two different video formats: the first one is the "8-bit
Sequential Bayer" format and can be used to obtain uncompressed video data
from the device through the current I/O method, while the second one provides
"raw" compressed video data (without the initial and final frame headers). The
compression quality may vary from 0 to 1 and can be selected or queried thanks
to the VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum
flexibility, the default active video format depends on how the image sensor
being used is initialized (as described in the documentation of the API for the
image sensors supplied by this driver).
11. Contact information
12. Contact information
=======================
I may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
......@@ -311,7 +349,7 @@ My public 1024-bit key should be available at any keyserver; the fingerprint
is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
12. Credits
13. Credits
===========
I would thank the following persons:
......
......@@ -71,12 +71,14 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
if (pci_enable_device (dev) < 0)
return -ENODEV;
dev->current_state = 0;
dev->dev.power.power_state = 0;
if (!dev->irq) {
dev_err (&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev));
return -ENODEV;
retval = -ENODEV;
goto done;
}
if (driver->flags & HCD_MEMORY) { // EHCI, OHCI
......@@ -85,7 +87,8 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
len = pci_resource_len (dev, 0);
if (!request_mem_region (resource, len, driver->description)) {
dev_dbg (&dev->dev, "controller already in use\n");
return -EBUSY;
retval = -EBUSY;
goto done;
}
base = ioremap_nocache (resource, len);
if (base == NULL) {
......@@ -95,7 +98,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
release_mem_region (resource, len);
dev_err (&dev->dev, "init %s fail, %d\n",
pci_name(dev), retval);
return retval;
goto done;
}
} else { // UHCI
......@@ -112,7 +115,8 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
}
if (region == PCI_ROM_RESOURCE) {
dev_dbg (&dev->dev, "no i/o regions available\n");
return -EBUSY;
retval = -EBUSY;
goto done;
}
base = (void __iomem *) resource;
}
......@@ -132,7 +136,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
release_region (resource, len);
dev_err (&dev->dev, "init %s fail, %d\n",
pci_name(dev), retval);
return retval;
goto done;
}
}
// hcd zeroed everything
......@@ -200,6 +204,9 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
usb_hcd_pci_remove (dev);
}
done:
if (retval != 0)
pci_disable_device (dev);
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_probe);
......@@ -297,82 +304,78 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
state = 4;
switch (hcd->state) {
case USB_STATE_HALT:
dev_dbg (hcd->self.controller, "halted; hcd not suspended\n");
break;
case HCD_STATE_SUSPENDED:
dev_dbg (hcd->self.controller, "PCI %s --> %s\n",
pci_state(dev->current_state),
pci_state(has_pci_pm ? state : 0));
if (state > 3)
state = 3;
if (state == dev->current_state)
break;
else if (state < dev->current_state)
retval = -EIO;
else if (has_pci_pm)
retval = pci_set_power_state (dev, state);
if (retval == 0)
dev->dev.power.power_state = state;
else
dev_dbg (hcd->self.controller,
"re-suspend fail, %d\n", retval);
break;
default:
/* entry if root hub wasn't yet suspended ... from sysfs,
* without autosuspend, or if USB_SUSPEND isn't configured.
*/
case USB_STATE_RUNNING:
hcd->state = USB_STATE_QUIESCING;
retval = hcd->driver->suspend (hcd, state);
if (retval)
if (retval) {
dev_dbg (hcd->self.controller,
"suspend fail, retval %d\n",
retval);
else {
hcd->state = HCD_STATE_SUSPENDED;
pci_save_state (dev);
break;
}
hcd->state = HCD_STATE_SUSPENDED;
/* FALLTHROUGH */
/* entry with CONFIG_USB_SUSPEND, or hcds that autosuspend: the
* controller and/or root hub will already have been suspended,
* but it won't be ready for a PCI resume call.
*
* FIXME only CONFIG_USB_SUSPEND guarantees hub_suspend() will
* have been called, otherwise root hub timers still run ...
*/
case HCD_STATE_SUSPENDED:
if (state <= dev->current_state)
break;
/* no DMA or IRQs except in D0 */
/* no DMA or IRQs except in D0 */
if (!dev->current_state) {
pci_save_state (dev);
pci_disable_device (dev);
free_irq (hcd->irq, hcd);
if (has_pci_pm) {
retval = pci_set_power_state (dev, state);
/* POLICY: ignore D1/D2/D3hot differences;
* we know D3hot will always work.
*/
if (retval < 0 && state < 3) {
retval = pci_set_power_state (dev, 3);
if (retval == 0)
state = 3;
}
if (retval == 0) {
dev->dev.power.power_state = state;
}
if (!has_pci_pm) {
dev_dbg (hcd->self.controller, "--> PCI D0/legacy\n");
break;
}
/* POLICY: ignore D1/D2/D3hot differences;
* we know D3hot will always work.
*/
retval = pci_set_power_state (dev, state);
if (retval < 0 && state < 3) {
retval = pci_set_power_state (dev, 3);
if (retval == 0)
state = 3;
}
if (retval == 0) {
dev_dbg (hcd->self.controller, "--> PCI %s\n",
pci_state(dev->current_state));
#ifdef CONFIG_USB_SUSPEND
pci_enable_wake (dev, state,
hcd->remote_wakeup);
pci_enable_wake (dev, 4,
hcd->remote_wakeup);
pci_enable_wake (dev, state, hcd->remote_wakeup);
pci_enable_wake (dev, 4, hcd->remote_wakeup);
#endif
}
} else {
if (state > 3)
state = 3;
dev->dev.power.power_state = state;
}
if (retval < 0) {
dev_dbg (&dev->dev,
"PCI %s suspend fail, %d\n",
pci_state(state),
retval);
(void) usb_hcd_pci_resume (dev);
} else {
dev_dbg(hcd->self.controller,
"suspended to PCI %s%s\n",
pci_state(dev->current_state),
has_pci_pm ? "" : " (legacy)");
}
} else if (retval < 0) {
dev_dbg (&dev->dev, "PCI %s suspend fail, %d\n",
pci_state(state), retval);
(void) usb_hcd_pci_resume (dev);
break;
}
break;
default:
dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
hcd->state);
retval = -EINVAL;
break;
}
/* update power_state **ONLY** to make sysfs happier */
if (retval == 0)
dev->dev.power.power_state = state;
return retval;
}
EXPORT_SYMBOL (usb_hcd_pci_suspend);
......@@ -390,6 +393,11 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int has_pci_pm;
hcd = pci_get_drvdata(dev);
if (hcd->state != HCD_STATE_SUSPENDED) {
dev_dbg (hcd->self.controller,
"can't resume, not suspended!\n");
return 0;
}
has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
/* D3cold resume isn't usually reported this way... */
......@@ -397,11 +405,6 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
pci_state(dev->current_state),
has_pci_pm ? "" : " (legacy)");
if (hcd->state != HCD_STATE_SUSPENDED) {
dev_dbg (hcd->self.controller,
"can't resume, not suspended!\n");
return -EL3HLT;
}
hcd->state = USB_STATE_RESUMING;
if (has_pci_pm)
......
......@@ -479,6 +479,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
/*
* Root Hub interrupt transfers are synthesized with a timer.
* Completions are called in_interrupt() but not in_irq().
*
* Note: some root hubs (including common UHCI based designs) can't
* correctly issue port change IRQs. They're the ones that _need_ a
* timer; most other root hubs don't. Some systems could save a
* lot of battery power by eliminating these root hub timer IRQs.
*/
static void rh_report_status (unsigned long ptr);
......@@ -488,10 +493,7 @@ static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb)
int len = 1 + (urb->dev->maxchild / 8);
/* rh_timer protected by hcd_data_lock */
if (hcd->rh_timer.data
|| urb->status != -EINPROGRESS
|| urb->transfer_buffer_length < len
|| !HCD_IS_RUNNING (hcd->state)) {
if (hcd->rh_timer.data || urb->transfer_buffer_length < len) {
dev_dbg (hcd->self.controller,
"not queuing rh status urb, stat %d\n",
urb->status);
......@@ -530,19 +532,19 @@ static void rh_report_status (unsigned long ptr)
return;
}
if (!HCD_IS_SUSPENDED (hcd->state))
length = hcd->driver->hub_status_data (
hcd, urb->transfer_buffer);
/* complete the status urb, or retrigger the timer */
spin_lock (&hcd_data_lock);
if (length > 0) {
hcd->rh_timer.data = 0;
urb->actual_length = length;
urb->status = 0;
urb->hcpriv = NULL;
} else if (!urb->dev->dev.power.power_state)
mod_timer (&hcd->rh_timer, jiffies + HZ/4);
if (urb->dev->state == USB_STATE_CONFIGURED) {
length = hcd->driver->hub_status_data (
hcd, urb->transfer_buffer);
if (length > 0) {
hcd->rh_timer.data = 0;
urb->actual_length = length;
urb->status = 0;
urb->hcpriv = NULL;
} else
mod_timer (&hcd->rh_timer, jiffies + HZ/4);
}
spin_unlock (&hcd_data_lock);
spin_unlock (&urb->lock);
......@@ -1103,13 +1105,17 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
spin_lock_irqsave (&hcd_data_lock, flags);
if (unlikely (urb->reject))
status = -EPERM;
else if (HCD_IS_RUNNING (hcd->state) &&
hcd->state != USB_STATE_QUIESCING) {
else switch (hcd->state) {
case USB_STATE_RUNNING:
case USB_STATE_RESUMING:
usb_get_dev (urb->dev);
list_add_tail (&urb->urb_list, &dev->urb_list);
status = 0;
} else
break;
default:
status = -ESHUTDOWN;
break;
}
spin_unlock_irqrestore (&hcd_data_lock, flags);
if (status) {
INIT_LIST_HEAD (&urb->urb_list);
......
......@@ -1373,7 +1373,10 @@ static int hub_port_reset(struct usb_device *hdev, int port,
status = hub_port_wait_reset(hdev, port, udev, delay);
/* return on disconnect or reset */
if (status == -ENOTCONN || status == 0) {
switch (status) {
case 0:
case -ENOTCONN:
case -ENODEV:
clear_port_feature(hdev,
port + 1, USB_PORT_FEAT_C_RESET);
/* FIXME need disconnect() for NOTATTACHED device */
......@@ -1524,7 +1527,7 @@ int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
if (port < 0)
return port;
if (udev->dev.power.power_state
if (udev->state == USB_STATE_SUSPENDED
|| udev->state == USB_STATE_NOTATTACHED) {
return 0;
}
......@@ -1595,16 +1598,16 @@ int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
*/
if (!udev->parent) {
struct usb_bus *bus = udev->bus;
if (bus && bus->op->hub_suspend)
if (bus && bus->op->hub_suspend) {
status = bus->op->hub_suspend (bus);
else
if (status == 0)
usb_set_device_state(udev,
USB_STATE_SUSPENDED);
} else
status = -EOPNOTSUPP;
} else
status = hub_port_suspend(udev->parent, port);
if (status == 0)
udev->dev.power.power_state = PM_SUSPEND_MEM;
up(&udev->serialize);
return status;
}
EXPORT_SYMBOL(__usb_suspend_device);
......@@ -1652,7 +1655,6 @@ static int finish_port_resume(struct usb_device *udev)
/* caller owns the udev device lock */
dev_dbg(&udev->dev, "usb resume\n");
udev->dev.power.power_state = PM_SUSPEND_ON;
/* usb ch9 identifies four variants of SUSPENDED, based on what
* state the device resumes to. Linux currently won't see the
......@@ -1809,14 +1811,15 @@ int usb_resume_device(struct usb_device *udev)
*/
if (!udev->parent) {
struct usb_bus *bus = udev->bus;
if (bus && bus->op->hub_resume)
if (bus && bus->op->hub_resume) {
status = bus->op->hub_resume (bus);
else
} else
status = -EOPNOTSUPP;
if (status == 0) {
/* TRSMRCY = 10 msec */
msleep(10);
status = hub_resume (bus->root_hub
usb_set_device_state (udev, USB_STATE_CONFIGURED);
status = hub_resume (udev
->actconfig->interface[0]);
}
} else if (udev->state == USB_STATE_SUSPENDED) {
......@@ -1824,7 +1827,6 @@ int usb_resume_device(struct usb_device *udev)
status = hub_port_resume(udev->parent, port);
} else {
status = 0;
udev->dev.power.power_state = PM_SUSPEND_ON;
}
if (status < 0) {
dev_dbg(&udev->dev, "can't resume, status %d\n",
......
......@@ -1395,10 +1395,6 @@ static int usb_generic_suspend(struct device *dev, u32 state)
struct usb_interface *intf;
struct usb_driver *driver;
/* there's only one USB suspend state */
if (dev->power.power_state)
return 0;
if (dev->driver == &usb_generic_driver)
return usb_suspend_device (to_usb_device(dev), state);
......@@ -1409,6 +1405,10 @@ static int usb_generic_suspend(struct device *dev, u32 state)
intf = to_usb_interface(dev);
driver = to_usb_driver(dev->driver);
/* there's only one USB suspend state */
if (intf->dev.power.power_state)
return 0;
if (driver->suspend)
return driver->suspend(intf, state);
return 0;
......
......@@ -3579,7 +3579,7 @@ static ssize_t show_file(struct device *dev, char *buf)
}
ssize_t store_ro(struct device *dev, const char *buf, size_t count)
static ssize_t store_ro(struct device *dev, const char *buf, size_t count)
{
ssize_t rc = count;
struct lun *curlun = dev_to_lun(dev);
......@@ -3603,7 +3603,7 @@ ssize_t store_ro(struct device *dev, const char *buf, size_t count)
return rc;
}
ssize_t store_file(struct device *dev, const char *buf, size_t count)
static ssize_t store_file(struct device *dev, const char *buf, size_t count)
{
struct lun *curlun = dev_to_lun(dev);
struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
......
......@@ -1275,7 +1275,7 @@ int rndis_rm_hdr (u8 *buf, u32 *length)
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
void *data)
{
char *out = page;
......@@ -1320,7 +1320,7 @@ int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
return len;
}
int rndis_proc_write (struct file *file, const char __user *buffer,
static int rndis_proc_write (struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
rndis_params *p = data;
......
......@@ -172,13 +172,6 @@ static int handshake (void __iomem *ptr, u32 mask, u32 done, int usec)
return -ETIMEDOUT;
}
/*
* hc states include: unknown, halted, ready, running
* transitional states are messy just now
* trying to avoid "running" unless urbs are active
* a "ready" hc can be finishing prefetched work
*/
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
......@@ -480,8 +473,8 @@ static int ehci_start (struct usb_hcd *hcd)
ehci->async->hw_qtd_next = EHCI_LIST_END;
ehci->async->qh_state = QH_STATE_LINKED;
ehci->async->hw_alt_next = QTD_NEXT (ehci->async->dummy->qtd_dma);
writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
}
writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
/*
* hcc_params controls whether ehci->regs->segment must (!!!)
......@@ -540,7 +533,6 @@ static int ehci_start (struct usb_hcd *hcd)
}
udev->speed = USB_SPEED_HIGH;
udev->state = first ? USB_STATE_ATTACHED : USB_STATE_CONFIGURED;
udev->dev.power.power_state = PM_SUSPEND_ON;
/*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
......@@ -663,20 +655,19 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
if (hcd->self.root_hub->dev.power.power_state)
return 0;
while (time_before (jiffies, ehci->next_statechange))
if (time_before (jiffies, ehci->next_statechange))
msleep (100);
#ifdef CONFIG_USB_SUSPEND
(void) usb_suspend_device (hcd->self.root_hub, state);
#else
/* FIXME lock root hub */
usb_lock_device (hcd->self.root_hub);
(void) ehci_hub_suspend (hcd);
usb_unlock_device (hcd->self.root_hub);
#endif
// save (PCI) FLADJ in case of Vaux power loss
// ... we'd only use it to handle clock skew
return 0;
}
......@@ -687,10 +678,11 @@ static int ehci_resume (struct usb_hcd *hcd)
unsigned port;
struct usb_device *root = hcd->self.root_hub;
int retval = -EINVAL;
int powerup = 0;
// maybe restore (PCI) FLADJ
while (time_before (jiffies, ehci->next_statechange))
if (time_before (jiffies, ehci->next_statechange))
msleep (100);
/* If any port is suspended, we know we can/must resume the HC. */
......@@ -704,6 +696,8 @@ static int ehci_resume (struct usb_hcd *hcd)
up (&hcd->self.root_hub->serialize);
break;
}
if ((status & PORT_POWER) == 0)
powerup = 1;
if (!root->children [port])
continue;
dbg_port (ehci, __FUNCTION__, port + 1, status);
......@@ -728,9 +722,20 @@ static int ehci_resume (struct usb_hcd *hcd)
/* restart; khubd will disconnect devices */
retval = ehci_start (hcd);
/* here we "know" root ports should always stay powered;
* but some controllers may lost all power.
*/
if (powerup) {
ehci_dbg (ehci, "...powerup ports...\n");
for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
(void) ehci_hub_control(hcd,
SetPortFeature, USB_PORT_FEAT_POWER,
port--, NULL, 0);
msleep(20);
}
}
if (retval == 0)
hcd->self.controller->power.power_state = 0;
return retval;
}
......
......@@ -33,24 +33,19 @@
static int ehci_hub_suspend (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
struct usb_device *root = hcd_to_bus (&ehci->hcd)->root_hub;
int port;
if (root->dev.power.power_state != 0)
return 0;
if (time_before (jiffies, ehci->next_statechange))
return -EAGAIN;
msleep(5);
port = HCS_N_PORTS (ehci->hcs_params);
spin_lock_irq (&ehci->lock);
/* for hcd->state HCD_STATE_SUSPENDED, also stop the non-USB side */
root->dev.power.power_state = 3;
root->state = USB_STATE_SUSPENDED;
/* stop schedules, clean any completed work */
if (HCD_IS_RUNNING(hcd->state))
if (HCD_IS_RUNNING(hcd->state)) {
ehci_quiesce (ehci);
ehci->hcd.state = USB_STATE_QUIESCING;
}
ehci->command = readl (&ehci->regs->command);
if (ehci->reclaim)
ehci->reclaim_ready = 1;
......@@ -78,6 +73,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* turn off now-idle HC */
ehci_halt (ehci);
ehci->hcd.state = HCD_STATE_SUSPENDED;
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
......@@ -89,27 +85,27 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
static int ehci_hub_resume (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
struct usb_device *root = hcd_to_bus (&ehci->hcd)->root_hub;
u32 temp;
int i;
int intr_enable;
if (!root->dev.power.power_state)
return 0;
if (time_before (jiffies, ehci->next_statechange))
return -EAGAIN;
msleep(5);
spin_lock_irq (&ehci->lock);
/* re-init operational registers in case we lost power */
if (readl (&ehci->regs->intr_enable) == 0) {
temp = 1;
writel (INTR_MASK, &ehci->regs->intr_enable);
/* at least some APM implementations will try to deliver
* IRQs right away, so delay them until we're ready.
*/
intr_enable = 1;
writel (0, &ehci->regs->segment);
writel (ehci->periodic_dma, &ehci->regs->frame_list);
writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
/* FIXME will this work even if (pci) vAUX was lost? */
} else
temp = 0;
intr_enable = 0;
ehci_dbg(ehci, "resume root hub%s\n",
temp ? " after power loss" : "");
intr_enable ? " after power loss" : "");
/* restore CMD_RUN, framelist size, and irq threshold */
writel (ehci->command, &ehci->regs->command);
......@@ -148,9 +144,14 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
writel (ehci->command, &ehci->regs->command);
}
root->dev.power.power_state = 0;
ehci->next_statechange = jiffies + msecs_to_jiffies(5);
ehci->hcd.state = USB_STATE_RUNNING;
/* Now we can safely re-enable irqs */
if (intr_enable)
writel (INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
return 0;
}
......@@ -210,6 +211,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
int ports, i, retval = 1;
unsigned long flags;
/* if !USB_SUSPEND, root hub timers won't get shut down ... */
if (!HCD_IS_RUNNING(ehci->hcd.state))
return 0;
/* init status to no-changes */
buf [0] = 0;
ports = HCS_N_PORTS (ehci->hcs_params);
......@@ -246,6 +251,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
status = STS_PCD;
}
}
/* FIXME autosuspend idle root hubs */
spin_unlock_irqrestore (&ehci->lock, flags);
return status ? retval : 0;
}
......
......@@ -908,6 +908,7 @@ itd_urb_transaction (
if (unlikely (0 == itd)) {
iso_sched_free (stream, sched);
spin_unlock_irqrestore (&ehci->lock, flags);
return -ENOMEM;
}
memset (itd, 0, sizeof *itd);
......
......@@ -109,7 +109,7 @@
#include <asm/byteorder.h>
#define DRIVER_VERSION "2004 Feb 02"
#define DRIVER_VERSION "2004 Nov 08"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
......@@ -657,8 +657,6 @@ static int ohci_run (struct ohci_hcd *ohci)
udev = hcd_to_bus (&ohci->hcd)->root_hub;
if (udev) {
udev->dev.power.power_state = 0;
usb_set_device_state (udev, USB_STATE_CONFIGURED);
return 0;
}
......@@ -799,6 +797,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
int temp;
int i;
struct urb_priv *priv;
struct usb_device *root = ohci->hcd.self.root_hub;
/* mark any devices gone, so they do nothing till khubd disconnects.
* recycle any "live" eds/tds (and urbs) right away.
......@@ -807,7 +806,11 @@ static int ohci_restart (struct ohci_hcd *ohci)
*/
spin_lock_irq(&ohci->lock);
disable (ohci);
usb_set_device_state (ohci->hcd.self.root_hub, USB_STATE_NOTATTACHED);
for (i = 0; i < root->maxchild; i++) {
if (root->children [i])
usb_set_device_state (root->children[i],
USB_STATE_NOTATTACHED);
}
if (!list_empty (&ohci->pending))
ohci_dbg(ohci, "abort schedule...\n");
list_for_each_entry (priv, &ohci->pending, pending) {
......@@ -864,7 +867,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
ohci_writel (ohci, RH_PS_PSS,
&ohci->regs->roothub.portstatus [temp]);
ohci_dbg (ohci, "restart complete\n");
ohci->hcd.state = USB_STATE_RUNNING;
}
return 0;
}
......
......@@ -48,15 +48,10 @@ static int ohci_restart (struct ohci_hcd *ohci);
static int ohci_hub_suspend (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
struct usb_device *root = hcd_to_bus (&ohci->hcd)->root_hub;
int status = 0;
unsigned long flags;
if (root->dev.power.power_state != 0)
return 0;
if (time_before (jiffies, ohci->next_statechange))
return -EAGAIN;
spin_lock_irq (&ohci->lock);
spin_lock_irqsave (&ohci->lock, flags);
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
......@@ -72,8 +67,8 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci_dbg (ohci, "needs reinit!\n");
goto done;
case OHCI_USB_SUSPEND:
ohci_dbg (ohci, "already suspended?\n");
goto succeed;
ohci_dbg (ohci, "already suspended\n");
goto done;
}
ohci_dbg (ohci, "suspend root hub\n");
......@@ -122,14 +117,10 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
/* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5);
succeed:
/* it's not HCD_STATE_SUSPENDED unless access to this
* hub from the non-usb side (PCI, SOC, etc) stopped
*/
root->dev.power.power_state = 3;
usb_set_device_state (root, USB_STATE_SUSPENDED);
done:
spin_unlock_irq (&ohci->lock);
if (status == 0)
ohci->hcd.state = HCD_STATE_SUSPENDED;
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
......@@ -145,22 +136,26 @@ static inline struct ed *find_head (struct ed *ed)
static int ohci_hub_resume (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
struct usb_device *root = hcd_to_bus (&ohci->hcd)->root_hub;
u32 temp, enables;
int status = -EINPROGRESS;
if (!root->dev.power.power_state)
return 0;
if (time_before (jiffies, ohci->next_statechange))
return -EAGAIN;
msleep(5);
spin_lock_irq (&ohci->lock);
ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
/* this can happen after suspend-to-disk */
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
status = -EBUSY;
if (hcd->state == USB_STATE_RESUMING) {
ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
ohci->hc_control);
status = -EBUSY;
/* this happens when pmcore resumes HC then root */
} else {
ohci_dbg (ohci, "duplicate resume\n");
status = 0;
}
} else switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_SUSPEND:
ohci->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES);
......@@ -175,7 +170,6 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
break;
case OHCI_USB_OPER:
ohci_dbg (ohci, "odd resume\n");
root->dev.power.power_state = 0;
status = 0;
break;
default: /* RESET, we lost power */
......@@ -245,8 +239,6 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
/* TRSMRCY */
msleep (10);
root->dev.power.power_state = 0;
usb_set_device_state (root, USB_STATE_CONFIGURED);
/* keep it alive for ~5x suspend + resume costs */
ohci->next_statechange = jiffies + msecs_to_jiffies (250);
......@@ -315,10 +307,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
int ports, i, changed = 0, length = 1;
int can_suspend = 1;
/* if !USB_SUSPEND, root hub timers won't get shut down ... */
if (!HCD_IS_RUNNING(ohci->hcd.state))
return 0;
ports = roothub_a (ohci) & RH_A_NDP;
if (ports > MAX_ROOT_PORTS) {
if (!HCD_IS_RUNNING(ohci->hcd.state))
return -ESHUTDOWN;
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
/* retry later; "should not happen" */
......@@ -362,6 +356,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
#ifdef CONFIG_PM
/* save power by suspending idle root hubs;
* INTR_RD wakes us when there's work
* NOTE: if we can do this, we don't need a root hub timer!
*/
if (can_suspend
&& !changed
......@@ -369,6 +364,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
&& usb_trylock_device (hcd->self.root_hub)
) {
ohci_vdbg (ohci, "autosuspend\n");
......@@ -409,7 +405,7 @@ ohci_hub_descriptor (
temp |= 0x0010;
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
temp |= 0x0008;
desc->wHubCharacteristics = cpu_to_hc16 (ohci, temp);
desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp);
/* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
rh = roothub_b (ohci);
......@@ -475,7 +471,7 @@ static void start_hnp(struct ohci_hcd *ohci);
/* called from some task, normally khubd */
static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
{
u32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
__hc32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
u32 temp;
u16 now = ohci_readl(ohci, &ohci->regs->fmnumber);
u16 reset_done = now + PORT_RESET_MSEC;
......
......@@ -106,7 +106,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
/* suspend root hub, hoping it keeps power during suspend */
while (time_before (jiffies, ohci->next_statechange))
if (time_before (jiffies, ohci->next_statechange))
msleep (100);
#ifdef CONFIG_USB_SUSPEND
......@@ -154,7 +154,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#endif
/* resume root hub */
while (time_before (jiffies, ohci->next_statechange))
if (time_before (jiffies, ohci->next_statechange))
msleep (100);
#ifdef CONFIG_USB_SUSPEND
/* get extra cleanup even if remote wakeup isn't in use */
......@@ -166,7 +166,6 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#endif
if (retval == 0) {
hcd->self.controller->power.power_state = 0;
#ifdef CONFIG_PMAC_PBOOK
if (_machine == _MACH_Pmac)
enable_irq (to_pci_dev(hcd->self.controller)->irq);
......
......@@ -510,7 +510,7 @@ static inline void ohci_writel (const struct ohci_hcd *ohci,
/* cpu to ohci */
static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x)
{
return big_endian(ohci) ? cpu_to_be16(x) : cpu_to_le16(x);
return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x);
}
static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x)
......@@ -520,7 +520,7 @@ static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x)
static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x)
{
return big_endian(ohci) ? cpu_to_be32(x) : cpu_to_le32(x);
return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x);
}
static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x)
......@@ -531,22 +531,22 @@ static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x)
/* ohci to cpu */
static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x)
{
return big_endian(ohci) ? be16_to_cpu(x) : le16_to_cpu(x);
return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x);
}
static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x)
{
return big_endian(ohci) ? be16_to_cpup(x) : le16_to_cpup(x);
return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x);
}
static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x)
{
return big_endian(ohci) ? be32_to_cpu(x) : le32_to_cpu(x);
return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x);
}
static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
{
return big_endian(ohci) ? be32_to_cpup(x) : le32_to_cpup(x);
return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);
}
/*-------------------------------------------------------------------------*/
......
......@@ -27,6 +27,7 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/types.h>
#include <linux/param.h>
......@@ -45,7 +46,8 @@
#define SN9C102_URBS 2
#define SN9C102_ISO_PACKETS 7
#define SN9C102_ALTERNATE_SETTING 8
#define SN9C102_CTRL_TIMEOUT 10*HZ
#define SN9C102_URB_TIMEOUT msecs_to_jiffies(3)
#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(100)
/*****************************************************************************/
......@@ -53,8 +55,8 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
#define SN9C102_MODULE_VERSION "1:1.12"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 12)
#define SN9C102_MODULE_VERSION "1:1.19"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 19)
enum sn9c102_bridge {
BRIDGE_SN9C101 = 0x01,
......@@ -100,7 +102,7 @@ enum sn9c102_stream_state {
};
struct sn9c102_sysfs_attr {
u8 reg, val, i2c_reg, i2c_val;
u8 reg, i2c_reg;
};
static DECLARE_MUTEX(sn9c102_sysfs_lock);
......@@ -121,11 +123,13 @@ struct sn9c102_device {
struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
struct list_head inqueue, outqueue;
u32 frame_count, nbuffers;
u32 frame_count, nbuffers, nreadbuffers;
enum sn9c102_io_method io;
enum sn9c102_stream_state stream;
struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs;
u16 reg[32];
......
This diff is collapsed.
/***************************************************************************
* Driver for PAS106B image sensor connected to the SN9C10x PC Camera *
* Plug-in for PAS106B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
* Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it> *
......@@ -38,14 +38,9 @@ static int pas106b_init(struct sn9c102_device* cam)
err += sn9c102_write_reg(cam, 0x09, 0x18);
err += sn9c102_i2c_write(cam, 0x02, 0x0c);
err += sn9c102_i2c_write(cam, 0x03, 0x12);
err += sn9c102_i2c_write(cam, 0x04, 0x05);
err += sn9c102_i2c_write(cam, 0x05, 0x5a);
err += sn9c102_i2c_write(cam, 0x06, 0x88);
err += sn9c102_i2c_write(cam, 0x07, 0x80);
err += sn9c102_i2c_write(cam, 0x08, 0x01);
err += sn9c102_i2c_write(cam, 0x0a, 0x01);
err += sn9c102_i2c_write(cam, 0x0b, 0x00);
err += sn9c102_i2c_write(cam, 0x10, 0x06);
err += sn9c102_i2c_write(cam, 0x11, 0x06);
err += sn9c102_i2c_write(cam, 0x12, 0x00);
......@@ -62,6 +57,15 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
{
int r1 = sn9c102_i2c_read(cam, 0x03),
r2 = sn9c102_i2c_read(cam, 0x04);
if (r1 < 0 || r2 < 0)
return -EIO;
ctrl->value = (r1 << 4) | (r2 & 0x0f);
}
return 0;
case V4L2_CID_RED_BALANCE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
return -EIO;
......@@ -77,16 +81,26 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
return -EIO;
ctrl->value &= 0x1f;
return 0;
case V4L2_CID_BRIGHTNESS:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
return -EIO;
ctrl->value &= 0x1f;
return 0;
case V4L2_CID_CONTRAST:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
return -EIO;
ctrl->value &= 0x07;
return 0;
case SN9C102_V4L2_CID_GREEN_BALANCE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0)
return -EIO;
ctrl->value = (ctrl->value & 0x1f) << 1;
return 0;
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
return -EIO;
ctrl->value &= 0xf8;
return 0;
case SN9C102_V4L2_CID_DAC_SIGN:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
return -EIO;
ctrl->value &= 0x01;
return 0;
default:
return -EINVAL;
}
......@@ -99,6 +113,10 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
int err = 0;
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
break;
case V4L2_CID_RED_BALANCE:
err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
break;
......@@ -108,12 +126,23 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
case V4L2_CID_GAIN:
err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
break;
case V4L2_CID_BRIGHTNESS:
err += sn9c102_i2c_write(cam, 0x0d, 0x1f - ctrl->value);
break;
case V4L2_CID_CONTRAST:
err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
break;
case SN9C102_V4L2_CID_GREEN_BALANCE:
err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
break;
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
break;
case SN9C102_V4L2_CID_DAC_SIGN:
{
int r;
err += (r = sn9c102_i2c_read(cam, 0x07)) < 0 ? r : 0;
err += sn9c102_i2c_write(cam, 0x07, r | ctrl->value);
}
break;
default:
return -EINVAL;
}
......@@ -147,6 +176,36 @@ static struct sn9c102_sensor pas106b = {
.slave_write_id = 0x40,
.init = &pas106b_init,
.qctrl = {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "exposure",
.minimum = 0x125,
.maximum = 0xfff,
.step = 0x01,
.default_value = 0x140,
.flags = 0,
},
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "global gain",
.minimum = 0x00,
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x0d,
.flags = 0,
},
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "contrast",
.minimum = 0x00,
.maximum = 0x07,
.step = 0x01,
.default_value = 0x00, /* 0x00~0x03 have same effect */
.flags = 0,
},
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
......@@ -168,33 +227,33 @@ static struct sn9c102_sensor pas106b = {
.flags = 0,
},
{
.id = V4L2_CID_GAIN,
.id = SN9C102_V4L2_CID_GREEN_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "global gain",
.name = "green balance",
.minimum = 0x00,
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x0d,
.maximum = 0x3e,
.step = 0x02,
.default_value = 0x02,
.flags = 0,
},
{
.id = V4L2_CID_BRIGHTNESS,
.id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "brightness",
.name = "DAC magnitude",
.minimum = 0x00,
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x1f,
.default_value = 0x01,
.flags = 0,
},
{
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "contrast",
.id = SN9C102_V4L2_CID_DAC_SIGN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "DAC sign",
.minimum = 0x00,
.maximum = 0x07,
.maximum = 0x01,
.step = 0x01,
.default_value = 0x00, /* 0x00~0x03 have same effect */
.default_value = 0x00,
.flags = 0,
},
},
......
/***************************************************************************
* Driver for PAS202BCB image sensor connected to the SN9C10x PC Camera *
* Plug-in for PAS202BCB image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
* Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
* <medaglia@undl.org.br> *
* http://cadu.homelinux.com:8080/ *
* *
* DAC Magnitude, DAC sign, exposure and green gain controls added by *
* Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
......@@ -41,14 +44,10 @@ static int pas202bcb_init(struct sn9c102_device* cam)
err += sn9c102_i2c_write(cam, 0x02, 0x14);
err += sn9c102_i2c_write(cam, 0x03, 0x40);
err += sn9c102_i2c_write(cam, 0x04, 0x07);
err += sn9c102_i2c_write(cam, 0x05, 0x25);
err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
err += sn9c102_i2c_write(cam, 0x0e, 0x01);
err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
err += sn9c102_i2c_write(cam, 0x10, 0x08);
err += sn9c102_i2c_write(cam, 0x0b, 0x01);
err += sn9c102_i2c_write(cam, 0x0c, 0x04);
err += sn9c102_i2c_write(cam, 0x13, 0x63);
err += sn9c102_i2c_write(cam, 0x15, 0x70);
err += sn9c102_i2c_write(cam, 0x11, 0x01);
......@@ -63,6 +62,15 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
struct v4l2_control* ctrl)
{
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
{
int r1 = sn9c102_i2c_read(cam, 0x04),
r2 = sn9c102_i2c_read(cam, 0x05);
if (r1 < 0 || r2 < 0)
return -EIO;
ctrl->value = (r1 << 6) | (r2 & 0x3f);
}
return 0;
case V4L2_CID_RED_BALANCE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
return -EIO;
......@@ -78,11 +86,20 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
return -EIO;
ctrl->value &= 0x1f;
return 0;
case V4L2_CID_BRIGHTNESS:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x06)) < 0)
case SN9C102_V4L2_CID_GREEN_BALANCE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
return -EIO;
ctrl->value &= 0x0f;
return 0;
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
return -EIO;
return 0;
case SN9C102_V4L2_CID_DAC_SIGN:
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0b)) < 0)
return -EIO;
ctrl->value &= 0x01;
return 0;
default:
return -EINVAL;
}
......@@ -95,6 +112,10 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
int err = 0;
switch (ctrl->id) {
case V4L2_CID_EXPOSURE:
err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
break;
case V4L2_CID_RED_BALANCE:
err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
break;
......@@ -104,8 +125,18 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
case V4L2_CID_GAIN:
err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
break;
case V4L2_CID_BRIGHTNESS:
err += sn9c102_i2c_write(cam, 0x06, 0x0f - ctrl->value);
case SN9C102_V4L2_CID_GREEN_BALANCE:
err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
break;
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
break;
case SN9C102_V4L2_CID_DAC_SIGN:
{
int r;
err += (r = sn9c102_i2c_read(cam, 0x0b)) < 0 ? r : 0;
err += sn9c102_i2c_write(cam, 0x0b, r | ctrl->value);
}
break;
default:
return -EINVAL;
......@@ -141,6 +172,26 @@ static struct sn9c102_sensor pas202bcb = {
.slave_write_id = 0x40,
.init = &pas202bcb_init,
.qctrl = {
{
.id = V4L2_CID_EXPOSURE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "exposure",
.minimum = 0x01e5,
.maximum = 0x3fff,
.step = 0x01,
.default_value = 0x01e5,
.flags = 0,
},
{
.id = V4L2_CID_GAIN,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "global gain",
.minimum = 0x00,
.maximum = 0x1f,
.step = 0x01,
.default_value = 0x0c,
.flags = 0,
},
{
.id = V4L2_CID_RED_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
......@@ -162,23 +213,33 @@ static struct sn9c102_sensor pas202bcb = {
.flags = 0,
},
{
.id = V4L2_CID_GAIN,
.id = SN9C102_V4L2_CID_GREEN_BALANCE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "global gain",
.name = "green balance",
.minimum = 0x00,
.maximum = 0x1f,
.maximum = 0x0f,
.step = 0x01,
.default_value = 0x0c,
.default_value = 0x00,
.flags = 0,
},
{
.id = V4L2_CID_BRIGHTNESS,
.id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "brightness",
.name = "DAC magnitude",
.minimum = 0x00,
.maximum = 0x0f,
.maximum = 0xff,
.step = 0x01,
.default_value = 0x0f,
.default_value = 0x04,
.flags = 0,
},
{
.id = SN9C102_V4L2_CID_DAC_SIGN,
.type = V4L2_CTRL_TYPE_BOOLEAN,
.name = "DAC sign",
.minimum = 0x00,
.maximum = 0x01,
.step = 0x01,
.default_value = 0x01,
.flags = 0,
},
},
......
......@@ -98,7 +98,7 @@ static const struct usb_device_id sn9c102_id_table[] = { \
{ USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \
{ USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \
{ USB_DEVICE(0x0c45, 0x602a), }, /* HV7131[D|E1] */ \
{ USB_DEVICE(0x0c45, 0x602b), }, \
{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */ \
{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
{ USB_DEVICE(0x0c45, 0x6080), }, \
......@@ -292,21 +292,25 @@ struct sn9c102_sensor {
NOTE: in case, you must program the SN9C10X chip to get rid of
blank pixels or blank lines at the _start_ of each line or
frame after each HSYNC or VSYNC, so that the image starts with
real RGB data (see regs 0x12,0x13) (having set H_SIZE and,
real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
V_SIZE you don't have to care about blank pixels or blank
lines at the end of each line or frame).
*/
struct v4l2_pix_format pix_format;
/*
What you have to define here are: initial 'width' and 'height' of
the target rectangle, the bayer 'pixelformat' and 'priv' which we'll
be used to indicate the number of bits per pixel, 8 or 9.
Nothing more.
What you have to define here are: 1) initial 'width' and 'height' of
the target rectangle 2) the initial 'pixelformat', which can be
either V4L2_PIX_FMT_SN9C10X (for compressed video) or
V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate the
number of bits per pixel for uncompressed video, 8 or 9 (despite the
current value of 'pixelformat').
NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
of cropcap.defrect.width and cropcap.defrect.height. I
suggest 1/1.
NOTE 2: as said above, you have to program the SN9C10X chip to get
NOTE 2: The initial compression quality is defined by the first bit
of reg 0x17 during the initialization of the image sensor.
NOTE 3: as said above, you have to program the SN9C10X chip to get
rid of any blank pixels, so that the output of the sensor
matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
*/
......@@ -333,4 +337,11 @@ struct sn9c102_sensor {
struct v4l2_rect _rect;
};
/*****************************************************************************/
/* Private ioctl's for control settings supported by some image sensors */
#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
#define SN9C102_V4L2_CID_DAC_SIGN V4L2_CID_PRIVATE_BASE + 1
#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 2
#endif /* _SN9C102_SENSOR_H_ */
/***************************************************************************
* Driver for TAS5110C1B image sensor connected to the SN9C10x PC Camera *
* Plug-in for TAS5110C1B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
* Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it> *
......@@ -150,7 +150,7 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
/* This sensor has no identifiers, so let's attach it anyway */
sn9c102_attach_sensor(cam, &tas5110c1b);
/* At the moment, sensor detection is based on USB pid/vid */
/* Sensor detection is based on USB pid/vid */
if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
tas5110c1b.usbdev->descriptor.idProduct != 0x6005 &&
tas5110c1b.usbdev->descriptor.idProduct != 0x60ab)
......
/***************************************************************************
* Driver for TAS5130D1B image sensor connected to the SN9C10x PC Camera *
* Plug-in for TAS5130D1B image sensor connected to the SN9C10x PC Camera *
* Controllers *
* *
* Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it> *
......@@ -96,8 +96,8 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam,
err += sn9c102_write_reg(cam, v_start, 0x13);
/* Do NOT change! */
err += sn9c102_write_reg(cam, 0x1d, 0x1a);
err += sn9c102_write_reg(cam, 0x10, 0x1b);
err += sn9c102_write_reg(cam, 0x1f, 0x1a);
err += sn9c102_write_reg(cam, 0x1a, 0x1b);
err += sn9c102_write_reg(cam, 0xf3, 0x19);
return err;
......@@ -165,7 +165,7 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
/* This sensor has no identifiers, so let's attach it anyway */
sn9c102_attach_sensor(cam, &tas5130d1b);
/* At the moment, sensor detection is based on USB pid/vid */
/* Sensor detection is based on USB pid/vid */
if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025 &&
tas5130d1b.usbdev->descriptor.idProduct != 0x60aa)
return -ENODEV;
......
......@@ -170,13 +170,11 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
err("Error executing ioctrl. code = %d",
le32_to_cpu(result));
err("Error executing ioctrl. code = %d", result);
retries = 0;
} else {
dbg("Executed ioctl. Result = %d (data=%04x)",
le32_to_cpu(result),
le32_to_cpu(*((long *) buffer)));
dbg("Executed ioctl. Result = %d (data=%02x)",
result, buffer[0]);
if (copy_to_user(rio_cmd.buffer, buffer,
rio_cmd.length)) {
free_page((unsigned long) buffer);
......@@ -239,12 +237,10 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
if (result == -ETIMEDOUT)
retries--;
else if (result < 0) {
err("Error executing ioctrl. code = %d",
le32_to_cpu(result));
err("Error executing ioctrl. code = %d", result);
retries = 0;
} else {
dbg("Executed ioctl. Result = %d",
le32_to_cpu(result));
dbg("Executed ioctl. Result = %d", result);
retries = 0;
}
......
......@@ -310,11 +310,11 @@ tiglusb_ioctl (struct inode *inode, struct file *filp,
ret = -EIO;
break;
case IOCTL_TIUSB_GET_MAXPS:
if (copy_to_user((int *) arg, &s->max_ps, sizeof(int)))
if (copy_to_user((int __user *) arg, &s->max_ps, sizeof(int)))
return -EFAULT;
break;
case IOCTL_TIUSB_GET_DEVID:
if (copy_to_user((int *) arg, &s->dev->descriptor.idProduct,
if (copy_to_user((int __user *) arg, &s->dev->descriptor.idProduct,
sizeof(int)))
return -EFAULT;
break;
......
......@@ -1355,7 +1355,7 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs)
"iso test, %lu errors\n",
ctx->errors);
complete (&ctx->done);
} else
}
done:
spin_unlock(&ctx->lock);
}
......@@ -1457,8 +1457,10 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
if (status < 0) {
ERROR (dev, "submit iso[%d], error %d\n", i, status);
if (i == 0)
if (i == 0) {
spin_unlock_irq (&context.lock);
goto fail;
}
simple_free_urb (urbs [i]);
context.pending--;
......
#
# USB Network devices configuration
#
comment "USB Network adaptors"
depends on USB
comment "Networking support is needed for USB Networking device support"
comment "Networking support is needed for USB Network Adapter support"
depends on USB && !NET
menu "USB Network Adapters"
depends on USB && NET
config USB_CATC
tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)"
depends on USB && NET && EXPERIMENTAL
depends on EXPERIMENTAL
select CRC32
---help---
Say Y if you want to use one of the following 10Mbps USB Ethernet
......@@ -29,7 +29,6 @@ config USB_CATC
config USB_KAWETH
tristate "USB KLSI KL5USB101-based ethernet device support"
depends on USB && NET
---help---
Say Y here if you want to use one of the following 10Mbps only
USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
......@@ -69,7 +68,6 @@ config USB_KAWETH
config USB_PEGASUS
tristate "USB Pegasus/Pegasus-II based ethernet device support"
depends on USB && NET
select MII
---help---
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
......@@ -85,7 +83,7 @@ config USB_PEGASUS
config USB_RTL8150
tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)"
depends on USB && NET && EXPERIMENTAL
depends on EXPERIMENTAL
help
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me <petkan@users.sourceforge.net> any comments you may have.
......@@ -96,7 +94,6 @@ config USB_RTL8150
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
depends on USB && NET
---help---
This driver supports several kinds of network links over USB,
with "minidrivers" built around a common network driver core
......@@ -206,6 +203,9 @@ config USB_ARMLINUX
such as the SA-11x0 and PXA-25x UDCs, or the tftp capabilities
in some PXA versions of the "blob" boot loader.
Linux-based "Gumstix" PXA-25x based systems use this protocol
to talk with other Linux systems.
Although the ROMs shipped with Sharp Zaurus products use a
different link level framing protocol, you can have them use
this simpler protocol by installing a different kernel.
......@@ -266,17 +266,20 @@ config USB_AX8817X
select MII
default y
help
This option adds support for ASIX AX88172 based USB 2.0
10/100 Ethernet devices.
This driver should work with at least the following devices:
* Aten UC210T
* ASIX AX88172
* Billionton Systems, USB2AR
* Buffalo LUA-U2-KTX
* Corega FEther USB2-TX
* D-Link DUB-E100
* Hawking UF200
* Linksys USB200M
* Netgear FA120
* Sitecom LN-029
* Intellinet USB 2.0 Ethernet
* ST Lab USB 2.0 Ethernet
* TrendNet TU2-ET100
......@@ -284,4 +287,4 @@ config USB_AX8817X
This driver creates an interface named "ethX", where X depends on
what other networking devices you have in use.
endmenu
This diff is collapsed.
......@@ -13,9 +13,9 @@
#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
struct edge_firmware_image_record {
unsigned short ExtAddr;
unsigned short Addr;
unsigned short Len;
__le16 ExtAddr;
__le16 Addr;
__le16 Len;
unsigned char Data[0];
} __attribute__ ((packed));
......
......@@ -13,9 +13,9 @@
#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
struct edge_firmware_image_record {
unsigned short ExtAddr;
unsigned short Addr;
unsigned short Len;
__le16 ExtAddr;
__le16 Addr;
__le16 Len;
unsigned char Data[0];
} __attribute__ ((packed));
......
......@@ -13,9 +13,9 @@
#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
struct edge_firmware_image_record {
unsigned short ExtAddr;
unsigned short Addr;
unsigned short Len;
__le16 ExtAddr;
__le16 Addr;
__le16 Len;
unsigned char Data[0];
} __attribute__ ((packed));
......
......@@ -13,9 +13,9 @@
#if !defined(DEFINED_EDGE_FIRMWARE_IMAGE_RECORD)
#define DEFINED_EDGE_FIRMWARE_IMAGE_RECORD
struct edge_firmware_image_record {
unsigned short ExtAddr;
unsigned short Addr;
unsigned short Len;
__le16 ExtAddr;
__le16 Addr;
__le16 Len;
unsigned char Data[0];
} __attribute__ ((packed));
......
......@@ -98,6 +98,9 @@ static struct usb_serial_device_type edgeport_2port_device = {
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
.break_ctl = edge_break,
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_data_callback,
};
static struct usb_serial_device_type edgeport_4port_device = {
......@@ -123,6 +126,9 @@ static struct usb_serial_device_type edgeport_4port_device = {
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
.break_ctl = edge_break,
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_data_callback,
};
static struct usb_serial_device_type edgeport_8port_device = {
......@@ -148,6 +154,9 @@ static struct usb_serial_device_type edgeport_8port_device = {
.write_room = edge_write_room,
.chars_in_buffer = edge_chars_in_buffer,
.break_ctl = edge_break,
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_data_callback,
};
#endif
......
This diff is collapsed.
......@@ -619,7 +619,7 @@ struct watchport_firmware_version
// Structure of header of download image in fw_down.h
struct ti_i2c_image_header
{
__u16 Length;
__le16 Length;
__u8 CheckSum;
}__attribute__((packed));
......
......@@ -773,9 +773,11 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
switch (cflag & CSIZE) {
case CS5:
dbg("%s - 5 bits/byte not supported", __FUNCTION__);
spin_unlock_irqrestore (&priv->lock, flags);
return ;
case CS6:
dbg("%s - 6 bits/byte not supported", __FUNCTION__);
spin_unlock_irqrestore (&priv->lock, flags);
return ;
case CS7:
priv->cfg.databits = kl5kusb105a_dtb_7;
......
......@@ -236,7 +236,7 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
{
unsigned int divisor;
__le32 divisor;
int rc;
unsigned char zero_byte = 0;
......
......@@ -463,6 +463,7 @@ static void destroy_serial(struct kref *kref)
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
}
}
......@@ -480,45 +481,51 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
struct usb_serial *serial;
struct usb_serial_port *port;
unsigned int portNumber;
int retval = -ENODEV;
int retval;
dbg("%s", __FUNCTION__);
/* initialize the pointer incase something fails */
tty->driver_data = NULL;
/* get the serial object associated with this tty pointer */
serial = usb_serial_get_by_index(tty->index);
if (!serial)
goto bailout;
if (!serial) {
tty->driver_data = NULL;
return -ENODEV;
}
/* set up our port structure making the tty driver remember our port object, and us it */
portNumber = tty->index - serial->minor;
port = serial->port[portNumber];
tty->driver_data = port;
port->tty = tty;
/* lock this module before we call it,
this may, which means we must bail out, safe because we are called with BKL held */
if (!try_module_get(serial->type->owner)) {
kref_put(&serial->kref, destroy_serial);
goto bailout;
}
retval = 0;
++port->open_count;
if (port->open_count == 1) {
/* set up our port structure making the tty driver
* remember our port object, and us it */
tty->driver_data = port;
port->tty = tty;
/* lock this module before we call it
* this may fail, which means we must bail out,
* safe because we are called with BKL held */
if (!try_module_get(serial->type->owner)) {
retval = -ENODEV;
goto bailout_kref_put;
}
/* only call the device specific open if this
* is the first time the port is opened */
retval = serial->type->open(port, filp);
if (retval) {
port->open_count = 0;
module_put(serial->type->owner);
kref_put(&serial->kref, destroy_serial);
}
if (retval)
goto bailout_module_put;
}
bailout:
return 0;
bailout_module_put:
module_put(serial->type->owner);
bailout_kref_put:
kref_put(&serial->kref, destroy_serial);
port->open_count = 0;
return retval;
}
......@@ -531,21 +538,24 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
dbg("%s - port %d", __FUNCTION__, port->number);
if (port->open_count == 0)
return;
--port->open_count;
if (port->open_count <= 0) {
if (port->open_count == 0) {
/* only call the device specific close if this
* port is being closed by the last owner */
port->serial->type->close(port, filp);
port->open_count = 0;
if (port->tty) {
if (port->tty->driver_data)
port->tty->driver_data = NULL;
port->tty = NULL;
}
module_put(port->serial->type->owner);
}
module_put(port->serial->type->owner);
kref_put(&port->serial->kref, destroy_serial);
}
......@@ -805,6 +815,7 @@ static void port_release(struct device *dev)
kfree(port->bulk_in_buffer);
kfree(port->bulk_out_buffer);
kfree(port->interrupt_in_buffer);
kfree(port->interrupt_out_buffer);
kfree(port);
}
......
......@@ -1114,11 +1114,11 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
command_port->write_urb->transfer_buffer_length = datasize + 1;
command_port->write_urb->dev = port->serial->dev;
retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
spin_unlock_irqrestore(&command_info->lock, flags);
if (retval) {
dbg("%s - submit urb failed", __FUNCTION__);
goto exit;
}
spin_unlock_irqrestore(&command_info->lock, flags);
/* wait for the command to complete */
wait_event_interruptible_timeout(command_info->wait_command,
......
......@@ -290,7 +290,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
case REQUEST_SENSE: /* 16 or 18 bytes? spec says 18, lots of devices only have 16 */
case MODE_SENSE:
case MODE_SENSE_10:
length = fst->Count;
length = le16_to_cpu(fst->Count);
break;
default:
length = srb->request_bufflen;
......
......@@ -281,6 +281,14 @@ UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
/* Yakumo Mega Image 47
* Reported by Bjoern Paetzel <kolrabi@kolrabi.de> */
UNUSUAL_DEV( 0x052b, 0x1905, 0x0100, 0x0100,
"Tekom Technologies, Inc",
"400_CAMERA",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony",
......@@ -447,6 +455,13 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
0 ),
#endif
/* Reported by Avi Kivity <avi@argo.co.il> */
UNUSUAL_DEV( 0x05ac, 0x1203, 0x0001, 0x0001,
"Apple",
"iPod",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
#ifdef CONFIG_USB_STORAGE_JUMPSHOT
UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
......
......@@ -219,6 +219,7 @@ struct v4l2_pix_format
/* Vendor-specific formats */
#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */
/*
* F O R M A T E N U M E R A T I O N
......
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